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