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