Randall Spangler | 814aaf0 | 2016-06-17 10:48:16 -0700 | [diff] [blame] | 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 "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 Spangler | d46461c | 2016-06-22 16:46:23 -0700 | [diff] [blame] | 28 | enum 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 Spangler | 814aaf0 | 2016-06-17 10:48:16 -0700 | [diff] [blame] | 43 | struct 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 | |
| 79 | struct vb2_private_key *vb2_read_private_key_pem( |
| 80 | const char* filename, |
| 81 | enum vb2_crypto_algorithm algorithm) |
| 82 | { |
Randall Spangler | 814aaf0 | 2016-06-17 10:48:16 -0700 | [diff] [blame] | 83 | 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 Spangler | d46461c | 2016-06-22 16:46:23 -0700 | [diff] [blame] | 90 | FILE *f = fopen(filename, "r"); |
Randall Spangler | 814aaf0 | 2016-06-17 10:48:16 -0700 | [diff] [blame] | 91 | if (!f) { |
| 92 | VB2_DEBUG("%s(): Couldn't open key file: %s\n", |
| 93 | __FUNCTION__, filename); |
| 94 | return NULL; |
| 95 | } |
Randall Spangler | d46461c | 2016-06-22 16:46:23 -0700 | [diff] [blame] | 96 | struct rsa_st *rsa_key = PEM_read_RSAPrivateKey(f, NULL, NULL, NULL); |
Randall Spangler | 814aaf0 | 2016-06-17 10:48:16 -0700 | [diff] [blame] | 97 | 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 Spangler | 939cc3a | 2016-06-21 15:23:32 -0700 | [diff] [blame] | 118 | |
Randall Spangler | d46461c | 2016-06-22 16:46:23 -0700 | [diff] [blame] | 119 | void 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 | |
| 128 | int 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 Spangler | 939cc3a | 2016-06-21 15:23:32 -0700 | [diff] [blame] | 164 | void 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 Spangler | f7559e4 | 2016-06-23 13:45:59 -0700 | [diff] [blame] | 173 | struct 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 Spangler | 939cc3a | 2016-06-21 15:23:32 -0700 | [diff] [blame] | 189 | int 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 | |
| 203 | struct vb2_packed_key *vb2_read_packed_key(const char *filename) |
| 204 | { |
Randall Spangler | 770202f | 2016-09-28 11:54:20 -0700 | [diff] [blame] | 205 | struct vb2_packed_key *key = NULL; |
| 206 | uint32_t file_size = 0; |
Randall Spangler | 939cc3a | 2016-06-21 15:23:32 -0700 | [diff] [blame] | 207 | |
| 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 Spangler | f7559e4 | 2016-06-23 13:45:59 -0700 | [diff] [blame] | 220 | |
| 221 | struct 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 | |
| 262 | int 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 | } |