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