cmd_sign.c 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063
  1. /*
  2. * Copyright 2014 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. #include <errno.h>
  7. #include <fcntl.h>
  8. #include <getopt.h>
  9. #include <inttypes.h>
  10. #include <limits.h>
  11. #include <stddef.h>
  12. #include <stdint.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <sys/stat.h>
  17. #include <sys/types.h>
  18. #include <unistd.h>
  19. #include "file_type.h"
  20. #include "file_type_bios.h"
  21. #include "fmap.h"
  22. #include "futility.h"
  23. #include "futility_options.h"
  24. #include "gbb_header.h"
  25. #include "host_common.h"
  26. #include "host_key2.h"
  27. #include "kernel_blob.h"
  28. #include "util_misc.h"
  29. #include "vb1_helper.h"
  30. #include "vb2_common.h"
  31. #include "vb2_struct.h"
  32. #include "vb21_common.h"
  33. #include "vboot_common.h"
  34. /* Options */
  35. struct sign_option_s sign_option = {
  36. .version = 1,
  37. .arch = ARCH_UNSPECIFIED,
  38. .kloadaddr = CROS_32BIT_ENTRY_ADDR,
  39. .padding = 65536,
  40. .type = FILE_TYPE_UNKNOWN,
  41. .hash_alg = VB2_HASH_SHA256, /* default */
  42. .ro_size = 0xffffffff,
  43. .rw_size = 0xffffffff,
  44. .ro_offset = 0xffffffff,
  45. .rw_offset = 0xffffffff,
  46. .sig_size = 1024,
  47. };
  48. /* Helper to complain about invalid args. Returns num errors discovered */
  49. static int no_opt_if(int expr, const char *optname)
  50. {
  51. if (expr) {
  52. fprintf(stderr, "Missing --%s option\n", optname);
  53. return 1;
  54. }
  55. return 0;
  56. }
  57. /* This wraps/signs a public key, producing a keyblock. */
  58. int ft_sign_pubkey(const char *name, uint8_t *buf, uint32_t len, void *data)
  59. {
  60. struct vb2_packed_key *data_key = (struct vb2_packed_key *)buf;
  61. struct vb2_keyblock *block;
  62. if (!packed_key_looks_ok(data_key, len)) {
  63. fprintf(stderr, "Public key looks bad.\n");
  64. return 1;
  65. }
  66. if (sign_option.pem_signpriv) {
  67. if (sign_option.pem_external) {
  68. /* External signing uses the PEM file directly. */
  69. block = vb2_create_keyblock_external(
  70. data_key,
  71. sign_option.pem_signpriv,
  72. sign_option.pem_algo,
  73. sign_option.flags,
  74. sign_option.pem_external);
  75. } else {
  76. sign_option.signprivate = vb2_read_private_key_pem(
  77. sign_option.pem_signpriv,
  78. sign_option.pem_algo);
  79. if (!sign_option.signprivate) {
  80. fprintf(stderr,
  81. "Unable to read PEM signing key: %s\n",
  82. strerror(errno));
  83. return 1;
  84. }
  85. block = vb2_create_keyblock(data_key,
  86. sign_option.signprivate,
  87. sign_option.flags);
  88. }
  89. } else {
  90. /* Not PEM. Should already have a signing key. */
  91. block = vb2_create_keyblock(data_key, sign_option.signprivate,
  92. sign_option.flags);
  93. }
  94. /* Write it out */
  95. return WriteSomeParts(sign_option.outfile,
  96. block, block->keyblock_size,
  97. NULL, 0);
  98. }
  99. int ft_sign_raw_kernel(const char *name, uint8_t *buf, uint32_t len,
  100. void *data)
  101. {
  102. uint8_t *vmlinuz_data, *kblob_data, *vblock_data;
  103. uint32_t vmlinuz_size, kblob_size, vblock_size;
  104. int rv;
  105. vmlinuz_data = buf;
  106. vmlinuz_size = len;
  107. kblob_data = CreateKernelBlob(
  108. vmlinuz_data, vmlinuz_size,
  109. sign_option.arch, sign_option.kloadaddr,
  110. sign_option.config_data, sign_option.config_size,
  111. sign_option.bootloader_data, sign_option.bootloader_size,
  112. &kblob_size);
  113. if (!kblob_data) {
  114. fprintf(stderr, "Unable to create kernel blob\n");
  115. return 1;
  116. }
  117. Debug("kblob_size = 0x%x\n", kblob_size);
  118. vblock_data = SignKernelBlob(kblob_data, kblob_size,
  119. sign_option.padding,
  120. sign_option.version,
  121. sign_option.kloadaddr,
  122. sign_option.keyblock,
  123. sign_option.signprivate,
  124. sign_option.flags, &vblock_size);
  125. if (!vblock_data) {
  126. fprintf(stderr, "Unable to sign kernel blob\n");
  127. free(kblob_data);
  128. return 1;
  129. }
  130. Debug("vblock_size = 0x%x\n", vblock_size);
  131. /* We should be creating a completely new output file.
  132. * If not, something's wrong. */
  133. if (!sign_option.create_new_outfile)
  134. DIE;
  135. if (sign_option.vblockonly)
  136. rv = WriteSomeParts(sign_option.outfile,
  137. vblock_data, vblock_size,
  138. NULL, 0);
  139. else
  140. rv = WriteSomeParts(sign_option.outfile,
  141. vblock_data, vblock_size,
  142. kblob_data, kblob_size);
  143. free(vblock_data);
  144. free(kblob_data);
  145. return rv;
  146. }
  147. int ft_sign_kern_preamble(const char *name, uint8_t *buf, uint32_t len,
  148. void *data)
  149. {
  150. uint8_t *kpart_data, *kblob_data, *vblock_data;
  151. uint32_t kpart_size, kblob_size, vblock_size;
  152. struct vb2_keyblock *keyblock = NULL;
  153. struct vb2_kernel_preamble *preamble = NULL;
  154. int rv = 0;
  155. kpart_data = buf;
  156. kpart_size = len;
  157. /* Note: This just sets some static pointers. It doesn't malloc. */
  158. kblob_data = unpack_kernel_partition(kpart_data, kpart_size,
  159. sign_option.padding,
  160. &keyblock, &preamble, &kblob_size);
  161. if (!kblob_data) {
  162. fprintf(stderr, "Unable to unpack kernel partition\n");
  163. return 1;
  164. }
  165. /*
  166. * We don't let --kloadaddr change when resigning, because the original
  167. * vbutil_kernel program didn't do it right. Since obviously no one
  168. * ever noticed, we'll maintain bug-compatibility by just not allowing
  169. * it here either. To enable it, we'd need to update the zeropage
  170. * table's cmd_line_ptr as well as the preamble.
  171. */
  172. sign_option.kloadaddr = preamble->body_load_address;
  173. /* Replace the config if asked */
  174. if (sign_option.config_data &&
  175. 0 != UpdateKernelBlobConfig(kblob_data, kblob_size,
  176. sign_option.config_data,
  177. sign_option.config_size)) {
  178. fprintf(stderr, "Unable to update config\n");
  179. return 1;
  180. }
  181. /* Preserve the version unless a new one is given */
  182. if (!sign_option.version_specified)
  183. sign_option.version = preamble->kernel_version;
  184. /* Preserve the flags if not specified */
  185. uint32_t kernel_flags = vb2_kernel_get_flags(preamble);
  186. if (sign_option.flags_specified == 0)
  187. sign_option.flags = kernel_flags;
  188. /* Replace the keyblock if asked */
  189. if (sign_option.keyblock)
  190. keyblock = sign_option.keyblock;
  191. /* Compute the new signature */
  192. vblock_data = SignKernelBlob(kblob_data, kblob_size,
  193. sign_option.padding,
  194. sign_option.version,
  195. sign_option.kloadaddr,
  196. keyblock,
  197. sign_option.signprivate,
  198. sign_option.flags,
  199. &vblock_size);
  200. if (!vblock_data) {
  201. fprintf(stderr, "Unable to sign kernel blob\n");
  202. return 1;
  203. }
  204. Debug("vblock_size = 0x%" PRIx64 "\n", vblock_size);
  205. if (sign_option.create_new_outfile) {
  206. /* Write out what we've been asked for */
  207. if (sign_option.vblockonly)
  208. rv = WriteSomeParts(sign_option.outfile,
  209. vblock_data, vblock_size,
  210. NULL, 0);
  211. else
  212. rv = WriteSomeParts(sign_option.outfile,
  213. vblock_data, vblock_size,
  214. kblob_data, kblob_size);
  215. } else {
  216. /* If we're modifying an existing file, it's mmap'ed so that
  217. * all our modifications to the buffer will get flushed to
  218. * disk when we close it. */
  219. memcpy(kpart_data, vblock_data, vblock_size);
  220. }
  221. free(vblock_data);
  222. return rv;
  223. }
  224. int ft_sign_raw_firmware(const char *name, uint8_t *buf, uint32_t len,
  225. void *data)
  226. {
  227. struct vb2_signature *body_sig;
  228. struct vb2_fw_preamble *preamble;
  229. int rv;
  230. body_sig = vb2_calculate_signature(buf, len, sign_option.signprivate);
  231. if (!body_sig) {
  232. fprintf(stderr, "Error calculating body signature\n");
  233. return 1;
  234. }
  235. preamble = vb2_create_fw_preamble(
  236. sign_option.version,
  237. (struct vb2_packed_key *)sign_option.kernel_subkey,
  238. body_sig,
  239. sign_option.signprivate,
  240. sign_option.flags);
  241. if (!preamble) {
  242. fprintf(stderr, "Error creating firmware preamble.\n");
  243. free(body_sig);
  244. return 1;
  245. }
  246. rv = WriteSomeParts(sign_option.outfile,
  247. sign_option.keyblock,
  248. sign_option.keyblock->keyblock_size,
  249. preamble, preamble->preamble_size);
  250. free(preamble);
  251. free(body_sig);
  252. return rv;
  253. }
  254. static const char usage_pubkey[] = "\n"
  255. "To sign a public key / create a new keyblock:\n"
  256. "\n"
  257. "Required PARAMS:\n"
  258. " [--datapubkey] INFILE The public key to wrap\n"
  259. " [--outfile] OUTFILE The resulting keyblock\n"
  260. "\n"
  261. "Optional PARAMS:\n"
  262. " A private signing key, specified as either\n"
  263. " -s|--signprivate FILE.vbprivk Signing key in .vbprivk format\n"
  264. " Or\n"
  265. " --pem_signpriv FILE.pem Signing key in PEM format...\n"
  266. " --pem_algo NUM AND the algorithm to use (0 - %d)\n"
  267. "\n"
  268. " If a signing key is not given, the keyblock will not be signed."
  269. "\n\n"
  270. "And these, too:\n\n"
  271. " -f|--flags NUM Flags specifying use conditions\n"
  272. " --pem_external PROGRAM"
  273. " External program to compute the signature\n"
  274. " (requires a PEM signing key)\n"
  275. "\n";
  276. static void print_help_pubkey(int argc, char *argv[])
  277. {
  278. printf(usage_pubkey, VB2_ALG_COUNT - 1);
  279. }
  280. static const char usage_fw_main[] = "\n"
  281. "To sign a raw firmware blob (FW_MAIN_A/B):\n"
  282. "\n"
  283. "Required PARAMS:\n"
  284. " -s|--signprivate FILE.vbprivk The private firmware data key\n"
  285. " -b|--keyblock FILE.keyblock The keyblock containing the\n"
  286. " public firmware data key\n"
  287. " -k|--kernelkey FILE.vbpubk The public kernel subkey\n"
  288. " -v|--version NUM The firmware version number\n"
  289. " [--fv] INFILE"
  290. " The raw firmware blob (FW_MAIN_A/B)\n"
  291. " [--outfile] OUTFILE Output VBLOCK_A/B\n"
  292. "\n"
  293. "Optional PARAMS:\n"
  294. " -f|--flags NUM The preamble flags value"
  295. " (default is 0)\n"
  296. "\n";
  297. static void print_help_raw_firmware(int argc, char *argv[])
  298. {
  299. puts(usage_fw_main);
  300. }
  301. static const char usage_bios[] = "\n"
  302. "To sign a complete firmware image (bios.bin):\n"
  303. "\n"
  304. "Required PARAMS:\n"
  305. " -s|--signprivate FILE.vbprivk The private firmware data key\n"
  306. " -b|--keyblock FILE.keyblock The keyblock containing the\n"
  307. " public firmware data key\n"
  308. " -k|--kernelkey FILE.vbpubk The public kernel subkey\n"
  309. " [--infile] INFILE Input firmware image (modified\n"
  310. " in place if no OUTFILE given)\n"
  311. "\n"
  312. "These are required if the A and B firmware differ:\n"
  313. " -S|--devsign FILE.vbprivk The DEV private firmware data key\n"
  314. " -B|--devkeyblock FILE.keyblock The keyblock containing the\n"
  315. " DEV public firmware data key\n"
  316. "\n"
  317. "Optional PARAMS:\n"
  318. " -v|--version NUM The firmware version number"
  319. " (default %d)\n"
  320. " -f|--flags NUM The preamble flags value"
  321. " (default is\n"
  322. " unchanged, or 0 if unknown)\n"
  323. " -d|--loemdir DIR Local OEM output vblock directory\n"
  324. " -l|--loemid STRING Local OEM vblock suffix\n"
  325. " [--outfile] OUTFILE Output firmware image\n"
  326. "\n";
  327. static void print_help_bios_image(int argc, char *argv[])
  328. {
  329. printf(usage_bios, sign_option.version);
  330. }
  331. static const char usage_new_kpart[] = "\n"
  332. "To create a new kernel partition image (/dev/sda2, /dev/mmcblk0p2):\n"
  333. "\n"
  334. "Required PARAMS:\n"
  335. " -s|--signprivate FILE.vbprivk"
  336. " The private key to sign the kernel blob\n"
  337. " -b|--keyblock FILE.keyblock Keyblock containing the public\n"
  338. " key to verify the kernel blob\n"
  339. " -v|--version NUM The kernel version number\n"
  340. " --bootloader FILE Bootloader stub\n"
  341. " --config FILE The kernel commandline file\n"
  342. " --arch ARCH The CPU architecture (one of\n"
  343. " x86|amd64, arm|aarch64, mips)\n"
  344. " [--vmlinuz] INFILE Linux kernel bzImage file\n"
  345. " [--outfile] OUTFILE Output kernel partition or vblock\n"
  346. "\n"
  347. "Optional PARAMS:\n"
  348. " --kloadaddr NUM"
  349. " RAM address to load the kernel body\n"
  350. " (default 0x%x)\n"
  351. " --pad NUM The vblock padding size in bytes\n"
  352. " (default 0x%x)\n"
  353. " --vblockonly Emit just the vblock (requires a\n"
  354. " distinct outfile)\n"
  355. " -f|--flags NUM The preamble flags value\n"
  356. "\n";
  357. static void print_help_raw_kernel(int argc, char *argv[])
  358. {
  359. printf(usage_new_kpart, sign_option.kloadaddr, sign_option.padding);
  360. }
  361. static const char usage_old_kpart[] = "\n"
  362. "To resign an existing kernel partition (/dev/sda2, /dev/mmcblk0p2):\n"
  363. "\n"
  364. "Required PARAMS:\n"
  365. " -s|--signprivate FILE.vbprivk"
  366. " The private key to sign the kernel blob\n"
  367. " [--infile] INFILE Input kernel partition (modified\n"
  368. " in place if no OUTFILE given)\n"
  369. "\n"
  370. "Optional PARAMS:\n"
  371. " -b|--keyblock FILE.keyblock Keyblock containing the public\n"
  372. " key to verify the kernel blob\n"
  373. " -v|--version NUM The kernel version number\n"
  374. " --config FILE The kernel commandline file\n"
  375. " --pad NUM The vblock padding size in bytes\n"
  376. " (default 0x%x)\n"
  377. " [--outfile] OUTFILE Output kernel partition or vblock\n"
  378. " --vblockonly Emit just the vblock (requires a\n"
  379. " distinct OUTFILE)\n"
  380. " -f|--flags NUM The preamble flags value\n"
  381. "\n";
  382. static void print_help_kern_preamble(int argc, char *argv[])
  383. {
  384. printf(usage_old_kpart, sign_option.padding);
  385. }
  386. static void print_help_usbpd1(int argc, char *argv[])
  387. {
  388. const struct vb2_text_vs_enum *entry;
  389. printf("\n"
  390. "Usage: " MYNAME " %s --type %s [options] INFILE [OUTFILE]\n"
  391. "\n"
  392. "This signs a %s.\n"
  393. "\n"
  394. "The INFILE is assumed to consist of equal-sized RO and RW"
  395. " sections,\n"
  396. "with the public key at the end of of the RO section and the"
  397. " signature\n"
  398. "at the end of the RW section (both in an opaque binary"
  399. " format).\n"
  400. "Signing the image will update both binary blobs, so both"
  401. " public and\n"
  402. "private keys are required.\n"
  403. "\n"
  404. "The signing key is specified with:\n"
  405. "\n"
  406. " --pem "
  407. "FILE Signing keypair in PEM format\n"
  408. "\n"
  409. " --hash_alg "
  410. "NUM Hash algorithm to use:\n",
  411. argv[0],
  412. futil_file_type_name(FILE_TYPE_USBPD1),
  413. futil_file_type_desc(FILE_TYPE_USBPD1));
  414. for (entry = vb2_text_vs_hash; entry->name; entry++)
  415. printf(" %d / %s%s\n",
  416. entry->num, entry->name,
  417. entry->num == VB2_HASH_SHA256 ? " (default)" : "");
  418. printf("\n"
  419. "The size and offset assumptions can be overridden. "
  420. "All numbers are in bytes.\n"
  421. "Specify a size of 0 to ignore that section.\n"
  422. "\n"
  423. " --ro_size NUM"
  424. " Size of the RO section (default half)\n"
  425. " --rw_size NUM"
  426. " Size of the RW section (default half)\n"
  427. " --ro_offset NUM"
  428. " Start of the RO section (default 0)\n"
  429. " --rw_offset NUM"
  430. " Start of the RW section (default half)\n"
  431. "\n");
  432. }
  433. static void print_help_rwsig(int argc, char *argv[])
  434. {
  435. printf("\n"
  436. "Usage: " MYNAME " %s --type %s [options] INFILE [OUTFILE]\n"
  437. "\n"
  438. "This signs a %s.\n"
  439. "\n"
  440. "The INFILE is a binary blob of arbitrary size."
  441. " It is signed using the\n"
  442. "private key and the vb21_signature blob emitted.\n"
  443. "\n"
  444. "If no OUTFILE is specified, the INFILE should contain"
  445. " an existing\n"
  446. "vb21_signature blob near its end. The data_size from that"
  447. " signature is\n"
  448. "used to re-sign a portion of the INFILE, and the old"
  449. " signature blob is\n"
  450. "replaced.\n"
  451. "\n"
  452. "Options:\n"
  453. "\n"
  454. " --prikey FILE.vbprik2 "
  455. "Private key in vb2 format (required)\n"
  456. " --sig_size NUM "
  457. "Offset from the end of INFILE where the\n"
  458. " "
  459. "signature blob should be located\n"
  460. " "
  461. "(default 1024 bytes)\n"
  462. " --data_size NUM "
  463. "Number of bytes of INFILE to sign\n"
  464. "\n",
  465. argv[0],
  466. futil_file_type_name(FILE_TYPE_RWSIG),
  467. futil_file_type_desc(FILE_TYPE_RWSIG));
  468. }
  469. static void (*help_type[NUM_FILE_TYPES])(int argc, char *argv[]) = {
  470. [FILE_TYPE_PUBKEY] = &print_help_pubkey,
  471. [FILE_TYPE_RAW_FIRMWARE] = &print_help_raw_firmware,
  472. [FILE_TYPE_BIOS_IMAGE] = &print_help_bios_image,
  473. [FILE_TYPE_RAW_KERNEL] = &print_help_raw_kernel,
  474. [FILE_TYPE_KERN_PREAMBLE] = &print_help_kern_preamble,
  475. [FILE_TYPE_USBPD1] = &print_help_usbpd1,
  476. [FILE_TYPE_RWSIG] = &print_help_rwsig,
  477. };
  478. static const char usage_default[] = "\n"
  479. "Usage: " MYNAME " %s [PARAMS] INFILE [OUTFILE]\n"
  480. "\n"
  481. "The following signing operations are supported:\n"
  482. "\n"
  483. " INFILE OUTFILE\n"
  484. " public key (.vbpubk) keyblock\n"
  485. " raw firmware blob (FW_MAIN_A/B) firmware preamble (VBLOCK_A/B)\n"
  486. " full firmware image (bios.bin) same, or signed in-place\n"
  487. " raw linux kernel (vmlinuz) kernel partition image\n"
  488. " kernel partition (/dev/sda2) same, or signed in-place\n"
  489. " usbpd1 firmware image same, or signed in-place\n"
  490. " RW device image same, or signed in-place\n"
  491. "\n"
  492. "For more information, use \"" MYNAME " help %s TYPE\", where\n"
  493. "TYPE is one of:\n\n";
  494. static void print_help_default(int argc, char *argv[])
  495. {
  496. enum futil_file_type type;
  497. printf(usage_default, argv[0], argv[0]);
  498. for (type = 0; type < NUM_FILE_TYPES; type++)
  499. if (help_type[type])
  500. printf(" %s", futil_file_type_name(type));
  501. printf("\n\n");
  502. }
  503. static void print_help(int argc, char *argv[])
  504. {
  505. enum futil_file_type type = FILE_TYPE_UNKNOWN;
  506. if (argc > 1)
  507. futil_str_to_file_type(argv[1], &type);
  508. if (help_type[type])
  509. help_type[type](argc, argv);
  510. else
  511. print_help_default(argc, argv);
  512. }
  513. enum no_short_opts {
  514. OPT_FV = 1000,
  515. OPT_INFILE,
  516. OPT_OUTFILE,
  517. OPT_BOOTLOADER,
  518. OPT_CONFIG,
  519. OPT_ARCH,
  520. OPT_KLOADADDR,
  521. OPT_PADDING,
  522. OPT_PEM_SIGNPRIV,
  523. OPT_PEM_ALGO,
  524. OPT_PEM_EXTERNAL,
  525. OPT_TYPE,
  526. OPT_HASH_ALG,
  527. OPT_RO_SIZE,
  528. OPT_RW_SIZE,
  529. OPT_RO_OFFSET,
  530. OPT_RW_OFFSET,
  531. OPT_DATA_SIZE,
  532. OPT_SIG_SIZE,
  533. OPT_PRIKEY,
  534. OPT_HELP,
  535. };
  536. static const struct option long_opts[] = {
  537. /* name hasarg *flag val */
  538. {"signprivate", 1, NULL, 's'},
  539. {"keyblock", 1, NULL, 'b'},
  540. {"kernelkey", 1, NULL, 'k'},
  541. {"devsign", 1, NULL, 'S'},
  542. {"devkeyblock", 1, NULL, 'B'},
  543. {"version", 1, NULL, 'v'},
  544. {"flags", 1, NULL, 'f'},
  545. {"loemdir", 1, NULL, 'd'},
  546. {"loemid", 1, NULL, 'l'},
  547. {"fv", 1, NULL, OPT_FV},
  548. {"infile", 1, NULL, OPT_INFILE},
  549. {"datapubkey", 1, NULL, OPT_INFILE}, /* alias */
  550. {"vmlinuz", 1, NULL, OPT_INFILE}, /* alias */
  551. {"outfile", 1, NULL, OPT_OUTFILE},
  552. {"bootloader", 1, NULL, OPT_BOOTLOADER},
  553. {"config", 1, NULL, OPT_CONFIG},
  554. {"arch", 1, NULL, OPT_ARCH},
  555. {"kloadaddr", 1, NULL, OPT_KLOADADDR},
  556. {"pad", 1, NULL, OPT_PADDING},
  557. {"pem_signpriv", 1, NULL, OPT_PEM_SIGNPRIV},
  558. {"pem", 1, NULL, OPT_PEM_SIGNPRIV}, /* alias */
  559. {"pem_algo", 1, NULL, OPT_PEM_ALGO},
  560. {"pem_external", 1, NULL, OPT_PEM_EXTERNAL},
  561. {"type", 1, NULL, OPT_TYPE},
  562. {"vblockonly", 0, &sign_option.vblockonly, 1},
  563. {"hash_alg", 1, NULL, OPT_HASH_ALG},
  564. {"ro_size", 1, NULL, OPT_RO_SIZE},
  565. {"rw_size", 1, NULL, OPT_RW_SIZE},
  566. {"ro_offset", 1, NULL, OPT_RO_OFFSET},
  567. {"rw_offset", 1, NULL, OPT_RW_OFFSET},
  568. {"data_size", 1, NULL, OPT_DATA_SIZE},
  569. {"sig_size", 1, NULL, OPT_SIG_SIZE},
  570. {"prikey", 1, NULL, OPT_PRIKEY},
  571. {"privkey", 1, NULL, OPT_PRIKEY}, /* alias */
  572. {"help", 0, NULL, OPT_HELP},
  573. {NULL, 0, NULL, 0},
  574. };
  575. static char *short_opts = ":s:b:k:S:B:v:f:d:l:";
  576. /* Return zero on success */
  577. static int parse_number_opt(const char *arg, const char *name, uint32_t *dest)
  578. {
  579. char *e;
  580. uint32_t val = strtoul(arg, &e, 0);
  581. if (!*arg || (e && *e)) {
  582. fprintf(stderr, "Invalid --%s \"%s\"\n", name, arg);
  583. return 1;
  584. }
  585. *dest = val;
  586. return 0;
  587. }
  588. static int do_sign(int argc, char *argv[])
  589. {
  590. char *infile = 0;
  591. int i;
  592. int ifd = -1;
  593. int errorcnt = 0;
  594. uint8_t *buf;
  595. uint32_t buf_len;
  596. char *e = 0;
  597. int mapping;
  598. int helpind = 0;
  599. int longindex;
  600. opterr = 0; /* quiet, you */
  601. while ((i = getopt_long(argc, argv, short_opts, long_opts,
  602. &longindex)) != -1) {
  603. switch (i) {
  604. case 's':
  605. sign_option.signprivate = vb2_read_private_key(optarg);
  606. if (!sign_option.signprivate) {
  607. fprintf(stderr, "Error reading %s\n", optarg);
  608. errorcnt++;
  609. }
  610. break;
  611. case 'b':
  612. sign_option.keyblock = vb2_read_keyblock(optarg);
  613. if (!sign_option.keyblock) {
  614. fprintf(stderr, "Error reading %s\n", optarg);
  615. errorcnt++;
  616. }
  617. break;
  618. case 'k':
  619. sign_option.kernel_subkey = vb2_read_packed_key(optarg);
  620. if (!sign_option.kernel_subkey) {
  621. fprintf(stderr, "Error reading %s\n", optarg);
  622. errorcnt++;
  623. }
  624. break;
  625. case 'S':
  626. sign_option.devsignprivate =
  627. vb2_read_private_key(optarg);
  628. if (!sign_option.devsignprivate) {
  629. fprintf(stderr, "Error reading %s\n", optarg);
  630. errorcnt++;
  631. }
  632. break;
  633. case 'B':
  634. sign_option.devkeyblock = vb2_read_keyblock(optarg);
  635. if (!sign_option.devkeyblock) {
  636. fprintf(stderr, "Error reading %s\n", optarg);
  637. errorcnt++;
  638. }
  639. break;
  640. case 'v':
  641. sign_option.version_specified = 1;
  642. sign_option.version = strtoul(optarg, &e, 0);
  643. if (!*optarg || (e && *e)) {
  644. fprintf(stderr,
  645. "Invalid --version \"%s\"\n", optarg);
  646. errorcnt++;
  647. }
  648. break;
  649. case 'f':
  650. sign_option.flags_specified = 1;
  651. errorcnt += parse_number_opt(optarg, "flags",
  652. &sign_option.flags);
  653. break;
  654. case 'd':
  655. sign_option.loemdir = optarg;
  656. break;
  657. case 'l':
  658. sign_option.loemid = optarg;
  659. break;
  660. case OPT_FV:
  661. sign_option.fv_specified = 1;
  662. /* fallthrough */
  663. case OPT_INFILE:
  664. sign_option.inout_file_count++;
  665. infile = optarg;
  666. break;
  667. case OPT_OUTFILE:
  668. sign_option.inout_file_count++;
  669. sign_option.outfile = optarg;
  670. break;
  671. case OPT_BOOTLOADER:
  672. sign_option.bootloader_data = ReadFile(
  673. optarg, &sign_option.bootloader_size);
  674. if (!sign_option.bootloader_data) {
  675. fprintf(stderr,
  676. "Error reading bootloader file: %s\n",
  677. strerror(errno));
  678. errorcnt++;
  679. }
  680. Debug("bootloader file size=0x%" PRIx64 "\n",
  681. sign_option.bootloader_size);
  682. break;
  683. case OPT_CONFIG:
  684. sign_option.config_data = ReadConfigFile(
  685. optarg, &sign_option.config_size);
  686. if (!sign_option.config_data) {
  687. fprintf(stderr,
  688. "Error reading config file: %s\n",
  689. strerror(errno));
  690. errorcnt++;
  691. }
  692. break;
  693. case OPT_ARCH:
  694. /* check the first 3 characters to also match x86_64 */
  695. if ((!strncasecmp(optarg, "x86", 3)) ||
  696. (!strcasecmp(optarg, "amd64")))
  697. sign_option.arch = ARCH_X86;
  698. else if ((!strcasecmp(optarg, "arm")) ||
  699. (!strcasecmp(optarg, "aarch64")))
  700. sign_option.arch = ARCH_ARM;
  701. else if (!strcasecmp(optarg, "mips"))
  702. sign_option.arch = ARCH_MIPS;
  703. else {
  704. fprintf(stderr,
  705. "Unknown architecture: \"%s\"\n",
  706. optarg);
  707. errorcnt++;
  708. }
  709. break;
  710. case OPT_KLOADADDR:
  711. errorcnt += parse_number_opt(optarg, "kloadaddr",
  712. &sign_option.kloadaddr);
  713. break;
  714. case OPT_PADDING:
  715. errorcnt += parse_number_opt(optarg, "padding",
  716. &sign_option.padding);
  717. break;
  718. case OPT_RO_SIZE:
  719. errorcnt += parse_number_opt(optarg, "ro_size",
  720. &sign_option.ro_size);
  721. break;
  722. case OPT_RW_SIZE:
  723. errorcnt += parse_number_opt(optarg, "rw_size",
  724. &sign_option.rw_size);
  725. break;
  726. case OPT_RO_OFFSET:
  727. errorcnt += parse_number_opt(optarg, "ro_offset",
  728. &sign_option.ro_offset);
  729. break;
  730. case OPT_RW_OFFSET:
  731. errorcnt += parse_number_opt(optarg, "rw_offset",
  732. &sign_option.rw_offset);
  733. break;
  734. case OPT_DATA_SIZE:
  735. errorcnt += parse_number_opt(optarg, "data_size",
  736. &sign_option.data_size);
  737. break;
  738. case OPT_SIG_SIZE:
  739. errorcnt += parse_number_opt(optarg, "sig_size",
  740. &sign_option.sig_size);
  741. break;
  742. case OPT_PEM_SIGNPRIV:
  743. sign_option.pem_signpriv = optarg;
  744. break;
  745. case OPT_PEM_ALGO:
  746. sign_option.pem_algo_specified = 1;
  747. sign_option.pem_algo = strtoul(optarg, &e, 0);
  748. if (!*optarg || (e && *e) ||
  749. (sign_option.pem_algo >= VB2_ALG_COUNT)) {
  750. fprintf(stderr,
  751. "Invalid --pem_algo \"%s\"\n", optarg);
  752. errorcnt++;
  753. }
  754. break;
  755. case OPT_HASH_ALG:
  756. if (!vb2_lookup_hash_alg(optarg,
  757. &sign_option.hash_alg)) {
  758. fprintf(stderr,
  759. "invalid hash_alg \"%s\"\n", optarg);
  760. errorcnt++;
  761. }
  762. break;
  763. case OPT_PEM_EXTERNAL:
  764. sign_option.pem_external = optarg;
  765. break;
  766. case OPT_TYPE:
  767. if (!futil_str_to_file_type(optarg,
  768. &sign_option.type)) {
  769. if (!strcasecmp("help", optarg))
  770. print_file_types_and_exit(errorcnt);
  771. fprintf(stderr,
  772. "Invalid --type \"%s\"\n", optarg);
  773. errorcnt++;
  774. }
  775. break;
  776. case OPT_PRIKEY:
  777. if (vb21_private_key_read(&sign_option.prikey,
  778. optarg)) {
  779. fprintf(stderr, "Error reading %s\n", optarg);
  780. errorcnt++;
  781. }
  782. break;
  783. case OPT_HELP:
  784. helpind = optind - 1;
  785. break;
  786. case '?':
  787. if (optopt)
  788. fprintf(stderr, "Unrecognized option: -%c\n",
  789. optopt);
  790. else
  791. fprintf(stderr, "Unrecognized option: %s\n",
  792. argv[optind - 1]);
  793. errorcnt++;
  794. break;
  795. case ':':
  796. fprintf(stderr, "Missing argument to -%c\n", optopt);
  797. errorcnt++;
  798. break;
  799. case 0: /* handled option */
  800. break;
  801. default:
  802. Debug("i=%d\n", i);
  803. DIE;
  804. }
  805. }
  806. if (helpind) {
  807. /* Skip all the options we've already parsed */
  808. optind--;
  809. argv[optind] = argv[0];
  810. argc -= optind;
  811. argv += optind;
  812. print_help(argc, argv);
  813. return !!errorcnt;
  814. }
  815. /* If we don't have an input file already, we need one */
  816. if (!infile) {
  817. if (argc - optind <= 0) {
  818. errorcnt++;
  819. fprintf(stderr, "ERROR: missing input filename\n");
  820. goto done;
  821. } else {
  822. sign_option.inout_file_count++;
  823. infile = argv[optind++];
  824. }
  825. }
  826. /* Look for an output file if we don't have one, just in case. */
  827. if (!sign_option.outfile && argc - optind > 0) {
  828. sign_option.inout_file_count++;
  829. sign_option.outfile = argv[optind++];
  830. }
  831. /* What are we looking at? */
  832. if (sign_option.type == FILE_TYPE_UNKNOWN &&
  833. futil_file_type(infile, &sign_option.type)) {
  834. errorcnt++;
  835. goto done;
  836. }
  837. /* We may be able to infer the type based on the other args */
  838. if (sign_option.type == FILE_TYPE_UNKNOWN) {
  839. if (sign_option.bootloader_data || sign_option.config_data
  840. || sign_option.arch != ARCH_UNSPECIFIED)
  841. sign_option.type = FILE_TYPE_RAW_KERNEL;
  842. else if (sign_option.kernel_subkey || sign_option.fv_specified)
  843. sign_option.type = FILE_TYPE_RAW_FIRMWARE;
  844. }
  845. Debug("type=%s\n", futil_file_type_name(sign_option.type));
  846. /* Check the arguments for the type of thing we want to sign */
  847. switch (sign_option.type) {
  848. case FILE_TYPE_PUBKEY:
  849. sign_option.create_new_outfile = 1;
  850. if (sign_option.signprivate && sign_option.pem_signpriv) {
  851. fprintf(stderr,
  852. "Only one of --signprivate and --pem_signpriv"
  853. " can be specified\n");
  854. errorcnt++;
  855. }
  856. if ((sign_option.signprivate &&
  857. sign_option.pem_algo_specified) ||
  858. (sign_option.pem_signpriv &&
  859. !sign_option.pem_algo_specified)) {
  860. fprintf(stderr, "--pem_algo must be used with"
  861. " --pem_signpriv\n");
  862. errorcnt++;
  863. }
  864. if (sign_option.pem_external && !sign_option.pem_signpriv) {
  865. fprintf(stderr, "--pem_external must be used with"
  866. " --pem_signpriv\n");
  867. errorcnt++;
  868. }
  869. /* We'll wait to read the PEM file, since the external signer
  870. * may want to read it instead. */
  871. break;
  872. case FILE_TYPE_BIOS_IMAGE:
  873. case FILE_TYPE_OLD_BIOS_IMAGE:
  874. errorcnt += no_opt_if(!sign_option.signprivate, "signprivate");
  875. errorcnt += no_opt_if(!sign_option.keyblock, "keyblock");
  876. errorcnt += no_opt_if(!sign_option.kernel_subkey, "kernelkey");
  877. break;
  878. case FILE_TYPE_KERN_PREAMBLE:
  879. errorcnt += no_opt_if(!sign_option.signprivate, "signprivate");
  880. if (sign_option.vblockonly || sign_option.inout_file_count > 1)
  881. sign_option.create_new_outfile = 1;
  882. break;
  883. case FILE_TYPE_RAW_FIRMWARE:
  884. sign_option.create_new_outfile = 1;
  885. errorcnt += no_opt_if(!sign_option.signprivate, "signprivate");
  886. errorcnt += no_opt_if(!sign_option.keyblock, "keyblock");
  887. errorcnt += no_opt_if(!sign_option.kernel_subkey, "kernelkey");
  888. errorcnt += no_opt_if(!sign_option.version_specified,
  889. "version");
  890. break;
  891. case FILE_TYPE_RAW_KERNEL:
  892. sign_option.create_new_outfile = 1;
  893. errorcnt += no_opt_if(!sign_option.signprivate, "signprivate");
  894. errorcnt += no_opt_if(!sign_option.keyblock, "keyblock");
  895. errorcnt += no_opt_if(!sign_option.version_specified,
  896. "version");
  897. errorcnt += no_opt_if(!sign_option.bootloader_data,
  898. "bootloader");
  899. errorcnt += no_opt_if(!sign_option.config_data, "config");
  900. errorcnt += no_opt_if(sign_option.arch == ARCH_UNSPECIFIED,
  901. "arch");
  902. break;
  903. case FILE_TYPE_USBPD1:
  904. errorcnt += no_opt_if(!sign_option.pem_signpriv, "pem");
  905. errorcnt += no_opt_if(sign_option.hash_alg == VB2_HASH_INVALID,
  906. "hash_alg");
  907. break;
  908. case FILE_TYPE_RWSIG:
  909. errorcnt += no_opt_if(!sign_option.prikey, "prikey");
  910. break;
  911. default:
  912. /* Anything else we don't care */
  913. break;
  914. }
  915. Debug("infile=%s\n", infile);
  916. Debug("sign_option.inout_file_count=%d\n", sign_option.inout_file_count);
  917. Debug("sign_option.create_new_outfile=%d\n",
  918. sign_option.create_new_outfile);
  919. /* Make sure we have an output file if one is needed */
  920. if (!sign_option.outfile) {
  921. if (sign_option.create_new_outfile) {
  922. errorcnt++;
  923. fprintf(stderr, "Missing output filename\n");
  924. goto done;
  925. } else {
  926. sign_option.outfile = infile;
  927. }
  928. }
  929. Debug("sign_option.outfile=%s\n", sign_option.outfile);
  930. if (argc - optind > 0) {
  931. errorcnt++;
  932. fprintf(stderr, "ERROR: too many arguments left over\n");
  933. }
  934. if (errorcnt)
  935. goto done;
  936. if (sign_option.create_new_outfile) {
  937. /* The input is read-only, the output is write-only. */
  938. mapping = MAP_RO;
  939. Debug("open RO %s\n", infile);
  940. ifd = open(infile, O_RDONLY);
  941. if (ifd < 0) {
  942. errorcnt++;
  943. fprintf(stderr, "Can't open %s for reading: %s\n",
  944. infile, strerror(errno));
  945. goto done;
  946. }
  947. } else {
  948. /* We'll read-modify-write the output file */
  949. mapping = MAP_RW;
  950. if (sign_option.inout_file_count > 1)
  951. futil_copy_file_or_die(infile, sign_option.outfile);
  952. Debug("open RW %s\n", sign_option.outfile);
  953. infile = sign_option.outfile;
  954. ifd = open(sign_option.outfile, O_RDWR);
  955. if (ifd < 0) {
  956. errorcnt++;
  957. fprintf(stderr, "Can't open %s for writing: %s\n",
  958. sign_option.outfile, strerror(errno));
  959. goto done;
  960. }
  961. }
  962. if (0 != futil_map_file(ifd, mapping, &buf, &buf_len)) {
  963. errorcnt++;
  964. goto done;
  965. }
  966. errorcnt += futil_file_type_sign(sign_option.type, infile,
  967. buf, buf_len);
  968. errorcnt += futil_unmap_file(ifd, mapping, buf, buf_len);
  969. done:
  970. if (ifd >= 0 && close(ifd)) {
  971. errorcnt++;
  972. fprintf(stderr, "Error when closing ifd: %s\n",
  973. strerror(errno));
  974. }
  975. if (sign_option.signprivate)
  976. free(sign_option.signprivate);
  977. if (sign_option.keyblock)
  978. free(sign_option.keyblock);
  979. if (sign_option.kernel_subkey)
  980. free(sign_option.kernel_subkey);
  981. if (errorcnt)
  982. fprintf(stderr, "Use --help for usage instructions\n");
  983. return !!errorcnt;
  984. }
  985. DECLARE_FUTIL_COMMAND(sign, do_sign, VBOOT_VERSION_ALL,
  986. "Sign / resign various binary components");