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.
WriteExplicitOctetStringField(uint8_t tag,const uint8_t * value,size_t value_size,uint8_t ** pos,uint8_t * start)154 static int WriteExplicitOctetStringField(uint8_t tag, const uint8_t* value,
155 size_t value_size, uint8_t** pos,
156 uint8_t* start) {
157 int ret = 0; // Used by MBEDTLS_ASN1_CHK_ADD.
158 int field_length = 0;
159 MBEDTLS_ASN1_CHK_ADD(field_length, mbedtls_asn1_write_octet_string(
160 pos, start, value, value_size));
161 // Explicitly tagged, so add the field tag too.
162 MBEDTLS_ASN1_CHK_ADD(field_length,
163 mbedtls_asn1_write_len(pos, start, field_length));
164 MBEDTLS_ASN1_CHK_ADD(field_length,
165 mbedtls_asn1_write_tag(pos, start, GetFieldTag(tag)));
166 return field_length;
167 }
168
GetDiceExtensionDataHelper(const DiceInputValues * input_values,uint8_t ** pos,uint8_t * start)169 static int GetDiceExtensionDataHelper(const DiceInputValues* input_values,
170 uint8_t** pos, uint8_t* start) {
171 // ASN.1 constants not defined by mbedtls.
172 const uint8_t kEnumTypeTag = 10;
173 // ASN.1 tags for extension fields.
174 const uint8_t kDiceFieldCodeHash = 0;
175 const uint8_t kDiceFieldCodeDescriptor = 1;
176 const uint8_t kDiceFieldConfigHash = 2;
177 const uint8_t kDiceFieldConfigDescriptor = 3;
178 const uint8_t kDiceFieldAuthorityHash = 4;
179 const uint8_t kDiceFieldAuthorityDescriptor = 5;
180 const uint8_t kDiceFieldMode = 6;
181
182 // Build up the extension ASN.1 in reverse order.
183 int ret = 0; // Used by MBEDTLS_ASN1_CHK_ADD.
184 int length = 0;
185
186 // Add the mode field.
187 MBEDTLS_ASN1_CHK_ADD(length,
188 mbedtls_asn1_write_int(pos, start, input_values->mode));
189 // Overwrite the 'int' type.
190 ++(*pos);
191 --length;
192 MBEDTLS_ASN1_CHK_ADD(length,
193 mbedtls_asn1_write_tag(pos, start, kEnumTypeTag));
194
195 // Explicitly tagged, so add the field tag too.
196 MBEDTLS_ASN1_CHK_ADD(length, mbedtls_asn1_write_len(pos, start, length));
197 MBEDTLS_ASN1_CHK_ADD(
198 length, mbedtls_asn1_write_tag(pos, start, GetFieldTag(kDiceFieldMode)));
199
200 // Add the authorityDescriptor field, if applicable.
201 if (input_values->authority_descriptor_size > 0) {
202 MBEDTLS_ASN1_CHK_ADD(
203 length,
204 WriteExplicitOctetStringField(
205 kDiceFieldAuthorityDescriptor, input_values->authority_descriptor,
206 input_values->authority_descriptor_size, pos, start));
207 }
208
209 // Add the authorityHash field.
210 MBEDTLS_ASN1_CHK_ADD(
211 length, WriteExplicitOctetStringField(kDiceFieldAuthorityHash,
212 input_values->authority_hash,
213 DICE_HASH_SIZE, pos, start));
214
215 // Add the configurationDescriptor field (and configurationHash field, if
216 // applicable).
217 if (input_values->config_type == kDiceConfigTypeDescriptor) {
218 uint8_t hash[DICE_HASH_SIZE];
219 int result = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512),
220 input_values->config_descriptor,
221 input_values->config_descriptor_size, hash);
222 if (result) {
223 return result;
224 }
225 MBEDTLS_ASN1_CHK_ADD(
226 length, WriteExplicitOctetStringField(
227 kDiceFieldConfigDescriptor, input_values->config_descriptor,
228 input_values->config_descriptor_size, pos, start));
229 MBEDTLS_ASN1_CHK_ADD(
230 length, WriteExplicitOctetStringField(kDiceFieldConfigHash, hash,
231 DICE_HASH_SIZE, pos, start));
232 } else if (input_values->config_type == kDiceConfigTypeInline) {
233 MBEDTLS_ASN1_CHK_ADD(
234 length, WriteExplicitOctetStringField(
235 kDiceFieldConfigDescriptor, input_values->config_value,
236 DICE_INLINE_CONFIG_SIZE, pos, start));
237 }
238
239 // Add the code descriptor field, if applicable.
240 if (input_values->code_descriptor_size > 0) {
241 MBEDTLS_ASN1_CHK_ADD(
242 length, WriteExplicitOctetStringField(
243 kDiceFieldCodeDescriptor, input_values->code_descriptor,
244 input_values->code_descriptor_size, pos, start));
245 }
246
247 // Add the code hash field.
248 MBEDTLS_ASN1_CHK_ADD(length, WriteExplicitOctetStringField(
249 kDiceFieldCodeHash, input_values->code_hash,
250 DICE_HASH_SIZE, pos, start));
251
252 // Add the sequence length and tag.
253 MBEDTLS_ASN1_CHK_ADD(length, mbedtls_asn1_write_len(pos, start, length));
254 MBEDTLS_ASN1_CHK_ADD(
255 length,
256 mbedtls_asn1_write_tag(pos, start,
257 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
258 return length;
259 }
260
GetDiceExtensionData(const DiceInputValues * input_values,size_t buffer_size,uint8_t * buffer,size_t * actual_size)261 static DiceResult GetDiceExtensionData(const DiceInputValues* input_values,
262 size_t buffer_size, uint8_t* buffer,
263 size_t* actual_size) {
264 uint8_t* pos = buffer + buffer_size;
265 int length_or_error = GetDiceExtensionDataHelper(input_values, &pos, buffer);
266 if (length_or_error == MBEDTLS_ERR_ASN1_BUF_TOO_SMALL) {
267 return kDiceResultBufferTooSmall;
268 } else if (length_or_error < 0) {
269 return kDiceResultPlatformError;
270 }
271 *actual_size = length_or_error;
272 memmove(buffer, pos, *actual_size);
273 return kDiceResultOk;
274 }
275
DiceHash(void * context_not_used,const uint8_t * input,size_t input_size,uint8_t output[DICE_HASH_SIZE])276 DiceResult DiceHash(void* context_not_used, const uint8_t* input,
277 size_t input_size, uint8_t output[DICE_HASH_SIZE]) {
278 (void)context_not_used;
279 if (0 != mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512), input,
280 input_size, output)) {
281 return kDiceResultPlatformError;
282 }
283 return kDiceResultOk;
284 }
285
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)286 DiceResult DiceKdf(void* context_not_used, size_t length, const uint8_t* ikm,
287 size_t ikm_size, const uint8_t* salt, size_t salt_size,
288 const uint8_t* info, size_t info_size, uint8_t* output) {
289 (void)context_not_used;
290 if (0 != mbedtls_hkdf(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512), salt,
291 salt_size, ikm, ikm_size, info, info_size, output,
292 length)) {
293 return kDiceResultPlatformError;
294 }
295 return kDiceResultOk;
296 }
297
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)298 DiceResult DiceGenerateCertificate(
299 void* context,
300 const uint8_t subject_private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE],
301 const uint8_t authority_private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE],
302 const DiceInputValues* input_values, size_t certificate_buffer_size,
303 uint8_t* certificate, size_t* certificate_actual_size) {
304 // 1.3.6.1.4.1.11129.2.1.24
305 // iso.org.dod.internet.private.enterprise.
306 // google.googleSecurity.certificateExtensions.diceAttestationData
307 const char* kDiceExtensionOid =
308 MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_DOD
309 "\x01\x04\x01\xd6\x79\x02\x01\x18";
310 const size_t kDiceExtensionOidLength = 10;
311
312 DiceResult result = kDiceResultOk;
313
314 // Initialize variables cleaned up on 'goto out'.
315 mbedtls_pk_context authority_key_context;
316 mbedtls_pk_init(&authority_key_context);
317 mbedtls_pk_context subject_key_context;
318 mbedtls_pk_init(&subject_key_context);
319 mbedtls_x509write_cert cert_context;
320 mbedtls_x509write_crt_init(&cert_context);
321 mbedtls_mpi serial_number;
322 mbedtls_mpi_init(&serial_number);
323
324 // Derive key pairs and IDs.
325 result = SetupKeyPair(authority_private_key_seed, &authority_key_context);
326 if (result != kDiceResultOk) {
327 goto out;
328 }
329
330 uint8_t authority_id[DICE_ID_SIZE];
331 result = GetIdFromKey(context, &authority_key_context, authority_id);
332 if (result != kDiceResultOk) {
333 goto out;
334 }
335
336 char authority_name[54];
337 GetNameFromId(authority_id, authority_name);
338
339 uint8_t authority_key_id[DICE_MAX_KEY_ID_SIZE];
340 size_t authority_key_id_size = 0;
341 result = GetAuthorityKeyIdFromId(authority_id, sizeof(authority_key_id),
342 authority_key_id, &authority_key_id_size);
343 if (result != kDiceResultOk) {
344 goto out;
345 }
346 result = SetupKeyPair(subject_private_key_seed, &subject_key_context);
347 if (result != kDiceResultOk) {
348 goto out;
349 }
350
351 uint8_t subject_id[DICE_ID_SIZE];
352 result = GetIdFromKey(context, &subject_key_context, subject_id);
353 if (result != kDiceResultOk) {
354 goto out;
355 }
356
357 char subject_name[54];
358 GetNameFromId(subject_id, subject_name);
359
360 uint8_t subject_key_id[DICE_MAX_KEY_ID_SIZE];
361 size_t subject_key_id_size = 0;
362 result = GetSubjectKeyIdFromId(subject_id, sizeof(subject_key_id),
363 subject_key_id, &subject_key_id_size);
364 if (result != kDiceResultOk) {
365 goto out;
366 }
367
368 uint8_t dice_extension[DICE_MAX_EXTENSION_SIZE];
369 size_t dice_extension_size = 0;
370 result = GetDiceExtensionData(input_values, sizeof(dice_extension),
371 dice_extension, &dice_extension_size);
372 if (result != kDiceResultOk) {
373 goto out;
374 }
375
376 // Construct the certificate.
377 mbedtls_x509write_crt_set_version(&cert_context, MBEDTLS_X509_CRT_VERSION_3);
378 if (0 !=
379 mbedtls_mpi_read_binary(&serial_number, subject_id, sizeof(subject_id))) {
380 result = kDiceResultPlatformError;
381 goto out;
382 }
383 if (0 != mbedtls_x509write_crt_set_serial(&cert_context, &serial_number)) {
384 result = kDiceResultPlatformError;
385 goto out;
386 }
387 // '20180322235959' is the date of publication of the DICE specification. Here
388 // it's used as a somewhat arbitrary backstop. '99991231235959' is suggested
389 // by RFC 5280 in cases where expiry is not meaningful. Basically, the
390 // certificate never expires.
391 if (0 != mbedtls_x509write_crt_set_validity(&cert_context, "20180322235959",
392 "99991231235959")) {
393 result = kDiceResultPlatformError;
394 goto out;
395 }
396 if (0 !=
397 mbedtls_x509write_crt_set_issuer_name(&cert_context, authority_name)) {
398 result = kDiceResultPlatformError;
399 goto out;
400 }
401 if (0 !=
402 mbedtls_x509write_crt_set_subject_name(&cert_context, subject_name)) {
403 result = kDiceResultPlatformError;
404 goto out;
405 }
406 mbedtls_x509write_crt_set_subject_key(&cert_context, &subject_key_context);
407 mbedtls_x509write_crt_set_issuer_key(&cert_context, &authority_key_context);
408 mbedtls_x509write_crt_set_md_alg(&cert_context, MBEDTLS_MD_SHA512);
409 if (0 != mbedtls_x509write_crt_set_extension(
410 &cert_context, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER,
411 MBEDTLS_OID_SIZE(MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER),
412 /*critical=*/0, authority_key_id, authority_key_id_size)) {
413 result = kDiceResultPlatformError;
414 goto out;
415 }
416 if (0 != mbedtls_x509write_crt_set_extension(
417 &cert_context, MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER,
418 MBEDTLS_OID_SIZE(MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER),
419 /*critical=*/0, subject_key_id, subject_key_id_size)) {
420 result = kDiceResultPlatformError;
421 goto out;
422 }
423 if (0 != mbedtls_x509write_crt_set_key_usage(&cert_context,
424 MBEDTLS_X509_KU_KEY_CERT_SIGN)) {
425 result = kDiceResultPlatformError;
426 goto out;
427 }
428 if (0 != mbedtls_x509write_crt_set_basic_constraints(&cert_context,
429 /*is_ca=*/1,
430 /*max_pathlen=*/-1)) {
431 result = kDiceResultPlatformError;
432 goto out;
433 }
434 if (0 != mbedtls_x509write_crt_set_extension(
435 &cert_context, kDiceExtensionOid, kDiceExtensionOidLength,
436 /*critical=*/0, dice_extension, dice_extension_size)) {
437 result = kDiceResultPlatformError;
438 goto out;
439 }
440 // This implementation is deterministic and assumes entropy is not available.
441 // If this code is run where entropy is available, however, f_rng and p_rng
442 // should be set appropriately.
443 uint8_t tmp_buffer[DICE_MAX_CERTIFICATE_SIZE];
444 int length_or_error =
445 mbedtls_x509write_crt_der(&cert_context, tmp_buffer, sizeof(tmp_buffer),
446 /*f_rng=*/NULL, /*p_rng=*/NULL);
447 if (length_or_error < 0) {
448 result = kDiceResultPlatformError;
449 goto out;
450 }
451 *certificate_actual_size = length_or_error;
452 if (*certificate_actual_size > certificate_buffer_size) {
453 result = kDiceResultBufferTooSmall;
454 goto out;
455 }
456 // The certificate has been written to the end of tmp_buffer. Skip unused
457 // buffer when copying.
458 memcpy(certificate,
459 &tmp_buffer[sizeof(tmp_buffer) - *certificate_actual_size],
460 *certificate_actual_size);
461
462 out:
463 mbedtls_mpi_free(&serial_number);
464 mbedtls_x509write_crt_free(&cert_context);
465 mbedtls_pk_free(&authority_key_context);
466 mbedtls_pk_free(&subject_key_context);
467 return result;
468 }
469