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