1 /* Copyright 2015 The ChromiumOS Authors
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 *
5 * The USB Type-C chargers released with Samus ("Pixel (2015)") have upgradable
6 * firmware. Due to space considerations, we don't have room for handy things
7 * like an FMAP or headers for the signatures. Accordingly, all the normally
8 * variable factors (image size, signature algorithms, etc.) are hard coded
9 * and the image itself just looks like a bunch of random numbers.
10 *
11 * This file handles those images, but PLEASE don't use it as a template for
12 * new devices. Look at file_type_rwsig.c instead.
13 */
14
15 #include <stdint.h>
16 #include <stdio.h>
17 #include <unistd.h>
18
19 #include "2common.h"
20 #include "2rsa.h"
21 #include "2sha.h"
22 #include "2sysincludes.h"
23 #include "file_type.h"
24 #include "futility.h"
25 #include "futility_options.h"
26 #include "host_common.h"
27 #include "host_common21.h"
28 #include "host_key21.h"
29 #include "host_signature21.h"
30 #include "util_misc.h"
31
32 /* Return 1 if okay, 0 if not */
parse_size_opts(const uint32_t len,uint32_t * ro_size_ptr,uint32_t * rw_size_ptr,uint32_t * ro_offset_ptr,uint32_t * rw_offset_ptr)33 static int parse_size_opts(const uint32_t len,
34 uint32_t *ro_size_ptr, uint32_t *rw_size_ptr,
35 uint32_t *ro_offset_ptr, uint32_t * rw_offset_ptr)
36 {
37 /* Assume the image has both RO and RW, evenly split. */
38 uint32_t ro_offset = 0;
39 uint32_t ro_size = len / 2;
40 uint32_t rw_size = len / 2;
41 uint32_t rw_offset = len / 2;
42
43 /* Unless told otherwise... */
44 if (sign_option.ro_size != 0xffffffff)
45 ro_size = sign_option.ro_size;
46 if (sign_option.ro_offset != 0xffffffff)
47 ro_offset = sign_option.ro_offset;
48
49 /* If RO is missing, the whole thing must be RW */
50 if (!ro_size) {
51 rw_size = len;
52 rw_offset = 0;
53 }
54
55 /* Unless that's overridden too */
56 if (sign_option.rw_size != 0xffffffff)
57 rw_size = sign_option.rw_size;
58 if (sign_option.rw_offset != 0xffffffff)
59 rw_offset = sign_option.rw_offset;
60
61 VB2_DEBUG("ro_size 0x%08x\n", ro_size);
62 VB2_DEBUG("ro_offset 0x%08x\n", ro_offset);
63 VB2_DEBUG("rw_size 0x%08x\n", rw_size);
64 VB2_DEBUG("rw_offset 0x%08x\n", rw_offset);
65
66 /* Now let's do some validity checks. */
67 if (ro_size > len || ro_offset > len - ro_size ||
68 rw_size > len || rw_offset > len - rw_size) {
69 printf("size/offset values are bogus\n");
70 return 0;
71 }
72
73 *ro_size_ptr = ro_size;
74 *rw_size_ptr = rw_size;
75 *ro_offset_ptr = ro_offset;
76 *rw_offset_ptr = rw_offset;
77
78 return 1;
79 }
80
ft_sign_usbpd1(const char * fname)81 int ft_sign_usbpd1(const char *fname)
82 {
83 struct vb2_private_key *key_ptr = 0;
84 struct vb21_signature *sig_ptr = 0;
85 uint8_t *keyb_data = 0;
86 uint32_t keyb_size;
87 int retval = 1;
88 uint32_t sig_size;
89 uint32_t sig_offset;
90 uint32_t pub_size;
91 uint32_t pub_offset;
92 uint32_t ro_size;
93 uint32_t rw_size;
94 uint32_t ro_offset;
95 uint32_t rw_offset;
96 uint32_t r;
97 uint8_t *buf = NULL;
98 uint32_t len;
99 int fd = -1;
100
101 if (futil_open_and_map_file(fname, &fd, FILE_MODE_SIGN(sign_option),
102 &buf, &len))
103 return 1;
104
105 VB2_DEBUG("name %s len %#.8x (%d)\n", fname, len, len);
106
107 /* Get image locations */
108 if (!parse_size_opts(len, &ro_size, &rw_size, &ro_offset, &rw_offset))
109 goto done;
110
111 /* Read the signing keypair file */
112 if (vb2_private_key_read_pem(&key_ptr, sign_option.pem_signpriv)) {
113 ERROR("Unable to read keypair from %s\n",
114 sign_option.pem_signpriv);
115 goto done;
116 }
117
118 /* Set the algs */
119 key_ptr->hash_alg = sign_option.hash_alg;
120 key_ptr->sig_alg = vb2_rsa_sig_alg(key_ptr->rsa_private_key);
121 if (key_ptr->sig_alg == VB2_SIG_INVALID) {
122 ERROR("Unsupported sig algorithm in RSA key\n");
123 goto done;
124 }
125
126 /* Figure out what needs signing */
127 sig_size = vb2_rsa_sig_size(key_ptr->sig_alg);
128 if (rw_size < sig_size) {
129 ERROR("The RW image is too small to hold the signature"
130 " (0x%08x < %08x)\n",
131 rw_size, sig_size);
132 goto done;
133 }
134 rw_size -= sig_size;
135 sig_offset = rw_offset + rw_size;
136
137 VB2_DEBUG("rw_size => 0x%08x\n", rw_size);
138 VB2_DEBUG("rw_offset => 0x%08x\n", rw_offset);
139 VB2_DEBUG("sig_size 0x%08x\n", sig_size);
140 VB2_DEBUG("sig_offset 0x%08x\n", sig_offset);
141
142 /* Sign the blob */
143 r = vb21_sign_data(&sig_ptr, buf + rw_offset, rw_size, key_ptr, "Bah");
144 if (r) {
145 ERROR("Unable to sign data (error 0x%08x, if that helps)\n", r);
146 goto done;
147 }
148
149 /* Double-check the size */
150 if (sig_ptr->sig_size != sig_size) {
151 ERROR("The sig size is %d bytes, not %d as expected.\n",
152 sig_ptr->sig_size, sig_size);
153 goto done;
154 }
155
156 /* Okay, looking good. Update the signature. */
157 memcpy(buf + sig_offset, (uint8_t *)sig_ptr + sig_ptr->sig_offset,
158 sig_ptr->sig_size);
159
160 /* If there's no RO section, we're done. */
161 if (!ro_size) {
162 retval = 0;
163 goto done;
164 }
165
166 /* Otherwise, now update the public key */
167 if (vb_keyb_from_private_key(key_ptr, &keyb_data, &keyb_size)) {
168 ERROR("Could not extract the public key\n");
169 goto done;
170 }
171 VB2_DEBUG("keyb_size is %#x (%d):\n", keyb_size, keyb_size);
172
173 /*
174 * Of course the packed public key format is different. Why would you
175 * think otherwise? Since the dawn of time, vboot has used this:
176 *
177 * uint32_t nwords size of RSA key in 32-bit words
178 * uint32_t n0inv magic RSA n0inv
179 * uint32_t n[nwords] magic RSA modulus little endian array
180 * uint32_t rr[nwords] magic RSA R^2 little endian array
181 *
182 * But for no discernable reason, the usbpd1 format uses this:
183 *
184 * uint32_t n[nwords] magic RSA modulus little endian array
185 * uint32_t rr[nwords] magic RSA R^2 little endian array
186 * uint32_t n0inv magic RSA n0inv
187 *
188 * There's no nwords field, and n0inv is last insted of first. Sigh.
189 */
190 pub_size = keyb_size - 4;
191
192 /* align pubkey size to 16-byte boundary */
193 uint32_t pub_pad = pub_size;
194 pub_size = (pub_size + 16) / 16 * 16;
195 pub_pad = pub_size - pub_pad;
196
197 pub_offset = ro_offset + ro_size - pub_size;
198
199 if (ro_size < pub_size) {
200 ERROR("The RO image is too small to hold the public key"
201 " (0x%08x < %08x)\n",
202 ro_size, pub_size);
203 goto done;
204 }
205
206 /* How many bytes in the arrays? */
207 uint32_t nbytes = 4 * (*(uint32_t *)keyb_data);
208 /* Source offsets from keyb_data */
209 uint32_t src_ofs_n0inv = 4;
210 uint32_t src_ofs_n = src_ofs_n0inv + 4;
211 uint32_t src_ofs_rr = src_ofs_n + nbytes;
212 /* Dest offsets from buf */
213 uint32_t dst_ofs_n = pub_offset + 0;
214 uint32_t dst_ofs_rr = dst_ofs_n + nbytes;
215 uint32_t dst_ofs_n0inv = dst_ofs_rr + nbytes;
216
217 VB2_DEBUG("len 0x%08x ro_size 0x%08x ro_offset 0x%08x\n",
218 len, ro_size, ro_offset);
219 VB2_DEBUG("pub_size 0x%08x pub_offset 0x%08x nbytes 0x%08x\n",
220 pub_size, pub_offset, nbytes);
221 VB2_DEBUG("pub_pad 0x%08x\n", pub_pad);
222
223 /* Copy n[nwords] */
224 memcpy(buf + dst_ofs_n, keyb_data + src_ofs_n, nbytes);
225 /* Copy rr[nwords] */
226 memcpy(buf + dst_ofs_rr, keyb_data + src_ofs_rr, nbytes);
227 /* Copy n0inv */
228 memcpy(buf + dst_ofs_n0inv, keyb_data + src_ofs_n0inv, 4);
229 /* Pad with 0xff */
230 memset(buf + dst_ofs_n0inv + 4, 0xff, pub_pad);
231
232 /* Finally */
233 retval = 0;
234 done:
235 futil_unmap_and_close_file(fd, FILE_MODE_SIGN(sign_option), buf, len);
236 if (key_ptr)
237 vb2_free_private_key(key_ptr);
238 if (keyb_data)
239 free(keyb_data);
240
241 return retval;
242 }
243
244 /*
245 * Algorithms that we want to try, in order. We've only ever shipped with
246 * RSA2048 / SHA256, but the others should work in tests.
247 */
248 static enum vb2_signature_algorithm sigs[] = {
249 VB2_SIG_RSA2048,
250 VB2_SIG_RSA2048_EXP3,
251 VB2_SIG_RSA1024,
252 VB2_SIG_RSA4096,
253 VB2_SIG_RSA8192,
254 };
255 static enum vb2_hash_algorithm hashes[] = {
256 VB2_HASH_SHA256,
257 VB2_HASH_SHA1,
258 VB2_HASH_SHA512,
259 };
260
261 /*
262 * The size of the public key structure used by usbpd1 is
263 * 2 x RSANUMBYTES for n and rr fields
264 * plus 4 for n0inv, aligned on a multiple of 16
265 */
usbpd1_packed_key_size(enum vb2_signature_algorithm sig_alg)266 static uint32_t usbpd1_packed_key_size(enum vb2_signature_algorithm sig_alg)
267 {
268 switch (sig_alg) {
269 case VB2_SIG_RSA1024:
270 return 272;
271 case VB2_SIG_RSA2048:
272 case VB2_SIG_RSA2048_EXP3:
273 return 528;
274 case VB2_SIG_RSA4096:
275 return 1040;
276 case VB2_SIG_RSA8192:
277 return 2064;
278 default:
279 return 0;
280 }
281 }
vb2_pubkey_from_usbpd1(struct vb2_public_key * key,enum vb2_signature_algorithm sig_alg,enum vb2_hash_algorithm hash_alg,const uint8_t * o_pubkey,uint32_t o_pubkey_size)282 static void vb2_pubkey_from_usbpd1(struct vb2_public_key *key,
283 enum vb2_signature_algorithm sig_alg,
284 enum vb2_hash_algorithm hash_alg,
285 const uint8_t *o_pubkey,
286 uint32_t o_pubkey_size)
287 {
288 key->arrsize = vb2_rsa_sig_size(sig_alg) / sizeof(uint32_t);
289 key->n0inv = *((uint32_t *)o_pubkey + 2 * key->arrsize);
290 key->n = (uint32_t *)o_pubkey;
291 key->rr = (uint32_t *)o_pubkey + key->arrsize;
292 key->sig_alg = sig_alg;
293 key->hash_alg = hash_alg;
294 key->desc = 0;
295 key->version = 0;
296 key->id = vb2_hash_id(hash_alg);
297 }
298
vb21_sig_from_usbpd1(struct vb21_signature ** sig,enum vb2_signature_algorithm sig_alg,enum vb2_hash_algorithm hash_alg,const uint8_t * o_sig,uint32_t o_sig_size,uint32_t data_size)299 static vb2_error_t vb21_sig_from_usbpd1(struct vb21_signature **sig,
300 enum vb2_signature_algorithm sig_alg,
301 enum vb2_hash_algorithm hash_alg,
302 const uint8_t *o_sig,
303 uint32_t o_sig_size, uint32_t data_size)
304 {
305 struct vb21_signature s = {
306 .c.magic = VB21_MAGIC_SIGNATURE,
307 .c.struct_version_major = VB21_SIGNATURE_VERSION_MAJOR,
308 .c.struct_version_minor = VB21_SIGNATURE_VERSION_MINOR,
309 .c.fixed_size = sizeof(s),
310 .sig_alg = sig_alg,
311 .hash_alg = hash_alg,
312 .data_size = data_size,
313 .sig_size = vb2_rsa_sig_size(sig_alg),
314 .sig_offset = sizeof(s),
315 };
316 const uint32_t total_size = sizeof(s) + o_sig_size;
317 uint8_t *buf = calloc(1, total_size);
318 if (!buf)
319 return VB2_ERROR_UNKNOWN;
320
321 memcpy(buf, &s, sizeof(s));
322 memcpy(buf + sizeof(s), o_sig, o_sig_size);
323
324 *sig = (struct vb21_signature *)buf;
325 return VB2_SUCCESS;
326 }
327
show_usbpd1_stuff(const char * fname,enum vb2_signature_algorithm sig_alg,enum vb2_hash_algorithm hash_alg,const uint8_t * o_pubkey,uint32_t o_pubkey_size)328 static void show_usbpd1_stuff(const char *fname,
329 enum vb2_signature_algorithm sig_alg,
330 enum vb2_hash_algorithm hash_alg,
331 const uint8_t *o_pubkey, uint32_t o_pubkey_size)
332 {
333 struct vb2_public_key key;
334 struct vb21_packed_key *pkey;
335 struct vb2_hash hash;
336 int i;
337
338 vb2_pubkey_from_usbpd1(&key, sig_alg, hash_alg,
339 o_pubkey, o_pubkey_size);
340
341 if (vb21_public_key_pack(&pkey, &key))
342 return;
343
344 vb2_hash_calculate(false, (uint8_t *)pkey + pkey->key_offset,
345 pkey->key_size, VB2_HASH_SHA1, &hash);
346
347 printf("USB-PD v1 image: %s\n", fname);
348 printf(" Algorithm: %s %s\n",
349 vb2_get_sig_algorithm_name(sig_alg),
350 vb2_get_hash_algorithm_name(hash_alg));
351 printf(" Key sha1sum: ");
352 for (i = 0; i < sizeof(hash.sha1); i++)
353 printf("%02x", hash.sha1[i]);
354 printf("\n");
355
356 free(pkey);
357 }
358
359 /* Returns VB2_SUCCESS or random error code */
try_our_own(enum vb2_signature_algorithm sig_alg,enum vb2_hash_algorithm hash_alg,const uint8_t * o_pubkey,uint32_t o_pubkey_size,const uint8_t * o_sig,uint32_t o_sig_size,const uint8_t * data,uint32_t data_size)360 static vb2_error_t try_our_own(enum vb2_signature_algorithm sig_alg,
361 enum vb2_hash_algorithm hash_alg,
362 const uint8_t *o_pubkey, uint32_t o_pubkey_size,
363 const uint8_t *o_sig, uint32_t o_sig_size,
364 const uint8_t *data, uint32_t data_size)
365 {
366 struct vb2_public_key pubkey;
367 struct vb21_signature *sig;
368 uint8_t buf[VB2_FIRMWARE_WORKBUF_RECOMMENDED_SIZE]
369 __attribute__((aligned(VB2_WORKBUF_ALIGN)));
370 struct vb2_workbuf wb = {
371 .buf = buf,
372 .size = sizeof(buf),
373 };
374 vb2_error_t rv = VB2_ERROR_UNKNOWN;
375
376 vb2_pubkey_from_usbpd1(&pubkey, sig_alg, hash_alg,
377 o_pubkey, o_pubkey_size);
378
379 if ((rv = vb21_sig_from_usbpd1(&sig, sig_alg, hash_alg,
380 o_sig, o_sig_size, data_size)))
381 return rv;
382
383 rv = vb21_verify_data(data, data_size, sig, &pubkey, &wb);
384
385 free(sig);
386
387 return rv;
388 }
389
390 /* Returns VB2_SUCCESS if the image validates itself */
check_self_consistency(const uint8_t * buf,const char * fname,uint32_t ro_size,uint32_t rw_size,uint32_t ro_offset,uint32_t rw_offset,enum vb2_signature_algorithm sig_alg,enum vb2_hash_algorithm hash_alg)391 static vb2_error_t check_self_consistency(const uint8_t *buf, const char *fname,
392 uint32_t ro_size, uint32_t rw_size,
393 uint32_t ro_offset,
394 uint32_t rw_offset,
395 enum vb2_signature_algorithm sig_alg,
396 enum vb2_hash_algorithm hash_alg)
397 {
398 /* Where are the important bits? */
399 const uint32_t sig_size = vb2_rsa_sig_size(sig_alg);
400 const uint32_t sig_offset = rw_offset + rw_size - sig_size;
401 const uint32_t pubkey_size = usbpd1_packed_key_size(sig_alg);
402 const uint32_t pubkey_offset = ro_offset + ro_size - pubkey_size;
403
404 /* Skip stuff that obviously doesn't work */
405 if (sig_size > rw_size || pubkey_size > ro_size)
406 return VB2_ERROR_UNKNOWN;
407
408 vb2_error_t rv = try_our_own(sig_alg, hash_alg, /* algs */
409 buf + pubkey_offset, pubkey_size, /* pubkey blob */
410 buf + sig_offset, sig_size, /* sig blob */
411 buf + rw_offset, rw_size - sig_size); /* RW image */
412
413 if (rv == VB2_SUCCESS && fname)
414 show_usbpd1_stuff(fname, sig_alg, hash_alg,
415 buf + pubkey_offset, pubkey_size);
416
417 return rv;
418 }
419
ft_show_usbpd1(const char * fname)420 int ft_show_usbpd1(const char *fname)
421 {
422 int fd = -1;
423 uint8_t *buf;
424 uint32_t len;
425 int rv = 1;
426
427 if (futil_open_and_map_file(fname, &fd, FILE_RO, &buf, &len))
428 return 1;
429
430 VB2_DEBUG("name %s len 0x%08x (%d)\n", fname, len, len);
431
432 /* Get image locations */
433 uint32_t ro_size, rw_size, ro_offset, rw_offset;
434 if (!parse_size_opts(len, &ro_size, &rw_size, &ro_offset, &rw_offset))
435 goto done;
436
437 /* TODO: If we don't have a RO image, ask for a public key
438 * TODO: If we're given an external public key, use it (and its alg) */
439 if (!ro_size) {
440 printf("Can't find the public key\n");
441 goto done;
442 }
443
444 /* TODO: Only loop through the numbers we haven't been given */
445 for (enum vb2_signature_algorithm s = 0; s < ARRAY_SIZE(sigs); s++) {
446 for (enum vb2_hash_algorithm h = 0; h < ARRAY_SIZE(hashes); h++) {
447 if (!check_self_consistency(buf, fname, ro_size, rw_size,
448 ro_offset, rw_offset,
449 sigs[s], hashes[h])) {
450 rv = 0;
451 goto done;
452 }
453 }
454 }
455
456 printf("This doesn't appear to be a complete usbpd1 image\n");
457 done:
458 futil_unmap_and_close_file(fd, FILE_RO, buf, len);
459 return rv;
460 }
461
ft_recognize_usbpd1(uint8_t * buf,uint32_t len)462 enum futil_file_type ft_recognize_usbpd1(uint8_t *buf, uint32_t len)
463 {
464 /*
465 * Since we don't use any headers to identify or locate the pubkey and
466 * signature, in order to identify blob as the right type we have to
467 * just assume that the RO & RW are 1) both present, and 2) evenly
468 * split. Then we just try to use what we think might be the pubkey to
469 * validate what we think might be the signature.
470 */
471 const uint32_t ro_offset = 0;
472 const uint32_t ro_size = len / 2;
473 const uint32_t rw_size = len / 2;
474 const uint32_t rw_offset = len / 2;
475
476 for (enum vb2_signature_algorithm s = 0; s < ARRAY_SIZE(sigs); s++) {
477 for (enum vb2_hash_algorithm h = 0; h < ARRAY_SIZE(hashes); h++) {
478 if (!check_self_consistency(buf, 0, ro_size, rw_size,
479 ro_offset, rw_offset,
480 sigs[s], hashes[h]))
481 return FILE_TYPE_USBPD1;
482 }
483 }
484
485 return FILE_TYPE_UNKNOWN;
486 }
487