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