blob: 730d17d9c87d497e37322797dd10dbee7f2d0415 [file] [log] [blame]
Daisuke Nojiriedc3c8e2016-05-03 16:23:53 -07001/* Copyright 2015 The Chromium OS Authors. All rights reserved.
Daisuke Nojirief4ae892016-05-03 09:29:16 -07002 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 *
5 * Host functions for signing
6 */
7
Daisuke Nojirief4ae892016-05-03 09:29:16 -07008#include <unistd.h>
9
Daisuke Nojiri9928e2f2016-09-19 16:46:37 -070010#include "2sysincludes.h"
11#include "2common.h"
Daisuke Nojiriedc3c8e2016-05-03 16:23:53 -070012#include "2sha.h"
Daisuke Nojirief4ae892016-05-03 09:29:16 -070013#include "bdb.h"
14#include "host.h"
15
16char *strzcpy(char *dest, const char *src, size_t size)
17{
18 strncpy(dest, src, size);
19 dest[size - 1] = 0;
20 return dest;
21}
22
23uint8_t *read_file(const char *filename, uint32_t *size_ptr)
24{
25 FILE *f;
26 uint8_t *buf;
27 long size;
28
29 *size_ptr = 0;
30
31 f = fopen(filename, "rb");
32 if (!f) {
33 fprintf(stderr, "Unable to open file %s\n", filename);
34 return NULL;
35 }
36
37 fseek(f, 0, SEEK_END);
38 size = ftell(f);
39 rewind(f);
40
41 if (size < 0 || size > UINT32_MAX) {
42 fclose(f);
43 return NULL;
44 }
45
46 buf = malloc(size);
47 if (!buf) {
48 fclose(f);
49 return NULL;
50 }
51
52 if (1 != fread(buf, size, 1, f)) {
53 fprintf(stderr, "Unable to read file %s\n", filename);
54 fclose(f);
55 free(buf);
56 return NULL;
57 }
58
59 fclose(f);
60
61 *size_ptr = size;
62 return buf;
63}
64
65int write_file(const char *filename, const void *buf, uint32_t size)
66{
67 FILE *f = fopen(filename, "wb");
68
69 if (!f) {
70 fprintf(stderr, "Unable to open file %s\n", filename);
71 return 1;
72 }
73
74 if (1 != fwrite(buf, size, 1, f)) {
75 fprintf(stderr, "Unable to write to file %s\n", filename);
76 fclose(f);
77 unlink(filename); /* Delete any partial file */
78 return 1;
79 }
80
81 fclose(f);
82 return 0;
83}
84
85struct rsa_st *read_pem(const char *filename)
86{
87 struct rsa_st *pem;
88 FILE *f;
89
90 /* Read private key */
91 f = fopen(filename, "rb");
92 if (!f) {
93 fprintf(stderr, "%s: unable to read key from %s\n",
94 __func__, filename);
95 return NULL;
96 }
97
98 pem = PEM_read_RSAPrivateKey(f, NULL, NULL, NULL);
99 fclose(f);
100
101 return pem;
102}
103
104struct bdb_key *bdb_create_key(const char *filename,
105 uint32_t key_version,
106 const char *desc)
107{
108 uint32_t sig_alg;
109 size_t key_size = sizeof(struct bdb_key);
110 struct bdb_key *k;
111 uint8_t *kdata;
112 uint32_t kdata_size = 0;
113
114 /*
115 * Read key data. Somewhat lame assumption that we can determine the
116 * signature algorithm from the key size, but it's true right now.
117 */
118 kdata = read_file(filename, &kdata_size);
119 if (kdata_size == BDB_RSA4096_KEY_DATA_SIZE) {
120 sig_alg = BDB_SIG_ALG_RSA4096;
121 } else if (kdata_size == BDB_RSA3072B_KEY_DATA_SIZE) {
122 sig_alg = BDB_SIG_ALG_RSA3072B;
123 } else {
124 fprintf(stderr, "%s: bad key size from %s\n",
125 __func__, filename);
Randall Spangler1589f942016-09-02 12:10:31 -0700126 free(kdata);
Daisuke Nojirief4ae892016-05-03 09:29:16 -0700127 return NULL;
128 }
129 key_size += kdata_size;
130
131 /* Allocate buffer */
132 k = (struct bdb_key *)calloc(key_size, 1);
133 if (!k) {
134 free(kdata);
135 return NULL;
136 }
137
138 k->struct_magic = BDB_KEY_MAGIC;
139 k->struct_major_version = BDB_KEY_VERSION_MAJOR;
140 k->struct_minor_version = BDB_KEY_VERSION_MINOR;
141 k->struct_size = key_size;
142 k->hash_alg = BDB_HASH_ALG_SHA256;
143 k->sig_alg = sig_alg;
144 k->key_version = key_version;
145
146 /* Copy description, if any */
147 if (desc)
148 strzcpy(k->description, desc, sizeof(k->description));
149
150 /* Copy key data */
151 memcpy(k->key_data, kdata, kdata_size);
152 free(kdata);
153
154 return k;
155}
156
157struct bdb_sig *bdb_create_sig(const void *data,
158 size_t size,
159 struct rsa_st *key,
160 uint32_t sig_alg,
161 const char *desc)
162{
163 static const uint8_t info[] = {
164 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
165 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
166 0x00, 0x04, 0x20
167 };
168
169 size_t sig_size = sizeof(struct bdb_sig);
170 uint8_t digest[sizeof(info) + BDB_SHA256_DIGEST_SIZE];
171 struct bdb_sig *sig;
172
173 if (size >= UINT32_MAX)
174 return NULL;
175
176 switch(sig_alg) {
177 case BDB_SIG_ALG_RSA4096:
178 sig_size += BDB_RSA4096_SIG_SIZE;
179 break;
180 case BDB_SIG_ALG_RSA3072B:
181 sig_size += BDB_RSA3072B_SIG_SIZE;
182 break;
183 default:
184 fprintf(stderr, "%s: bad signature algorithm %d\n",
185 __func__, sig_alg);
186 return NULL;
187 }
188
189 /* Allocate buffer */
190 sig = (struct bdb_sig *)calloc(sig_size, 1);
191 if (!sig)
192 return NULL;
193
194 sig->struct_magic = BDB_SIG_MAGIC;
195 sig->struct_major_version = BDB_SIG_VERSION_MAJOR;
196 sig->struct_minor_version = BDB_SIG_VERSION_MINOR;
197 sig->struct_size = sig_size;
198 sig->hash_alg = BDB_HASH_ALG_SHA256;
199 sig->sig_alg = sig_alg;
200 sig->signed_size = size;
201
202 /* Copy description, if any */
203 if (desc)
204 strzcpy(sig->description, desc, sizeof(sig->description));
205
206 /* Calculate info-padded digest */
207 memcpy(digest, info, sizeof(info));
Daisuke Nojiriedc3c8e2016-05-03 16:23:53 -0700208 if (vb2_digest_buffer((uint8_t *)data, size,
209 VB2_HASH_SHA256,
210 digest + sizeof(info), BDB_SHA256_DIGEST_SIZE)) {
Daisuke Nojirief4ae892016-05-03 09:29:16 -0700211 free(sig);
212 return NULL;
213 }
214
215 /* RSA-encrypt the signature */
216 if (RSA_private_encrypt(sizeof(digest),
217 digest,
218 sig->sig_data,
219 key,
220 RSA_PKCS1_PADDING) == -1) {
221 free(sig);
222 return NULL;
223 }
224 return sig;
225}
226
Daisuke Nojiri9928e2f2016-09-19 16:46:37 -0700227int bdb_sign_datakey(uint8_t **bdb, struct rsa_st *key)
228{
229 const struct bdb_header *header = bdb_get_header(*bdb);
230 const struct bdb_key *bdbkey = bdb_get_bdbkey(*bdb);
231 const void *oem = bdb_get_oem_area_0(*bdb);
232 const struct bdb_sig *sig = bdb_get_header_sig(*bdb);
233 struct bdb_sig *new_sig;
234 uint8_t *new_bdb, *src, *dst;
235 size_t len;
236
237 new_sig = bdb_create_sig(oem, header->signed_size,
238 key, bdbkey->sig_alg, NULL);
239 new_bdb = calloc(1, header->bdb_size
240 + (new_sig->struct_size - sig->struct_size));
241 if (!new_bdb)
242 return BDB_ERROR_UNKNOWN;
243
244 /* copy up to sig */
245 src = *bdb;
246 dst = new_bdb;
247 len = bdb_offset_of_header_sig(*bdb);
248 memcpy(dst, src, len);
249
250 /* copy new sig */
251 src += len;
252 dst += len;
253 memcpy(dst, new_sig, new_sig->struct_size);
254
255 /* copy the rest */
256 src += sig->struct_size;
257 dst += new_sig->struct_size;
258 len = bdb_size_of(*bdb) - vb2_offset_of(*bdb, src);
259 memcpy(dst, src, len);
260
261 free(*bdb);
262 free(new_sig);
263 *bdb = new_bdb;
264
265 return BDB_SUCCESS;
266}
267
268int bdb_sign_data(uint8_t **bdb, struct rsa_st *key)
269{
270 const struct bdb_key *datakey = bdb_get_datakey(*bdb);
271 const struct bdb_data *data = bdb_get_data(*bdb);
272 const uint64_t sig_offset = vb2_offset_of(*bdb, bdb_get_data_sig(*bdb));
273 struct bdb_sig *new_sig;
274 uint8_t *new_bdb;
275
276 new_sig = bdb_create_sig(data, data->signed_size,
277 key, datakey->sig_alg, NULL);
278 new_bdb = calloc(1, sig_offset + new_sig->struct_size);
279 if (!new_bdb)
280 return BDB_ERROR_UNKNOWN;
281
282 /* copy all data up to the data sig */
283 memcpy(new_bdb, *bdb, sig_offset);
284
285 /* copy the new signature */
286 memcpy(new_bdb + sig_offset, new_sig, new_sig->struct_size);
287
288 free(*bdb);
289 free(new_sig);
290 *bdb = new_bdb;
291
292 return BDB_SUCCESS;
293}
294
Daisuke Nojirief4ae892016-05-03 09:29:16 -0700295struct bdb_header *bdb_create(struct bdb_create_params *p)
296{
297 size_t bdb_size = 0;
298 size_t sig_size = sizeof(struct bdb_sig) + BDB_RSA4096_SIG_SIZE;
299 size_t hashes_size = sizeof(struct bdb_hash) * p->num_hashes;
300 uint8_t *buf, *bnext;
301 struct bdb_header *h;
302 struct bdb_sig *sig;
303 struct bdb_data *data;
304 const void *oem;
305
306 /* We can do some checks before we even allocate the buffer */
307
308 /* Make sure OEM sizes are aligned */
309 if ((p->oem_area_0_size & 3) || (p->oem_area_1_size & 3)) {
310 fprintf(stderr, "%s: OEM areas not 32-bit aligned\n",
311 __func__);
312 return NULL;
313 }
314
315 /* Hash count must fit in uint8_t */
316 if (p->num_hashes > 255) {
317 fprintf(stderr, "%s: too many hashes\n", __func__);
318 return NULL;
319 }
320
321 /* Calculate BDB size */
322 bdb_size = sizeof(struct bdb_header);
323 bdb_size += p->bdbkey->struct_size;
324 bdb_size += p->oem_area_0_size;
Daisuke Nojiri8fc59162016-05-03 16:46:55 -0700325 bdb_size += p->datakey->struct_size;
Daisuke Nojirief4ae892016-05-03 09:29:16 -0700326 bdb_size += sig_size;
327 bdb_size += sizeof(struct bdb_data);
328 bdb_size += p->oem_area_1_size;
329 bdb_size += sizeof(struct bdb_hash) * p->num_hashes;
330 bdb_size += sig_size;
331
332 /* Make sure it fits */
333 if (bdb_size > UINT32_MAX) {
334 fprintf(stderr, "%s: BDB size > UINT32_MAX\n", __func__);
335 return NULL;
336 }
337
338 /* Allocate a buffer */
339 bnext = buf = calloc(bdb_size, 1);
340 if (!buf) {
341 fprintf(stderr, "%s: can't allocate buffer\n", __func__);
342 return NULL;
343 }
344
345 /* Fill in the header */
346 h = (struct bdb_header *)bnext;
347 h->struct_magic = BDB_HEADER_MAGIC;
348 h->struct_major_version = BDB_HEADER_VERSION_MAJOR;
349 h->struct_minor_version = BDB_HEADER_VERSION_MINOR;
350 h->struct_size = sizeof(*h);
351 h->bdb_load_address = p->bdb_load_address;
352 h->bdb_size = bdb_size;
Daisuke Nojiri8fc59162016-05-03 16:46:55 -0700353 h->signed_size = p->oem_area_0_size + p->datakey->struct_size;
Daisuke Nojirief4ae892016-05-03 09:29:16 -0700354 h->oem_area_0_size = p->oem_area_0_size;
355 bnext += h->struct_size;
356
357 /* Copy BDB key */
358 memcpy(bnext, p->bdbkey, p->bdbkey->struct_size);
359 bnext += p->bdbkey->struct_size;
360
361 /* Copy OEM area 0 */
362 oem = bnext;
363 if (p->oem_area_0_size) {
364 memcpy(bnext, p->oem_area_0, p->oem_area_0_size);
365 bnext += p->oem_area_0_size;
366 }
367
Daisuke Nojiri8fc59162016-05-03 16:46:55 -0700368 /* Copy datakey */
369 memcpy(bnext, p->datakey, p->datakey->struct_size);
370 bnext += p->datakey->struct_size;
Daisuke Nojirief4ae892016-05-03 09:29:16 -0700371
372 /*
373 * Create header signature using private BDB key.
374 *
375 * TODO: create the header signature in a totally separate step. That
376 * way, the private BDB key is not required each time a BDB is created.
377 */
378 sig = bdb_create_sig(oem, h->signed_size, p->private_bdbkey,
379 p->bdbkey->sig_alg, p->header_sig_description);
380 memcpy(bnext, sig, sig->struct_size);
381 bnext += sig->struct_size;
382
383 /* Fill in the data */
384 data = (struct bdb_data *)bnext;
385 data->struct_magic = BDB_DATA_MAGIC;
386 data->struct_major_version = BDB_DATA_VERSION_MAJOR;
387 data->struct_minor_version = BDB_DATA_VERSION_MINOR;
388 data->struct_size = sizeof(struct bdb_data);
389 data->data_version = p->data_version;
390 data->oem_area_1_size = p->oem_area_1_size;
391 data->num_hashes = p->num_hashes;
392 data->hash_entry_size = sizeof(struct bdb_hash);
393 data->signed_size = data->struct_size + data->oem_area_1_size +
394 hashes_size;
395 if (p->data_description) {
396 strzcpy(data->description, p->data_description,
397 sizeof(data->description));
398 }
399 bnext += data->struct_size;
400
401 /* Copy OEM area 1 */
402 oem = bnext;
403 if (p->oem_area_1_size) {
404 memcpy(bnext, p->oem_area_1, p->oem_area_1_size);
405 bnext += p->oem_area_1_size;
406 }
407
408 /* Copy hashes */
409 memcpy(bnext, p->hash, hashes_size);
410 bnext += hashes_size;
411
Daisuke Nojiri8fc59162016-05-03 16:46:55 -0700412 /* Create data signature using private datakey */
413 sig = bdb_create_sig(data, data->signed_size, p->private_datakey,
414 p->datakey->sig_alg, p->data_sig_description);
Daisuke Nojirief4ae892016-05-03 09:29:16 -0700415 memcpy(bnext, sig, sig->struct_size);
416
417 /* Return the BDB */
418 return h;
419}