file_type_usbpd1.c 13 KB

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