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/profile_name.h"
39 #include "dice/utils.h"
40 #include "openssl/curve25519.h"
41 #include "openssl/is_boringssl.h"
42
43 // A well-formed certificate, but with zeros in all fields to be filled.
44 static const uint8_t kTemplate[638] = {
45 // Constant encoding.
46 0x30, 0x82, 0x02, 0x7a,
47 // Offset 4: TBS starts here.
48 // Constant encoding.
49 0x30, 0x82, 0x02, 0x2c, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x14,
50 // Offset 15: Serial number, 20 bytes.
51 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
52 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
53 // Constant encoding.
54 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x30, 0x33, 0x31, 0x31, 0x30,
55 0x2f, 0x06, 0x03, 0x55, 0x04, 0x05, 0x13, 0x28,
56 // Offset 55: Issuer name, 40 bytes.
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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60 0x00, 0x00, 0x00, 0x00,
61 // Constant encoding.
62 0x30, 0x20, 0x17, 0x0d, 0x31, 0x38, 0x30, 0x33, 0x32, 0x32, 0x32, 0x33,
63 0x35, 0x39, 0x35, 0x39, 0x5a, 0x18, 0x0f, 0x39, 0x39, 0x39, 0x39, 0x31,
64 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x33,
65 0x31, 0x31, 0x30, 0x2f, 0x06, 0x03, 0x55, 0x04, 0x05, 0x13, 0x28,
66 // Offset 142: Subject name, 40 bytes.
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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70 0x00, 0x00, 0x00, 0x00,
71 // Constant encoding.
72 0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21, 0x00,
73 // Offset 194: Subject public key, 32 bytes.
74 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77 // Constant encoding.
78 0xa3, 0x82, 0x01, 0x4e, 0x30, 0x82, 0x01, 0x4a, 0x30, 0x1f, 0x06, 0x03,
79 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14,
80 // Offset 247: Authority key identifier, 20 bytes.
81 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
82 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83 // Constant encoding.
84 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14,
85 // Offset 278: Subject key identifier, 20 bytes.
86 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88 // Constant encoding.
89 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04,
90 0x03, 0x02, 0x02, 0x04, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
91 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x81, 0xe6,
92 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, 0x01, 0x18,
93 0x01, 0x01, 0xff, 0x04, 0x81, 0xd4, 0x30, 0x81, 0xd1, 0xa0, 0x42, 0x04,
94 0x40,
95 // Offset 356: Code hash, 64 bytes.
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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
101 0x00, 0x00, 0x00, 0x00,
102 // Constant encoding.
103 0xa3, 0x42, 0x04, 0x40,
104 // Offset 424: Configuration value, 64 bytes.
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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
110 0x00, 0x00, 0x00, 0x00,
111 // Constant encoding.
112 0xa4, 0x42, 0x04, 0x40,
113 // Offset 492: Authority hash, 64 bytes.
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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
119 0x00, 0x00, 0x00, 0x00,
120 // Constant encoding.
121 0xa6, 0x03, 0x0a, 0x01,
122 // Offset 560: Mode, 1 byte.
123 0x00,
124 // Offset 561: TBS ends here.
125 // Constant encoding.
126 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x41, 0x00,
127 // Offset 571: Signature, 64 bytes.
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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
133 0x00, 0x00, 0x00, 0x00};
134
135 static const struct {
136 size_t offset;
137 size_t length;
138 } kFieldTable[] = {{15, 20}, // Serial number
139 {55, 40}, // Issuer name
140 {142, 40}, // Subject name
141 {194, 32}, // Subject public key
142 {247, 20}, // Authority key id
143 {278, 20}, // Subject key id
144 {359, 64}, // Code hash
145 {427, 64}, // Config descriptor
146 {495, 64}, // Authority hash
147 {563, 1}, // Mode
148 {574, 64}, // Signature
149 {4, 560}}; // Entire TBS
150
151 static const size_t kFieldIndexSerial = 0;
152 static const size_t kFieldIndexIssuerName = 1;
153 static const size_t kFieldIndexSubjectName = 2;
154 static const size_t kFieldIndexSubjectPublicKey = 3;
155 static const size_t kFieldIndexAuthorityKeyId = 4;
156 static const size_t kFieldIndexSubjectKeyId = 5;
157 static const size_t kFieldIndexCodeHash = 6;
158 static const size_t kFieldIndexConfigDescriptor = 7;
159 static const size_t kFieldIndexAuthorityHash = 8;
160 static const size_t kFieldIndexMode = 9;
161 static const size_t kFieldIndexSignature = 10;
162 static const size_t kFieldIndexTbs = 11;
163
164 // |buffer| must point to the beginning of the template buffer and |src| must
165 // point to at least <field-length> bytes.
CopyField(const uint8_t * src,size_t index,uint8_t * buffer)166 static void CopyField(const uint8_t* src, size_t index, uint8_t* buffer) {
167 memcpy(&buffer[kFieldTable[index].offset], src, kFieldTable[index].length);
168 }
169
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)170 DiceResult DiceGenerateCertificate(
171 void* context,
172 const uint8_t subject_private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE],
173 const uint8_t authority_private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE],
174 const DiceInputValues* input_values, size_t certificate_buffer_size,
175 uint8_t* certificate, size_t* certificate_actual_size) {
176 DiceResult result = kDiceResultOk;
177
178 DiceKeyParam key_param;
179 result = DiceGetKeyParam(context, kDicePrincipalSubject, &key_param);
180 if (result != kDiceResultOk) {
181 goto out;
182 }
183
184 // Variable length descriptors are not supported.
185 if (input_values->code_descriptor_size > 0 ||
186 input_values->config_type != kDiceConfigTypeInline ||
187 input_values->authority_descriptor_size > 0 || DICE_PROFILE_NAME) {
188 return kDiceResultInvalidInput;
189 }
190
191 // We know the certificate size upfront so we can do the buffer size check.
192 *certificate_actual_size = sizeof(kTemplate);
193 if (certificate_buffer_size < sizeof(kTemplate)) {
194 return kDiceResultBufferTooSmall;
195 }
196
197 // Declare buffers which are cleared on 'goto out'.
198 uint8_t subject_bssl_private_key[64];
199 uint8_t authority_bssl_private_key[64];
200
201 // Derive keys and IDs from the private key seeds.
202 uint8_t subject_public_key[32];
203 ED25519_keypair_from_seed(subject_public_key, subject_bssl_private_key,
204 subject_private_key_seed);
205
206 uint8_t subject_id[DICE_ID_SIZE];
207 result =
208 DiceDeriveCdiCertificateId(context, subject_public_key, 32, subject_id);
209 if (result != kDiceResultOk) {
210 goto out;
211 }
212 uint8_t subject_id_hex[40];
213 DiceHexEncode(subject_id, sizeof(subject_id), subject_id_hex,
214 sizeof(subject_id_hex));
215
216 uint8_t authority_public_key[32];
217 ED25519_keypair_from_seed(authority_public_key, authority_bssl_private_key,
218 authority_private_key_seed);
219
220 uint8_t authority_id[DICE_ID_SIZE];
221 result = DiceDeriveCdiCertificateId(context, authority_public_key, 32,
222 authority_id);
223 if (result != kDiceResultOk) {
224 goto out;
225 }
226 uint8_t authority_id_hex[40];
227 DiceHexEncode(authority_id, sizeof(authority_id), authority_id_hex,
228 sizeof(authority_id_hex));
229
230 // First copy in the entire template, then fill in the fields.
231 memcpy(certificate, kTemplate, sizeof(kTemplate));
232 CopyField(subject_id, kFieldIndexSerial, certificate);
233 CopyField(authority_id_hex, kFieldIndexIssuerName, certificate);
234 CopyField(subject_id_hex, kFieldIndexSubjectName, certificate);
235 CopyField(subject_public_key, kFieldIndexSubjectPublicKey, certificate);
236 CopyField(authority_id, kFieldIndexAuthorityKeyId, certificate);
237 CopyField(subject_id, kFieldIndexSubjectKeyId, certificate);
238 CopyField(input_values->code_hash, kFieldIndexCodeHash, certificate);
239 CopyField(input_values->config_value, kFieldIndexConfigDescriptor,
240 certificate);
241 CopyField(input_values->authority_hash, kFieldIndexAuthorityHash,
242 certificate);
243 certificate[kFieldTable[kFieldIndexMode].offset] = input_values->mode;
244
245 // All the TBS fields are filled in, we're ready to sign.
246 uint8_t signature[64];
247 if (1 != ED25519_sign(signature,
248 &certificate[kFieldTable[kFieldIndexTbs].offset],
249 kFieldTable[kFieldIndexTbs].length,
250 authority_bssl_private_key)) {
251 result = kDiceResultPlatformError;
252 goto out;
253 }
254 if (1 != ED25519_verify(&certificate[kFieldTable[kFieldIndexTbs].offset],
255 kFieldTable[kFieldIndexTbs].length, signature,
256 authority_public_key)) {
257 result = kDiceResultPlatformError;
258 goto out;
259 }
260 CopyField(signature, kFieldIndexSignature, certificate);
261
262 out:
263 DiceClearMemory(context, sizeof(subject_bssl_private_key),
264 subject_bssl_private_key);
265 DiceClearMemory(context, sizeof(authority_bssl_private_key),
266 authority_bssl_private_key);
267 return result;
268 }
269