1 /* 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 "cryptolib.h"
17 #include "host_common.h"
18 #include "host_key.h"
19 #include "host_misc.h"
20 #include "vboot_common.h"
21
22
PrivateKeyReadPem(const char * filename,uint64_t algorithm)23 VbPrivateKey* PrivateKeyReadPem(const char* filename, uint64_t algorithm) {
24
25 VbPrivateKey* key;
26 RSA* rsa_key;
27 FILE* f;
28
29 if (algorithm >= kNumAlgorithms) {
30 VBDEBUG(("%s() called with invalid algorithm!\n", __FUNCTION__));
31 return NULL;
32 }
33
34 /* Read private key */
35 f = fopen(filename, "r");
36 if (!f) {
37 VBDEBUG(("%s(): Couldn't open key file: %s\n", __FUNCTION__, filename));
38 return NULL;
39 }
40 rsa_key = PEM_read_RSAPrivateKey(f, NULL, NULL, NULL);
41 fclose(f);
42 if (!rsa_key) {
43 VBDEBUG(("%s(): Couldn't read private key from file: %s\n", __FUNCTION__,
44 filename));
45 return NULL;
46 }
47
48 /* Store key and algorithm in our struct */
49 key = (VbPrivateKey*)malloc(sizeof(VbPrivateKey));
50 if (!key) {
51 RSA_free(rsa_key);
52 return NULL;
53 }
54 key->rsa_private_key = rsa_key;
55 key->algorithm = algorithm;
56
57 /* Return the key */
58 return key;
59 }
60
61
PrivateKeyFree(VbPrivateKey * key)62 void PrivateKeyFree(VbPrivateKey* key) {
63 if (!key)
64 return;
65 if (key->rsa_private_key)
66 RSA_free(key->rsa_private_key);
67 free(key);
68 }
69
70
71 /* Write a private key to a file in .vbprivk format. */
PrivateKeyWrite(const char * filename,const VbPrivateKey * key)72 int PrivateKeyWrite(const char* filename, const VbPrivateKey* key) {
73 uint8_t *outbuf = 0;
74 int buflen;
75 FILE *f;
76
77 buflen = i2d_RSAPrivateKey(key->rsa_private_key, &outbuf);
78 if (buflen <= 0) {
79 VbExError("Unable to write private key buffer\n");
80 return 1;
81 }
82
83 f = fopen(filename, "wb");
84 if (!f) {
85 VbExError("Unable to open file %s\n", filename);
86 free(outbuf);
87 return 1;
88 }
89
90 if (1 != fwrite(&key->algorithm, sizeof(key->algorithm), 1, f)) {
91 VbExError("Unable to write to file %s\n", filename);
92 fclose(f);
93 free(outbuf);
94 unlink(filename); /* Delete any partial file */
95 }
96
97 if (1 != fwrite(outbuf, buflen, 1, f)) {
98 VbExError("Unable to write to file %s\n", filename);
99 fclose(f);
100 unlink(filename); /* Delete any partial file */
101 free(outbuf);
102 }
103
104 fclose(f);
105 free(outbuf);
106 return 0;
107 }
108
PrivateKeyRead(const char * filename)109 VbPrivateKey* PrivateKeyRead(const char* filename) {
110 VbPrivateKey *key;
111 uint64_t filelen = 0;
112 uint8_t *buffer;
113 const unsigned char *start;
114
115 buffer = ReadFile(filename, &filelen);
116 if (!buffer) {
117 VbExError("unable to read from file %s\n", filename);
118 return 0;
119 }
120
121 key = (VbPrivateKey*)malloc(sizeof(VbPrivateKey));
122 if (!key) {
123 VbExError("Unable to allocate VbPrivateKey\n");
124 free(buffer);
125 return 0;
126 }
127
128 key->algorithm = *(typeof(key->algorithm) *)buffer;
129 start = buffer + sizeof(key->algorithm);
130
131 key->rsa_private_key = d2i_RSAPrivateKey(0, &start,
132 filelen - sizeof(key->algorithm));
133
134 if (!key->rsa_private_key) {
135 VbExError("Unable to parse RSA private key\n");
136 free(buffer);
137 free(key);
138 return 0;
139 }
140
141 free(buffer);
142 return key;
143 }
144
145
146 /* Allocate a new public key with space for a [key_size] byte key. */
PublicKeyAlloc(uint64_t key_size,uint64_t algorithm,uint64_t version)147 VbPublicKey* PublicKeyAlloc(uint64_t key_size, uint64_t algorithm,
148 uint64_t version) {
149 VbPublicKey* key = (VbPublicKey*)malloc(sizeof(VbPublicKey) + key_size);
150 if (!key)
151 return NULL;
152
153 key->algorithm = algorithm;
154 key->key_version = version;
155 key->key_size = key_size;
156 key->key_offset = sizeof(VbPublicKey);
157 return key;
158 }
159
PublicKeyReadKeyb(const char * filename,uint64_t algorithm,uint64_t version)160 VbPublicKey* PublicKeyReadKeyb(const char* filename, uint64_t algorithm,
161 uint64_t version) {
162 VbPublicKey* key;
163 uint8_t* key_data;
164 uint64_t key_size;
165 uint64_t expected_key_size;
166
167 if (algorithm >= kNumAlgorithms) {
168 VBDEBUG(("PublicKeyReadKeyb() called with invalid algorithm!\n"));
169 return NULL;
170 }
171 if (version > 0xFFFF) {
172 /* Currently, TPM only supports 16-bit version */
173 VBDEBUG(("PublicKeyReadKeyb() called with invalid version!\n"));
174 return NULL;
175 }
176
177 key_data = ReadFile(filename, &key_size);
178 if (!key_data)
179 return NULL;
180
181 if (!RSAProcessedKeySize(algorithm, &expected_key_size) ||
182 expected_key_size != key_size) {
183 VBDEBUG(("PublicKeyReadKeyb() wrong key size for algorithm\n"));
184 free(key_data);
185 return NULL;
186 }
187
188 key = PublicKeyAlloc(key_size, algorithm, version);
189 if (!key) {
190 free(key_data);
191 return NULL;
192 }
193 Memcpy(GetPublicKeyData(key), key_data, key_size);
194
195 free(key_data);
196 return key;
197 }
198
199
PublicKeyLooksOkay(VbPublicKey * key,uint64_t file_size)200 int PublicKeyLooksOkay(VbPublicKey *key, uint64_t file_size)
201 {
202 uint64_t key_size;
203
204 /* Sanity-check key data */
205 if (0 != VerifyPublicKeyInside(key, file_size, key)) {
206 VBDEBUG(("PublicKeyRead() not a VbPublicKey\n"));
207 return 0;
208 }
209 if (key->algorithm >= kNumAlgorithms) {
210 VBDEBUG(("PublicKeyRead() invalid algorithm\n"));
211 return 0;
212 }
213 if (key->key_version > 0xFFFF) {
214 VBDEBUG(("PublicKeyRead() invalid version\n"));
215 return 0; /* Currently, TPM only supports 16-bit version */
216 }
217 if (!RSAProcessedKeySize(key->algorithm, &key_size) ||
218 key_size != key->key_size) {
219 VBDEBUG(("PublicKeyRead() wrong key size for algorithm\n"));
220 return 0;
221 }
222
223 /* Success */
224 return 1;
225 }
226
227
228
PublicKeyRead(const char * filename)229 VbPublicKey* PublicKeyRead(const char* filename) {
230 VbPublicKey* key;
231 uint64_t file_size;
232
233 key = (VbPublicKey*)ReadFile(filename, &file_size);
234 if (!key)
235 return NULL;
236
237 if (PublicKeyLooksOkay(key, file_size))
238 return key;
239
240 /* Error */
241 free(key);
242 return NULL;
243 }
244
PublicKeyWrite(const char * filename,const VbPublicKey * key)245 int PublicKeyWrite(const char* filename, const VbPublicKey* key) {
246 VbPublicKey* kcopy;
247 int rv;
248
249 /* Copy the key, so its data is contiguous with the header */
250 kcopy = PublicKeyAlloc(key->key_size, 0, 0);
251 if (!kcopy)
252 return 1;
253 if (0 != PublicKeyCopy(kcopy, key)) {
254 free(kcopy);
255 return 1;
256 }
257
258 /* Write the copy, then free it */
259 rv = WriteFile(filename, kcopy, kcopy->key_offset + kcopy->key_size);
260 free(kcopy);
261 return rv;
262 }
263