blob: 0f4168ed3afbb5c35559a65254153f747e8b0330 [file] [log] [blame]
Randall Spangler814aaf02016-06-17 10:48:16 -07001/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
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/* TODO: change all 'return 0', 'return 1' into meaningful return codes */
9
10#include <openssl/pem.h>
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <unistd.h>
15
16#include "2sysincludes.h"
17#include "2common.h"
18#include "2rsa.h"
19#include "2sha.h"
20#include "cryptolib.h"
21#include "host_common.h"
22#include "host_key.h"
23#include "host_key2.h"
24#include "host_misc.h"
25#include "vb2_common.h"
26#include "vboot_common.h"
27
Randall Spanglerd46461c2016-06-22 16:46:23 -070028enum vb2_crypto_algorithm vb2_get_crypto_algorithm(
29 enum vb2_hash_algorithm hash_alg,
30 enum vb2_signature_algorithm sig_alg)
31{
32 /* Make sure algorithms are in the range supported by crypto alg */
33 if (sig_alg < VB2_SIG_RSA1024 || sig_alg > VB2_SIG_RSA8192)
34 return VB2_ALG_COUNT;
35 if (hash_alg < VB2_HASH_SHA1 || hash_alg > VB2_HASH_SHA512)
36 return VB2_ALG_COUNT;
37
38 return (sig_alg - VB2_SIG_RSA1024)
39 * (VB2_HASH_SHA512 - VB2_HASH_SHA1 + 1)
40 + (hash_alg - VB2_HASH_SHA1);
41};
42
Randall Spangler814aaf02016-06-17 10:48:16 -070043struct vb2_private_key *vb2_read_private_key(const char *filename)
44{
45 uint8_t *buf = NULL;
46 uint32_t bufsize = 0;
47 if (VB2_SUCCESS != vb2_read_file(filename, &buf, &bufsize)) {
48 VbExError("unable to read from file %s\n", filename);
49 return NULL;
50 }
51
52 struct vb2_private_key *key =
53 (struct vb2_private_key *)calloc(sizeof(*key), 1);
54 if (!key) {
55 VbExError("Unable to allocate private key\n");
56 free(buf);
57 return NULL;
58 }
59
60 uint64_t alg = *(uint64_t *)buf;
61 key->hash_alg = vb2_crypto_to_hash(alg);
62 key->sig_alg = vb2_crypto_to_signature(alg);
63 const unsigned char *start = buf + sizeof(alg);
64
65 key->rsa_private_key =
66 d2i_RSAPrivateKey(0, &start, bufsize - sizeof(alg));
67
68 if (!key->rsa_private_key) {
69 VbExError("Unable to parse RSA private key\n");
70 free(buf);
71 free(key);
72 return NULL;
73 }
74
75 free(buf);
76 return key;
77}
78
79struct vb2_private_key *vb2_read_private_key_pem(
80 const char* filename,
81 enum vb2_crypto_algorithm algorithm)
82{
Randall Spangler814aaf02016-06-17 10:48:16 -070083 if (algorithm >= VB2_ALG_COUNT) {
84 VB2_DEBUG("%s() called with invalid algorithm!\n",
85 __FUNCTION__);
86 return NULL;
87 }
88
89 /* Read private key */
Randall Spanglerd46461c2016-06-22 16:46:23 -070090 FILE *f = fopen(filename, "r");
Randall Spangler814aaf02016-06-17 10:48:16 -070091 if (!f) {
92 VB2_DEBUG("%s(): Couldn't open key file: %s\n",
93 __FUNCTION__, filename);
94 return NULL;
95 }
Randall Spanglerd46461c2016-06-22 16:46:23 -070096 struct rsa_st *rsa_key = PEM_read_RSAPrivateKey(f, NULL, NULL, NULL);
Randall Spangler814aaf02016-06-17 10:48:16 -070097 fclose(f);
98 if (!rsa_key) {
99 VB2_DEBUG("%s(): Couldn't read private key from file: %s\n",
100 __FUNCTION__, filename);
101 return NULL;
102 }
103
104 /* Store key and algorithm in our struct */
105 struct vb2_private_key *key =
106 (struct vb2_private_key *)calloc(sizeof(*key), 1);
107 if (!key) {
108 RSA_free(rsa_key);
109 return NULL;
110 }
111 key->rsa_private_key = rsa_key;
112 key->hash_alg = vb2_crypto_to_hash(algorithm);
113 key->sig_alg = vb2_crypto_to_signature(algorithm);
114
115 /* Return the key */
116 return key;
117}
Randall Spangler939cc3a2016-06-21 15:23:32 -0700118
Randall Spanglerd46461c2016-06-22 16:46:23 -0700119void vb2_free_private_key(struct vb2_private_key *key)
120{
121 if (!key)
122 return;
123 if (key->rsa_private_key)
124 RSA_free(key->rsa_private_key);
125 free(key);
126}
127
128int vb2_write_private_key(const char *filename,
129 const struct vb2_private_key *key)
130{
131 /* Convert back to legacy vb1 algorithm enum */
132 uint64_t alg = vb2_get_crypto_algorithm(key->hash_alg, key->sig_alg);
133 if (alg == VB2_ALG_COUNT)
134 return VB2_ERROR_VB1_CRYPTO_ALGORITHM;
135
136 uint8_t *outbuf = NULL;
137 int buflen = i2d_RSAPrivateKey(key->rsa_private_key, &outbuf);
138 if (buflen <= 0) {
139 fprintf(stderr, "Unable to write private key buffer\n");
140 return VB2_ERROR_PRIVATE_KEY_WRITE_RSA;
141 }
142
143 FILE *f = fopen(filename, "wb");
144 if (!f) {
145 fprintf(stderr, "Unable to open file %s\n", filename);
146 free(outbuf);
147 return VB2_ERROR_PRIVATE_KEY_WRITE_FILE;
148 }
149
150 if (1 != fwrite(&alg, sizeof(alg), 1, f) ||
151 1 != fwrite(outbuf, buflen, 1, f)) {
152 fprintf(stderr, "Unable to write to file %s\n", filename);
153 fclose(f);
154 unlink(filename); /* Delete any partial file */
155 free(outbuf);
156 return VB2_ERROR_PRIVATE_KEY_WRITE_FILE;
157 }
158
159 fclose(f);
160 free(outbuf);
161 return VB2_SUCCESS;
162}
163
Randall Spangler939cc3a2016-06-21 15:23:32 -0700164void vb2_init_packed_key(struct vb2_packed_key *key, uint8_t *key_data,
165 uint32_t key_size)
166{
167 memset(key, 0, sizeof(*key));
168 key->key_offset = vb2_offset_of(key, key_data);
169 key->key_size = key_size;
170 key->algorithm = VB2_ALG_COUNT; /* Key not present yet */
171}
172
Randall Spanglerf7559e42016-06-23 13:45:59 -0700173struct vb2_packed_key *vb2_alloc_packed_key(uint32_t key_size,
174 uint32_t algorithm,
175 uint32_t version)
176{
177 struct vb2_packed_key *key =
178 (struct vb2_packed_key *)calloc(sizeof(*key) + key_size, 1);
179 if (!key)
180 return NULL;
181
182 key->algorithm = algorithm;
183 key->key_version = version;
184 key->key_size = key_size;
185 key->key_offset = sizeof(*key);
186 return key;
187}
188
Randall Spangler939cc3a2016-06-21 15:23:32 -0700189int vb2_copy_packed_key(struct vb2_packed_key *dest,
190 const struct vb2_packed_key *src)
191{
192 if (dest->key_size < src->key_size)
193 return VB2_ERROR_COPY_KEY_SIZE;
194
195 dest->key_size = src->key_size;
196 dest->algorithm = src->algorithm;
197 dest->key_version = src->key_version;
198 memcpy((uint8_t *)vb2_packed_key_data(dest),
199 vb2_packed_key_data(src), src->key_size);
200 return VB2_SUCCESS;
201}
202
203struct vb2_packed_key *vb2_read_packed_key(const char *filename)
204{
Randall Spangler770202f2016-09-28 11:54:20 -0700205 struct vb2_packed_key *key = NULL;
206 uint32_t file_size = 0;
Randall Spangler939cc3a2016-06-21 15:23:32 -0700207
208 if (VB2_SUCCESS !=
209 vb2_read_file(filename, (uint8_t **)&key, &file_size)) {
210 return NULL;
211 }
212
213 if (packed_key_looks_ok(key, file_size))
214 return key;
215
216 /* Error */
217 free(key);
218 return NULL;
219}
Randall Spanglerf7559e42016-06-23 13:45:59 -0700220
221struct vb2_packed_key *vb2_read_packed_keyb(const char *filename,
222 uint32_t algorithm,
223 uint32_t version)
224{
225 if (algorithm >= VB2_ALG_COUNT) {
226 fprintf(stderr, "%s() - invalid algorithm\n", __func__);
227 return NULL;
228 }
229 if (version > VB2_MAX_KEY_VERSION) {
230 /* Currently, TPM only supports 16-bit version */
231 fprintf(stderr, "%s() - invalid version 0x%x\n", __func__,
232 version);
233 return NULL;
234 }
235
236 uint8_t *key_data = NULL;
237 uint32_t key_size = 0;
238 if (VB2_SUCCESS != vb2_read_file(filename, &key_data, &key_size))
239 return NULL;
240
241 uint64_t expected_key_size;
242 if (!RSAProcessedKeySize(algorithm, &expected_key_size) ||
243 expected_key_size != key_size) {
244 fprintf(stderr, "%s() - wrong key size %u for algorithm %u\n",
245 __func__, key_size, algorithm);
246 free(key_data);
247 return NULL;
248 }
249
250 struct vb2_packed_key *key =
251 vb2_alloc_packed_key(key_size, algorithm, version);
252 if (!key) {
253 free(key_data);
254 return NULL;
255 }
256 memcpy((uint8_t *)vb2_packed_key_data(key), key_data, key_size);
257
258 free(key_data);
259 return key;
260}
261
262int vb2_write_packed_key(const char *filename,
263 const struct vb2_packed_key *key)
264{
265 /* Copy the key, so its data is contiguous with the header */
266 struct vb2_packed_key *kcopy =
267 vb2_alloc_packed_key(key->key_size, 0, 0);
268 if (!kcopy)
269 return VB2_ERROR_PACKED_KEY_ALLOC;
270 if (VB2_SUCCESS != vb2_copy_packed_key(kcopy, key)) {
271 free(kcopy);
272 return VB2_ERROR_PACKED_KEY_COPY;
273 }
274
275 /* Write the copy, then free it */
276 int rv = vb2_write_file(filename, kcopy,
277 kcopy->key_offset + kcopy->key_size);
278 free(kcopy);
279 return rv;
280}