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