1 // Copyright 2020 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14
15 // This is an implementation of DiceGenerateCertificate and the crypto
16 // operations that uses mbedtls. The algorithms used are SHA512, HKDF-SHA512,
17 // and deterministic ECDSA-P256-SHA512.
18
19 #include <stdint.h>
20 #include <string.h>
21
22 #include "dice/dice.h"
23 #include "dice/ops.h"
24 #include "dice/utils.h"
25 #include "mbedtls/asn1.h"
26 #include "mbedtls/asn1write.h"
27 #include "mbedtls/bignum.h"
28 #include "mbedtls/ecdsa.h"
29 #include "mbedtls/ecp.h"
30 #include "mbedtls/hkdf.h"
31 #include "mbedtls/hmac_drbg.h"
32 #include "mbedtls/md.h"
33 #include "mbedtls/oid.h"
34 #include "mbedtls/pk.h"
35 #include "mbedtls/x509.h"
36 #include "mbedtls/x509_crt.h"
37
38 #define DICE_MAX_CERTIFICATE_SIZE 2048
39 #define DICE_MAX_EXTENSION_SIZE 2048
40 #define DICE_MAX_KEY_ID_SIZE 40
41
SetupKeyPair(const uint8_t private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE],mbedtls_pk_context * context)42 static DiceResult SetupKeyPair(
43 const uint8_t private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE],
44 mbedtls_pk_context* context) {
45 if (0 !=
46 mbedtls_pk_setup(context, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY))) {
47 return kDiceResultPlatformError;
48 }
49 // Use the |private_key_seed| directly to seed a PRNG which is then in turn
50 // used to generate the private key. This implementation uses HMAC_DRBG in a
51 // loop with no reduction, like RFC6979.
52 DiceResult result = kDiceResultOk;
53 mbedtls_hmac_drbg_context rng_context;
54 mbedtls_hmac_drbg_init(&rng_context);
55 if (0 != mbedtls_hmac_drbg_seed_buf(
56 &rng_context, mbedtls_md_info_from_type(MBEDTLS_MD_SHA512),
57 private_key_seed, DICE_PRIVATE_KEY_SEED_SIZE)) {
58 result = kDiceResultPlatformError;
59 goto out;
60 }
61 if (0 != mbedtls_ecp_gen_key(MBEDTLS_ECP_DP_SECP256R1,
62 mbedtls_pk_ec(*context),
63 mbedtls_hmac_drbg_random, &rng_context)) {
64 result = kDiceResultPlatformError;
65 goto out;
66 }
67
68 out:
69 mbedtls_hmac_drbg_free(&rng_context);
70 return result;
71 }
72
GetIdFromKey(void * context,const mbedtls_pk_context * pk_context,uint8_t id[DICE_ID_SIZE])73 static DiceResult GetIdFromKey(void* context,
74 const mbedtls_pk_context* pk_context,
75 uint8_t id[DICE_ID_SIZE]) {
76 uint8_t raw_public_key[33];
77 size_t raw_public_key_size = 0;
78 mbedtls_ecp_keypair* key = mbedtls_pk_ec(*pk_context);
79
80 if (0 != mbedtls_ecp_point_write_binary(
81 &key->grp, &key->Q, MBEDTLS_ECP_PF_COMPRESSED,
82 &raw_public_key_size, raw_public_key, sizeof(raw_public_key))) {
83 return kDiceResultPlatformError;
84 }
85 return DiceDeriveCdiCertificateId(context, raw_public_key,
86 raw_public_key_size, id);
87 }
88
89 // 54 byte name is prefix (13), hex id (40), and a null terminator.
GetNameFromId(const uint8_t id[DICE_ID_SIZE],char name[54])90 static void GetNameFromId(const uint8_t id[DICE_ID_SIZE], char name[54]) {
91 strcpy(name, "serialNumber=");
92 DiceHexEncode(id, /*num_bytes=*/DICE_ID_SIZE, (uint8_t*)&name[13],
93 /*out_size=*/40);
94 name[53] = '\0';
95 }
96
GetSubjectKeyIdFromId(const uint8_t id[DICE_ID_SIZE],size_t buffer_size,uint8_t * buffer,size_t * actual_size)97 static DiceResult GetSubjectKeyIdFromId(const uint8_t id[DICE_ID_SIZE],
98 size_t buffer_size, uint8_t* buffer,
99 size_t* actual_size) {
100 uint8_t* pos = buffer + buffer_size;
101 int length_or_error =
102 mbedtls_asn1_write_octet_string(&pos, buffer, id, DICE_ID_SIZE);
103 if (length_or_error < 0) {
104 return kDiceResultPlatformError;
105 }
106 *actual_size = length_or_error;
107 memmove(buffer, pos, *actual_size);
108 return kDiceResultOk;
109 }
110
AddAuthorityKeyIdEncoding(uint8_t ** pos,uint8_t * start,int length)111 static int AddAuthorityKeyIdEncoding(uint8_t** pos, uint8_t* start,
112 int length) {
113 // From RFC 5280 4.2.1.1.
114 const int kKeyIdentifierTag = 0;
115
116 int ret = 0; // Used by MBEDTLS_ASN1_CHK_ADD.
117 MBEDTLS_ASN1_CHK_ADD(length, mbedtls_asn1_write_len(pos, start, length));
118 MBEDTLS_ASN1_CHK_ADD(
119 length,
120 mbedtls_asn1_write_tag(
121 pos, start, MBEDTLS_ASN1_CONTEXT_SPECIFIC | kKeyIdentifierTag));
122
123 MBEDTLS_ASN1_CHK_ADD(length, mbedtls_asn1_write_len(pos, start, length));
124 MBEDTLS_ASN1_CHK_ADD(
125 length,
126 mbedtls_asn1_write_tag(pos, start,
127 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
128 return length;
129 }
130
GetAuthorityKeyIdFromId(const uint8_t id[DICE_ID_SIZE],size_t buffer_size,uint8_t * buffer,size_t * actual_size)131 static DiceResult GetAuthorityKeyIdFromId(const uint8_t id[DICE_ID_SIZE],
132 size_t buffer_size, uint8_t* buffer,
133 size_t* actual_size) {
134 uint8_t* pos = buffer + buffer_size;
135 int length_or_error =
136 mbedtls_asn1_write_raw_buffer(&pos, buffer, id, DICE_ID_SIZE);
137 if (length_or_error < 0) {
138 return kDiceResultPlatformError;
139 }
140 length_or_error = AddAuthorityKeyIdEncoding(&pos, buffer, length_or_error);
141 if (length_or_error < 0) {
142 return kDiceResultPlatformError;
143 }
144 *actual_size = length_or_error;
145 memmove(buffer, pos, *actual_size);
146 return kDiceResultOk;
147 }
148
GetFieldTag(uint8_t tag)149 static uint8_t GetFieldTag(uint8_t tag) {
150 return MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag;
151 }
152
153 // Can be used with MBEDTLS_ASN1_CHK_ADD.
WriteExplicitModeField(uint8_t tag,int value,uint8_t ** pos,uint8_t * start)154 static int WriteExplicitModeField(uint8_t tag, int value, uint8_t** pos,
155 uint8_t* start) {
156 // ASN.1 constants not defined by mbedtls.
157 const uint8_t kEnumTypeTag = 10;
158
159 int ret = 0; // Used by MBEDTLS_ASN1_CHK_ADD.
160 int field_length = 0;
161 MBEDTLS_ASN1_CHK_ADD(field_length, mbedtls_asn1_write_int(pos, start, value));
162 // Overwrite the 'int' type.
163 ++(*pos);
164 --field_length;
165 MBEDTLS_ASN1_CHK_ADD(field_length,
166 mbedtls_asn1_write_tag(pos, start, kEnumTypeTag));
167
168 // Explicitly tagged, so add the field tag too.
169 MBEDTLS_ASN1_CHK_ADD(field_length,
170 mbedtls_asn1_write_len(pos, start, field_length));
171 MBEDTLS_ASN1_CHK_ADD(field_length,
172 mbedtls_asn1_write_tag(pos, start, GetFieldTag(tag)));
173 return field_length;
174 }
175
176 // Can be used with MBEDTLS_ASN1_CHK_ADD.
WriteExplicitUtf8StringField(uint8_t tag,const void * value,size_t value_size,uint8_t ** pos,uint8_t * start)177 static int WriteExplicitUtf8StringField(uint8_t tag, const void* value,
178 size_t value_size, uint8_t** pos,
179 uint8_t* start) {
180 int ret = 0; // Used by MBEDTLS_ASN1_CHK_ADD.
181 int field_length = 0;
182 MBEDTLS_ASN1_CHK_ADD(field_length, mbedtls_asn1_write_utf8_string(
183 pos, start, value, value_size));
184 // Explicitly tagged, so add the field tag too.
185 MBEDTLS_ASN1_CHK_ADD(field_length,
186 mbedtls_asn1_write_len(pos, start, field_length));
187 MBEDTLS_ASN1_CHK_ADD(field_length,
188 mbedtls_asn1_write_tag(pos, start, GetFieldTag(tag)));
189 return field_length;
190 }
191
192 // Can be used with MBEDTLS_ASN1_CHK_ADD.
WriteExplicitOctetStringField(uint8_t tag,const uint8_t * value,size_t value_size,uint8_t ** pos,uint8_t * start)193 static int WriteExplicitOctetStringField(uint8_t tag, const uint8_t* value,
194 size_t value_size, uint8_t** pos,
195 uint8_t* start) {
196 int ret = 0; // Used by MBEDTLS_ASN1_CHK_ADD.
197 int field_length = 0;
198 MBEDTLS_ASN1_CHK_ADD(field_length, mbedtls_asn1_write_octet_string(
199 pos, start, value, value_size));
200 // Explicitly tagged, so add the field tag too.
201 MBEDTLS_ASN1_CHK_ADD(field_length,
202 mbedtls_asn1_write_len(pos, start, field_length));
203 MBEDTLS_ASN1_CHK_ADD(field_length,
204 mbedtls_asn1_write_tag(pos, start, GetFieldTag(tag)));
205 return field_length;
206 }
207
GetDiceExtensionDataHelper(const DiceInputValues * input_values,uint8_t ** pos,uint8_t * start)208 static int GetDiceExtensionDataHelper(const DiceInputValues* input_values,
209 uint8_t** pos, uint8_t* start) {
210 // ASN.1 tags for extension fields.
211 const uint8_t kDiceFieldCodeHash = 0;
212 const uint8_t kDiceFieldCodeDescriptor = 1;
213 const uint8_t kDiceFieldConfigHash = 2;
214 const uint8_t kDiceFieldConfigDescriptor = 3;
215 const uint8_t kDiceFieldAuthorityHash = 4;
216 const uint8_t kDiceFieldAuthorityDescriptor = 5;
217 const uint8_t kDiceFieldMode = 6;
218 const uint8_t kDiceFieldProfileName = 7;
219
220 // Build up the extension ASN.1 in reverse order.
221 int ret = 0; // Used by MBEDTLS_ASN1_CHK_ADD.
222 int length = 0;
223
224 // Add the profile name field.
225 if (DICE_PROFILE_NAME) {
226 MBEDTLS_ASN1_CHK_ADD(length, WriteExplicitUtf8StringField(
227 kDiceFieldProfileName, DICE_PROFILE_NAME,
228 strlen(DICE_PROFILE_NAME), pos, start));
229 }
230
231 // Add the mode field.
232 MBEDTLS_ASN1_CHK_ADD(
233 length,
234 WriteExplicitModeField(kDiceFieldMode, input_values->mode, pos, start));
235
236 // Add the authorityDescriptor field, if applicable.
237 if (input_values->authority_descriptor_size > 0) {
238 MBEDTLS_ASN1_CHK_ADD(
239 length,
240 WriteExplicitOctetStringField(
241 kDiceFieldAuthorityDescriptor, input_values->authority_descriptor,
242 input_values->authority_descriptor_size, pos, start));
243 }
244
245 // Add the authorityHash field.
246 MBEDTLS_ASN1_CHK_ADD(
247 length, WriteExplicitOctetStringField(kDiceFieldAuthorityHash,
248 input_values->authority_hash,
249 DICE_HASH_SIZE, pos, start));
250
251 // Add the configurationDescriptor field (and configurationHash field, if
252 // applicable).
253 if (input_values->config_type == kDiceConfigTypeDescriptor) {
254 uint8_t hash[DICE_HASH_SIZE];
255 int result = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512),
256 input_values->config_descriptor,
257 input_values->config_descriptor_size, hash);
258 if (result) {
259 return result;
260 }
261 MBEDTLS_ASN1_CHK_ADD(
262 length, WriteExplicitOctetStringField(
263 kDiceFieldConfigDescriptor, input_values->config_descriptor,
264 input_values->config_descriptor_size, pos, start));
265 MBEDTLS_ASN1_CHK_ADD(
266 length, WriteExplicitOctetStringField(kDiceFieldConfigHash, hash,
267 DICE_HASH_SIZE, pos, start));
268 } else if (input_values->config_type == kDiceConfigTypeInline) {
269 MBEDTLS_ASN1_CHK_ADD(
270 length, WriteExplicitOctetStringField(
271 kDiceFieldConfigDescriptor, input_values->config_value,
272 DICE_INLINE_CONFIG_SIZE, pos, start));
273 }
274
275 // Add the code descriptor field, if applicable.
276 if (input_values->code_descriptor_size > 0) {
277 MBEDTLS_ASN1_CHK_ADD(
278 length, WriteExplicitOctetStringField(
279 kDiceFieldCodeDescriptor, input_values->code_descriptor,
280 input_values->code_descriptor_size, pos, start));
281 }
282
283 // Add the code hash field.
284 MBEDTLS_ASN1_CHK_ADD(length, WriteExplicitOctetStringField(
285 kDiceFieldCodeHash, input_values->code_hash,
286 DICE_HASH_SIZE, pos, start));
287
288 // Add the sequence length and tag.
289 MBEDTLS_ASN1_CHK_ADD(length, mbedtls_asn1_write_len(pos, start, length));
290 MBEDTLS_ASN1_CHK_ADD(
291 length,
292 mbedtls_asn1_write_tag(pos, start,
293 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
294 return length;
295 }
296
GetDiceExtensionData(const DiceInputValues * input_values,size_t buffer_size,uint8_t * buffer,size_t * actual_size)297 static DiceResult GetDiceExtensionData(const DiceInputValues* input_values,
298 size_t buffer_size, uint8_t* buffer,
299 size_t* actual_size) {
300 uint8_t* pos = buffer + buffer_size;
301 int length_or_error = GetDiceExtensionDataHelper(input_values, &pos, buffer);
302 if (length_or_error == MBEDTLS_ERR_ASN1_BUF_TOO_SMALL) {
303 return kDiceResultBufferTooSmall;
304 } else if (length_or_error < 0) {
305 return kDiceResultPlatformError;
306 }
307 *actual_size = length_or_error;
308 memmove(buffer, pos, *actual_size);
309 return kDiceResultOk;
310 }
311
DiceHash(void * context_not_used,const uint8_t * input,size_t input_size,uint8_t output[DICE_HASH_SIZE])312 DiceResult DiceHash(void* context_not_used, const uint8_t* input,
313 size_t input_size, uint8_t output[DICE_HASH_SIZE]) {
314 (void)context_not_used;
315 if (0 != mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512), input,
316 input_size, output)) {
317 return kDiceResultPlatformError;
318 }
319 return kDiceResultOk;
320 }
321
DiceKdf(void * context_not_used,size_t length,const uint8_t * ikm,size_t ikm_size,const uint8_t * salt,size_t salt_size,const uint8_t * info,size_t info_size,uint8_t * output)322 DiceResult DiceKdf(void* context_not_used, size_t length, const uint8_t* ikm,
323 size_t ikm_size, const uint8_t* salt, size_t salt_size,
324 const uint8_t* info, size_t info_size, uint8_t* output) {
325 (void)context_not_used;
326 if (0 != mbedtls_hkdf(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512), salt,
327 salt_size, ikm, ikm_size, info, info_size, output,
328 length)) {
329 return kDiceResultPlatformError;
330 }
331 return kDiceResultOk;
332 }
333
DiceGenerateCertificate(void * context,const uint8_t subject_private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE],const uint8_t authority_private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE],const DiceInputValues * input_values,size_t certificate_buffer_size,uint8_t * certificate,size_t * certificate_actual_size)334 DiceResult DiceGenerateCertificate(
335 void* context,
336 const uint8_t subject_private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE],
337 const uint8_t authority_private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE],
338 const DiceInputValues* input_values, size_t certificate_buffer_size,
339 uint8_t* certificate, size_t* certificate_actual_size) {
340 // 1.3.6.1.4.1.11129.2.1.24
341 // iso.org.dod.internet.private.enterprise.
342 // google.googleSecurity.certificateExtensions.diceAttestationData
343 const char* kDiceExtensionOid =
344 MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_DOD
345 "\x01\x04\x01\xd6\x79\x02\x01\x18";
346 const size_t kDiceExtensionOidLength = 10;
347
348 DiceResult result = kDiceResultOk;
349
350 // Initialize variables cleaned up on 'goto out'.
351 mbedtls_pk_context authority_key_context;
352 mbedtls_pk_init(&authority_key_context);
353 mbedtls_pk_context subject_key_context;
354 mbedtls_pk_init(&subject_key_context);
355 mbedtls_x509write_cert cert_context;
356 mbedtls_x509write_crt_init(&cert_context);
357 mbedtls_mpi serial_number;
358 mbedtls_mpi_init(&serial_number);
359
360 // Derive key pairs and IDs.
361 result = SetupKeyPair(authority_private_key_seed, &authority_key_context);
362 if (result != kDiceResultOk) {
363 goto out;
364 }
365
366 uint8_t authority_id[DICE_ID_SIZE];
367 result = GetIdFromKey(context, &authority_key_context, authority_id);
368 if (result != kDiceResultOk) {
369 goto out;
370 }
371
372 char authority_name[54];
373 GetNameFromId(authority_id, authority_name);
374
375 uint8_t authority_key_id[DICE_MAX_KEY_ID_SIZE];
376 size_t authority_key_id_size = 0;
377 result = GetAuthorityKeyIdFromId(authority_id, sizeof(authority_key_id),
378 authority_key_id, &authority_key_id_size);
379 if (result != kDiceResultOk) {
380 goto out;
381 }
382 result = SetupKeyPair(subject_private_key_seed, &subject_key_context);
383 if (result != kDiceResultOk) {
384 goto out;
385 }
386
387 uint8_t subject_id[DICE_ID_SIZE];
388 result = GetIdFromKey(context, &subject_key_context, subject_id);
389 if (result != kDiceResultOk) {
390 goto out;
391 }
392
393 char subject_name[54];
394 GetNameFromId(subject_id, subject_name);
395
396 uint8_t subject_key_id[DICE_MAX_KEY_ID_SIZE];
397 size_t subject_key_id_size = 0;
398 result = GetSubjectKeyIdFromId(subject_id, sizeof(subject_key_id),
399 subject_key_id, &subject_key_id_size);
400 if (result != kDiceResultOk) {
401 goto out;
402 }
403
404 uint8_t dice_extension[DICE_MAX_EXTENSION_SIZE];
405 size_t dice_extension_size = 0;
406 result = GetDiceExtensionData(input_values, sizeof(dice_extension),
407 dice_extension, &dice_extension_size);
408 if (result != kDiceResultOk) {
409 goto out;
410 }
411
412 // Construct the certificate.
413 mbedtls_x509write_crt_set_version(&cert_context, MBEDTLS_X509_CRT_VERSION_3);
414 if (0 !=
415 mbedtls_mpi_read_binary(&serial_number, subject_id, sizeof(subject_id))) {
416 result = kDiceResultPlatformError;
417 goto out;
418 }
419 if (0 != mbedtls_x509write_crt_set_serial(&cert_context, &serial_number)) {
420 result = kDiceResultPlatformError;
421 goto out;
422 }
423 // '20180322235959' is the date of publication of the DICE specification. Here
424 // it's used as a somewhat arbitrary backstop. '99991231235959' is suggested
425 // by RFC 5280 in cases where expiry is not meaningful. Basically, the
426 // certificate never expires.
427 if (0 != mbedtls_x509write_crt_set_validity(&cert_context, "20180322235959",
428 "99991231235959")) {
429 result = kDiceResultPlatformError;
430 goto out;
431 }
432 if (0 !=
433 mbedtls_x509write_crt_set_issuer_name(&cert_context, authority_name)) {
434 result = kDiceResultPlatformError;
435 goto out;
436 }
437 if (0 !=
438 mbedtls_x509write_crt_set_subject_name(&cert_context, subject_name)) {
439 result = kDiceResultPlatformError;
440 goto out;
441 }
442 mbedtls_x509write_crt_set_subject_key(&cert_context, &subject_key_context);
443 mbedtls_x509write_crt_set_issuer_key(&cert_context, &authority_key_context);
444 mbedtls_x509write_crt_set_md_alg(&cert_context, MBEDTLS_MD_SHA512);
445 if (0 != mbedtls_x509write_crt_set_extension(
446 &cert_context, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER,
447 MBEDTLS_OID_SIZE(MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER),
448 /*critical=*/0, authority_key_id, authority_key_id_size)) {
449 result = kDiceResultPlatformError;
450 goto out;
451 }
452 if (0 != mbedtls_x509write_crt_set_extension(
453 &cert_context, MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER,
454 MBEDTLS_OID_SIZE(MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER),
455 /*critical=*/0, subject_key_id, subject_key_id_size)) {
456 result = kDiceResultPlatformError;
457 goto out;
458 }
459 if (0 != mbedtls_x509write_crt_set_key_usage(&cert_context,
460 MBEDTLS_X509_KU_KEY_CERT_SIGN)) {
461 result = kDiceResultPlatformError;
462 goto out;
463 }
464 if (0 != mbedtls_x509write_crt_set_basic_constraints(&cert_context,
465 /*is_ca=*/1,
466 /*max_pathlen=*/-1)) {
467 result = kDiceResultPlatformError;
468 goto out;
469 }
470 if (0 != mbedtls_x509write_crt_set_extension(
471 &cert_context, kDiceExtensionOid, kDiceExtensionOidLength,
472 /*critical=*/1, dice_extension, dice_extension_size)) {
473 result = kDiceResultPlatformError;
474 goto out;
475 }
476 // This implementation is deterministic and assumes entropy is not available.
477 // If this code is run where entropy is available, however, f_rng and p_rng
478 // should be set to use that entropy. As is, we'll provide a DRBG for blinding
479 // but it will be ineffective.
480 mbedtls_hmac_drbg_context drbg;
481 mbedtls_hmac_drbg_init(&drbg);
482 mbedtls_hmac_drbg_seed_buf(&drbg,
483 mbedtls_md_info_from_type(MBEDTLS_MD_SHA512),
484 subject_key_id, subject_key_id_size);
485 uint8_t tmp_buffer[DICE_MAX_CERTIFICATE_SIZE];
486 int length_or_error =
487 mbedtls_x509write_crt_der(&cert_context, tmp_buffer, sizeof(tmp_buffer),
488 mbedtls_hmac_drbg_random, &drbg);
489 mbedtls_hmac_drbg_free(&drbg);
490 if (length_or_error < 0) {
491 result = kDiceResultPlatformError;
492 goto out;
493 }
494 *certificate_actual_size = length_or_error;
495 if (*certificate_actual_size > certificate_buffer_size) {
496 result = kDiceResultBufferTooSmall;
497 goto out;
498 }
499 // The certificate has been written to the end of tmp_buffer. Skip unused
500 // buffer when copying.
501 memcpy(certificate,
502 &tmp_buffer[sizeof(tmp_buffer) - *certificate_actual_size],
503 *certificate_actual_size);
504
505 out:
506 mbedtls_mpi_free(&serial_number);
507 mbedtls_x509write_crt_free(&cert_context);
508 mbedtls_pk_free(&authority_key_context);
509 mbedtls_pk_free(&subject_key_context);
510 return result;
511 }
512