xref: /aosp_15_r20/external/open-dice/src/template_cert_op.c (revision 60b67249c2e226f42f35cc6cfe66c6048e0bae6b)
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 the DiceGenerateCertificate that generates an
16*60b67249SAndroid Build Coastguard Worker // X.509 certificate based on a template using the ED25519-SHA512 signature
17*60b67249SAndroid Build Coastguard Worker // scheme.
18*60b67249SAndroid Build Coastguard Worker //
19*60b67249SAndroid Build Coastguard Worker // If no variable length descriptors are used in a DICE certificate, the
20*60b67249SAndroid Build Coastguard Worker // certificate can be constructed from a template instead of using an ASN.1
21*60b67249SAndroid Build Coastguard Worker // library. This implementation includes only hashes and inline configuration in
22*60b67249SAndroid Build Coastguard Worker // the DICE extension. For convenience this uses the lower level curve25519
23*60b67249SAndroid Build Coastguard Worker // implementation in boringssl but does not use anything else (no ASN.1, X.509,
24*60b67249SAndroid Build Coastguard Worker // etc). This approach may be especially useful in very low level components
25*60b67249SAndroid Build Coastguard Worker // where simplicity is paramount.
26*60b67249SAndroid Build Coastguard Worker //
27*60b67249SAndroid Build Coastguard Worker // This function will return kDiceResultInvalidInput if 'input_values' specifies
28*60b67249SAndroid Build Coastguard Worker // any variable length descriptors. In particular:
29*60b67249SAndroid Build Coastguard Worker //   * code_descriptor_size must be zero
30*60b67249SAndroid Build Coastguard Worker //   * authority_descriptor_size must be zero
31*60b67249SAndroid Build Coastguard Worker //   * config_type must be kDiceConfigTypeInline
32*60b67249SAndroid Build Coastguard Worker 
33*60b67249SAndroid Build Coastguard Worker #include <stdint.h>
34*60b67249SAndroid Build Coastguard Worker #include <string.h>
35*60b67249SAndroid Build Coastguard Worker 
36*60b67249SAndroid Build Coastguard Worker #include "dice/dice.h"
37*60b67249SAndroid Build Coastguard Worker #include "dice/ops.h"
38*60b67249SAndroid Build Coastguard Worker #include "dice/utils.h"
39*60b67249SAndroid Build Coastguard Worker #include "openssl/curve25519.h"
40*60b67249SAndroid Build Coastguard Worker #include "openssl/is_boringssl.h"
41*60b67249SAndroid Build Coastguard Worker 
42*60b67249SAndroid Build Coastguard Worker // A well-formed certificate, but with zeros in all fields to be filled.
43*60b67249SAndroid Build Coastguard Worker static const uint8_t kTemplate[638] = {
44*60b67249SAndroid Build Coastguard Worker     // Constant encoding.
45*60b67249SAndroid Build Coastguard Worker     0x30, 0x82, 0x02, 0x7a,
46*60b67249SAndroid Build Coastguard Worker     // Offset 4: TBS starts here.
47*60b67249SAndroid Build Coastguard Worker     // Constant encoding.
48*60b67249SAndroid Build Coastguard Worker     0x30, 0x82, 0x02, 0x2c, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x14,
49*60b67249SAndroid Build Coastguard Worker     // Offset 15: Serial number, 20 bytes.
50*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
51*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
52*60b67249SAndroid Build Coastguard Worker     // Constant encoding.
53*60b67249SAndroid Build Coastguard Worker     0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x30, 0x33, 0x31, 0x31, 0x30,
54*60b67249SAndroid Build Coastguard Worker     0x2f, 0x06, 0x03, 0x55, 0x04, 0x05, 0x13, 0x28,
55*60b67249SAndroid Build Coastguard Worker     // Offset 55: Issuer name, 40 bytes.
56*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00,
60*60b67249SAndroid Build Coastguard Worker     // Constant encoding.
61*60b67249SAndroid Build Coastguard Worker     0x30, 0x20, 0x17, 0x0d, 0x31, 0x38, 0x30, 0x33, 0x32, 0x32, 0x32, 0x33,
62*60b67249SAndroid Build Coastguard Worker     0x35, 0x39, 0x35, 0x39, 0x5a, 0x18, 0x0f, 0x39, 0x39, 0x39, 0x39, 0x31,
63*60b67249SAndroid Build Coastguard Worker     0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x33,
64*60b67249SAndroid Build Coastguard Worker     0x31, 0x31, 0x30, 0x2f, 0x06, 0x03, 0x55, 0x04, 0x05, 0x13, 0x28,
65*60b67249SAndroid Build Coastguard Worker     // Offset 142: Subject name, 40 bytes.
66*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
67*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
68*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
69*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00,
70*60b67249SAndroid Build Coastguard Worker     // Constant encoding.
71*60b67249SAndroid Build Coastguard Worker     0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21, 0x00,
72*60b67249SAndroid Build Coastguard Worker     // Offset 194: Subject public key, 32 bytes.
73*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76*60b67249SAndroid Build Coastguard Worker     // Constant encoding.
77*60b67249SAndroid Build Coastguard Worker     0xa3, 0x82, 0x01, 0x4e, 0x30, 0x82, 0x01, 0x4a, 0x30, 0x1f, 0x06, 0x03,
78*60b67249SAndroid Build Coastguard Worker     0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14,
79*60b67249SAndroid Build Coastguard Worker     // Offset 247: Authority key identifier, 20 bytes.
80*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
81*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
82*60b67249SAndroid Build Coastguard Worker     // Constant encoding.
83*60b67249SAndroid Build Coastguard Worker     0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14,
84*60b67249SAndroid Build Coastguard Worker     // Offset 278: Subject key identifier, 20 bytes.
85*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87*60b67249SAndroid Build Coastguard Worker     // Constant encoding.
88*60b67249SAndroid Build Coastguard Worker     0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04,
89*60b67249SAndroid Build Coastguard Worker     0x03, 0x02, 0x02, 0x04, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
90*60b67249SAndroid Build Coastguard Worker     0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x81, 0xe6,
91*60b67249SAndroid Build Coastguard Worker     0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, 0x01, 0x18,
92*60b67249SAndroid Build Coastguard Worker     0x01, 0x01, 0xff, 0x04, 0x81, 0xd4, 0x30, 0x81, 0xd1, 0xa0, 0x42, 0x04,
93*60b67249SAndroid Build Coastguard Worker     0x40,
94*60b67249SAndroid Build Coastguard Worker     // Offset 356: Code hash, 64 bytes.
95*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
97*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
98*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
99*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00,
101*60b67249SAndroid Build Coastguard Worker     // Constant encoding.
102*60b67249SAndroid Build Coastguard Worker     0xa3, 0x42, 0x04, 0x40,
103*60b67249SAndroid Build Coastguard Worker     // Offset 424: Configuration value, 64 bytes.
104*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
105*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
106*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
107*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
108*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
109*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00,
110*60b67249SAndroid Build Coastguard Worker     // Constant encoding.
111*60b67249SAndroid Build Coastguard Worker     0xa4, 0x42, 0x04, 0x40,
112*60b67249SAndroid Build Coastguard Worker     // Offset 492: Authority hash, 64 bytes.
113*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
114*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
115*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
117*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
118*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00,
119*60b67249SAndroid Build Coastguard Worker     // Constant encoding.
120*60b67249SAndroid Build Coastguard Worker     0xa6, 0x03, 0x0a, 0x01,
121*60b67249SAndroid Build Coastguard Worker     // Offset 560: Mode, 1 byte.
122*60b67249SAndroid Build Coastguard Worker     0x00,
123*60b67249SAndroid Build Coastguard Worker     // Offset 561: TBS ends here.
124*60b67249SAndroid Build Coastguard Worker     // Constant encoding.
125*60b67249SAndroid Build Coastguard Worker     0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x41, 0x00,
126*60b67249SAndroid Build Coastguard Worker     // Offset 571: Signature, 64 bytes.
127*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
128*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
129*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
130*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
131*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
132*60b67249SAndroid Build Coastguard Worker     0x00, 0x00, 0x00, 0x00};
133*60b67249SAndroid Build Coastguard Worker 
134*60b67249SAndroid Build Coastguard Worker static const struct {
135*60b67249SAndroid Build Coastguard Worker   size_t offset;
136*60b67249SAndroid Build Coastguard Worker   size_t length;
137*60b67249SAndroid Build Coastguard Worker } kFieldTable[] = {{15, 20},   // Serial number
138*60b67249SAndroid Build Coastguard Worker                    {55, 40},   // Issuer name
139*60b67249SAndroid Build Coastguard Worker                    {142, 40},  // Subject name
140*60b67249SAndroid Build Coastguard Worker                    {194, 32},  // Subject public key
141*60b67249SAndroid Build Coastguard Worker                    {247, 20},  // Authority key id
142*60b67249SAndroid Build Coastguard Worker                    {278, 20},  // Subject key id
143*60b67249SAndroid Build Coastguard Worker                    {359, 64},  // Code hash
144*60b67249SAndroid Build Coastguard Worker                    {427, 64},  // Config descriptor
145*60b67249SAndroid Build Coastguard Worker                    {495, 64},  // Authority hash
146*60b67249SAndroid Build Coastguard Worker                    {563, 1},   // Mode
147*60b67249SAndroid Build Coastguard Worker                    {574, 64},  // Signature
148*60b67249SAndroid Build Coastguard Worker                    {4, 560}};  // Entire TBS
149*60b67249SAndroid Build Coastguard Worker 
150*60b67249SAndroid Build Coastguard Worker static const size_t kFieldIndexSerial = 0;
151*60b67249SAndroid Build Coastguard Worker static const size_t kFieldIndexIssuerName = 1;
152*60b67249SAndroid Build Coastguard Worker static const size_t kFieldIndexSubjectName = 2;
153*60b67249SAndroid Build Coastguard Worker static const size_t kFieldIndexSubjectPublicKey = 3;
154*60b67249SAndroid Build Coastguard Worker static const size_t kFieldIndexAuthorityKeyId = 4;
155*60b67249SAndroid Build Coastguard Worker static const size_t kFieldIndexSubjectKeyId = 5;
156*60b67249SAndroid Build Coastguard Worker static const size_t kFieldIndexCodeHash = 6;
157*60b67249SAndroid Build Coastguard Worker static const size_t kFieldIndexConfigDescriptor = 7;
158*60b67249SAndroid Build Coastguard Worker static const size_t kFieldIndexAuthorityHash = 8;
159*60b67249SAndroid Build Coastguard Worker static const size_t kFieldIndexMode = 9;
160*60b67249SAndroid Build Coastguard Worker static const size_t kFieldIndexSignature = 10;
161*60b67249SAndroid Build Coastguard Worker static const size_t kFieldIndexTbs = 11;
162*60b67249SAndroid Build Coastguard Worker 
163*60b67249SAndroid Build Coastguard Worker // |buffer| must point to the beginning of the template buffer and |src| must
164*60b67249SAndroid Build Coastguard Worker // point to at least <field-length> bytes.
CopyField(const uint8_t * src,size_t index,uint8_t * buffer)165*60b67249SAndroid Build Coastguard Worker static void CopyField(const uint8_t* src, size_t index, uint8_t* buffer) {
166*60b67249SAndroid Build Coastguard Worker   memcpy(&buffer[kFieldTable[index].offset], src, kFieldTable[index].length);
167*60b67249SAndroid Build Coastguard Worker }
168*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)169*60b67249SAndroid Build Coastguard Worker DiceResult DiceGenerateCertificate(
170*60b67249SAndroid Build Coastguard Worker     void* context,
171*60b67249SAndroid Build Coastguard Worker     const uint8_t subject_private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE],
172*60b67249SAndroid Build Coastguard Worker     const uint8_t authority_private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE],
173*60b67249SAndroid Build Coastguard Worker     const DiceInputValues* input_values, size_t certificate_buffer_size,
174*60b67249SAndroid Build Coastguard Worker     uint8_t* certificate, size_t* certificate_actual_size) {
175*60b67249SAndroid Build Coastguard Worker   DiceResult result = kDiceResultOk;
176*60b67249SAndroid Build Coastguard Worker 
177*60b67249SAndroid Build Coastguard Worker   DiceKeyParam key_param;
178*60b67249SAndroid Build Coastguard Worker   result = DiceGetKeyParam(context, kDicePrincipalSubject, &key_param);
179*60b67249SAndroid Build Coastguard Worker   if (result != kDiceResultOk) {
180*60b67249SAndroid Build Coastguard Worker     goto out;
181*60b67249SAndroid Build Coastguard Worker   }
182*60b67249SAndroid Build Coastguard Worker 
183*60b67249SAndroid Build Coastguard Worker   // Variable length descriptors are not supported.
184*60b67249SAndroid Build Coastguard Worker   if (input_values->code_descriptor_size > 0 ||
185*60b67249SAndroid Build Coastguard Worker       input_values->config_type != kDiceConfigTypeInline ||
186*60b67249SAndroid Build Coastguard Worker       input_values->authority_descriptor_size > 0 || key_param.profile_name) {
187*60b67249SAndroid Build Coastguard Worker     return kDiceResultInvalidInput;
188*60b67249SAndroid Build Coastguard Worker   }
189*60b67249SAndroid Build Coastguard Worker 
190*60b67249SAndroid Build Coastguard Worker   // We know the certificate size upfront so we can do the buffer size check.
191*60b67249SAndroid Build Coastguard Worker   *certificate_actual_size = sizeof(kTemplate);
192*60b67249SAndroid Build Coastguard Worker   if (certificate_buffer_size < sizeof(kTemplate)) {
193*60b67249SAndroid Build Coastguard Worker     return kDiceResultBufferTooSmall;
194*60b67249SAndroid Build Coastguard Worker   }
195*60b67249SAndroid Build Coastguard Worker 
196*60b67249SAndroid Build Coastguard Worker   // Declare buffers which are cleared on 'goto out'.
197*60b67249SAndroid Build Coastguard Worker   uint8_t subject_bssl_private_key[64];
198*60b67249SAndroid Build Coastguard Worker   uint8_t authority_bssl_private_key[64];
199*60b67249SAndroid Build Coastguard Worker 
200*60b67249SAndroid Build Coastguard Worker   // Derive keys and IDs from the private key seeds.
201*60b67249SAndroid Build Coastguard Worker   uint8_t subject_public_key[32];
202*60b67249SAndroid Build Coastguard Worker   ED25519_keypair_from_seed(subject_public_key, subject_bssl_private_key,
203*60b67249SAndroid Build Coastguard Worker                             subject_private_key_seed);
204*60b67249SAndroid Build Coastguard Worker 
205*60b67249SAndroid Build Coastguard Worker   uint8_t subject_id[DICE_ID_SIZE];
206*60b67249SAndroid Build Coastguard Worker   result =
207*60b67249SAndroid Build Coastguard Worker       DiceDeriveCdiCertificateId(context, subject_public_key, 32, subject_id);
208*60b67249SAndroid Build Coastguard Worker   if (result != kDiceResultOk) {
209*60b67249SAndroid Build Coastguard Worker     goto out;
210*60b67249SAndroid Build Coastguard Worker   }
211*60b67249SAndroid Build Coastguard Worker   uint8_t subject_id_hex[40];
212*60b67249SAndroid Build Coastguard Worker   DiceHexEncode(subject_id, sizeof(subject_id), subject_id_hex,
213*60b67249SAndroid Build Coastguard Worker                 sizeof(subject_id_hex));
214*60b67249SAndroid Build Coastguard Worker 
215*60b67249SAndroid Build Coastguard Worker   uint8_t authority_public_key[32];
216*60b67249SAndroid Build Coastguard Worker   ED25519_keypair_from_seed(authority_public_key, authority_bssl_private_key,
217*60b67249SAndroid Build Coastguard Worker                             authority_private_key_seed);
218*60b67249SAndroid Build Coastguard Worker 
219*60b67249SAndroid Build Coastguard Worker   uint8_t authority_id[DICE_ID_SIZE];
220*60b67249SAndroid Build Coastguard Worker   result = DiceDeriveCdiCertificateId(context, authority_public_key, 32,
221*60b67249SAndroid Build Coastguard Worker                                       authority_id);
222*60b67249SAndroid Build Coastguard Worker   if (result != kDiceResultOk) {
223*60b67249SAndroid Build Coastguard Worker     goto out;
224*60b67249SAndroid Build Coastguard Worker   }
225*60b67249SAndroid Build Coastguard Worker   uint8_t authority_id_hex[40];
226*60b67249SAndroid Build Coastguard Worker   DiceHexEncode(authority_id, sizeof(authority_id), authority_id_hex,
227*60b67249SAndroid Build Coastguard Worker                 sizeof(authority_id_hex));
228*60b67249SAndroid Build Coastguard Worker 
229*60b67249SAndroid Build Coastguard Worker   // First copy in the entire template, then fill in the fields.
230*60b67249SAndroid Build Coastguard Worker   memcpy(certificate, kTemplate, sizeof(kTemplate));
231*60b67249SAndroid Build Coastguard Worker   CopyField(subject_id, kFieldIndexSerial, certificate);
232*60b67249SAndroid Build Coastguard Worker   CopyField(authority_id_hex, kFieldIndexIssuerName, certificate);
233*60b67249SAndroid Build Coastguard Worker   CopyField(subject_id_hex, kFieldIndexSubjectName, certificate);
234*60b67249SAndroid Build Coastguard Worker   CopyField(subject_public_key, kFieldIndexSubjectPublicKey, certificate);
235*60b67249SAndroid Build Coastguard Worker   CopyField(authority_id, kFieldIndexAuthorityKeyId, certificate);
236*60b67249SAndroid Build Coastguard Worker   CopyField(subject_id, kFieldIndexSubjectKeyId, certificate);
237*60b67249SAndroid Build Coastguard Worker   CopyField(input_values->code_hash, kFieldIndexCodeHash, certificate);
238*60b67249SAndroid Build Coastguard Worker   CopyField(input_values->config_value, kFieldIndexConfigDescriptor,
239*60b67249SAndroid Build Coastguard Worker             certificate);
240*60b67249SAndroid Build Coastguard Worker   CopyField(input_values->authority_hash, kFieldIndexAuthorityHash,
241*60b67249SAndroid Build Coastguard Worker             certificate);
242*60b67249SAndroid Build Coastguard Worker   certificate[kFieldTable[kFieldIndexMode].offset] = input_values->mode;
243*60b67249SAndroid Build Coastguard Worker 
244*60b67249SAndroid Build Coastguard Worker   // All the TBS fields are filled in, we're ready to sign.
245*60b67249SAndroid Build Coastguard Worker   uint8_t signature[64];
246*60b67249SAndroid Build Coastguard Worker   if (1 != ED25519_sign(signature,
247*60b67249SAndroid Build Coastguard Worker                         &certificate[kFieldTable[kFieldIndexTbs].offset],
248*60b67249SAndroid Build Coastguard Worker                         kFieldTable[kFieldIndexTbs].length,
249*60b67249SAndroid Build Coastguard Worker                         authority_bssl_private_key)) {
250*60b67249SAndroid Build Coastguard Worker     result = kDiceResultPlatformError;
251*60b67249SAndroid Build Coastguard Worker     goto out;
252*60b67249SAndroid Build Coastguard Worker   }
253*60b67249SAndroid Build Coastguard Worker   if (1 != ED25519_verify(&certificate[kFieldTable[kFieldIndexTbs].offset],
254*60b67249SAndroid Build Coastguard Worker                           kFieldTable[kFieldIndexTbs].length, signature,
255*60b67249SAndroid Build Coastguard Worker                           authority_public_key)) {
256*60b67249SAndroid Build Coastguard Worker     result = kDiceResultPlatformError;
257*60b67249SAndroid Build Coastguard Worker     goto out;
258*60b67249SAndroid Build Coastguard Worker   }
259*60b67249SAndroid Build Coastguard Worker   CopyField(signature, kFieldIndexSignature, certificate);
260*60b67249SAndroid Build Coastguard Worker 
261*60b67249SAndroid Build Coastguard Worker out:
262*60b67249SAndroid Build Coastguard Worker   DiceClearMemory(context, sizeof(subject_bssl_private_key),
263*60b67249SAndroid Build Coastguard Worker                   subject_bssl_private_key);
264*60b67249SAndroid Build Coastguard Worker   DiceClearMemory(context, sizeof(authority_bssl_private_key),
265*60b67249SAndroid Build Coastguard Worker                   authority_bssl_private_key);
266*60b67249SAndroid Build Coastguard Worker   return result;
267*60b67249SAndroid Build Coastguard Worker }
268