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 * Host functions for keys.
6*8617a60dSAndroid Build Coastguard Worker */
7*8617a60dSAndroid Build Coastguard Worker
8*8617a60dSAndroid Build Coastguard Worker #include <openssl/pem.h>
9*8617a60dSAndroid Build Coastguard Worker
10*8617a60dSAndroid Build Coastguard Worker #include <errno.h>
11*8617a60dSAndroid Build Coastguard Worker #include <stdio.h>
12*8617a60dSAndroid Build Coastguard Worker #include <stdlib.h>
13*8617a60dSAndroid Build Coastguard Worker #include <unistd.h>
14*8617a60dSAndroid Build Coastguard Worker
15*8617a60dSAndroid Build Coastguard Worker #include "2common.h"
16*8617a60dSAndroid Build Coastguard Worker #include "2rsa.h"
17*8617a60dSAndroid Build Coastguard Worker #include "2sha.h"
18*8617a60dSAndroid Build Coastguard Worker #include "2sysincludes.h"
19*8617a60dSAndroid Build Coastguard Worker #include "host_common.h"
20*8617a60dSAndroid Build Coastguard Worker #include "host_common21.h"
21*8617a60dSAndroid Build Coastguard Worker #include "host_key21.h"
22*8617a60dSAndroid Build Coastguard Worker #include "host_key.h"
23*8617a60dSAndroid Build Coastguard Worker #include "host_misc.h"
24*8617a60dSAndroid Build Coastguard Worker #include "host_p11.h"
25*8617a60dSAndroid Build Coastguard Worker
vb2_get_crypto_algorithm(enum vb2_hash_algorithm hash_alg,enum vb2_signature_algorithm sig_alg)26*8617a60dSAndroid Build Coastguard Worker enum vb2_crypto_algorithm vb2_get_crypto_algorithm(
27*8617a60dSAndroid Build Coastguard Worker enum vb2_hash_algorithm hash_alg,
28*8617a60dSAndroid Build Coastguard Worker enum vb2_signature_algorithm sig_alg)
29*8617a60dSAndroid Build Coastguard Worker {
30*8617a60dSAndroid Build Coastguard Worker /* Make sure algorithms are in the range supported by crypto alg */
31*8617a60dSAndroid Build Coastguard Worker if (sig_alg < VB2_SIG_RSA1024 || sig_alg >= VB2_SIG_ALG_COUNT)
32*8617a60dSAndroid Build Coastguard Worker return VB2_ALG_COUNT;
33*8617a60dSAndroid Build Coastguard Worker if (hash_alg < VB2_HASH_SHA1 || hash_alg > VB2_HASH_SHA512)
34*8617a60dSAndroid Build Coastguard Worker return VB2_ALG_COUNT;
35*8617a60dSAndroid Build Coastguard Worker
36*8617a60dSAndroid Build Coastguard Worker return (sig_alg - VB2_SIG_RSA1024)
37*8617a60dSAndroid Build Coastguard Worker * (VB2_HASH_SHA512 - VB2_HASH_SHA1 + 1)
38*8617a60dSAndroid Build Coastguard Worker + (hash_alg - VB2_HASH_SHA1);
39*8617a60dSAndroid Build Coastguard Worker };
40*8617a60dSAndroid Build Coastguard Worker
vb2_read_local_private_key(uint8_t * buf,uint32_t bufsize,struct vb2_private_key * key)41*8617a60dSAndroid Build Coastguard Worker static vb2_error_t vb2_read_local_private_key(uint8_t *buf, uint32_t bufsize,
42*8617a60dSAndroid Build Coastguard Worker struct vb2_private_key *key)
43*8617a60dSAndroid Build Coastguard Worker {
44*8617a60dSAndroid Build Coastguard Worker uint64_t alg = *(uint64_t *)buf;
45*8617a60dSAndroid Build Coastguard Worker key->key_location = PRIVATE_KEY_LOCAL;
46*8617a60dSAndroid Build Coastguard Worker key->hash_alg = vb2_crypto_to_hash(alg);
47*8617a60dSAndroid Build Coastguard Worker key->sig_alg = vb2_crypto_to_signature(alg);
48*8617a60dSAndroid Build Coastguard Worker const unsigned char *start = buf + sizeof(alg);
49*8617a60dSAndroid Build Coastguard Worker
50*8617a60dSAndroid Build Coastguard Worker key->rsa_private_key = d2i_RSAPrivateKey(0, &start, bufsize - sizeof(alg));
51*8617a60dSAndroid Build Coastguard Worker
52*8617a60dSAndroid Build Coastguard Worker if (!key->rsa_private_key) {
53*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Unable to parse RSA private key\n");
54*8617a60dSAndroid Build Coastguard Worker return VB2_ERROR_UNKNOWN;
55*8617a60dSAndroid Build Coastguard Worker }
56*8617a60dSAndroid Build Coastguard Worker return VB2_SUCCESS;
57*8617a60dSAndroid Build Coastguard Worker }
58*8617a60dSAndroid Build Coastguard Worker
vb2_read_p11_private_key(const char * key_info,struct vb2_private_key * key)59*8617a60dSAndroid Build Coastguard Worker static vb2_error_t vb2_read_p11_private_key(const char *key_info, struct vb2_private_key *key)
60*8617a60dSAndroid Build Coastguard Worker {
61*8617a60dSAndroid Build Coastguard Worker /* The format of p11 key info: "remote:{lib_path}:{slot_id}:{key_label}" */
62*8617a60dSAndroid Build Coastguard Worker char *p11_lib = NULL, *p11_label = NULL;
63*8617a60dSAndroid Build Coastguard Worker int p11_slot_id;
64*8617a60dSAndroid Build Coastguard Worker vb2_error_t ret = VB2_ERROR_UNKNOWN;
65*8617a60dSAndroid Build Coastguard Worker if (sscanf(key_info, "remote:%m[^:]:%i:%m[^:]", &p11_lib, &p11_slot_id, &p11_label) !=
66*8617a60dSAndroid Build Coastguard Worker 3) {
67*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Failed to parse pkcs11 key info\n");
68*8617a60dSAndroid Build Coastguard Worker goto done;
69*8617a60dSAndroid Build Coastguard Worker }
70*8617a60dSAndroid Build Coastguard Worker
71*8617a60dSAndroid Build Coastguard Worker if (pkcs11_init(p11_lib) != VB2_SUCCESS) {
72*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Unable to initialize pkcs11 library\n");
73*8617a60dSAndroid Build Coastguard Worker goto done;
74*8617a60dSAndroid Build Coastguard Worker }
75*8617a60dSAndroid Build Coastguard Worker
76*8617a60dSAndroid Build Coastguard Worker struct pkcs11_key *p11_key = pkcs11_get_key(p11_slot_id, p11_label);
77*8617a60dSAndroid Build Coastguard Worker if (!p11_key) {
78*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Unable to get pkcs11 key\n");
79*8617a60dSAndroid Build Coastguard Worker goto done;
80*8617a60dSAndroid Build Coastguard Worker }
81*8617a60dSAndroid Build Coastguard Worker
82*8617a60dSAndroid Build Coastguard Worker key->key_location = PRIVATE_KEY_P11;
83*8617a60dSAndroid Build Coastguard Worker key->p11_key = p11_key;
84*8617a60dSAndroid Build Coastguard Worker key->sig_alg = pkcs11_get_sig_alg(p11_key);
85*8617a60dSAndroid Build Coastguard Worker key->hash_alg = pkcs11_get_hash_alg(p11_key);
86*8617a60dSAndroid Build Coastguard Worker if (key->sig_alg == VB2_SIG_INVALID || key->hash_alg == VB2_HASH_INVALID) {
87*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Unable to get signature or hash algorithm\n");
88*8617a60dSAndroid Build Coastguard Worker pkcs11_free_key(p11_key);
89*8617a60dSAndroid Build Coastguard Worker goto done;
90*8617a60dSAndroid Build Coastguard Worker }
91*8617a60dSAndroid Build Coastguard Worker ret = VB2_SUCCESS;
92*8617a60dSAndroid Build Coastguard Worker done:
93*8617a60dSAndroid Build Coastguard Worker free(p11_lib);
94*8617a60dSAndroid Build Coastguard Worker free(p11_label);
95*8617a60dSAndroid Build Coastguard Worker return ret;
96*8617a60dSAndroid Build Coastguard Worker }
97*8617a60dSAndroid Build Coastguard Worker
is_vb21_private_key(const uint8_t * buf,uint32_t bufsize)98*8617a60dSAndroid Build Coastguard Worker static bool is_vb21_private_key(const uint8_t *buf, uint32_t bufsize)
99*8617a60dSAndroid Build Coastguard Worker {
100*8617a60dSAndroid Build Coastguard Worker const struct vb21_packed_private_key *pkey =
101*8617a60dSAndroid Build Coastguard Worker (const struct vb21_packed_private_key *)buf;
102*8617a60dSAndroid Build Coastguard Worker return bufsize >= sizeof(pkey->c.magic) &&
103*8617a60dSAndroid Build Coastguard Worker pkey->c.magic == VB21_MAGIC_PACKED_PRIVATE_KEY;
104*8617a60dSAndroid Build Coastguard Worker }
105*8617a60dSAndroid Build Coastguard Worker
vb2_read_private_key(const char * key_info)106*8617a60dSAndroid Build Coastguard Worker struct vb2_private_key *vb2_read_private_key(const char *key_info)
107*8617a60dSAndroid Build Coastguard Worker {
108*8617a60dSAndroid Build Coastguard Worker struct vb2_private_key *key = (struct vb2_private_key *)calloc(sizeof(*key), 1);
109*8617a60dSAndroid Build Coastguard Worker if (!key) {
110*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Unable to allocate private key\n");
111*8617a60dSAndroid Build Coastguard Worker return NULL;
112*8617a60dSAndroid Build Coastguard Worker }
113*8617a60dSAndroid Build Coastguard Worker
114*8617a60dSAndroid Build Coastguard Worker static const char p11_prefix[] = "remote";
115*8617a60dSAndroid Build Coastguard Worker static const char local_prefix[] = "local";
116*8617a60dSAndroid Build Coastguard Worker char *colon = strchr(key_info, ':');
117*8617a60dSAndroid Build Coastguard Worker if (colon) {
118*8617a60dSAndroid Build Coastguard Worker int prefix_size = colon - key_info;
119*8617a60dSAndroid Build Coastguard Worker if (!strncmp(key_info, p11_prefix, prefix_size)) {
120*8617a60dSAndroid Build Coastguard Worker if (vb2_read_p11_private_key(key_info, key) != VB2_SUCCESS) {
121*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Unable to read pkcs11 private key\n");
122*8617a60dSAndroid Build Coastguard Worker free(key);
123*8617a60dSAndroid Build Coastguard Worker return NULL;
124*8617a60dSAndroid Build Coastguard Worker }
125*8617a60dSAndroid Build Coastguard Worker return key;
126*8617a60dSAndroid Build Coastguard Worker }
127*8617a60dSAndroid Build Coastguard Worker if (!strncmp(key_info, local_prefix, prefix_size))
128*8617a60dSAndroid Build Coastguard Worker key_info = colon + 1;
129*8617a60dSAndroid Build Coastguard Worker }
130*8617a60dSAndroid Build Coastguard Worker
131*8617a60dSAndroid Build Coastguard Worker // Read the private key from local file.
132*8617a60dSAndroid Build Coastguard Worker uint8_t *buf = NULL;
133*8617a60dSAndroid Build Coastguard Worker uint32_t bufsize = 0;
134*8617a60dSAndroid Build Coastguard Worker if (vb2_read_file(key_info, &buf, &bufsize) != VB2_SUCCESS) {
135*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("unable to read from file %s\n", key_info);
136*8617a60dSAndroid Build Coastguard Worker return NULL;
137*8617a60dSAndroid Build Coastguard Worker }
138*8617a60dSAndroid Build Coastguard Worker
139*8617a60dSAndroid Build Coastguard Worker vb2_error_t rv;
140*8617a60dSAndroid Build Coastguard Worker bool is_vb21 = is_vb21_private_key(buf, bufsize);
141*8617a60dSAndroid Build Coastguard Worker if (is_vb21)
142*8617a60dSAndroid Build Coastguard Worker rv = vb21_private_key_unpack_raw(buf, bufsize, key);
143*8617a60dSAndroid Build Coastguard Worker else
144*8617a60dSAndroid Build Coastguard Worker rv = vb2_read_local_private_key(buf, bufsize, key);
145*8617a60dSAndroid Build Coastguard Worker
146*8617a60dSAndroid Build Coastguard Worker free(buf);
147*8617a60dSAndroid Build Coastguard Worker if (rv != VB2_SUCCESS) {
148*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Unable to read local %s private key\n", is_vb21 ? "vb21" : "vb2");
149*8617a60dSAndroid Build Coastguard Worker free(key);
150*8617a60dSAndroid Build Coastguard Worker return NULL;
151*8617a60dSAndroid Build Coastguard Worker }
152*8617a60dSAndroid Build Coastguard Worker return key;
153*8617a60dSAndroid Build Coastguard Worker }
154*8617a60dSAndroid Build Coastguard Worker
vb2_read_private_key_pem(const char * filename,enum vb2_crypto_algorithm algorithm)155*8617a60dSAndroid Build Coastguard Worker struct vb2_private_key *vb2_read_private_key_pem(
156*8617a60dSAndroid Build Coastguard Worker const char* filename,
157*8617a60dSAndroid Build Coastguard Worker enum vb2_crypto_algorithm algorithm)
158*8617a60dSAndroid Build Coastguard Worker {
159*8617a60dSAndroid Build Coastguard Worker if (algorithm >= VB2_ALG_COUNT) {
160*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("%s() called with invalid algorithm!\n",
161*8617a60dSAndroid Build Coastguard Worker __FUNCTION__);
162*8617a60dSAndroid Build Coastguard Worker return NULL;
163*8617a60dSAndroid Build Coastguard Worker }
164*8617a60dSAndroid Build Coastguard Worker
165*8617a60dSAndroid Build Coastguard Worker /* Read private key */
166*8617a60dSAndroid Build Coastguard Worker FILE *f = fopen(filename, "r");
167*8617a60dSAndroid Build Coastguard Worker if (!f) {
168*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("%s(): Couldn't open key file: %s\n",
169*8617a60dSAndroid Build Coastguard Worker __FUNCTION__, filename);
170*8617a60dSAndroid Build Coastguard Worker return NULL;
171*8617a60dSAndroid Build Coastguard Worker }
172*8617a60dSAndroid Build Coastguard Worker struct rsa_st *rsa_key = PEM_read_RSAPrivateKey(f, NULL, NULL, NULL);
173*8617a60dSAndroid Build Coastguard Worker fclose(f);
174*8617a60dSAndroid Build Coastguard Worker if (!rsa_key) {
175*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("%s(): Couldn't read private key from file: %s\n",
176*8617a60dSAndroid Build Coastguard Worker __FUNCTION__, filename);
177*8617a60dSAndroid Build Coastguard Worker return NULL;
178*8617a60dSAndroid Build Coastguard Worker }
179*8617a60dSAndroid Build Coastguard Worker
180*8617a60dSAndroid Build Coastguard Worker /* Store key and algorithm in our struct */
181*8617a60dSAndroid Build Coastguard Worker struct vb2_private_key *key =
182*8617a60dSAndroid Build Coastguard Worker (struct vb2_private_key *)calloc(sizeof(*key), 1);
183*8617a60dSAndroid Build Coastguard Worker if (!key) {
184*8617a60dSAndroid Build Coastguard Worker RSA_free(rsa_key);
185*8617a60dSAndroid Build Coastguard Worker return NULL;
186*8617a60dSAndroid Build Coastguard Worker }
187*8617a60dSAndroid Build Coastguard Worker key->rsa_private_key = rsa_key;
188*8617a60dSAndroid Build Coastguard Worker key->hash_alg = vb2_crypto_to_hash(algorithm);
189*8617a60dSAndroid Build Coastguard Worker key->sig_alg = vb2_crypto_to_signature(algorithm);
190*8617a60dSAndroid Build Coastguard Worker
191*8617a60dSAndroid Build Coastguard Worker /* Return the key */
192*8617a60dSAndroid Build Coastguard Worker return key;
193*8617a60dSAndroid Build Coastguard Worker }
194*8617a60dSAndroid Build Coastguard Worker
vb2_free_private_key(struct vb2_private_key * key)195*8617a60dSAndroid Build Coastguard Worker void vb2_free_private_key(struct vb2_private_key *key)
196*8617a60dSAndroid Build Coastguard Worker {
197*8617a60dSAndroid Build Coastguard Worker if (!key)
198*8617a60dSAndroid Build Coastguard Worker return;
199*8617a60dSAndroid Build Coastguard Worker
200*8617a60dSAndroid Build Coastguard Worker if (key->key_location == PRIVATE_KEY_LOCAL && key->rsa_private_key)
201*8617a60dSAndroid Build Coastguard Worker RSA_free(key->rsa_private_key);
202*8617a60dSAndroid Build Coastguard Worker else if (key->key_location == PRIVATE_KEY_P11 && key->p11_key)
203*8617a60dSAndroid Build Coastguard Worker pkcs11_free_key(key->p11_key);
204*8617a60dSAndroid Build Coastguard Worker
205*8617a60dSAndroid Build Coastguard Worker if (key->desc)
206*8617a60dSAndroid Build Coastguard Worker free(key->desc);
207*8617a60dSAndroid Build Coastguard Worker
208*8617a60dSAndroid Build Coastguard Worker free(key);
209*8617a60dSAndroid Build Coastguard Worker }
210*8617a60dSAndroid Build Coastguard Worker
vb2_write_private_key(const char * filename,const struct vb2_private_key * key)211*8617a60dSAndroid Build Coastguard Worker vb2_error_t vb2_write_private_key(const char *filename,
212*8617a60dSAndroid Build Coastguard Worker const struct vb2_private_key *key)
213*8617a60dSAndroid Build Coastguard Worker {
214*8617a60dSAndroid Build Coastguard Worker /* Convert back to legacy vb1 algorithm enum */
215*8617a60dSAndroid Build Coastguard Worker uint64_t alg = vb2_get_crypto_algorithm(key->hash_alg, key->sig_alg);
216*8617a60dSAndroid Build Coastguard Worker if (alg == VB2_ALG_COUNT) {
217*8617a60dSAndroid Build Coastguard Worker fprintf(stderr, "Can't find crypto algorithm\n");
218*8617a60dSAndroid Build Coastguard Worker return VB2_ERROR_VB1_CRYPTO_ALGORITHM;
219*8617a60dSAndroid Build Coastguard Worker }
220*8617a60dSAndroid Build Coastguard Worker
221*8617a60dSAndroid Build Coastguard Worker uint8_t *outbuf = NULL;
222*8617a60dSAndroid Build Coastguard Worker int buflen = i2d_RSAPrivateKey(key->rsa_private_key, &outbuf);
223*8617a60dSAndroid Build Coastguard Worker if (buflen <= 0) {
224*8617a60dSAndroid Build Coastguard Worker fprintf(stderr, "Unable to write private key buffer\n");
225*8617a60dSAndroid Build Coastguard Worker return VB2_ERROR_PRIVATE_KEY_WRITE_RSA;
226*8617a60dSAndroid Build Coastguard Worker }
227*8617a60dSAndroid Build Coastguard Worker
228*8617a60dSAndroid Build Coastguard Worker FILE *f = fopen(filename, "wb");
229*8617a60dSAndroid Build Coastguard Worker if (!f) {
230*8617a60dSAndroid Build Coastguard Worker fprintf(stderr, "Unable to open file %s\n", filename);
231*8617a60dSAndroid Build Coastguard Worker free(outbuf);
232*8617a60dSAndroid Build Coastguard Worker return VB2_ERROR_PRIVATE_KEY_WRITE_FILE;
233*8617a60dSAndroid Build Coastguard Worker }
234*8617a60dSAndroid Build Coastguard Worker
235*8617a60dSAndroid Build Coastguard Worker if (1 != fwrite(&alg, sizeof(alg), 1, f) ||
236*8617a60dSAndroid Build Coastguard Worker 1 != fwrite(outbuf, buflen, 1, f)) {
237*8617a60dSAndroid Build Coastguard Worker fprintf(stderr, "Unable to write to file %s\n", filename);
238*8617a60dSAndroid Build Coastguard Worker fclose(f);
239*8617a60dSAndroid Build Coastguard Worker unlink(filename); /* Delete any partial file */
240*8617a60dSAndroid Build Coastguard Worker free(outbuf);
241*8617a60dSAndroid Build Coastguard Worker return VB2_ERROR_PRIVATE_KEY_WRITE_FILE;
242*8617a60dSAndroid Build Coastguard Worker }
243*8617a60dSAndroid Build Coastguard Worker
244*8617a60dSAndroid Build Coastguard Worker fclose(f);
245*8617a60dSAndroid Build Coastguard Worker free(outbuf);
246*8617a60dSAndroid Build Coastguard Worker return VB2_SUCCESS;
247*8617a60dSAndroid Build Coastguard Worker }
248*8617a60dSAndroid Build Coastguard Worker
vb2_init_packed_key(struct vb2_packed_key * key,uint8_t * key_data,uint32_t key_size)249*8617a60dSAndroid Build Coastguard Worker void vb2_init_packed_key(struct vb2_packed_key *key, uint8_t *key_data,
250*8617a60dSAndroid Build Coastguard Worker uint32_t key_size)
251*8617a60dSAndroid Build Coastguard Worker {
252*8617a60dSAndroid Build Coastguard Worker memset(key, 0, sizeof(*key));
253*8617a60dSAndroid Build Coastguard Worker key->key_offset = vb2_offset_of(key, key_data);
254*8617a60dSAndroid Build Coastguard Worker key->key_size = key_size;
255*8617a60dSAndroid Build Coastguard Worker key->algorithm = VB2_ALG_COUNT; /* Key not present yet */
256*8617a60dSAndroid Build Coastguard Worker }
257*8617a60dSAndroid Build Coastguard Worker
vb2_alloc_packed_key(uint32_t key_size,uint32_t algorithm,uint32_t version)258*8617a60dSAndroid Build Coastguard Worker struct vb2_packed_key *vb2_alloc_packed_key(uint32_t key_size,
259*8617a60dSAndroid Build Coastguard Worker uint32_t algorithm,
260*8617a60dSAndroid Build Coastguard Worker uint32_t version)
261*8617a60dSAndroid Build Coastguard Worker {
262*8617a60dSAndroid Build Coastguard Worker struct vb2_packed_key *key =
263*8617a60dSAndroid Build Coastguard Worker (struct vb2_packed_key *)calloc(sizeof(*key) + key_size, 1);
264*8617a60dSAndroid Build Coastguard Worker if (!key)
265*8617a60dSAndroid Build Coastguard Worker return NULL;
266*8617a60dSAndroid Build Coastguard Worker
267*8617a60dSAndroid Build Coastguard Worker key->algorithm = algorithm;
268*8617a60dSAndroid Build Coastguard Worker key->key_version = version;
269*8617a60dSAndroid Build Coastguard Worker key->key_size = key_size;
270*8617a60dSAndroid Build Coastguard Worker key->key_offset = sizeof(*key);
271*8617a60dSAndroid Build Coastguard Worker return key;
272*8617a60dSAndroid Build Coastguard Worker }
273*8617a60dSAndroid Build Coastguard Worker
vb2_copy_packed_key(struct vb2_packed_key * dest,const struct vb2_packed_key * src)274*8617a60dSAndroid Build Coastguard Worker vb2_error_t vb2_copy_packed_key(struct vb2_packed_key *dest,
275*8617a60dSAndroid Build Coastguard Worker const struct vb2_packed_key *src)
276*8617a60dSAndroid Build Coastguard Worker {
277*8617a60dSAndroid Build Coastguard Worker if (dest->key_size < src->key_size)
278*8617a60dSAndroid Build Coastguard Worker return VB2_ERROR_COPY_KEY_SIZE;
279*8617a60dSAndroid Build Coastguard Worker
280*8617a60dSAndroid Build Coastguard Worker dest->key_size = src->key_size;
281*8617a60dSAndroid Build Coastguard Worker dest->algorithm = src->algorithm;
282*8617a60dSAndroid Build Coastguard Worker dest->key_version = src->key_version;
283*8617a60dSAndroid Build Coastguard Worker memcpy(vb2_packed_key_data_mutable(dest),
284*8617a60dSAndroid Build Coastguard Worker vb2_packed_key_data(src),
285*8617a60dSAndroid Build Coastguard Worker src->key_size);
286*8617a60dSAndroid Build Coastguard Worker return VB2_SUCCESS;
287*8617a60dSAndroid Build Coastguard Worker }
288*8617a60dSAndroid Build Coastguard Worker
vb2_read_packed_key(const char * filename)289*8617a60dSAndroid Build Coastguard Worker struct vb2_packed_key *vb2_read_packed_key(const char *filename)
290*8617a60dSAndroid Build Coastguard Worker {
291*8617a60dSAndroid Build Coastguard Worker struct vb2_packed_key *key = NULL;
292*8617a60dSAndroid Build Coastguard Worker uint32_t file_size = 0;
293*8617a60dSAndroid Build Coastguard Worker
294*8617a60dSAndroid Build Coastguard Worker if (VB2_SUCCESS !=
295*8617a60dSAndroid Build Coastguard Worker vb2_read_file(filename, (uint8_t **)&key, &file_size)) {
296*8617a60dSAndroid Build Coastguard Worker return NULL;
297*8617a60dSAndroid Build Coastguard Worker }
298*8617a60dSAndroid Build Coastguard Worker
299*8617a60dSAndroid Build Coastguard Worker if (vb2_packed_key_looks_ok(key, file_size) == VB2_SUCCESS)
300*8617a60dSAndroid Build Coastguard Worker return key;
301*8617a60dSAndroid Build Coastguard Worker
302*8617a60dSAndroid Build Coastguard Worker /* Error */
303*8617a60dSAndroid Build Coastguard Worker free(key);
304*8617a60dSAndroid Build Coastguard Worker return NULL;
305*8617a60dSAndroid Build Coastguard Worker }
306*8617a60dSAndroid Build Coastguard Worker
vb2_read_packed_keyb(const char * filename,uint32_t algorithm,uint32_t version)307*8617a60dSAndroid Build Coastguard Worker struct vb2_packed_key *vb2_read_packed_keyb(const char *filename,
308*8617a60dSAndroid Build Coastguard Worker uint32_t algorithm,
309*8617a60dSAndroid Build Coastguard Worker uint32_t version)
310*8617a60dSAndroid Build Coastguard Worker {
311*8617a60dSAndroid Build Coastguard Worker if (algorithm >= VB2_ALG_COUNT) {
312*8617a60dSAndroid Build Coastguard Worker fprintf(stderr, "%s() - invalid algorithm\n", __func__);
313*8617a60dSAndroid Build Coastguard Worker return NULL;
314*8617a60dSAndroid Build Coastguard Worker }
315*8617a60dSAndroid Build Coastguard Worker if (version > VB2_MAX_KEY_VERSION) {
316*8617a60dSAndroid Build Coastguard Worker /* Currently, TPM only supports 16-bit version */
317*8617a60dSAndroid Build Coastguard Worker fprintf(stderr, "%s() - invalid version %#x\n", __func__,
318*8617a60dSAndroid Build Coastguard Worker version);
319*8617a60dSAndroid Build Coastguard Worker return NULL;
320*8617a60dSAndroid Build Coastguard Worker }
321*8617a60dSAndroid Build Coastguard Worker
322*8617a60dSAndroid Build Coastguard Worker uint8_t *key_data = NULL;
323*8617a60dSAndroid Build Coastguard Worker uint32_t key_size = 0;
324*8617a60dSAndroid Build Coastguard Worker if (VB2_SUCCESS != vb2_read_file(filename, &key_data, &key_size))
325*8617a60dSAndroid Build Coastguard Worker return NULL;
326*8617a60dSAndroid Build Coastguard Worker
327*8617a60dSAndroid Build Coastguard Worker uint32_t expected_key_size =
328*8617a60dSAndroid Build Coastguard Worker vb2_packed_key_size(vb2_crypto_to_signature(algorithm));
329*8617a60dSAndroid Build Coastguard Worker if (!expected_key_size || expected_key_size != key_size) {
330*8617a60dSAndroid Build Coastguard Worker fprintf(stderr, "%s() - wrong key size %u for algorithm %u\n",
331*8617a60dSAndroid Build Coastguard Worker __func__, key_size, algorithm);
332*8617a60dSAndroid Build Coastguard Worker free(key_data);
333*8617a60dSAndroid Build Coastguard Worker return NULL;
334*8617a60dSAndroid Build Coastguard Worker }
335*8617a60dSAndroid Build Coastguard Worker
336*8617a60dSAndroid Build Coastguard Worker struct vb2_packed_key *key =
337*8617a60dSAndroid Build Coastguard Worker vb2_alloc_packed_key(key_size, algorithm, version);
338*8617a60dSAndroid Build Coastguard Worker if (!key) {
339*8617a60dSAndroid Build Coastguard Worker free(key_data);
340*8617a60dSAndroid Build Coastguard Worker return NULL;
341*8617a60dSAndroid Build Coastguard Worker }
342*8617a60dSAndroid Build Coastguard Worker memcpy(vb2_packed_key_data_mutable(key), key_data, key_size);
343*8617a60dSAndroid Build Coastguard Worker
344*8617a60dSAndroid Build Coastguard Worker free(key_data);
345*8617a60dSAndroid Build Coastguard Worker return key;
346*8617a60dSAndroid Build Coastguard Worker }
347*8617a60dSAndroid Build Coastguard Worker
vb2_write_packed_key(const char * filename,const struct vb2_packed_key * key)348*8617a60dSAndroid Build Coastguard Worker vb2_error_t vb2_write_packed_key(const char *filename,
349*8617a60dSAndroid Build Coastguard Worker const struct vb2_packed_key *key)
350*8617a60dSAndroid Build Coastguard Worker {
351*8617a60dSAndroid Build Coastguard Worker /* Copy the key, so its data is contiguous with the header */
352*8617a60dSAndroid Build Coastguard Worker struct vb2_packed_key *kcopy =
353*8617a60dSAndroid Build Coastguard Worker vb2_alloc_packed_key(key->key_size, 0, 0);
354*8617a60dSAndroid Build Coastguard Worker if (!kcopy)
355*8617a60dSAndroid Build Coastguard Worker return VB2_ERROR_PACKED_KEY_ALLOC;
356*8617a60dSAndroid Build Coastguard Worker if (VB2_SUCCESS != vb2_copy_packed_key(kcopy, key)) {
357*8617a60dSAndroid Build Coastguard Worker free(kcopy);
358*8617a60dSAndroid Build Coastguard Worker return VB2_ERROR_PACKED_KEY_COPY;
359*8617a60dSAndroid Build Coastguard Worker }
360*8617a60dSAndroid Build Coastguard Worker
361*8617a60dSAndroid Build Coastguard Worker /* Write the copy, then free it */
362*8617a60dSAndroid Build Coastguard Worker vb2_error_t rv = vb2_write_file(filename, kcopy,
363*8617a60dSAndroid Build Coastguard Worker kcopy->key_offset + kcopy->key_size);
364*8617a60dSAndroid Build Coastguard Worker free(kcopy);
365*8617a60dSAndroid Build Coastguard Worker return rv;
366*8617a60dSAndroid Build Coastguard Worker }
367*8617a60dSAndroid Build Coastguard Worker
vb2_packed_key_looks_ok(const struct vb2_packed_key * key,uint32_t size)368*8617a60dSAndroid Build Coastguard Worker vb2_error_t vb2_packed_key_looks_ok(const struct vb2_packed_key *key,
369*8617a60dSAndroid Build Coastguard Worker uint32_t size)
370*8617a60dSAndroid Build Coastguard Worker {
371*8617a60dSAndroid Build Coastguard Worker struct vb2_public_key pubkey;
372*8617a60dSAndroid Build Coastguard Worker vb2_error_t rv;
373*8617a60dSAndroid Build Coastguard Worker
374*8617a60dSAndroid Build Coastguard Worker rv = vb2_unpack_key_buffer(&pubkey, (const uint8_t *)key, size);
375*8617a60dSAndroid Build Coastguard Worker if (rv)
376*8617a60dSAndroid Build Coastguard Worker return rv;
377*8617a60dSAndroid Build Coastguard Worker
378*8617a60dSAndroid Build Coastguard Worker if (key->key_version > VB2_MAX_KEY_VERSION) {
379*8617a60dSAndroid Build Coastguard Worker /* Currently, TPM only supports 16-bit version */
380*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("packed key invalid version\n");
381*8617a60dSAndroid Build Coastguard Worker return VB2_ERROR_PACKED_KEY_VERSION;
382*8617a60dSAndroid Build Coastguard Worker }
383*8617a60dSAndroid Build Coastguard Worker
384*8617a60dSAndroid Build Coastguard Worker return VB2_SUCCESS;
385*8617a60dSAndroid Build Coastguard Worker }
386*8617a60dSAndroid Build Coastguard Worker
vb2_unpack_key_data(struct vb2_public_key * key,const uint8_t * key_data,uint32_t key_size)387*8617a60dSAndroid Build Coastguard Worker vb2_error_t vb2_unpack_key_data(struct vb2_public_key *key,
388*8617a60dSAndroid Build Coastguard Worker const uint8_t *key_data, uint32_t key_size)
389*8617a60dSAndroid Build Coastguard Worker {
390*8617a60dSAndroid Build Coastguard Worker const uint32_t *buf32 = (const uint32_t *)key_data;
391*8617a60dSAndroid Build Coastguard Worker uint32_t expected_key_size = vb2_packed_key_size(key->sig_alg);
392*8617a60dSAndroid Build Coastguard Worker
393*8617a60dSAndroid Build Coastguard Worker /* Make sure buffer is the correct length */
394*8617a60dSAndroid Build Coastguard Worker if (!expected_key_size || expected_key_size != key_size) {
395*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Wrong key size for algorithm\n");
396*8617a60dSAndroid Build Coastguard Worker return VB2_ERROR_UNPACK_KEY_SIZE;
397*8617a60dSAndroid Build Coastguard Worker }
398*8617a60dSAndroid Build Coastguard Worker
399*8617a60dSAndroid Build Coastguard Worker /* Check for alignment */
400*8617a60dSAndroid Build Coastguard Worker if (!vb2_aligned(buf32, sizeof(uint32_t)))
401*8617a60dSAndroid Build Coastguard Worker return VB2_ERROR_UNPACK_KEY_ALIGN;
402*8617a60dSAndroid Build Coastguard Worker
403*8617a60dSAndroid Build Coastguard Worker key->arrsize = buf32[0];
404*8617a60dSAndroid Build Coastguard Worker
405*8617a60dSAndroid Build Coastguard Worker /* Validity check key array size */
406*8617a60dSAndroid Build Coastguard Worker if (key->arrsize * sizeof(uint32_t) != vb2_rsa_sig_size(key->sig_alg))
407*8617a60dSAndroid Build Coastguard Worker return VB2_ERROR_UNPACK_KEY_ARRAY_SIZE;
408*8617a60dSAndroid Build Coastguard Worker
409*8617a60dSAndroid Build Coastguard Worker key->n0inv = buf32[1];
410*8617a60dSAndroid Build Coastguard Worker
411*8617a60dSAndroid Build Coastguard Worker /* Arrays point inside the key data */
412*8617a60dSAndroid Build Coastguard Worker key->n = buf32 + 2;
413*8617a60dSAndroid Build Coastguard Worker key->rr = buf32 + 2 + key->arrsize;
414*8617a60dSAndroid Build Coastguard Worker
415*8617a60dSAndroid Build Coastguard Worker return VB2_SUCCESS;
416*8617a60dSAndroid Build Coastguard Worker }
417