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, "ed_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