xref: /aosp_15_r20/external/vboot_reference/futility/cmd_vbutil_key.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
1*8617a60dSAndroid Build Coastguard Worker /* Copyright 2011 The ChromiumOS Authors
2*8617a60dSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
3*8617a60dSAndroid Build Coastguard Worker  * found in the LICENSE file.
4*8617a60dSAndroid Build Coastguard Worker  *
5*8617a60dSAndroid Build Coastguard Worker  * Verified boot key utility
6*8617a60dSAndroid Build Coastguard Worker  */
7*8617a60dSAndroid Build Coastguard Worker 
8*8617a60dSAndroid Build Coastguard Worker #include <getopt.h>
9*8617a60dSAndroid Build Coastguard Worker #include <inttypes.h>		/* For PRIu64 */
10*8617a60dSAndroid Build Coastguard Worker #include <stdarg.h>
11*8617a60dSAndroid Build Coastguard Worker #include <stdio.h>
12*8617a60dSAndroid Build Coastguard Worker #include <stdlib.h>
13*8617a60dSAndroid Build Coastguard Worker #include <string.h>
14*8617a60dSAndroid Build Coastguard Worker 
15*8617a60dSAndroid Build Coastguard Worker #include "futility.h"
16*8617a60dSAndroid Build Coastguard Worker #include "host_common.h"
17*8617a60dSAndroid Build Coastguard Worker #include "host_key21.h"
18*8617a60dSAndroid Build Coastguard Worker #include "util_misc.h"
19*8617a60dSAndroid Build Coastguard Worker #include "vb1_helper.h"
20*8617a60dSAndroid Build Coastguard Worker 
21*8617a60dSAndroid Build Coastguard Worker /* Command line options */
22*8617a60dSAndroid Build Coastguard Worker enum {
23*8617a60dSAndroid Build Coastguard Worker 	OPT_INKEY = 1000,
24*8617a60dSAndroid Build Coastguard Worker 	OPT_KEY_VERSION,
25*8617a60dSAndroid Build Coastguard Worker 	OPT_ALGORITHM,
26*8617a60dSAndroid Build Coastguard Worker 	OPT_MODE_PACK,
27*8617a60dSAndroid Build Coastguard Worker 	OPT_MODE_UNPACK,
28*8617a60dSAndroid Build Coastguard Worker 	OPT_COPYTO,
29*8617a60dSAndroid Build Coastguard Worker 	OPT_HELP,
30*8617a60dSAndroid Build Coastguard Worker };
31*8617a60dSAndroid Build Coastguard Worker 
32*8617a60dSAndroid Build Coastguard Worker static const struct option long_opts[] = {
33*8617a60dSAndroid Build Coastguard Worker 	{"key", 1, 0, OPT_INKEY},
34*8617a60dSAndroid Build Coastguard Worker 	{"version", 1, 0, OPT_KEY_VERSION},
35*8617a60dSAndroid Build Coastguard Worker 	{"algorithm", 1, 0, OPT_ALGORITHM},
36*8617a60dSAndroid Build Coastguard Worker 	{"pack", 1, 0, OPT_MODE_PACK},
37*8617a60dSAndroid Build Coastguard Worker 	{"unpack", 1, 0, OPT_MODE_UNPACK},
38*8617a60dSAndroid Build Coastguard Worker 	{"copyto", 1, 0, OPT_COPYTO},
39*8617a60dSAndroid Build Coastguard Worker 	{"help", 0, 0, OPT_HELP},
40*8617a60dSAndroid Build Coastguard Worker 	{NULL, 0, 0, 0}
41*8617a60dSAndroid Build Coastguard Worker };
42*8617a60dSAndroid Build Coastguard Worker 
print_help(int argc,char * argv[])43*8617a60dSAndroid Build Coastguard Worker static void print_help(int argc, char *argv[])
44*8617a60dSAndroid Build Coastguard Worker {
45*8617a60dSAndroid Build Coastguard Worker 	printf("\n"
46*8617a60dSAndroid Build Coastguard Worker 	       "Usage:  " MYNAME " %s --pack <outfile> [PARAMETERS]\n"
47*8617a60dSAndroid Build Coastguard Worker 	       "\n"
48*8617a60dSAndroid Build Coastguard Worker 	       "  Required parameters:\n"
49*8617a60dSAndroid Build Coastguard Worker 	       "    --key <infile>              RSA key file (.keyb or .pem)\n"
50*8617a60dSAndroid Build Coastguard Worker 	       "    --version <number>          Key version number "
51*8617a60dSAndroid Build Coastguard Worker 	       "(required for .keyb,\n"
52*8617a60dSAndroid Build Coastguard Worker 	       "                                  ignored for .pem)\n"
53*8617a60dSAndroid Build Coastguard Worker 	       "    --algorithm <number>        "
54*8617a60dSAndroid Build Coastguard Worker 	       "Signing algorithm to use with key:\n", argv[0]);
55*8617a60dSAndroid Build Coastguard Worker 
56*8617a60dSAndroid Build Coastguard Worker 	for (enum vb2_crypto_algorithm i = 0; i < VB2_ALG_COUNT; i++) {
57*8617a60dSAndroid Build Coastguard Worker 		printf("                                  %d = (%s)\n",
58*8617a60dSAndroid Build Coastguard Worker 		       i, vb2_get_crypto_algorithm_name(i));
59*8617a60dSAndroid Build Coastguard Worker 	}
60*8617a60dSAndroid Build Coastguard Worker 
61*8617a60dSAndroid Build Coastguard Worker 	printf("\nOR\n\n"
62*8617a60dSAndroid Build Coastguard Worker 	       "Usage:  " MYNAME " %s --unpack <infile>\n"
63*8617a60dSAndroid Build Coastguard Worker 	       "\n"
64*8617a60dSAndroid Build Coastguard Worker 	       "  Optional parameters:\n"
65*8617a60dSAndroid Build Coastguard Worker 	       "    --copyto <file>             "
66*8617a60dSAndroid Build Coastguard Worker 	       "Write a copy of the key to this file.\n\n", argv[0]);
67*8617a60dSAndroid Build Coastguard Worker }
68*8617a60dSAndroid Build Coastguard Worker 
69*8617a60dSAndroid Build Coastguard Worker /* Pack a .keyb file into a .vbpubk, or a .pem into a .vbprivk */
do_pack(const char * infile,const char * outfile,uint32_t algorithm,uint32_t version)70*8617a60dSAndroid Build Coastguard Worker static int do_pack(const char *infile, const char *outfile, uint32_t algorithm,
71*8617a60dSAndroid Build Coastguard Worker 		   uint32_t version)
72*8617a60dSAndroid Build Coastguard Worker {
73*8617a60dSAndroid Build Coastguard Worker 	if (!infile || !outfile) {
74*8617a60dSAndroid Build Coastguard Worker 		ERROR("vbutil_key: Must specify --in and --out\n");
75*8617a60dSAndroid Build Coastguard Worker 		return 1;
76*8617a60dSAndroid Build Coastguard Worker 	}
77*8617a60dSAndroid Build Coastguard Worker 
78*8617a60dSAndroid Build Coastguard Worker 	struct vb2_packed_key *pubkey =
79*8617a60dSAndroid Build Coastguard Worker 		vb2_read_packed_keyb(infile, algorithm, version);
80*8617a60dSAndroid Build Coastguard Worker 	if (pubkey) {
81*8617a60dSAndroid Build Coastguard Worker 		if (vb2_write_packed_key(outfile, pubkey)) {
82*8617a60dSAndroid Build Coastguard Worker 			ERROR("vbutil_key: Error writing key.\n");
83*8617a60dSAndroid Build Coastguard Worker 			free(pubkey);
84*8617a60dSAndroid Build Coastguard Worker 			return 1;
85*8617a60dSAndroid Build Coastguard Worker 		}
86*8617a60dSAndroid Build Coastguard Worker 		free(pubkey);
87*8617a60dSAndroid Build Coastguard Worker 		return 0;
88*8617a60dSAndroid Build Coastguard Worker 	}
89*8617a60dSAndroid Build Coastguard Worker 
90*8617a60dSAndroid Build Coastguard Worker 	struct vb2_private_key *privkey =
91*8617a60dSAndroid Build Coastguard Worker 		vb2_read_private_key_pem(infile, algorithm);
92*8617a60dSAndroid Build Coastguard Worker 	if (privkey) {
93*8617a60dSAndroid Build Coastguard Worker 		if (VB2_SUCCESS != vb2_write_private_key(outfile, privkey)) {
94*8617a60dSAndroid Build Coastguard Worker 			ERROR("vbutil_key: Error writing key.\n");
95*8617a60dSAndroid Build Coastguard Worker 			free(privkey);
96*8617a60dSAndroid Build Coastguard Worker 			return 1;
97*8617a60dSAndroid Build Coastguard Worker 		}
98*8617a60dSAndroid Build Coastguard Worker 		free(privkey);
99*8617a60dSAndroid Build Coastguard Worker 		return 0;
100*8617a60dSAndroid Build Coastguard Worker 	}
101*8617a60dSAndroid Build Coastguard Worker 
102*8617a60dSAndroid Build Coastguard Worker 	FATAL("Unable to parse either .keyb or .pem from %s\n", infile);
103*8617a60dSAndroid Build Coastguard Worker 	return 1;
104*8617a60dSAndroid Build Coastguard Worker }
105*8617a60dSAndroid Build Coastguard Worker 
106*8617a60dSAndroid Build Coastguard Worker /* Unpack a .vbpubk, .vbprivk, or .vbprik2 */
do_unpack(const char * infile,const char * outfile)107*8617a60dSAndroid Build Coastguard Worker static int do_unpack(const char *infile, const char *outfile)
108*8617a60dSAndroid Build Coastguard Worker {
109*8617a60dSAndroid Build Coastguard Worker 	struct vb2_packed_key *pubkey;
110*8617a60dSAndroid Build Coastguard Worker 
111*8617a60dSAndroid Build Coastguard Worker 	if (!infile) {
112*8617a60dSAndroid Build Coastguard Worker 		ERROR("Need file to unpack\n");
113*8617a60dSAndroid Build Coastguard Worker 		return 1;
114*8617a60dSAndroid Build Coastguard Worker 	}
115*8617a60dSAndroid Build Coastguard Worker 
116*8617a60dSAndroid Build Coastguard Worker 	pubkey = vb2_read_packed_key(infile);
117*8617a60dSAndroid Build Coastguard Worker 	if (pubkey) {
118*8617a60dSAndroid Build Coastguard Worker 		printf("Public Key file:   %s\n", infile);
119*8617a60dSAndroid Build Coastguard Worker 		printf("Algorithm:         %u %s\n", pubkey->algorithm,
120*8617a60dSAndroid Build Coastguard Worker 		       vb2_get_crypto_algorithm_name(pubkey->algorithm));
121*8617a60dSAndroid Build Coastguard Worker 		printf("Key Version:       %u\n", pubkey->key_version);
122*8617a60dSAndroid Build Coastguard Worker 		printf("Key sha1sum:       %s\n",
123*8617a60dSAndroid Build Coastguard Worker 		       packed_key_sha1_string(pubkey));
124*8617a60dSAndroid Build Coastguard Worker 		if (outfile &&
125*8617a60dSAndroid Build Coastguard Worker 		    VB2_SUCCESS != vb2_write_packed_key(outfile, pubkey)) {
126*8617a60dSAndroid Build Coastguard Worker 			ERROR("butil_key: Error writing key copy\n");
127*8617a60dSAndroid Build Coastguard Worker 			free(pubkey);
128*8617a60dSAndroid Build Coastguard Worker 			return 1;
129*8617a60dSAndroid Build Coastguard Worker 		}
130*8617a60dSAndroid Build Coastguard Worker 		free(pubkey);
131*8617a60dSAndroid Build Coastguard Worker 		return 0;
132*8617a60dSAndroid Build Coastguard Worker 	}
133*8617a60dSAndroid Build Coastguard Worker 
134*8617a60dSAndroid Build Coastguard Worker 	struct vb2_private_key *privkey = vb2_read_private_key(infile);
135*8617a60dSAndroid Build Coastguard Worker 	if (privkey) {
136*8617a60dSAndroid Build Coastguard Worker 		printf("Private Key file:  %s\n", infile);
137*8617a60dSAndroid Build Coastguard Worker 
138*8617a60dSAndroid Build Coastguard Worker 		enum vb2_crypto_algorithm alg =
139*8617a60dSAndroid Build Coastguard Worker 			vb2_get_crypto_algorithm(privkey->hash_alg,
140*8617a60dSAndroid Build Coastguard Worker 						 privkey->sig_alg);
141*8617a60dSAndroid Build Coastguard Worker 		printf("Algorithm:         %u %s\n", alg,
142*8617a60dSAndroid Build Coastguard Worker 		       vb2_get_crypto_algorithm_name(alg));
143*8617a60dSAndroid Build Coastguard Worker 		if (outfile &&
144*8617a60dSAndroid Build Coastguard Worker 		    VB2_SUCCESS != vb2_write_private_key(outfile, privkey)) {
145*8617a60dSAndroid Build Coastguard Worker 			ERROR("vbutil_key: Error writing key copy\n");
146*8617a60dSAndroid Build Coastguard Worker 			free(privkey);
147*8617a60dSAndroid Build Coastguard Worker 			return 1;
148*8617a60dSAndroid Build Coastguard Worker 		}
149*8617a60dSAndroid Build Coastguard Worker 		free(privkey);
150*8617a60dSAndroid Build Coastguard Worker 		return 0;
151*8617a60dSAndroid Build Coastguard Worker 	}
152*8617a60dSAndroid Build Coastguard Worker 
153*8617a60dSAndroid Build Coastguard Worker 	FATAL("Unable to parse either .vbpubk or vbprivk from %s\n", infile);
154*8617a60dSAndroid Build Coastguard Worker 	return 1;
155*8617a60dSAndroid Build Coastguard Worker }
156*8617a60dSAndroid Build Coastguard Worker 
do_vbutil_key(int argc,char * argv[])157*8617a60dSAndroid Build Coastguard Worker static int do_vbutil_key(int argc, char *argv[])
158*8617a60dSAndroid Build Coastguard Worker {
159*8617a60dSAndroid Build Coastguard Worker 
160*8617a60dSAndroid Build Coastguard Worker 	char *infile = NULL;
161*8617a60dSAndroid Build Coastguard Worker 	char *outfile = NULL;
162*8617a60dSAndroid Build Coastguard Worker 	int mode = 0;
163*8617a60dSAndroid Build Coastguard Worker 	int parse_error = 0;
164*8617a60dSAndroid Build Coastguard Worker 	uint32_t version = 1;
165*8617a60dSAndroid Build Coastguard Worker 	uint32_t algorithm = VB2_ALG_COUNT;
166*8617a60dSAndroid Build Coastguard Worker 	char *e;
167*8617a60dSAndroid Build Coastguard Worker 	int i;
168*8617a60dSAndroid Build Coastguard Worker 
169*8617a60dSAndroid Build Coastguard Worker 	while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
170*8617a60dSAndroid Build Coastguard Worker 		switch (i) {
171*8617a60dSAndroid Build Coastguard Worker 		case '?':
172*8617a60dSAndroid Build Coastguard Worker 			/* Unhandled option */
173*8617a60dSAndroid Build Coastguard Worker 			FATAL("Unknown option\n");
174*8617a60dSAndroid Build Coastguard Worker 			parse_error = 1;
175*8617a60dSAndroid Build Coastguard Worker 			break;
176*8617a60dSAndroid Build Coastguard Worker 		case OPT_HELP:
177*8617a60dSAndroid Build Coastguard Worker 			print_help(argc, argv);
178*8617a60dSAndroid Build Coastguard Worker 			return !!parse_error;
179*8617a60dSAndroid Build Coastguard Worker 
180*8617a60dSAndroid Build Coastguard Worker 		case OPT_INKEY:
181*8617a60dSAndroid Build Coastguard Worker 			infile = optarg;
182*8617a60dSAndroid Build Coastguard Worker 			break;
183*8617a60dSAndroid Build Coastguard Worker 
184*8617a60dSAndroid Build Coastguard Worker 		case OPT_KEY_VERSION:
185*8617a60dSAndroid Build Coastguard Worker 			version = strtoul(optarg, &e, 0);
186*8617a60dSAndroid Build Coastguard Worker 			if (!*optarg || (e && *e)) {
187*8617a60dSAndroid Build Coastguard Worker 				FATAL("Invalid --version\n");
188*8617a60dSAndroid Build Coastguard Worker 				parse_error = 1;
189*8617a60dSAndroid Build Coastguard Worker 			}
190*8617a60dSAndroid Build Coastguard Worker 			break;
191*8617a60dSAndroid Build Coastguard Worker 
192*8617a60dSAndroid Build Coastguard Worker 		case OPT_ALGORITHM:
193*8617a60dSAndroid Build Coastguard Worker 			algorithm = strtoul(optarg, &e, 0);
194*8617a60dSAndroid Build Coastguard Worker 			if (!*optarg || (e && *e)) {
195*8617a60dSAndroid Build Coastguard Worker 				FATAL("Invalid --algorithm\n");
196*8617a60dSAndroid Build Coastguard Worker 				parse_error = 1;
197*8617a60dSAndroid Build Coastguard Worker 			}
198*8617a60dSAndroid Build Coastguard Worker 			break;
199*8617a60dSAndroid Build Coastguard Worker 
200*8617a60dSAndroid Build Coastguard Worker 		case OPT_MODE_PACK:
201*8617a60dSAndroid Build Coastguard Worker 			mode = i;
202*8617a60dSAndroid Build Coastguard Worker 			outfile = optarg;
203*8617a60dSAndroid Build Coastguard Worker 			break;
204*8617a60dSAndroid Build Coastguard Worker 
205*8617a60dSAndroid Build Coastguard Worker 		case OPT_MODE_UNPACK:
206*8617a60dSAndroid Build Coastguard Worker 			mode = i;
207*8617a60dSAndroid Build Coastguard Worker 			infile = optarg;
208*8617a60dSAndroid Build Coastguard Worker 			break;
209*8617a60dSAndroid Build Coastguard Worker 
210*8617a60dSAndroid Build Coastguard Worker 		case OPT_COPYTO:
211*8617a60dSAndroid Build Coastguard Worker 			outfile = optarg;
212*8617a60dSAndroid Build Coastguard Worker 			break;
213*8617a60dSAndroid Build Coastguard Worker 		}
214*8617a60dSAndroid Build Coastguard Worker 	}
215*8617a60dSAndroid Build Coastguard Worker 
216*8617a60dSAndroid Build Coastguard Worker 	if (parse_error) {
217*8617a60dSAndroid Build Coastguard Worker 		print_help(argc, argv);
218*8617a60dSAndroid Build Coastguard Worker 		return 1;
219*8617a60dSAndroid Build Coastguard Worker 	}
220*8617a60dSAndroid Build Coastguard Worker 
221*8617a60dSAndroid Build Coastguard Worker 	switch (mode) {
222*8617a60dSAndroid Build Coastguard Worker 	case OPT_MODE_PACK:
223*8617a60dSAndroid Build Coastguard Worker 		return do_pack(infile, outfile, algorithm, version);
224*8617a60dSAndroid Build Coastguard Worker 	case OPT_MODE_UNPACK:
225*8617a60dSAndroid Build Coastguard Worker 		return do_unpack(infile, outfile);
226*8617a60dSAndroid Build Coastguard Worker 	default:
227*8617a60dSAndroid Build Coastguard Worker 		printf("Must specify a mode.\n");
228*8617a60dSAndroid Build Coastguard Worker 		print_help(argc, argv);
229*8617a60dSAndroid Build Coastguard Worker 		return 1;
230*8617a60dSAndroid Build Coastguard Worker 	}
231*8617a60dSAndroid Build Coastguard Worker }
232*8617a60dSAndroid Build Coastguard Worker 
233*8617a60dSAndroid Build Coastguard Worker DECLARE_FUTIL_COMMAND(vbutil_key, do_vbutil_key, VBOOT_VERSION_1_0,
234*8617a60dSAndroid Build Coastguard Worker 		      "Wraps RSA keys with vboot headers");
235