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 30namespace trunks { 31 32const uint8_t kContinueSession = 1; 33const size_t kAesKeySize = 16; // 128 bits is minimum AES key size. 34const 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); 61class 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