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 a DiceGenerateCertificate implementation that uses boringssl for
16*60b67249SAndroid Build Coastguard Worker // crypto and certificate generation. The algorithms used are SHA512,
17*60b67249SAndroid Build Coastguard Worker // HKDF-SHA512, and Ed25519-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 "openssl/asn1.h"
26*60b67249SAndroid Build Coastguard Worker #include "openssl/asn1t.h"
27*60b67249SAndroid Build Coastguard Worker #include "openssl/bn.h"
28*60b67249SAndroid Build Coastguard Worker #include "openssl/curve25519.h"
29*60b67249SAndroid Build Coastguard Worker #include "openssl/evp.h"
30*60b67249SAndroid Build Coastguard Worker #include "openssl/is_boringssl.h"
31*60b67249SAndroid Build Coastguard Worker #include "openssl/objects.h"
32*60b67249SAndroid Build Coastguard Worker #include "openssl/x509.h"
33*60b67249SAndroid Build Coastguard Worker #include "openssl/x509v3.h"
34*60b67249SAndroid Build Coastguard Worker
35*60b67249SAndroid Build Coastguard Worker #define DICE_MAX_EXTENSION_SIZE 2048
36*60b67249SAndroid Build Coastguard Worker
37*60b67249SAndroid Build Coastguard Worker typedef struct DiceExtensionAsn1 {
38*60b67249SAndroid Build Coastguard Worker ASN1_OCTET_STRING* code_hash;
39*60b67249SAndroid Build Coastguard Worker ASN1_OCTET_STRING* code_descriptor;
40*60b67249SAndroid Build Coastguard Worker ASN1_OCTET_STRING* config_hash;
41*60b67249SAndroid Build Coastguard Worker ASN1_OCTET_STRING* config_descriptor;
42*60b67249SAndroid Build Coastguard Worker ASN1_OCTET_STRING* authority_hash;
43*60b67249SAndroid Build Coastguard Worker ASN1_OCTET_STRING* authority_descriptor;
44*60b67249SAndroid Build Coastguard Worker ASN1_ENUMERATED* mode;
45*60b67249SAndroid Build Coastguard Worker ASN1_UTF8STRING* profile_name;
46*60b67249SAndroid Build Coastguard Worker } DiceExtensionAsn1;
47*60b67249SAndroid Build Coastguard Worker
48*60b67249SAndroid Build Coastguard Worker // clang-format off
49*60b67249SAndroid Build Coastguard Worker ASN1_SEQUENCE(DiceExtensionAsn1) = {
50*60b67249SAndroid Build Coastguard Worker ASN1_EXP_OPT(DiceExtensionAsn1, code_hash, ASN1_OCTET_STRING, 0),
51*60b67249SAndroid Build Coastguard Worker ASN1_EXP_OPT(DiceExtensionAsn1, code_descriptor, ASN1_OCTET_STRING, 1),
52*60b67249SAndroid Build Coastguard Worker ASN1_EXP_OPT(DiceExtensionAsn1, config_hash, ASN1_OCTET_STRING, 2),
53*60b67249SAndroid Build Coastguard Worker ASN1_EXP_OPT(DiceExtensionAsn1, config_descriptor, ASN1_OCTET_STRING, 3),
54*60b67249SAndroid Build Coastguard Worker ASN1_EXP_OPT(DiceExtensionAsn1, authority_hash, ASN1_OCTET_STRING, 4),
55*60b67249SAndroid Build Coastguard Worker ASN1_EXP_OPT(DiceExtensionAsn1, authority_descriptor, ASN1_OCTET_STRING, 5),
56*60b67249SAndroid Build Coastguard Worker ASN1_EXP_OPT(DiceExtensionAsn1, mode, ASN1_ENUMERATED, 6),
57*60b67249SAndroid Build Coastguard Worker ASN1_EXP_OPT(DiceExtensionAsn1, profile_name, ASN1_UTF8STRING, 7),
58*60b67249SAndroid Build Coastguard Worker } ASN1_SEQUENCE_END(DiceExtensionAsn1)
59*60b67249SAndroid Build Coastguard Worker DECLARE_ASN1_FUNCTIONS(DiceExtensionAsn1)
60*60b67249SAndroid Build Coastguard Worker IMPLEMENT_ASN1_FUNCTIONS(DiceExtensionAsn1)
61*60b67249SAndroid Build Coastguard Worker
62*60b67249SAndroid Build Coastguard Worker static DiceResult AddStandardFields(X509* x509, const uint8_t subject_id[DICE_ID_SIZE],
63*60b67249SAndroid Build Coastguard Worker const uint8_t authority_id[DICE_ID_SIZE]) {
64*60b67249SAndroid Build Coastguard Worker // clang-format on
65*60b67249SAndroid Build Coastguard Worker DiceResult result = kDiceResultOk;
66*60b67249SAndroid Build Coastguard Worker
67*60b67249SAndroid Build Coastguard Worker // Initialize variables that are cleaned up on 'goto out'.
68*60b67249SAndroid Build Coastguard Worker ASN1_INTEGER* serial = NULL;
69*60b67249SAndroid Build Coastguard Worker BIGNUM* serial_bn = NULL;
70*60b67249SAndroid Build Coastguard Worker X509_NAME* issuer_name = NULL;
71*60b67249SAndroid Build Coastguard Worker X509_NAME* subject_name = NULL;
72*60b67249SAndroid Build Coastguard Worker ASN1_TIME* not_before = NULL;
73*60b67249SAndroid Build Coastguard Worker ASN1_TIME* not_after = NULL;
74*60b67249SAndroid Build Coastguard Worker
75*60b67249SAndroid Build Coastguard Worker serial = ASN1_INTEGER_new();
76*60b67249SAndroid Build Coastguard Worker if (!serial) {
77*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
78*60b67249SAndroid Build Coastguard Worker goto out;
79*60b67249SAndroid Build Coastguard Worker }
80*60b67249SAndroid Build Coastguard Worker issuer_name = X509_NAME_new();
81*60b67249SAndroid Build Coastguard Worker if (!issuer_name) {
82*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
83*60b67249SAndroid Build Coastguard Worker goto out;
84*60b67249SAndroid Build Coastguard Worker }
85*60b67249SAndroid Build Coastguard Worker subject_name = X509_NAME_new();
86*60b67249SAndroid Build Coastguard Worker if (!subject_name) {
87*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
88*60b67249SAndroid Build Coastguard Worker goto out;
89*60b67249SAndroid Build Coastguard Worker }
90*60b67249SAndroid Build Coastguard Worker not_before = ASN1_TIME_new();
91*60b67249SAndroid Build Coastguard Worker if (!not_before) {
92*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
93*60b67249SAndroid Build Coastguard Worker goto out;
94*60b67249SAndroid Build Coastguard Worker }
95*60b67249SAndroid Build Coastguard Worker not_after = ASN1_TIME_new();
96*60b67249SAndroid Build Coastguard Worker if (!not_after) {
97*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
98*60b67249SAndroid Build Coastguard Worker goto out;
99*60b67249SAndroid Build Coastguard Worker }
100*60b67249SAndroid Build Coastguard Worker
101*60b67249SAndroid Build Coastguard Worker if (!X509_set_version(x509, 2)) {
102*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
103*60b67249SAndroid Build Coastguard Worker goto out;
104*60b67249SAndroid Build Coastguard Worker }
105*60b67249SAndroid Build Coastguard Worker
106*60b67249SAndroid Build Coastguard Worker serial_bn = BN_bin2bn(subject_id, DICE_ID_SIZE, NULL);
107*60b67249SAndroid Build Coastguard Worker if (!serial_bn) {
108*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
109*60b67249SAndroid Build Coastguard Worker goto out;
110*60b67249SAndroid Build Coastguard Worker }
111*60b67249SAndroid Build Coastguard Worker BN_to_ASN1_INTEGER(serial_bn, serial);
112*60b67249SAndroid Build Coastguard Worker if (!X509_set_serialNumber(x509, serial)) {
113*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
114*60b67249SAndroid Build Coastguard Worker goto out;
115*60b67249SAndroid Build Coastguard Worker }
116*60b67249SAndroid Build Coastguard Worker
117*60b67249SAndroid Build Coastguard Worker uint8_t id_hex[40];
118*60b67249SAndroid Build Coastguard Worker DiceHexEncode(authority_id, DICE_ID_SIZE, id_hex, sizeof(id_hex));
119*60b67249SAndroid Build Coastguard Worker if (!X509_NAME_add_entry_by_NID(issuer_name, NID_serialNumber, MBSTRING_UTF8,
120*60b67249SAndroid Build Coastguard Worker id_hex, sizeof(id_hex), 0, 0)) {
121*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
122*60b67249SAndroid Build Coastguard Worker goto out;
123*60b67249SAndroid Build Coastguard Worker }
124*60b67249SAndroid Build Coastguard Worker if (!X509_set_issuer_name(x509, issuer_name)) {
125*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
126*60b67249SAndroid Build Coastguard Worker goto out;
127*60b67249SAndroid Build Coastguard Worker }
128*60b67249SAndroid Build Coastguard Worker
129*60b67249SAndroid Build Coastguard Worker DiceHexEncode(subject_id, DICE_ID_SIZE, id_hex, sizeof(id_hex));
130*60b67249SAndroid Build Coastguard Worker if (!X509_NAME_add_entry_by_NID(subject_name, NID_serialNumber, MBSTRING_UTF8,
131*60b67249SAndroid Build Coastguard Worker id_hex, sizeof(id_hex), 0, 0)) {
132*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
133*60b67249SAndroid Build Coastguard Worker goto out;
134*60b67249SAndroid Build Coastguard Worker }
135*60b67249SAndroid Build Coastguard Worker if (!X509_set_subject_name(x509, subject_name)) {
136*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
137*60b67249SAndroid Build Coastguard Worker goto out;
138*60b67249SAndroid Build Coastguard Worker }
139*60b67249SAndroid Build Coastguard Worker
140*60b67249SAndroid Build Coastguard Worker // '180322235959Z' is the date of publication of the DICE specification. Here
141*60b67249SAndroid Build Coastguard Worker // it's used as a somewhat arbitrary backstop.
142*60b67249SAndroid Build Coastguard Worker if (!ASN1_TIME_set_string(not_before, "180322235959Z")) {
143*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
144*60b67249SAndroid Build Coastguard Worker goto out;
145*60b67249SAndroid Build Coastguard Worker }
146*60b67249SAndroid Build Coastguard Worker if (!X509_set_notBefore(x509, not_before)) {
147*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
148*60b67249SAndroid Build Coastguard Worker goto out;
149*60b67249SAndroid Build Coastguard Worker }
150*60b67249SAndroid Build Coastguard Worker // '99991231235959Z' is suggested by RFC 5280 in cases where expiry is not
151*60b67249SAndroid Build Coastguard Worker // meaningful. Basically, the certificate never expires.
152*60b67249SAndroid Build Coastguard Worker if (!ASN1_TIME_set_string(not_after, "99991231235959Z")) {
153*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
154*60b67249SAndroid Build Coastguard Worker goto out;
155*60b67249SAndroid Build Coastguard Worker }
156*60b67249SAndroid Build Coastguard Worker if (!X509_set_notAfter(x509, not_after)) {
157*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
158*60b67249SAndroid Build Coastguard Worker goto out;
159*60b67249SAndroid Build Coastguard Worker }
160*60b67249SAndroid Build Coastguard Worker out:
161*60b67249SAndroid Build Coastguard Worker if (serial) {
162*60b67249SAndroid Build Coastguard Worker ASN1_INTEGER_free(serial);
163*60b67249SAndroid Build Coastguard Worker }
164*60b67249SAndroid Build Coastguard Worker if (serial_bn) {
165*60b67249SAndroid Build Coastguard Worker BN_free(serial_bn);
166*60b67249SAndroid Build Coastguard Worker }
167*60b67249SAndroid Build Coastguard Worker if (issuer_name) {
168*60b67249SAndroid Build Coastguard Worker X509_NAME_free(issuer_name);
169*60b67249SAndroid Build Coastguard Worker }
170*60b67249SAndroid Build Coastguard Worker if (subject_name) {
171*60b67249SAndroid Build Coastguard Worker X509_NAME_free(subject_name);
172*60b67249SAndroid Build Coastguard Worker }
173*60b67249SAndroid Build Coastguard Worker if (not_before) {
174*60b67249SAndroid Build Coastguard Worker ASN1_TIME_free(not_before);
175*60b67249SAndroid Build Coastguard Worker }
176*60b67249SAndroid Build Coastguard Worker if (not_after) {
177*60b67249SAndroid Build Coastguard Worker ASN1_TIME_free(not_after);
178*60b67249SAndroid Build Coastguard Worker }
179*60b67249SAndroid Build Coastguard Worker return result;
180*60b67249SAndroid Build Coastguard Worker }
181*60b67249SAndroid Build Coastguard Worker
AddStandardExtensions(X509 * x509,const uint8_t subject_id[DICE_ID_SIZE],const uint8_t authority_id[DICE_ID_SIZE])182*60b67249SAndroid Build Coastguard Worker static DiceResult AddStandardExtensions(
183*60b67249SAndroid Build Coastguard Worker X509* x509, const uint8_t subject_id[DICE_ID_SIZE],
184*60b67249SAndroid Build Coastguard Worker const uint8_t authority_id[DICE_ID_SIZE]) {
185*60b67249SAndroid Build Coastguard Worker DiceResult result = kDiceResultOk;
186*60b67249SAndroid Build Coastguard Worker
187*60b67249SAndroid Build Coastguard Worker // Initialize variables that are cleaned up on 'goto out'.
188*60b67249SAndroid Build Coastguard Worker AUTHORITY_KEYID* authority_key_id = NULL;
189*60b67249SAndroid Build Coastguard Worker ASN1_OCTET_STRING* subject_key_id = NULL;
190*60b67249SAndroid Build Coastguard Worker ASN1_BIT_STRING* key_usage = NULL;
191*60b67249SAndroid Build Coastguard Worker BASIC_CONSTRAINTS* basic_constraints = NULL;
192*60b67249SAndroid Build Coastguard Worker X509_EXTENSION* authority_key_id_ext = NULL;
193*60b67249SAndroid Build Coastguard Worker X509_EXTENSION* subject_key_id_ext = NULL;
194*60b67249SAndroid Build Coastguard Worker X509_EXTENSION* key_usage_ext = NULL;
195*60b67249SAndroid Build Coastguard Worker X509_EXTENSION* basic_constraints_ext = NULL;
196*60b67249SAndroid Build Coastguard Worker
197*60b67249SAndroid Build Coastguard Worker // The authority key identifier extension contains the same raw authority id
198*60b67249SAndroid Build Coastguard Worker // that appears in the issuer name.
199*60b67249SAndroid Build Coastguard Worker authority_key_id = AUTHORITY_KEYID_new();
200*60b67249SAndroid Build Coastguard Worker if (!authority_key_id) {
201*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
202*60b67249SAndroid Build Coastguard Worker goto out;
203*60b67249SAndroid Build Coastguard Worker }
204*60b67249SAndroid Build Coastguard Worker authority_key_id->keyid = ASN1_OCTET_STRING_new();
205*60b67249SAndroid Build Coastguard Worker if (!authority_key_id->keyid) {
206*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
207*60b67249SAndroid Build Coastguard Worker goto out;
208*60b67249SAndroid Build Coastguard Worker }
209*60b67249SAndroid Build Coastguard Worker if (!ASN1_OCTET_STRING_set(authority_key_id->keyid, authority_id,
210*60b67249SAndroid Build Coastguard Worker DICE_ID_SIZE)) {
211*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
212*60b67249SAndroid Build Coastguard Worker goto out;
213*60b67249SAndroid Build Coastguard Worker }
214*60b67249SAndroid Build Coastguard Worker
215*60b67249SAndroid Build Coastguard Worker // The subject key identifier extension contains the same raw subject id that
216*60b67249SAndroid Build Coastguard Worker // appears in the serial number and the subject name.
217*60b67249SAndroid Build Coastguard Worker subject_key_id = ASN1_OCTET_STRING_new();
218*60b67249SAndroid Build Coastguard Worker if (!subject_key_id) {
219*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
220*60b67249SAndroid Build Coastguard Worker goto out;
221*60b67249SAndroid Build Coastguard Worker }
222*60b67249SAndroid Build Coastguard Worker if (!ASN1_OCTET_STRING_set(subject_key_id, subject_id, DICE_ID_SIZE)) {
223*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
224*60b67249SAndroid Build Coastguard Worker goto out;
225*60b67249SAndroid Build Coastguard Worker }
226*60b67249SAndroid Build Coastguard Worker
227*60b67249SAndroid Build Coastguard Worker // The key usage extension contains only "keyCertSign".
228*60b67249SAndroid Build Coastguard Worker key_usage = ASN1_BIT_STRING_new();
229*60b67249SAndroid Build Coastguard Worker if (!key_usage) {
230*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
231*60b67249SAndroid Build Coastguard Worker goto out;
232*60b67249SAndroid Build Coastguard Worker }
233*60b67249SAndroid Build Coastguard Worker ASN1_BIT_STRING_set_bit(key_usage, 5 /*keyCertSign*/, 1);
234*60b67249SAndroid Build Coastguard Worker
235*60b67249SAndroid Build Coastguard Worker // The basic constraints specify this is a CA with unspecified pathlen.
236*60b67249SAndroid Build Coastguard Worker basic_constraints = BASIC_CONSTRAINTS_new();
237*60b67249SAndroid Build Coastguard Worker if (!basic_constraints) {
238*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
239*60b67249SAndroid Build Coastguard Worker goto out;
240*60b67249SAndroid Build Coastguard Worker }
241*60b67249SAndroid Build Coastguard Worker basic_constraints->ca = 1;
242*60b67249SAndroid Build Coastguard Worker
243*60b67249SAndroid Build Coastguard Worker // Encode all the extension objects.
244*60b67249SAndroid Build Coastguard Worker authority_key_id_ext = X509V3_EXT_i2d(NID_authority_key_identifier,
245*60b67249SAndroid Build Coastguard Worker /*crit=*/0, authority_key_id);
246*60b67249SAndroid Build Coastguard Worker if (!authority_key_id_ext) {
247*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
248*60b67249SAndroid Build Coastguard Worker goto out;
249*60b67249SAndroid Build Coastguard Worker }
250*60b67249SAndroid Build Coastguard Worker subject_key_id_ext = X509V3_EXT_i2d(NID_subject_key_identifier,
251*60b67249SAndroid Build Coastguard Worker /*crit=*/0, subject_key_id);
252*60b67249SAndroid Build Coastguard Worker if (!subject_key_id_ext) {
253*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
254*60b67249SAndroid Build Coastguard Worker goto out;
255*60b67249SAndroid Build Coastguard Worker }
256*60b67249SAndroid Build Coastguard Worker key_usage_ext = X509V3_EXT_i2d(NID_key_usage, /*crit=*/1, key_usage);
257*60b67249SAndroid Build Coastguard Worker if (!key_usage_ext) {
258*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
259*60b67249SAndroid Build Coastguard Worker goto out;
260*60b67249SAndroid Build Coastguard Worker }
261*60b67249SAndroid Build Coastguard Worker basic_constraints_ext = X509V3_EXT_i2d(NID_basic_constraints,
262*60b67249SAndroid Build Coastguard Worker /*crit=*/1, basic_constraints);
263*60b67249SAndroid Build Coastguard Worker if (!basic_constraints_ext) {
264*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
265*60b67249SAndroid Build Coastguard Worker goto out;
266*60b67249SAndroid Build Coastguard Worker }
267*60b67249SAndroid Build Coastguard Worker
268*60b67249SAndroid Build Coastguard Worker // Add all the extensions to the given X509 object.
269*60b67249SAndroid Build Coastguard Worker if (!X509_add_ext(x509, authority_key_id_ext, -1)) {
270*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
271*60b67249SAndroid Build Coastguard Worker goto out;
272*60b67249SAndroid Build Coastguard Worker }
273*60b67249SAndroid Build Coastguard Worker if (!X509_add_ext(x509, subject_key_id_ext, -1)) {
274*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
275*60b67249SAndroid Build Coastguard Worker goto out;
276*60b67249SAndroid Build Coastguard Worker }
277*60b67249SAndroid Build Coastguard Worker if (!X509_add_ext(x509, key_usage_ext, -1)) {
278*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
279*60b67249SAndroid Build Coastguard Worker goto out;
280*60b67249SAndroid Build Coastguard Worker }
281*60b67249SAndroid Build Coastguard Worker if (!X509_add_ext(x509, basic_constraints_ext, -1)) {
282*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
283*60b67249SAndroid Build Coastguard Worker goto out;
284*60b67249SAndroid Build Coastguard Worker }
285*60b67249SAndroid Build Coastguard Worker out:
286*60b67249SAndroid Build Coastguard Worker if (authority_key_id) {
287*60b67249SAndroid Build Coastguard Worker AUTHORITY_KEYID_free(authority_key_id);
288*60b67249SAndroid Build Coastguard Worker }
289*60b67249SAndroid Build Coastguard Worker if (subject_key_id) {
290*60b67249SAndroid Build Coastguard Worker ASN1_OCTET_STRING_free(subject_key_id);
291*60b67249SAndroid Build Coastguard Worker }
292*60b67249SAndroid Build Coastguard Worker if (key_usage) {
293*60b67249SAndroid Build Coastguard Worker ASN1_BIT_STRING_free(key_usage);
294*60b67249SAndroid Build Coastguard Worker }
295*60b67249SAndroid Build Coastguard Worker if (basic_constraints) {
296*60b67249SAndroid Build Coastguard Worker BASIC_CONSTRAINTS_free(basic_constraints);
297*60b67249SAndroid Build Coastguard Worker }
298*60b67249SAndroid Build Coastguard Worker if (authority_key_id_ext) {
299*60b67249SAndroid Build Coastguard Worker X509_EXTENSION_free(authority_key_id_ext);
300*60b67249SAndroid Build Coastguard Worker }
301*60b67249SAndroid Build Coastguard Worker if (subject_key_id_ext) {
302*60b67249SAndroid Build Coastguard Worker X509_EXTENSION_free(subject_key_id_ext);
303*60b67249SAndroid Build Coastguard Worker }
304*60b67249SAndroid Build Coastguard Worker if (key_usage_ext) {
305*60b67249SAndroid Build Coastguard Worker X509_EXTENSION_free(key_usage_ext);
306*60b67249SAndroid Build Coastguard Worker }
307*60b67249SAndroid Build Coastguard Worker if (basic_constraints_ext) {
308*60b67249SAndroid Build Coastguard Worker X509_EXTENSION_free(basic_constraints_ext);
309*60b67249SAndroid Build Coastguard Worker }
310*60b67249SAndroid Build Coastguard Worker return result;
311*60b67249SAndroid Build Coastguard Worker }
312*60b67249SAndroid Build Coastguard Worker
GetDiceExtensionData(const char * profile_name,const DiceInputValues * input_values,size_t buffer_size,uint8_t * buffer,size_t * actual_size)313*60b67249SAndroid Build Coastguard Worker static DiceResult GetDiceExtensionData(const char* profile_name,
314*60b67249SAndroid Build Coastguard Worker const DiceInputValues* input_values,
315*60b67249SAndroid Build Coastguard Worker size_t buffer_size, uint8_t* buffer,
316*60b67249SAndroid Build Coastguard Worker size_t* actual_size) {
317*60b67249SAndroid Build Coastguard Worker DiceResult result = kDiceResultOk;
318*60b67249SAndroid Build Coastguard Worker
319*60b67249SAndroid Build Coastguard Worker DiceExtensionAsn1* asn1 = DiceExtensionAsn1_new();
320*60b67249SAndroid Build Coastguard Worker if (!asn1) {
321*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
322*60b67249SAndroid Build Coastguard Worker goto out;
323*60b67249SAndroid Build Coastguard Worker }
324*60b67249SAndroid Build Coastguard Worker
325*60b67249SAndroid Build Coastguard Worker // Allocate required fields. Optional fields will be allocated as needed.
326*60b67249SAndroid Build Coastguard Worker asn1->code_hash = ASN1_OCTET_STRING_new();
327*60b67249SAndroid Build Coastguard Worker if (!asn1->code_hash) {
328*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
329*60b67249SAndroid Build Coastguard Worker goto out;
330*60b67249SAndroid Build Coastguard Worker }
331*60b67249SAndroid Build Coastguard Worker asn1->config_descriptor = ASN1_OCTET_STRING_new();
332*60b67249SAndroid Build Coastguard Worker if (!asn1->config_descriptor) {
333*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
334*60b67249SAndroid Build Coastguard Worker goto out;
335*60b67249SAndroid Build Coastguard Worker }
336*60b67249SAndroid Build Coastguard Worker asn1->authority_hash = ASN1_OCTET_STRING_new();
337*60b67249SAndroid Build Coastguard Worker if (!asn1->authority_hash) {
338*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
339*60b67249SAndroid Build Coastguard Worker goto out;
340*60b67249SAndroid Build Coastguard Worker }
341*60b67249SAndroid Build Coastguard Worker asn1->mode = ASN1_ENUMERATED_new();
342*60b67249SAndroid Build Coastguard Worker if (!asn1->mode) {
343*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
344*60b67249SAndroid Build Coastguard Worker goto out;
345*60b67249SAndroid Build Coastguard Worker }
346*60b67249SAndroid Build Coastguard Worker
347*60b67249SAndroid Build Coastguard Worker // Encode code input.
348*60b67249SAndroid Build Coastguard Worker if (!ASN1_OCTET_STRING_set(asn1->code_hash, input_values->code_hash,
349*60b67249SAndroid Build Coastguard Worker DICE_HASH_SIZE)) {
350*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
351*60b67249SAndroid Build Coastguard Worker goto out;
352*60b67249SAndroid Build Coastguard Worker }
353*60b67249SAndroid Build Coastguard Worker if (input_values->code_descriptor_size > 0) {
354*60b67249SAndroid Build Coastguard Worker asn1->code_descriptor = ASN1_OCTET_STRING_new();
355*60b67249SAndroid Build Coastguard Worker if (!asn1->code_descriptor) {
356*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
357*60b67249SAndroid Build Coastguard Worker goto out;
358*60b67249SAndroid Build Coastguard Worker }
359*60b67249SAndroid Build Coastguard Worker if (!ASN1_OCTET_STRING_set(asn1->code_descriptor,
360*60b67249SAndroid Build Coastguard Worker input_values->code_descriptor,
361*60b67249SAndroid Build Coastguard Worker input_values->code_descriptor_size)) {
362*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
363*60b67249SAndroid Build Coastguard Worker goto out;
364*60b67249SAndroid Build Coastguard Worker }
365*60b67249SAndroid Build Coastguard Worker }
366*60b67249SAndroid Build Coastguard Worker
367*60b67249SAndroid Build Coastguard Worker // Encode configuration inputs.
368*60b67249SAndroid Build Coastguard Worker if (input_values->config_type == kDiceConfigTypeDescriptor) {
369*60b67249SAndroid Build Coastguard Worker // The 'descriptor' type means the configuration input is in the descriptor
370*60b67249SAndroid Build Coastguard Worker // field and the hash of this was used as the DICE input. In the extension
371*60b67249SAndroid Build Coastguard Worker // both are stored.
372*60b67249SAndroid Build Coastguard Worker uint8_t hash_buffer[DICE_HASH_SIZE];
373*60b67249SAndroid Build Coastguard Worker asn1->config_hash = ASN1_OCTET_STRING_new();
374*60b67249SAndroid Build Coastguard Worker if (!asn1->config_hash) {
375*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
376*60b67249SAndroid Build Coastguard Worker goto out;
377*60b67249SAndroid Build Coastguard Worker }
378*60b67249SAndroid Build Coastguard Worker if (!ASN1_OCTET_STRING_set(asn1->config_descriptor,
379*60b67249SAndroid Build Coastguard Worker input_values->config_descriptor,
380*60b67249SAndroid Build Coastguard Worker input_values->config_descriptor_size)) {
381*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
382*60b67249SAndroid Build Coastguard Worker goto out;
383*60b67249SAndroid Build Coastguard Worker }
384*60b67249SAndroid Build Coastguard Worker if (!ASN1_OCTET_STRING_set(
385*60b67249SAndroid Build Coastguard Worker asn1->config_hash,
386*60b67249SAndroid Build Coastguard Worker SHA512(input_values->config_descriptor,
387*60b67249SAndroid Build Coastguard Worker input_values->config_descriptor_size, hash_buffer),
388*60b67249SAndroid Build Coastguard Worker DICE_HASH_SIZE)) {
389*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
390*60b67249SAndroid Build Coastguard Worker goto out;
391*60b67249SAndroid Build Coastguard Worker }
392*60b67249SAndroid Build Coastguard Worker } else if (input_values->config_type == kDiceConfigTypeInline) {
393*60b67249SAndroid Build Coastguard Worker // The 'inline' type means the configuration value is 64 bytes and was used
394*60b67249SAndroid Build Coastguard Worker // directly as the DICE input. In the extension this value is stored in the
395*60b67249SAndroid Build Coastguard Worker // descriptor and the hash is omitted.
396*60b67249SAndroid Build Coastguard Worker if (!ASN1_OCTET_STRING_set(asn1->config_descriptor,
397*60b67249SAndroid Build Coastguard Worker input_values->config_value,
398*60b67249SAndroid Build Coastguard Worker DICE_INLINE_CONFIG_SIZE)) {
399*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
400*60b67249SAndroid Build Coastguard Worker goto out;
401*60b67249SAndroid Build Coastguard Worker }
402*60b67249SAndroid Build Coastguard Worker } else {
403*60b67249SAndroid Build Coastguard Worker result = kDiceResultInvalidInput;
404*60b67249SAndroid Build Coastguard Worker goto out;
405*60b67249SAndroid Build Coastguard Worker }
406*60b67249SAndroid Build Coastguard Worker
407*60b67249SAndroid Build Coastguard Worker // Encode authority input.
408*60b67249SAndroid Build Coastguard Worker if (!ASN1_OCTET_STRING_set(asn1->authority_hash, input_values->authority_hash,
409*60b67249SAndroid Build Coastguard Worker DICE_HASH_SIZE)) {
410*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
411*60b67249SAndroid Build Coastguard Worker goto out;
412*60b67249SAndroid Build Coastguard Worker }
413*60b67249SAndroid Build Coastguard Worker if (input_values->authority_descriptor_size > 0) {
414*60b67249SAndroid Build Coastguard Worker asn1->authority_descriptor = ASN1_OCTET_STRING_new();
415*60b67249SAndroid Build Coastguard Worker if (!asn1->authority_descriptor) {
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 (!ASN1_OCTET_STRING_set(asn1->authority_descriptor,
420*60b67249SAndroid Build Coastguard Worker input_values->authority_descriptor,
421*60b67249SAndroid Build Coastguard Worker input_values->authority_descriptor_size)) {
422*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
423*60b67249SAndroid Build Coastguard Worker goto out;
424*60b67249SAndroid Build Coastguard Worker }
425*60b67249SAndroid Build Coastguard Worker }
426*60b67249SAndroid Build Coastguard Worker
427*60b67249SAndroid Build Coastguard Worker // Encode mode input.
428*60b67249SAndroid Build Coastguard Worker if (!ASN1_ENUMERATED_set(asn1->mode, input_values->mode)) {
429*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
430*60b67249SAndroid Build Coastguard Worker goto out;
431*60b67249SAndroid Build Coastguard Worker }
432*60b67249SAndroid Build Coastguard Worker
433*60b67249SAndroid Build Coastguard Worker // Encode profile name.
434*60b67249SAndroid Build Coastguard Worker if (profile_name) {
435*60b67249SAndroid Build Coastguard Worker asn1->profile_name = ASN1_UTF8STRING_new();
436*60b67249SAndroid Build Coastguard Worker if (!asn1->profile_name) {
437*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
438*60b67249SAndroid Build Coastguard Worker goto out;
439*60b67249SAndroid Build Coastguard Worker }
440*60b67249SAndroid Build Coastguard Worker if (!ASN1_STRING_set(asn1->profile_name, profile_name,
441*60b67249SAndroid Build Coastguard Worker strlen(profile_name))) {
442*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
443*60b67249SAndroid Build Coastguard Worker goto out;
444*60b67249SAndroid Build Coastguard Worker }
445*60b67249SAndroid Build Coastguard Worker }
446*60b67249SAndroid Build Coastguard Worker
447*60b67249SAndroid Build Coastguard Worker *actual_size = i2d_DiceExtensionAsn1(asn1, NULL);
448*60b67249SAndroid Build Coastguard Worker if (buffer_size < *actual_size) {
449*60b67249SAndroid Build Coastguard Worker result = kDiceResultBufferTooSmall;
450*60b67249SAndroid Build Coastguard Worker goto out;
451*60b67249SAndroid Build Coastguard Worker }
452*60b67249SAndroid Build Coastguard Worker i2d_DiceExtensionAsn1(asn1, &buffer);
453*60b67249SAndroid Build Coastguard Worker
454*60b67249SAndroid Build Coastguard Worker out:
455*60b67249SAndroid Build Coastguard Worker if (asn1) {
456*60b67249SAndroid Build Coastguard Worker DiceExtensionAsn1_free(asn1);
457*60b67249SAndroid Build Coastguard Worker }
458*60b67249SAndroid Build Coastguard Worker return result;
459*60b67249SAndroid Build Coastguard Worker }
460*60b67249SAndroid Build Coastguard Worker
AddDiceExtension(const char * profile_name,const DiceInputValues * input_values,X509 * x509)461*60b67249SAndroid Build Coastguard Worker static DiceResult AddDiceExtension(const char* profile_name,
462*60b67249SAndroid Build Coastguard Worker const DiceInputValues* input_values,
463*60b67249SAndroid Build Coastguard Worker X509* x509) {
464*60b67249SAndroid Build Coastguard Worker const char* kDiceExtensionOid = "1.3.6.1.4.1.11129.2.1.24";
465*60b67249SAndroid Build Coastguard Worker
466*60b67249SAndroid Build Coastguard Worker // Initialize variables that are cleaned up on 'goto out'.
467*60b67249SAndroid Build Coastguard Worker ASN1_OBJECT* oid = NULL;
468*60b67249SAndroid Build Coastguard Worker ASN1_OCTET_STRING* octets = NULL;
469*60b67249SAndroid Build Coastguard Worker X509_EXTENSION* extension = NULL;
470*60b67249SAndroid Build Coastguard Worker
471*60b67249SAndroid Build Coastguard Worker uint8_t extension_buffer[DICE_MAX_EXTENSION_SIZE];
472*60b67249SAndroid Build Coastguard Worker size_t extension_size = 0;
473*60b67249SAndroid Build Coastguard Worker DiceResult result =
474*60b67249SAndroid Build Coastguard Worker GetDiceExtensionData(profile_name, input_values, sizeof(extension_buffer),
475*60b67249SAndroid Build Coastguard Worker extension_buffer, &extension_size);
476*60b67249SAndroid Build Coastguard Worker if (result != kDiceResultOk) {
477*60b67249SAndroid Build Coastguard Worker goto out;
478*60b67249SAndroid Build Coastguard Worker }
479*60b67249SAndroid Build Coastguard Worker
480*60b67249SAndroid Build Coastguard Worker oid = OBJ_txt2obj(kDiceExtensionOid, 1);
481*60b67249SAndroid Build Coastguard Worker if (!oid) {
482*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
483*60b67249SAndroid Build Coastguard Worker goto out;
484*60b67249SAndroid Build Coastguard Worker }
485*60b67249SAndroid Build Coastguard Worker
486*60b67249SAndroid Build Coastguard Worker octets = ASN1_OCTET_STRING_new();
487*60b67249SAndroid Build Coastguard Worker if (!octets) {
488*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
489*60b67249SAndroid Build Coastguard Worker goto out;
490*60b67249SAndroid Build Coastguard Worker }
491*60b67249SAndroid Build Coastguard Worker if (!ASN1_OCTET_STRING_set(octets, extension_buffer, extension_size)) {
492*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
493*60b67249SAndroid Build Coastguard Worker goto out;
494*60b67249SAndroid Build Coastguard Worker }
495*60b67249SAndroid Build Coastguard Worker
496*60b67249SAndroid Build Coastguard Worker extension =
497*60b67249SAndroid Build Coastguard Worker X509_EXTENSION_create_by_OBJ(/*ex=*/NULL, oid, /*crit=*/1, octets);
498*60b67249SAndroid Build Coastguard Worker if (!extension) {
499*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
500*60b67249SAndroid Build Coastguard Worker goto out;
501*60b67249SAndroid Build Coastguard Worker }
502*60b67249SAndroid Build Coastguard Worker
503*60b67249SAndroid Build Coastguard Worker if (!X509_add_ext(x509, extension, -1)) {
504*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
505*60b67249SAndroid Build Coastguard Worker goto out;
506*60b67249SAndroid Build Coastguard Worker }
507*60b67249SAndroid Build Coastguard Worker out:
508*60b67249SAndroid Build Coastguard Worker if (oid) {
509*60b67249SAndroid Build Coastguard Worker ASN1_OBJECT_free(oid);
510*60b67249SAndroid Build Coastguard Worker }
511*60b67249SAndroid Build Coastguard Worker if (octets) {
512*60b67249SAndroid Build Coastguard Worker ASN1_OCTET_STRING_free(octets);
513*60b67249SAndroid Build Coastguard Worker }
514*60b67249SAndroid Build Coastguard Worker if (extension) {
515*60b67249SAndroid Build Coastguard Worker X509_EXTENSION_free(extension);
516*60b67249SAndroid Build Coastguard Worker }
517*60b67249SAndroid Build Coastguard Worker return result;
518*60b67249SAndroid Build Coastguard Worker }
519*60b67249SAndroid Build Coastguard Worker
GetIdFromKey(void * context,const EVP_PKEY * key,uint8_t id[DICE_ID_SIZE])520*60b67249SAndroid Build Coastguard Worker static DiceResult GetIdFromKey(void* context, const EVP_PKEY* key,
521*60b67249SAndroid Build Coastguard Worker uint8_t id[DICE_ID_SIZE]) {
522*60b67249SAndroid Build Coastguard Worker uint8_t raw_public_key[32];
523*60b67249SAndroid Build Coastguard Worker size_t raw_public_key_size = sizeof(raw_public_key);
524*60b67249SAndroid Build Coastguard Worker if (!EVP_PKEY_get_raw_public_key(key, raw_public_key, &raw_public_key_size)) {
525*60b67249SAndroid Build Coastguard Worker return kDiceResultPlatformError;
526*60b67249SAndroid Build Coastguard Worker }
527*60b67249SAndroid Build Coastguard Worker return DiceDeriveCdiCertificateId(context, raw_public_key,
528*60b67249SAndroid Build Coastguard Worker raw_public_key_size, id);
529*60b67249SAndroid Build Coastguard Worker }
530*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)531*60b67249SAndroid Build Coastguard Worker DiceResult DiceGenerateCertificate(
532*60b67249SAndroid Build Coastguard Worker void* context,
533*60b67249SAndroid Build Coastguard Worker const uint8_t subject_private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE],
534*60b67249SAndroid Build Coastguard Worker const uint8_t authority_private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE],
535*60b67249SAndroid Build Coastguard Worker const DiceInputValues* input_values, size_t certificate_buffer_size,
536*60b67249SAndroid Build Coastguard Worker uint8_t* certificate, size_t* certificate_actual_size) {
537*60b67249SAndroid Build Coastguard Worker DiceResult result = kDiceResultOk;
538*60b67249SAndroid Build Coastguard Worker
539*60b67249SAndroid Build Coastguard Worker // Initialize variables that are cleaned up on 'goto out'.
540*60b67249SAndroid Build Coastguard Worker X509* x509 = NULL;
541*60b67249SAndroid Build Coastguard Worker EVP_PKEY* authority_key = NULL;
542*60b67249SAndroid Build Coastguard Worker EVP_PKEY* subject_key = NULL;
543*60b67249SAndroid Build Coastguard Worker
544*60b67249SAndroid Build Coastguard Worker x509 = X509_new();
545*60b67249SAndroid Build Coastguard Worker if (!x509) {
546*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
547*60b67249SAndroid Build Coastguard Worker goto out;
548*60b67249SAndroid Build Coastguard Worker }
549*60b67249SAndroid Build Coastguard Worker authority_key = EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, NULL,
550*60b67249SAndroid Build Coastguard Worker authority_private_key_seed,
551*60b67249SAndroid Build Coastguard Worker DICE_PRIVATE_KEY_SEED_SIZE);
552*60b67249SAndroid Build Coastguard Worker if (!authority_key) {
553*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
554*60b67249SAndroid Build Coastguard Worker goto out;
555*60b67249SAndroid Build Coastguard Worker }
556*60b67249SAndroid Build Coastguard Worker subject_key = EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, NULL,
557*60b67249SAndroid Build Coastguard Worker subject_private_key_seed,
558*60b67249SAndroid Build Coastguard Worker DICE_PRIVATE_KEY_SEED_SIZE);
559*60b67249SAndroid Build Coastguard Worker if (!subject_key) {
560*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
561*60b67249SAndroid Build Coastguard Worker goto out;
562*60b67249SAndroid Build Coastguard Worker }
563*60b67249SAndroid Build Coastguard Worker if (!X509_set_pubkey(x509, subject_key)) {
564*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
565*60b67249SAndroid Build Coastguard Worker goto out;
566*60b67249SAndroid Build Coastguard Worker }
567*60b67249SAndroid Build Coastguard Worker
568*60b67249SAndroid Build Coastguard Worker uint8_t authority_id[DICE_ID_SIZE];
569*60b67249SAndroid Build Coastguard Worker result = GetIdFromKey(context, authority_key, authority_id);
570*60b67249SAndroid Build Coastguard Worker if (result != kDiceResultOk) {
571*60b67249SAndroid Build Coastguard Worker goto out;
572*60b67249SAndroid Build Coastguard Worker }
573*60b67249SAndroid Build Coastguard Worker uint8_t subject_id[DICE_ID_SIZE];
574*60b67249SAndroid Build Coastguard Worker result = GetIdFromKey(context, subject_key, subject_id);
575*60b67249SAndroid Build Coastguard Worker if (result != kDiceResultOk) {
576*60b67249SAndroid Build Coastguard Worker goto out;
577*60b67249SAndroid Build Coastguard Worker }
578*60b67249SAndroid Build Coastguard Worker
579*60b67249SAndroid Build Coastguard Worker result = AddStandardFields(x509, subject_id, authority_id);
580*60b67249SAndroid Build Coastguard Worker if (result != kDiceResultOk) {
581*60b67249SAndroid Build Coastguard Worker goto out;
582*60b67249SAndroid Build Coastguard Worker }
583*60b67249SAndroid Build Coastguard Worker result = AddStandardExtensions(x509, subject_id, authority_id);
584*60b67249SAndroid Build Coastguard Worker if (result != kDiceResultOk) {
585*60b67249SAndroid Build Coastguard Worker goto out;
586*60b67249SAndroid Build Coastguard Worker }
587*60b67249SAndroid Build Coastguard Worker DiceKeyParam key_param;
588*60b67249SAndroid Build Coastguard Worker result = DiceGetKeyParam(context, kDicePrincipalSubject, &key_param);
589*60b67249SAndroid Build Coastguard Worker if (result != kDiceResultOk) {
590*60b67249SAndroid Build Coastguard Worker goto out;
591*60b67249SAndroid Build Coastguard Worker }
592*60b67249SAndroid Build Coastguard Worker result = AddDiceExtension(key_param.profile_name, input_values, x509);
593*60b67249SAndroid Build Coastguard Worker if (result != kDiceResultOk) {
594*60b67249SAndroid Build Coastguard Worker goto out;
595*60b67249SAndroid Build Coastguard Worker }
596*60b67249SAndroid Build Coastguard Worker if (!X509_sign(x509, authority_key, NULL /*ED25519 always uses SHA-512*/)) {
597*60b67249SAndroid Build Coastguard Worker result = kDiceResultPlatformError;
598*60b67249SAndroid Build Coastguard Worker goto out;
599*60b67249SAndroid Build Coastguard Worker }
600*60b67249SAndroid Build Coastguard Worker *certificate_actual_size = i2d_X509(x509, NULL);
601*60b67249SAndroid Build Coastguard Worker if (*certificate_actual_size > certificate_buffer_size) {
602*60b67249SAndroid Build Coastguard Worker result = kDiceResultBufferTooSmall;
603*60b67249SAndroid Build Coastguard Worker goto out;
604*60b67249SAndroid Build Coastguard Worker }
605*60b67249SAndroid Build Coastguard Worker *certificate_actual_size = i2d_X509(x509, &certificate);
606*60b67249SAndroid Build Coastguard Worker out:
607*60b67249SAndroid Build Coastguard Worker if (x509) {
608*60b67249SAndroid Build Coastguard Worker X509_free(x509);
609*60b67249SAndroid Build Coastguard Worker }
610*60b67249SAndroid Build Coastguard Worker if (authority_key) {
611*60b67249SAndroid Build Coastguard Worker EVP_PKEY_free(authority_key);
612*60b67249SAndroid Build Coastguard Worker }
613*60b67249SAndroid Build Coastguard Worker if (subject_key) {
614*60b67249SAndroid Build Coastguard Worker EVP_PKEY_free(subject_key);
615*60b67249SAndroid Build Coastguard Worker }
616*60b67249SAndroid Build Coastguard Worker return result;
617*60b67249SAndroid Build Coastguard Worker }
618