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 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. 101 void set_entity_authorization_value(const std::string& auth_value) { 102 entity_authorization_value_ = auth_value; 103 } 104 105 std::string entity_authorization_value() const { 106 return entity_authorization_value_; 107 } 108 109 TPM_HANDLE session_handle() const { return session_handle_; } 110 111 void set_use_entity_authorization_for_encryption_only(bool value) { 112 use_entity_authorization_for_encryption_only_ = value; 113 } 114 115 protected: 116 FRIEND_TEST(HmacAuthorizationDelegateFixture, NonceRegenerationTest); 117 FRIEND_TEST(HmacAuthorizationDelegateTest, EncryptDecryptTest); 118 FRIEND_TEST(HmacAuthorizationDelegateTest, SessionKeyTest); 119 120 private: 121 // This method implements the key derivation function used in the TPM. 122 // NOTE: It only returns 32 byte keys. 123 std::string CreateKey(const std::string& hmac_key, 124 const std::string& label, 125 const TPM2B_NONCE& nonce_newer, 126 const TPM2B_NONCE& nonce_older); 127 // This method performs a FIPS198 HMAC operation on |data| using |key| 128 std::string HmacSha256(const std::string& key, const std::string& data); 129 // This method performs an AES operation using a 128 bit key. 130 // |operation_type| can be either AES_ENCRYPT or AES_DECRYPT and it 131 // determines if the operation is an encryption or decryption. 132 void AesOperation(std::string* parameter, 133 const TPM2B_NONCE& nonce_newer, 134 const TPM2B_NONCE& nonce_older, 135 int operation_type); 136 // This method regenerates the caller nonce. The new nonce is the same 137 // length as the previous nonce. The buffer is filled with random data using 138 // openssl's |RAND_bytes| function. 139 // NOTE: This operation is DESTRUCTIVE, and rewrites the caller_nonce_ field. 140 void RegenerateCallerNonce(); 141 142 TPM_HANDLE session_handle_; 143 TPM2B_NONCE caller_nonce_; 144 TPM2B_NONCE tpm_nonce_; 145 bool is_parameter_encryption_enabled_; 146 bool nonce_generated_; 147 std::string session_key_; 148 std::string entity_authorization_value_; 149 bool future_authorization_value_set_; 150 std::string future_authorization_value_; 151 // This boolean flag determines if the entity_authorization_value_ is needed 152 // when computing the hmac_key to create the authorization hmac. Defaults 153 // to false, but policy sessions may set this flag to true. 154 bool use_entity_authorization_for_encryption_only_; 155 156 DISALLOW_COPY_AND_ASSIGN(HmacAuthorizationDelegate); 157 }; 158 159 } // namespace trunks 160 161 #endif // TRUNKS_HMAC_AUTHORIZATION_DELEGATE_H_ 162