• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2024 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "ffi.h"
6 
7 #include <android-base/logging.h>
8 #include <openssl/bio.h>
9 #include <openssl/bn.h>
10 #include <openssl/cipher.h>
11 #include <openssl/ecdsa.h>
12 #include <openssl/hmac.h>
13 #include <openssl/mem.h>
14 #include <openssl/rand.h>
15 #include <openssl/rsa.h>
16 #include <openssl/sha.h>
17 
18 #include "multiple_authorization_delegate.h"
19 #include "password_authorization_delegate.h"
20 
21 namespace trunks {
22 
23 namespace {
24 
25 constexpr TPMA_OBJECT kFixedTPM = 1U << 1;
26 constexpr TPMA_OBJECT kFixedParent = 1U << 4;
27 constexpr TPMA_OBJECT kSensitiveDataOrigin = 1U << 5;
28 constexpr TPMA_OBJECT kUserWithAuth = 1U << 6;
29 constexpr TPMA_OBJECT kNoDA = 1U << 10;
30 constexpr TPMA_OBJECT kRestricted = 1U << 16;
31 constexpr TPMA_OBJECT kDecrypt = 1U << 17;
32 constexpr TPMA_OBJECT kSign = 1U << 18;
33 
34 // Returns a general public area for our keys. This default may be further
35 // manipulated to produce the public area for specific keys (such as SRK or
36 // AIK).
DefaultPublicArea()37 TPMT_PUBLIC DefaultPublicArea() {
38   TPMT_PUBLIC public_area;
39   memset(&public_area, 0, sizeof(public_area));
40   public_area.type = TPM_ALG_ECC;
41   public_area.name_alg = TPM_ALG_SHA256;
42   public_area.auth_policy = Make_TPM2B_DIGEST("");
43   public_area.object_attributes = kFixedTPM | kFixedParent;
44   public_area.parameters.ecc_detail.scheme.scheme = TPM_ALG_NULL;
45   public_area.parameters.ecc_detail.symmetric.algorithm = TPM_ALG_NULL;
46   public_area.parameters.ecc_detail.curve_id = TPM_ECC_NIST_P256;
47   public_area.parameters.ecc_detail.kdf.scheme = TPM_ALG_NULL;
48   public_area.unique.ecc.x = Make_TPM2B_ECC_PARAMETER("");
49   public_area.unique.ecc.y = Make_TPM2B_ECC_PARAMETER("");
50   return public_area;
51 }
52 
GetOpenSSLError()53 std::string GetOpenSSLError() {
54   BIO* bio = BIO_new(BIO_s_mem());
55   ERR_print_errors(bio);
56   char* data = nullptr;
57   int data_len = BIO_get_mem_data(bio, &data);
58   std::string error_string(data, data_len);
59   BIO_free(bio);
60   return error_string;
61 }
62 
StringAsOpenSSLBuffer(std::string * s)63 unsigned char* StringAsOpenSSLBuffer(std::string* s) {
64   return reinterpret_cast<unsigned char*>(std::data(*s));
65 }
66 
67 // Converts a TPMT_SIGNATURE into a DER-encoded ECDSA signature.
TpmSignatureToString(TPMT_SIGNATURE signature,std::string * encoded)68 TPM_RC TpmSignatureToString(TPMT_SIGNATURE signature, std::string* encoded) {
69   std::string r =
70       StringFrom_TPM2B_ECC_PARAMETER(signature.signature.ecdsa.signature_r);
71   std::string s =
72       StringFrom_TPM2B_ECC_PARAMETER(signature.signature.ecdsa.signature_s);
73   BIGNUM* r_bn =
74       BN_bin2bn(reinterpret_cast<const uint8_t*>(r.data()), r.length(), NULL);
75   BIGNUM* s_bn =
76       BN_bin2bn(reinterpret_cast<const uint8_t*>(s.data()), s.length(), NULL);
77   ECDSA_SIG* sig = ECDSA_SIG_new();
78   if (r_bn == NULL || s_bn == NULL || sig == NULL) {
79     LOG(ERROR) << "BoringSSL allocation failure";
80     return TPM_RC_FAILURE;
81   }
82   // Note: if successful, this transfers ownership of r_bn and s_bin to sig.
83   if (ECDSA_SIG_set0(sig, r_bn, s_bn) != 1) {
84     LOG(ERROR) << "ECDSA_SIG_set0 failed";
85     ECDSA_SIG_free(sig);
86     BN_free(r_bn);
87     BN_free(s_bn);
88     return TPM_RC_FAILURE;
89   }
90   unsigned char* openssl_buffer = nullptr;
91   int size = i2d_ECDSA_SIG(sig, &openssl_buffer);
92   ECDSA_SIG_free(sig);
93   if (size < 0 || openssl_buffer == nullptr) {
94     LOG(ERROR) << "i2d_ECDSA_SIG failed";
95     return TPM_RC_FAILURE;
96   }
97   encoded->assign(reinterpret_cast<const char*>(openssl_buffer), size);
98   OPENSSL_free(openssl_buffer);
99   return TPM_RC_SUCCESS;
100 }
101 
102 }  // namespace
103 
EncryptDataForCa(const std::string & data,const std::string & public_key_hex,const std::string & key_id,std::string & wrapped_key,std::string & iv,std::string & mac,std::string & encrypted_data,std::string & wrapping_key_id)104 bool EncryptDataForCa(const std::string& data,
105                       const std::string& public_key_hex,
106                       const std::string& key_id, std::string& wrapped_key,
107                       std::string& iv, std::string& mac,
108                       std::string& encrypted_data,
109                       std::string& wrapping_key_id) {
110   const size_t kAesKeySize = 32;
111   const size_t kAesBlockSize = 16;
112   // The exponent of the attestation CA key pairs.
113   const unsigned int kWellKnownExponent = 65537;
114   RSA* rsa = nullptr;
115   BIGNUM* e = nullptr;
116   BIGNUM* n = nullptr;
117   EVP_CIPHER_CTX* encryption_context = nullptr;
118   // This lambda returns early in case of error. The values it allocates are
119   // cleaned up after it returns regardless of outcome.
120   bool out = [&]() {
121     rsa = RSA_new();
122     e = BN_new();
123     n = BN_new();
124     if (!rsa || !e || !n) {
125       LOG(ERROR) << "Failed to allocate RSA or BIGNUMs";
126       return false;
127     }
128     if (!BN_set_word(e, kWellKnownExponent)) {
129       LOG(ERROR) << "Failed to generate exponent";
130       return false;
131     }
132     if (!BN_hex2bn(&n, public_key_hex.c_str())) {
133       LOG(ERROR) << "Failed to generate modulus";
134       return false;
135     }
136     if (!RSA_set0_key(rsa, n, e, nullptr)) {
137       LOG(ERROR) << "Failed to set exponent or modulus";
138       return false;
139     }
140     // RSA_set0_key succeeded, so ownership of n and e are transferred into rsa.
141     // Reset e and n to avoid double-BN_free.
142     e = nullptr;
143     n = nullptr;
144     std::string key;
145     key.resize(kAesKeySize);
146     if (RAND_bytes(StringAsOpenSSLBuffer(&key), kAesKeySize) != 1) {
147       LOG(ERROR) << "RAND_bytes for key failed";
148       return false;
149     }
150     iv.resize(kAesBlockSize);
151     if (RAND_bytes(StringAsOpenSSLBuffer(&iv), kAesBlockSize) != 1) {
152       LOG(ERROR) << "RAND_bytes for iv failed";
153       return false;
154     }
155     // Allocate enough space for the output including padding.
156     encrypted_data.resize(data.size() + kAesBlockSize -
157                           (data.size() % kAesBlockSize));
158     encryption_context = EVP_CIPHER_CTX_new();
159     if (!encryption_context) {
160       LOG(ERROR) << "Failed to allocate EVP_CIPHER_CTX: " << GetOpenSSLError();
161       return false;
162     }
163     if (!EVP_EncryptInit_ex(encryption_context, EVP_aes_256_cbc(), nullptr,
164                             StringAsOpenSSLBuffer(&key),
165                             StringAsOpenSSLBuffer(&iv))) {
166       LOG(ERROR) << "EVP_EncryptInit_ex failed: " << GetOpenSSLError();
167       return false;
168     }
169     unsigned char* output_buffer = StringAsOpenSSLBuffer(&encrypted_data);
170     int update_size = 0;
171     const uint8_t* input_buffer =
172         reinterpret_cast<const uint8_t*>(std::data(data));
173     if (!EVP_EncryptUpdate(encryption_context, output_buffer, &update_size,
174                            input_buffer, data.size())) {
175       LOG(ERROR) << "EVP_EncryptUpdate failed: " << GetOpenSSLError();
176       return false;
177     }
178     output_buffer += update_size;
179     int final_size = 0;
180     if (!EVP_EncryptFinal_ex(encryption_context, output_buffer, &final_size)) {
181       LOG(ERROR) << "EVP_EncryptFinal_ex failed: " << GetOpenSSLError();
182       return false;
183     }
184     encrypted_data.resize(update_size + final_size);
185     mac.resize(SHA512_DIGEST_LENGTH);
186     std::string hmac_data = iv + encrypted_data;
187     HMAC(EVP_sha512(), key.data(), key.size(),
188          StringAsOpenSSLBuffer(&hmac_data), hmac_data.size(),
189          StringAsOpenSSLBuffer(&mac), nullptr);
190     wrapped_key.resize(RSA_size(rsa));
191     int length = RSA_public_encrypt(
192         key.size(), reinterpret_cast<const unsigned char*>(key.data()),
193         StringAsOpenSSLBuffer(&wrapped_key), rsa, RSA_PKCS1_OAEP_PADDING);
194     if (length < 0) {
195       LOG(ERROR) << "RSA_public_encrypt failed: " << GetOpenSSLError();
196       return false;
197     }
198     wrapping_key_id = key_id;
199     return true;
200   }();
201   if (rsa) {
202     RSA_free(rsa);
203   }
204   if (e) {
205     BN_free(e);
206   }
207   if (n) {
208     BN_free(n);
209   }
210   if (encryption_context) {
211     EVP_CIPHER_CTX_free(encryption_context);
212   }
213   return out;
214 }
215 
PasswordAuthorizationDelegate_New(const std::string & password)216 std::unique_ptr<AuthorizationDelegate> PasswordAuthorizationDelegate_New(
217     const std::string& password) {
218   return std::make_unique<PasswordAuthorizationDelegate>(password);
219 }
220 
SerializeCommand_Create(const TPMI_DH_OBJECT & parent_handle,const std::string & parent_handle_name,const TPM2B_SENSITIVE_CREATE & in_sensitive,const TPM2B_PUBLIC & in_public,const TPM2B_DATA & outside_info,const TPML_PCR_SELECTION & creation_pcr,std::string & serialized_command,const std::unique_ptr<AuthorizationDelegate> & authorization_delegate)221 TPM_RC SerializeCommand_Create(
222     const TPMI_DH_OBJECT& parent_handle, const std::string& parent_handle_name,
223     const TPM2B_SENSITIVE_CREATE& in_sensitive, const TPM2B_PUBLIC& in_public,
224     const TPM2B_DATA& outside_info, const TPML_PCR_SELECTION& creation_pcr,
225     std::string& serialized_command,
226     const std::unique_ptr<AuthorizationDelegate>& authorization_delegate) {
227   return Tpm::SerializeCommand_Create(
228       parent_handle, parent_handle_name, in_sensitive, in_public, outside_info,
229       creation_pcr, &serialized_command, authorization_delegate.get());
230 }
231 
ParseResponse_Create(const std::string & response,std::string & out_private,std::string & out_public,TPM2B_CREATION_DATA & creation_data,TPM2B_DIGEST & creation_hash,TPMT_TK_CREATION & creation_ticket,const std::unique_ptr<AuthorizationDelegate> & authorization_delegate)232 TPM_RC ParseResponse_Create(
233     const std::string& response, std::string& out_private,
234     std::string& out_public, TPM2B_CREATION_DATA& creation_data,
235     TPM2B_DIGEST& creation_hash, TPMT_TK_CREATION& creation_ticket,
236     const std::unique_ptr<AuthorizationDelegate>& authorization_delegate) {
237   TPM2B_PRIVATE typed_private;
238   TPM2B_PUBLIC typed_public;
239   TPM_RC rc = Tpm::ParseResponse_Create(
240       response, &typed_private, &typed_public, &creation_data, &creation_hash,
241       &creation_ticket, authorization_delegate.get());
242   if (rc != TPM_RC_SUCCESS) {
243     return rc;
244   }
245   out_private = StringFrom_TPM2B_PRIVATE(typed_private);
246   return Serialize_TPM2B_PUBLIC(typed_public, &out_public);
247 }
248 
SerializeCommand_CreatePrimary(const TPMI_RH_HIERARCHY & primary_handle,const std::string & primary_handle_name,const TPM2B_SENSITIVE_CREATE & in_sensitive,const TPM2B_PUBLIC & in_public,const TPM2B_DATA & outside_info,const TPML_PCR_SELECTION & creation_pcr,std::string & serialized_command,const std::unique_ptr<AuthorizationDelegate> & authorization_delegate)249 TPM_RC SerializeCommand_CreatePrimary(
250     const TPMI_RH_HIERARCHY& primary_handle,
251     const std::string& primary_handle_name,
252     const TPM2B_SENSITIVE_CREATE& in_sensitive, const TPM2B_PUBLIC& in_public,
253     const TPM2B_DATA& outside_info, const TPML_PCR_SELECTION& creation_pcr,
254     std::string& serialized_command,
255     const std::unique_ptr<AuthorizationDelegate>& authorization_delegate) {
256   return Tpm::SerializeCommand_CreatePrimary(
257       primary_handle, primary_handle_name, in_sensitive, in_public,
258       outside_info, creation_pcr, &serialized_command,
259       authorization_delegate.get());
260 }
261 
ParseResponse_CreatePrimary(const std::string & response,TPM_HANDLE & object_handle,TPM2B_PUBLIC & out_public,TPM2B_CREATION_DATA & creation_data,TPM2B_DIGEST & creation_hash,TPMT_TK_CREATION & creation_ticket,std::string & name,const std::unique_ptr<AuthorizationDelegate> & authorization_delegate)262 TPM_RC ParseResponse_CreatePrimary(
263     const std::string& response, TPM_HANDLE& object_handle,
264     TPM2B_PUBLIC& out_public, TPM2B_CREATION_DATA& creation_data,
265     TPM2B_DIGEST& creation_hash, TPMT_TK_CREATION& creation_ticket,
266     std::string& name,
267     const std::unique_ptr<AuthorizationDelegate>& authorization_delegate) {
268   TPM2B_NAME tpm2b_name;
269   TPM_RC rc = Tpm::ParseResponse_CreatePrimary(
270       response, &object_handle, &out_public, &creation_data, &creation_hash,
271       &creation_ticket, &tpm2b_name, authorization_delegate.get());
272   if (rc != TPM_RC_SUCCESS) {
273     return rc;
274   }
275   return Serialize_TPM2B_NAME(tpm2b_name, &name);
276 }
277 
SerializeCommand_Load(const TPMI_DH_OBJECT & parent_handle,const std::string & parent_handle_name,const std::string & in_private,const std::string & in_public,std::string & serialized_command,const std::unique_ptr<AuthorizationDelegate> & authorization_delegate)278 TPM_RC SerializeCommand_Load(
279     const TPMI_DH_OBJECT& parent_handle, const std::string& parent_handle_name,
280     const std::string& in_private, const std::string& in_public,
281     std::string& serialized_command,
282     const std::unique_ptr<AuthorizationDelegate>& authorization_delegate) {
283   std::string buffer_public = in_public;
284   TPM2B_PUBLIC typed_public;
285   TPM_RC rc = Parse_TPM2B_PUBLIC(&buffer_public, &typed_public, nullptr);
286   if (rc != TPM_RC_SUCCESS) {
287     return rc;
288   }
289   return Tpm::SerializeCommand_Load(
290       parent_handle, parent_handle_name, Make_TPM2B_PRIVATE(in_private),
291       typed_public, &serialized_command, authorization_delegate.get());
292 }
293 
ParseResponse_Load(const std::string & response,TPM_HANDLE & object_handle,std::string & name,const std::unique_ptr<AuthorizationDelegate> & authorization_delegate)294 TPM_RC ParseResponse_Load(
295     const std::string& response, TPM_HANDLE& object_handle, std::string& name,
296     const std::unique_ptr<AuthorizationDelegate>& authorization_delegate) {
297   TPM2B_NAME typed_name;
298   TPM_RC rc = Tpm::ParseResponse_Load(response, &object_handle, &typed_name,
299                                       authorization_delegate.get());
300   if (rc != TPM_RC_SUCCESS) {
301     return rc;
302   }
303   name = StringFrom_TPM2B_NAME(typed_name);
304   return TPM_RC_SUCCESS;
305 }
306 
SerializeCommand_NV_Certify(const TPMI_DH_OBJECT & sign_handle,const std::string & sign_handle_name,const TPMI_RH_NV_AUTH & auth_handle,const std::string & auth_handle_name,const TPMI_RH_NV_INDEX & nv_index,const std::string & nv_index_name,const TPM2B_DATA & qualifying_data,const TPMT_SIG_SCHEME & in_scheme,const UINT16 & size,const UINT16 & offset,std::string & serialized_command)307 TPM_RC SerializeCommand_NV_Certify(
308     const TPMI_DH_OBJECT& sign_handle, const std::string& sign_handle_name,
309     const TPMI_RH_NV_AUTH& auth_handle, const std::string& auth_handle_name,
310     const TPMI_RH_NV_INDEX& nv_index, const std::string& nv_index_name,
311     const TPM2B_DATA& qualifying_data, const TPMT_SIG_SCHEME& in_scheme,
312     const UINT16& size, const UINT16& offset, std::string& serialized_command) {
313   PasswordAuthorizationDelegate password("");
314   MultipleAuthorizations authorizations;
315   authorizations.AddAuthorizationDelegate(&password);
316   authorizations.AddAuthorizationDelegate(&password);
317   return Tpm::SerializeCommand_NV_Certify(
318       sign_handle, sign_handle_name, auth_handle, auth_handle_name, nv_index,
319       nv_index_name, qualifying_data, in_scheme, size, offset,
320       &serialized_command, &authorizations);
321 }
322 
ParseResponse_NV_Certify(const std::string & response,std::string & certify_info,std::string & signature)323 TPM_RC ParseResponse_NV_Certify(const std::string& response,
324                                 std::string& certify_info,
325                                 std::string& signature) {
326   TPM2B_ATTEST certify_info_typed;
327   TPMT_SIGNATURE signature_typed;
328   PasswordAuthorizationDelegate password("");
329   MultipleAuthorizations authorizations;
330   authorizations.AddAuthorizationDelegate(&password);
331   authorizations.AddAuthorizationDelegate(&password);
332   TPM_RC rc = Tpm::ParseResponse_NV_Certify(response, &certify_info_typed,
333                                             &signature_typed, &authorizations);
334   if (rc != TPM_RC_SUCCESS) {
335     return rc;
336   }
337   certify_info = StringFrom_TPM2B_ATTEST(certify_info_typed);
338   return TpmSignatureToString(signature_typed, &signature);
339 }
340 
SerializeCommand_NV_Read(const TPMI_RH_NV_AUTH & auth_handle,const std::string & auth_handle_name,const TPMI_RH_NV_INDEX & nv_index,const std::string & nv_index_name,const UINT16 & size,const UINT16 & offset,std::string & serialized_command,const std::unique_ptr<AuthorizationDelegate> & authorization_delegate)341 TPM_RC SerializeCommand_NV_Read(
342     const TPMI_RH_NV_AUTH& auth_handle, const std::string& auth_handle_name,
343     const TPMI_RH_NV_INDEX& nv_index, const std::string& nv_index_name,
344     const UINT16& size, const UINT16& offset, std::string& serialized_command,
345     const std::unique_ptr<AuthorizationDelegate>& authorization_delegate) {
346   return Tpm::SerializeCommand_NV_Read(
347       auth_handle, auth_handle_name, nv_index, nv_index_name, size, offset,
348       &serialized_command, authorization_delegate.get());
349 }
350 
ParseResponse_NV_Read(const std::string & response,std::string & data,const std::unique_ptr<AuthorizationDelegate> & authorization_delegate)351 TPM_RC ParseResponse_NV_Read(
352     const std::string& response, std::string& data,
353     const std::unique_ptr<AuthorizationDelegate>& authorization_delegate) {
354   TPM2B_MAX_NV_BUFFER buffer;
355   TPM_RC rc = Tpm::ParseResponse_NV_Read(response, &buffer,
356                                          authorization_delegate.get());
357   if (rc != TPM_RC_SUCCESS) {
358     return rc;
359   }
360   data = StringFrom_TPM2B_MAX_NV_BUFFER(buffer);
361   return TPM_RC_SUCCESS;
362 }
363 
SerializeCommand_NV_ReadPublic(const TPMI_RH_NV_INDEX & nv_index,const std::string & nv_index_name,std::string & serialized_command,const std::unique_ptr<AuthorizationDelegate> & authorization_delegate)364 TPM_RC SerializeCommand_NV_ReadPublic(
365     const TPMI_RH_NV_INDEX& nv_index, const std::string& nv_index_name,
366     std::string& serialized_command,
367     const std::unique_ptr<AuthorizationDelegate>& authorization_delegate) {
368   return Tpm::SerializeCommand_NV_ReadPublic(nv_index, nv_index_name,
369                                              &serialized_command,
370                                              authorization_delegate.get());
371 }
372 
ParseResponse_NV_ReadPublic(const std::string & response,uint16_t & nv_public_data_size,std::string & nv_name,const std::unique_ptr<AuthorizationDelegate> & authorization_delegate)373 TPM_RC ParseResponse_NV_ReadPublic(
374     const std::string& response, uint16_t& nv_public_data_size,
375     std::string& nv_name,
376     const std::unique_ptr<AuthorizationDelegate>& authorization_delegate) {
377   TPM2B_NV_PUBLIC nv_public;
378   TPM2B_NAME nv_name_typed;
379   TPM_RC rc = Tpm::ParseResponse_NV_ReadPublic(
380       response, &nv_public, &nv_name_typed, authorization_delegate.get());
381   if (rc != TPM_RC_SUCCESS) {
382     return rc;
383   }
384   nv_public_data_size = nv_public.nv_public.data_size;
385   nv_name = StringFrom_TPM2B_NAME(nv_name_typed);
386   return TPM_RC_SUCCESS;
387 }
388 
SerializeCommand_Quote(const TPMI_DH_OBJECT & sign_handle,const std::string & sign_handle_name,const TPM2B_DATA & qualifying_data,const TPMT_SIG_SCHEME & in_scheme,const TPML_PCR_SELECTION & pcrselect,std::string & serialized_command,const std::unique_ptr<AuthorizationDelegate> & authorization_delegate)389 TPM_RC SerializeCommand_Quote(
390     const TPMI_DH_OBJECT& sign_handle, const std::string& sign_handle_name,
391     const TPM2B_DATA& qualifying_data, const TPMT_SIG_SCHEME& in_scheme,
392     const TPML_PCR_SELECTION& pcrselect, std::string& serialized_command,
393     const std::unique_ptr<AuthorizationDelegate>& authorization_delegate) {
394   return Tpm::SerializeCommand_Quote(
395       sign_handle, sign_handle_name, qualifying_data, in_scheme, pcrselect,
396       &serialized_command, authorization_delegate.get());
397 }
398 
ParseResponse_Quote(const std::string & response,std::string & quoted,std::string & signature,const std::unique_ptr<AuthorizationDelegate> & authorization_delegate)399 TPM_RC ParseResponse_Quote(
400     const std::string& response, std::string& quoted, std::string& signature,
401     const std::unique_ptr<AuthorizationDelegate>& authorization_delegate) {
402   TPM2B_ATTEST quoted_typed;
403   TPMT_SIGNATURE signature_typed;
404   TPM_RC rc = Tpm::ParseResponse_Quote(
405       response, &quoted_typed, &signature_typed, authorization_delegate.get());
406   if (rc != TPM_RC_SUCCESS) {
407     return rc;
408   }
409   quoted = StringFrom_TPM2B_ATTEST(quoted_typed);
410   return TpmSignatureToString(signature_typed, &signature);
411 }
412 
SerializeCommand_PCR_Read(const TPML_PCR_SELECTION & pcr_selection_in,std::string & serialized_command,const std::unique_ptr<AuthorizationDelegate> & authorization_delegate)413 TPM_RC SerializeCommand_PCR_Read(
414     const TPML_PCR_SELECTION& pcr_selection_in, std::string& serialized_command,
415     const std::unique_ptr<AuthorizationDelegate>& authorization_delegate) {
416   return Tpm::SerializeCommand_PCR_Read(pcr_selection_in, &serialized_command,
417                                         authorization_delegate.get());
418 }
419 
ParseResponse_PCR_Read(const std::string & response,UINT32 & pcr_update_counter,TPML_PCR_SELECTION & pcr_selection_out,std::string & pcr_values,const std::unique_ptr<AuthorizationDelegate> & authorization_delegate)420 TPM_RC ParseResponse_PCR_Read(
421     const std::string& response, UINT32& pcr_update_counter,
422     TPML_PCR_SELECTION& pcr_selection_out, std::string& pcr_values,
423     const std::unique_ptr<AuthorizationDelegate>& authorization_delegate) {
424   TPML_DIGEST pcr_values_typed;
425   TPM_RC rc = Tpm::ParseResponse_PCR_Read(response, &pcr_update_counter,
426                                           &pcr_selection_out, &pcr_values_typed,
427                                           authorization_delegate.get());
428   if (rc != TPM_RC_SUCCESS) {
429     return rc;
430   }
431   if (pcr_values_typed.count != 1) {
432     LOG(ERROR) << "Unexpected PCR count " << pcr_values_typed.count
433                << " in TPM2_PCR_Read reply.";
434     return TPM_RC_FAILURE;
435   }
436   pcr_values = StringFrom_TPM2B_DIGEST(pcr_values_typed.digests[0]);
437   return TPM_RC_SUCCESS;
438 }
439 
NameFromHandle(const TPM_HANDLE & handle)440 std::unique_ptr<std::string> NameFromHandle(const TPM_HANDLE& handle) {
441   std::string name;
442   Serialize_TPM_HANDLE(handle, &name);
443   return std::make_unique<std::string>(std::move(name));
444 }
445 
TPM2B_CREATION_DATA_New()446 std::unique_ptr<TPM2B_CREATION_DATA> TPM2B_CREATION_DATA_New() {
447   return std::make_unique<TPM2B_CREATION_DATA>();
448 }
449 
TPM2B_DATA_New(const std::string & bytes)450 std::unique_ptr<TPM2B_DATA> TPM2B_DATA_New(const std::string& bytes) {
451   return std::make_unique<TPM2B_DATA>(Make_TPM2B_DATA(bytes));
452 }
453 
TPM2B_DIGEST_New()454 std::unique_ptr<TPM2B_DIGEST> TPM2B_DIGEST_New() {
455   return std::make_unique<TPM2B_DIGEST>();
456 }
457 
AttestationIdentityKeyTemplate()458 std::unique_ptr<TPM2B_PUBLIC> AttestationIdentityKeyTemplate() {
459   TPMT_PUBLIC public_area = DefaultPublicArea();
460   public_area.object_attributes |=
461       (kSensitiveDataOrigin | kUserWithAuth | kNoDA | kRestricted | kSign);
462   public_area.parameters.ecc_detail.scheme.scheme = TPM_ALG_ECDSA;
463   public_area.parameters.ecc_detail.scheme.details.ecdsa.hash_alg =
464       TPM_ALG_SHA256;
465   return std::make_unique<TPM2B_PUBLIC>(Make_TPM2B_PUBLIC(public_area));
466 }
467 
StorageRootKeyTemplate()468 std::unique_ptr<TPM2B_PUBLIC> StorageRootKeyTemplate() {
469   TPMT_PUBLIC public_area = DefaultPublicArea();
470   public_area.object_attributes |=
471       (kSensitiveDataOrigin | kUserWithAuth | kNoDA | kRestricted | kDecrypt);
472   public_area.parameters.asym_detail.symmetric.algorithm = TPM_ALG_AES;
473   public_area.parameters.asym_detail.symmetric.key_bits.aes = 128;
474   public_area.parameters.asym_detail.symmetric.mode.aes = TPM_ALG_CFB;
475   return std::make_unique<TPM2B_PUBLIC>(Make_TPM2B_PUBLIC(public_area));
476 }
477 
Tpm2bPublicToTpmtPublic(const std::string & tpm2b_public,std::string & tpmt_public)478 TPM_RC Tpm2bPublicToTpmtPublic(const std::string& tpm2b_public,
479                                std::string& tpmt_public) {
480   std::string buffer_public = tpm2b_public;
481   TPM2B_PUBLIC typed_public;
482   TPM_RC rc = Parse_TPM2B_PUBLIC(&buffer_public, &typed_public, nullptr);
483   if (rc != TPM_RC_SUCCESS) {
484     return rc;
485   }
486   return Serialize_TPMT_PUBLIC(typed_public.public_area, &tpmt_public);
487 }
488 
TPM2B_SENSITIVE_CREATE_New(const std::string & user_auth,const std::string & data)489 std::unique_ptr<TPM2B_SENSITIVE_CREATE> TPM2B_SENSITIVE_CREATE_New(
490     const std::string& user_auth, const std::string& data) {
491   TPMS_SENSITIVE_CREATE sensitive;
492   sensitive.user_auth = Make_TPM2B_DIGEST(user_auth);
493   sensitive.data = Make_TPM2B_SENSITIVE_DATA(data);
494   return std::make_unique<TPM2B_SENSITIVE_CREATE>(
495       Make_TPM2B_SENSITIVE_CREATE(sensitive));
496 }
497 
EmptyPcrSelection()498 std::unique_ptr<TPML_PCR_SELECTION> EmptyPcrSelection() {
499   TPML_PCR_SELECTION creation_pcrs = {};
500   creation_pcrs.count = 0;
501   return std::make_unique<TPML_PCR_SELECTION>(creation_pcrs);
502 }
503 
SinglePcrSelection(uint8_t pcr)504 std::unique_ptr<TPML_PCR_SELECTION> SinglePcrSelection(uint8_t pcr) {
505   TPML_PCR_SELECTION pcr_select;
506   pcr_select.count = 1;
507   pcr_select.pcr_selections[0].hash = TPM_ALG_SHA256;
508   pcr_select.pcr_selections[0].sizeof_select = PCR_SELECT_MIN;
509   memset(pcr_select.pcr_selections[0].pcr_select, 0, PCR_SELECT_MIN);
510   if (pcr / 8 >= PCR_SELECT_MIN) {
511     LOG(ERROR) << "Invalid PCR number " << pcr;
512     return nullptr;
513   }
514   pcr_select.pcr_selections[0].pcr_select[pcr / 8] = 1u << (pcr % 8);
515   return std::make_unique<TPML_PCR_SELECTION>(pcr_select);
516 }
517 
Sha256EcdsaSigScheme()518 std::unique_ptr<TPMT_SIG_SCHEME> Sha256EcdsaSigScheme() {
519   TPMT_SIG_SCHEME scheme;
520   scheme.details.any.hash_alg = TPM_ALG_SHA256;
521   scheme.scheme = TPM_ALG_ECDSA;
522   return std::make_unique<TPMT_SIG_SCHEME>(scheme);
523 }
524 
TPMT_TK_CREATION_New()525 std::unique_ptr<TPMT_TK_CREATION> TPMT_TK_CREATION_New() {
526   return std::make_unique<TPMT_TK_CREATION>();
527 }
528 
529 }  // namespace trunks
530