• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (C) 2014 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #ifndef TRUNKS_HMAC_AUTHORIZATION_DELEGATE_H_
18 #define TRUNKS_HMAC_AUTHORIZATION_DELEGATE_H_
19 
20 #include <string>
21 
22 #include <base/gtest_prod_util.h>
23 #include <crypto/secure_hash.h>
24 #include <gtest/gtest_prod.h>
25 
26 #include "trunks/authorization_delegate.h"
27 #include "trunks/tpm_generated.h"
28 #include "trunks/trunks_export.h"
29 
30 namespace trunks {
31 
32 const uint8_t kContinueSession = 1;
33 const size_t kAesKeySize = 16;      // 128 bits is minimum AES key size.
34 const size_t kHashDigestSize = 32;  // 256 bits is SHA256 digest size.
35 
36 // HmacAuthorizationDelegate is an implementation of the AuthorizationDelegate
37 // interface. It provides the necessary Auth data for HMAC sessions.
38 // This delegate also does parameter encryption on sessions that support it.
39 
40 // Usage:
41 // 1) After running the StartAuthSession command on the TPM2.0, we declare this
42 // delegate using the constructor. We can specify if we want parameter
43 // obfuscation enabled or not.
44 // 2) We initialize the session using |InitSession|. We feed in the handle and
45 // tpm_nonce returned by StartAuthSession. Additionally we inject the
46 // caller_nonce, salt and auth_value of the bound entity we fed into
47 // StartAuthSession.
48 // 3) Pass a pointer to this delegate to any TPM command that needs
49 // authorization using this delegate.
50 
51 // Sample control flow:
52 //  TrunksProxy proxy;
53 //  proxy.Init();
54 //  Tpm tpm(&proxy);
55 //  tpm.StartAuthSession(...);
56 //  HmacAuthorizationDelegate hmac();
57 //  hmac.InitSession(...);
58 //  tpm.Create(..., &hmac);
59 //  hmac.set_entity_authorization_value(...);
60 //  tpm.Load(..., &hmac);
61 class TRUNKS_EXPORT HmacAuthorizationDelegate: public AuthorizationDelegate {
62  public:
63   HmacAuthorizationDelegate();
64   ~HmacAuthorizationDelegate() override;
65 
66   // AuthorizationDelegate methods.
67   bool GetCommandAuthorization(const std::string& command_hash,
68                                bool is_command_parameter_encryption_possible,
69                                bool is_response_parameter_encryption_possible,
70                                std::string* authorization) override;
71   bool CheckResponseAuthorization(const std::string& response_hash,
72                                   const std::string& authorization) override;
73   bool EncryptCommandParameter(std::string* parameter) override;
74   bool DecryptResponseParameter(std::string* parameter) override;
75 
76   // This function is called with the return data of |StartAuthSession|. It
77   // will initialize the session to start providing auth information. It can
78   // only be called once per delegate, and must be called before the delegate
79   // is used for any operation. The boolean arg |enable_parameter_encryption|
80   // specifies if parameter encryption should be enabled for this delegate.
81   // |salt| and |bind_auth_value| specify the injected auth values into this
82   // delegate.
83   bool InitSession(TPM_HANDLE session_handle,
84                    const TPM2B_NONCE& tpm_nonce,
85                    const TPM2B_NONCE& caller_nonce,
86                    const std::string& salt,
87                    const std::string& bind_auth_value,
88                    bool enable_parameter_encryption);
89 
90   // This method sets the FutureAuthorizationValue. This value is used in
91   // computing the HMAC response of TPM2_HierarchyChangeAuth.
92   void set_future_authorization_value(const std::string& auth_value);
93 
future_authorization_value()94   std::string future_authorization_value() {
95     return future_authorization_value_;
96   }
97 
98   // This method is used to inject an auth_value associated with an entity.
99   // This auth_value is then used when generating HMACs and encryption keys.
100   // Note: This value will be used for all commands until explicitly reset.
set_entity_authorization_value(const std::string & auth_value)101   void set_entity_authorization_value(const std::string& auth_value) {
102     entity_authorization_value_ = auth_value;
103   }
104 
entity_authorization_value()105   std::string entity_authorization_value() const {
106     return entity_authorization_value_;
107   }
108 
session_handle()109   TPM_HANDLE session_handle() const {
110     return session_handle_;
111   }
112 
set_use_entity_authorization_for_encryption_only(bool value)113   void set_use_entity_authorization_for_encryption_only(bool value) {
114     use_entity_authorization_for_encryption_only_ = value;
115   }
116 
117  protected:
118   FRIEND_TEST(HmacAuthorizationDelegateFixture, NonceRegenerationTest);
119   FRIEND_TEST(HmacAuthorizationDelegateTest, EncryptDecryptTest);
120   FRIEND_TEST(HmacAuthorizationDelegateTest, SessionKeyTest);
121 
122  private:
123   // This method implements the key derivation function used in the TPM.
124   // NOTE: It only returns 32 byte keys.
125   std::string CreateKey(const std::string& hmac_key,
126                         const std::string& label,
127                         const TPM2B_NONCE& nonce_newer,
128                         const TPM2B_NONCE& nonce_older);
129   // This method performs a FIPS198 HMAC operation on |data| using |key|
130   std::string HmacSha256(const std::string& key,
131                          const std::string& data);
132   // This method performs an AES operation using a 128 bit key.
133   // |operation_type| can be either AES_ENCRYPT or AES_DECRYPT and it
134   // determines if the operation is an encryption or decryption.
135   void AesOperation(std::string* parameter,
136                     const TPM2B_NONCE& nonce_newer,
137                     const TPM2B_NONCE& nonce_older,
138                     int operation_type);
139   // This method regenerates the caller nonce. The new nonce is the same
140   // length as the previous nonce. The buffer is filled with random data using
141   // openssl's |RAND_bytes| function.
142   // NOTE: This operation is DESTRUCTIVE, and rewrites the caller_nonce_ field.
143   void RegenerateCallerNonce();
144 
145   TPM_HANDLE session_handle_;
146   TPM2B_NONCE caller_nonce_;
147   TPM2B_NONCE tpm_nonce_;
148   bool is_parameter_encryption_enabled_;
149   bool nonce_generated_;
150   std::string session_key_;
151   std::string entity_authorization_value_;
152   bool future_authorization_value_set_;
153   std::string future_authorization_value_;
154   // This boolean flag determines if the entity_authorization_value_ is needed
155   // when computing the hmac_key to create the authorization hmac. Defaults
156   // to false, but policy sessions may set this flag to true.
157   bool use_entity_authorization_for_encryption_only_;
158 
159   DISALLOW_COPY_AND_ASSIGN(HmacAuthorizationDelegate);
160 };
161 
162 }  // namespace trunks
163 
164 #endif  // TRUNKS_HMAC_AUTHORIZATION_DELEGATE_H_
165