xref: /aosp_15_r20/external/vboot_reference/futility/vb2_helper.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
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 
6 #include <openssl/pem.h>
7 
8 #include "2common.h"
9 #include "2id.h"
10 #include "2rsa.h"
11 #include "2sha.h"
12 #include "2sysincludes.h"
13 #include "file_type.h"
14 #include "futility.h"
15 #include "futility_options.h"
16 #include "host_common.h"
17 #include "host_common21.h"
18 #include "host_key21.h"
19 #include "host_misc21.h"
20 #include "openssl_compat.h"
21 #include "util_misc.h"
22 
ft_recognize_vb21_key(uint8_t * buf,uint32_t len)23 enum futil_file_type ft_recognize_vb21_key(uint8_t *buf, uint32_t len)
24 {
25 	struct vb2_public_key pubkey;
26 	struct vb2_private_key *privkey = 0;
27 
28 	/* The pubkey points into buf, so nothing to free */
29 	if (VB2_SUCCESS == vb21_unpack_key(&pubkey, buf, len))
30 		return FILE_TYPE_VB2_PUBKEY;
31 
32 	/* The private key unpacks into new structs */
33 	if (VB2_SUCCESS == vb21_private_key_unpack(&privkey, buf, len)) {
34 		vb2_free_private_key(privkey);
35 		return FILE_TYPE_VB2_PRIVKEY;
36 	}
37 
38 	return FILE_TYPE_UNKNOWN;
39 }
40 
vb2_public_key_sha1sum(struct vb2_public_key * key,struct vb2_hash * hash)41 static int vb2_public_key_sha1sum(struct vb2_public_key *key,
42 				  struct vb2_hash *hash)
43 {
44 	struct vb21_packed_key *pkey;
45 
46 	if (vb21_public_key_pack(&pkey, key))
47 		return 0;
48 
49 	vb2_hash_calculate(false, (uint8_t *)pkey + pkey->key_offset,
50 			   pkey->key_size, VB2_HASH_SHA1, hash);
51 
52 	free(pkey);
53 	return 1;
54 }
55 
show_vb21_pubkey_buf(const char * fname,uint8_t * buf,uint32_t len)56 int show_vb21_pubkey_buf(const char *fname, uint8_t *buf, uint32_t len)
57 {
58 	struct vb2_public_key key;
59 	struct vb2_hash hash;
60 
61 	/* The key's members will point into the state buffer after this. Don't
62 	 * free anything. */
63 	if (VB2_SUCCESS != vb21_unpack_key(&key, buf, len))
64 		return 1;
65 
66 	printf("Public Key file:       %s\n", fname);
67 	printf("  Vboot API:           2.1\n");
68 	printf("  Desc:                \"%s\"\n", key.desc);
69 	printf("  Signature Algorithm: %d %s\n", key.sig_alg,
70 	       vb2_get_sig_algorithm_name(key.sig_alg));
71 	printf("  Hash Algorithm:      %d %s\n", key.hash_alg,
72 	       vb2_get_hash_algorithm_name(key.hash_alg));
73 	printf("  Version:             0x%08x\n", key.version);
74 	printf("  ID:                  ");
75 	print_bytes(key.id, sizeof(*key.id));
76 	printf("\n");
77 	if (vb2_public_key_sha1sum(&key, &hash) &&
78 	    memcmp(key.id, hash.sha1, sizeof(*key.id))) {
79 		printf("  Key sha1sum:         ");
80 		print_bytes(hash.sha1, sizeof(hash.sha1));
81 		printf("\n");
82 	}
83 	return 0;
84 }
85 
ft_show_vb21_pubkey(const char * fname)86 int ft_show_vb21_pubkey(const char *fname)
87 {
88 	int fd = -1;
89 	uint8_t *buf;
90 	uint32_t len;
91 	int rv;
92 
93 	if (show_option.parseable) {
94 		ERROR("Parseable output not supported for this file.\n");
95 		return 1;
96 	}
97 
98 	if (futil_open_and_map_file(fname, &fd, FILE_RO, &buf, &len))
99 		return 1;
100 
101 	rv = show_vb21_pubkey_buf(fname, buf, len);
102 
103 	futil_unmap_and_close_file(fd, FILE_RO, buf, len);
104 	return rv;
105 }
106 
vb2_private_key_sha1sum(struct vb2_private_key * key,struct vb2_hash * hash)107 static int vb2_private_key_sha1sum(struct vb2_private_key *key,
108 				   struct vb2_hash *hash)
109 {
110 	uint8_t *buf;
111 	uint32_t buflen;
112 
113 	if (vb_keyb_from_rsa(key->rsa_private_key, &buf, &buflen))
114 		return 0;
115 
116 	vb2_hash_calculate(false, buf, buflen, VB2_HASH_SHA1, hash);
117 
118 	free(buf);
119 	return 1;
120 }
121 
ft_show_vb21_privkey(const char * fname)122 int ft_show_vb21_privkey(const char *fname)
123 {
124 	struct vb2_private_key *key = 0;
125 	struct vb2_hash hash;
126 	int fd = -1;
127 	uint8_t *buf;
128 	uint32_t len;
129 	int rv = 0;
130 
131 	if (show_option.parseable) {
132 		ERROR("Parseable output not supported for this file.\n");
133 		return 1;
134 	}
135 
136 	if (futil_open_and_map_file(fname, &fd, FILE_RO, &buf, &len))
137 		return 1;
138 
139 	if (VB2_SUCCESS != vb21_private_key_unpack(&key, buf, len)) {
140 		rv = 1;
141 		goto done;
142 	}
143 
144 	printf("Private key file:      %s\n", fname);
145 	printf("  Vboot API:           2.1\n");
146 	printf("  Desc:                \"%s\"\n", key->desc ? key->desc : "");
147 	printf("  Signature Algorithm: %d %s\n", key->sig_alg,
148 	       vb2_get_sig_algorithm_name(key->sig_alg));
149 	printf("  Hash Algorithm:      %d %s\n", key->hash_alg,
150 	       vb2_get_hash_algorithm_name(key->hash_alg));
151 	printf("  ID:                  ");
152 	print_bytes(&key->id, sizeof(key->id));
153 	printf("\n");
154 	if (vb2_private_key_sha1sum(key, &hash) &&
155 	    memcmp(&key->id, hash.sha1, sizeof(key->id))) {
156 		printf("  Key sha1sum:         ");
157 		print_bytes(hash.sha1, sizeof(hash.sha1));
158 		printf("\n");
159 	}
160 	vb2_free_private_key(key);
161 done:
162 	futil_unmap_and_close_file(fd, FILE_RO, buf, len);
163 	return rv;
164 }
165 
rsa_from_buffer(uint8_t * buf,uint32_t len)166 static RSA *rsa_from_buffer(uint8_t *buf, uint32_t len)
167 {
168 	BIO *bp;
169 	RSA *rsa_key;
170 
171 	bp = BIO_new_mem_buf(buf, len);
172 	if (!bp)
173 		return 0;
174 
175 	rsa_key = PEM_read_bio_RSAPrivateKey(bp, NULL, NULL, NULL);
176 	if (!rsa_key) {
177 		if (BIO_reset(bp) < 0)
178 			return 0;
179 		rsa_key = PEM_read_bio_RSA_PUBKEY(bp, NULL, NULL, NULL);
180 	}
181 	if (!rsa_key) {
182 		BIO_free(bp);
183 		return 0;
184 	}
185 
186 	BIO_free(bp);
187 
188 	return rsa_key;
189 }
190 
ft_recognize_pem(uint8_t * buf,uint32_t len)191 enum futil_file_type ft_recognize_pem(uint8_t *buf, uint32_t len)
192 {
193 	RSA *rsa_key = rsa_from_buffer(buf, len);
194 
195 	if (rsa_key) {
196 		RSA_free(rsa_key);
197 		return FILE_TYPE_PEM;
198 	}
199 
200 	return FILE_TYPE_UNKNOWN;
201 }
202 
ft_show_pem(const char * fname)203 int ft_show_pem(const char *fname)
204 {
205 	RSA *rsa_key;
206 	uint8_t *keyb;
207 	uint32_t keyb_len;
208 	struct vb2_hash hash;
209 	int i, bits;
210 	const BIGNUM *rsa_key_n, *rsa_key_d;
211 	int fd = -1;
212 	uint8_t *buf;
213 	uint32_t len;
214 	int rv = 0;
215 
216 	if (show_option.parseable) {
217 		ERROR("Parseable output not supported for this file.\n");
218 		return 1;
219 	}
220 
221 	if (futil_open_and_map_file(fname, &fd, FILE_RO, &buf, &len))
222 		return 1;
223 
224 	/* We're called only after ft_recognize_pem, so this should work. */
225 	rsa_key = rsa_from_buffer(buf, len);
226 	if (!rsa_key)
227 		FATAL("No RSA key found in buffer\n");
228 
229 	/* Use to presence of the private exponent to decide if it's public */
230 	RSA_get0_key(rsa_key, &rsa_key_n, NULL, &rsa_key_d);
231 	printf("%s Key file:      %s\n", rsa_key_d ? "Private" : "Public", fname);
232 
233 	bits = BN_num_bits(rsa_key_n);
234 	printf("  Key length:          %d\n", bits);
235 
236 	if (vb_keyb_from_rsa(rsa_key, &keyb, &keyb_len)) {
237 		printf("  Key sha1sum:         <error>");
238 		RSA_free(rsa_key);
239 		rv = 1;
240 		goto done;
241 	}
242 
243 	printf("  Key sha1sum:         ");
244 	vb2_hash_calculate(false, keyb, keyb_len, VB2_HASH_SHA1, &hash);
245 	for (i = 0; i < sizeof(hash.sha1); i++)
246 		printf("%02x", hash.sha1[i]);
247 	printf("\n");
248 
249 	free(keyb);
250 	RSA_free(rsa_key);
251 done:
252 	futil_unmap_and_close_file(fd, FILE_RO, buf, len);
253 	return rv;
254 }
255