hmac_authorization_delegate.h revision 4dc4629c415e7ca90ff146d7bb75b5646ecd8b17
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