• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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