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