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