xref: /aosp_15_r20/external/open-dice/src/template_cert_op.c (revision 60b67249c2e226f42f35cc6cfe66c6048e0bae6b)
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