• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   // Variable length descriptors are not supported.
178   if (input_values->code_descriptor_size > 0 ||
179       input_values->config_type != kDiceConfigTypeInline ||
180       input_values->authority_descriptor_size > 0 || DICE_PROFILE_NAME) {
181     return kDiceResultInvalidInput;
182   }
183 
184   // We know the certificate size upfront so we can do the buffer size check.
185   *certificate_actual_size = sizeof(kTemplate);
186   if (certificate_buffer_size < sizeof(kTemplate)) {
187     return kDiceResultBufferTooSmall;
188   }
189 
190   // Declare buffers which are cleared on 'goto out'.
191   uint8_t subject_bssl_private_key[64];
192   uint8_t authority_bssl_private_key[64];
193 
194   // Derive keys and IDs from the private key seeds.
195   uint8_t subject_public_key[32];
196   ED25519_keypair_from_seed(subject_public_key, subject_bssl_private_key,
197                             subject_private_key_seed);
198 
199   uint8_t subject_id[DICE_ID_SIZE];
200   result =
201       DiceDeriveCdiCertificateId(context, subject_public_key, 32, subject_id);
202   if (result != kDiceResultOk) {
203     goto out;
204   }
205   uint8_t subject_id_hex[40];
206   DiceHexEncode(subject_id, sizeof(subject_id), subject_id_hex,
207                 sizeof(subject_id_hex));
208 
209   uint8_t authority_public_key[32];
210   ED25519_keypair_from_seed(authority_public_key, authority_bssl_private_key,
211                             authority_private_key_seed);
212 
213   uint8_t authority_id[DICE_ID_SIZE];
214   result = DiceDeriveCdiCertificateId(context, authority_public_key, 32,
215                                       authority_id);
216   if (result != kDiceResultOk) {
217     goto out;
218   }
219   uint8_t authority_id_hex[40];
220   DiceHexEncode(authority_id, sizeof(authority_id), authority_id_hex,
221                 sizeof(authority_id_hex));
222 
223   // First copy in the entire template, then fill in the fields.
224   memcpy(certificate, kTemplate, sizeof(kTemplate));
225   CopyField(subject_id, kFieldIndexSerial, certificate);
226   CopyField(authority_id_hex, kFieldIndexIssuerName, certificate);
227   CopyField(subject_id_hex, kFieldIndexSubjectName, certificate);
228   CopyField(subject_public_key, kFieldIndexSubjectPublicKey, certificate);
229   CopyField(authority_id, kFieldIndexAuthorityKeyId, certificate);
230   CopyField(subject_id, kFieldIndexSubjectKeyId, certificate);
231   CopyField(input_values->code_hash, kFieldIndexCodeHash, certificate);
232   CopyField(input_values->config_value, kFieldIndexConfigDescriptor,
233             certificate);
234   CopyField(input_values->authority_hash, kFieldIndexAuthorityHash,
235             certificate);
236   certificate[kFieldTable[kFieldIndexMode].offset] = input_values->mode;
237 
238   // All the TBS fields are filled in, we're ready to sign.
239   uint8_t signature[64];
240   if (1 != ED25519_sign(signature,
241                         &certificate[kFieldTable[kFieldIndexTbs].offset],
242                         kFieldTable[kFieldIndexTbs].length,
243                         authority_bssl_private_key)) {
244     result = kDiceResultPlatformError;
245     goto out;
246   }
247   if (1 != ED25519_verify(&certificate[kFieldTable[kFieldIndexTbs].offset],
248                           kFieldTable[kFieldIndexTbs].length, signature,
249                           authority_public_key)) {
250     result = kDiceResultPlatformError;
251     goto out;
252   }
253   CopyField(signature, kFieldIndexSignature, certificate);
254 
255 out:
256   DiceClearMemory(context, sizeof(subject_bssl_private_key),
257                   subject_bssl_private_key);
258   DiceClearMemory(context, sizeof(authority_bssl_private_key),
259                   authority_bssl_private_key);
260   return result;
261 }
262