| OLD | NEW |
| 1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| 2 * Use of this source code is governed by a BSD-style license that can be | 2 * Use of this source code is governed by a BSD-style license that can be |
| 3 * found in the LICENSE file. | 3 * found in the LICENSE file. |
| 4 * | 4 * |
| 5 * Host functions for keys. | 5 * Host functions for keys. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 /* TODO: change all 'return 0', 'return 1' into meaningful return codes */ | 8 /* TODO: change all 'return 0', 'return 1' into meaningful return codes */ |
| 9 | 9 |
| 10 #define OPENSSL_NO_SHA | 10 #define OPENSSL_NO_SHA |
| 11 #include <openssl/engine.h> | 11 #include <openssl/engine.h> |
| 12 #include <openssl/pem.h> | 12 #include <openssl/pem.h> |
| 13 #include <openssl/rsa.h> | 13 #include <openssl/rsa.h> |
| 14 #include <openssl/x509.h> |
| 14 | 15 |
| 15 #include <stdio.h> | 16 #include <stdio.h> |
| 16 #include <stdlib.h> | 17 #include <stdlib.h> |
| 17 #include <unistd.h> | 18 #include <unistd.h> |
| 18 | 19 |
| 19 #include "host_key.h" | 20 #include "host_key.h" |
| 20 | 21 |
| 21 #include "cryptolib.h" | 22 #include "cryptolib.h" |
| 22 #include "host_misc.h" | 23 #include "host_misc.h" |
| 23 #include "utility.h" | 24 #include "utility.h" |
| 24 #include "vboot_common.h" | 25 #include "vboot_common.h" |
| 25 | 26 |
| 26 | 27 |
| 27 VbPrivateKey* PrivateKeyReadPem(const char* filename, uint64_t algorithm) { | 28 VbPrivateKey* PrivateKeyReadPem(const char* filename, uint64_t algorithm) { |
| 28 | 29 |
| 29 VbPrivateKey* key; | 30 VbPrivateKey* key; |
| 30 RSA* rsa_key; | 31 RSA* rsa_key; |
| 31 FILE* f; | 32 FILE* f; |
| 32 | 33 |
| 33 if (algorithm >= kNumAlgorithms) { | 34 if (algorithm >= kNumAlgorithms) { |
| 34 debug("%s() called with invalid algorithm!\n", __FUNCTION__); | 35 VBDEBUG(("%s() called with invalid algorithm!\n", __FUNCTION__)); |
| 35 return NULL; | 36 return NULL; |
| 36 } | 37 } |
| 37 | 38 |
| 38 /* Read private key */ | 39 /* Read private key */ |
| 39 f = fopen(filename, "r"); | 40 f = fopen(filename, "r"); |
| 40 if (!f) { | 41 if (!f) { |
| 41 debug("%s(): Couldn't open key file: %s\n", __FUNCTION__, filename); | 42 VBDEBUG(("%s(): Couldn't open key file: %s\n", __FUNCTION__, filename)); |
| 42 return NULL; | 43 return NULL; |
| 43 } | 44 } |
| 44 rsa_key = PEM_read_RSAPrivateKey(f, NULL, NULL, NULL); | 45 rsa_key = PEM_read_RSAPrivateKey(f, NULL, NULL, NULL); |
| 45 fclose(f); | 46 fclose(f); |
| 46 if (!rsa_key) { | 47 if (!rsa_key) { |
| 47 debug("%s(): Couldn't read private key from file: %s\n", __FUNCTION__, | 48 VBDEBUG(("%s(): Couldn't read private key from file: %s\n", __FUNCTION__, |
| 48 filename); | 49 filename)); |
| 49 return NULL; | 50 return NULL; |
| 50 } | 51 } |
| 51 | 52 |
| 52 /* Store key and algorithm in our struct */ | 53 /* Store key and algorithm in our struct */ |
| 53 key = (VbPrivateKey*)Malloc(sizeof(VbPrivateKey)); | 54 key = (VbPrivateKey*)Malloc(sizeof(VbPrivateKey)); |
| 54 if (!key) { | 55 if (!key) { |
| 55 RSA_free(rsa_key); | 56 RSA_free(rsa_key); |
| 56 return NULL; | 57 return NULL; |
| 57 } | 58 } |
| 58 key->rsa_private_key = rsa_key; | 59 key->rsa_private_key = rsa_key; |
| 59 key->algorithm = algorithm; | 60 key->algorithm = algorithm; |
| 60 | 61 |
| 61 /* Return the key */ | 62 /* Return the key */ |
| 62 return key; | 63 return key; |
| 63 } | 64 } |
| 64 | 65 |
| 65 | 66 |
| 66 void PrivateKeyFree(VbPrivateKey* key) { | 67 void PrivateKeyFree(VbPrivateKey* key) { |
| 67 if (!key) | 68 if (!key) |
| 68 return; | 69 return; |
| 69 if (key->rsa_private_key) | 70 if (key->rsa_private_key) |
| 70 RSA_free(key->rsa_private_key); | 71 RSA_free(key->rsa_private_key); |
| 71 Free(key); | 72 Free(key); |
| 72 } | 73 } |
| 73 | 74 |
| 74 | 75 |
| 76 /* Write a private key to a file in .vbprivk format. */ |
| 77 int PrivateKeyWrite(const char* filename, const VbPrivateKey* key) { |
| 78 uint8_t *outbuf = 0; |
| 79 int buflen; |
| 80 FILE *f; |
| 81 |
| 82 buflen = i2d_RSAPrivateKey(key->rsa_private_key, &outbuf); |
| 83 if (buflen <= 0) { |
| 84 error("Unable to write private key buffer\n"); |
| 85 return 1; |
| 86 } |
| 87 |
| 88 f = fopen(filename, "wb"); |
| 89 if (!f) { |
| 90 error("Unable to open file %s\n", filename); |
| 91 Free(outbuf); |
| 92 return 1; |
| 93 } |
| 94 |
| 95 if (1 != fwrite(&key->algorithm, sizeof(key->algorithm), 1, f)) { |
| 96 error("Unable to write to file %s\n", filename); |
| 97 fclose(f); |
| 98 Free(outbuf); |
| 99 unlink(filename); /* Delete any partial file */ |
| 100 } |
| 101 |
| 102 if (1 != fwrite(outbuf, buflen, 1, f)) { |
| 103 error("Unable to write to file %s\n", filename); |
| 104 fclose(f); |
| 105 unlink(filename); /* Delete any partial file */ |
| 106 Free(outbuf); |
| 107 } |
| 108 |
| 109 fclose(f); |
| 110 Free(outbuf); |
| 111 return 0; |
| 112 } |
| 113 |
| 114 VbPrivateKey* PrivateKeyRead(const char* filename) { |
| 115 VbPrivateKey *key; |
| 116 uint64_t filelen = 0; |
| 117 uint8_t *buffer; |
| 118 const unsigned char *start; |
| 119 |
| 120 buffer = ReadFile(filename, &filelen); |
| 121 if (!buffer) { |
| 122 error("unable to read from file %s\n", filename); |
| 123 return 0; |
| 124 } |
| 125 |
| 126 key = (VbPrivateKey*)Malloc(sizeof(VbPrivateKey)); |
| 127 if (!key) { |
| 128 error("Unable to allocate VbPrivateKey\n"); |
| 129 Free(buffer); |
| 130 return 0; |
| 131 } |
| 132 |
| 133 key->algorithm = *(typeof(key->algorithm) *)buffer; |
| 134 start = buffer + sizeof(key->algorithm); |
| 135 |
| 136 key->rsa_private_key = d2i_RSAPrivateKey(0, &start, |
| 137 filelen - sizeof(key->algorithm)); |
| 138 |
| 139 if (!key->rsa_private_key) { |
| 140 error("Unable to parse RSA private key\n"); |
| 141 Free(buffer); |
| 142 Free(key); |
| 143 return 0; |
| 144 } |
| 145 |
| 146 Free(buffer); |
| 147 return key; |
| 148 } |
| 149 |
| 150 |
| 151 |
| 152 |
| 75 /* Allocate a new public key with space for a [key_size] byte key. */ | 153 /* Allocate a new public key with space for a [key_size] byte key. */ |
| 76 VbPublicKey* PublicKeyAlloc(uint64_t key_size, uint64_t algorithm, | 154 VbPublicKey* PublicKeyAlloc(uint64_t key_size, uint64_t algorithm, |
| 77 uint64_t version) { | 155 uint64_t version) { |
| 78 VbPublicKey* key = (VbPublicKey*)Malloc(sizeof(VbPublicKey) + key_size); | 156 VbPublicKey* key = (VbPublicKey*)Malloc(sizeof(VbPublicKey) + key_size); |
| 79 if (!key) | 157 if (!key) |
| 80 return NULL; | 158 return NULL; |
| 81 | 159 |
| 82 key->algorithm = algorithm; | 160 key->algorithm = algorithm; |
| 83 key->key_version = version; | 161 key->key_version = version; |
| 84 key->key_size = key_size; | 162 key->key_size = key_size; |
| 85 key->key_offset = sizeof(VbPublicKey); | 163 key->key_offset = sizeof(VbPublicKey); |
| 86 return key; | 164 return key; |
| 87 } | 165 } |
| 88 | 166 |
| 89 | 167 |
| 90 VbPublicKey* PublicKeyReadKeyb(const char* filename, uint64_t algorithm, | 168 VbPublicKey* PublicKeyReadKeyb(const char* filename, uint64_t algorithm, |
| 91 uint64_t version) { | 169 uint64_t version) { |
| 92 VbPublicKey* key; | 170 VbPublicKey* key; |
| 93 uint8_t* key_data; | 171 uint8_t* key_data; |
| 94 uint64_t key_size; | 172 uint64_t key_size; |
| 95 | 173 |
| 96 if (algorithm >= kNumAlgorithms) { | 174 if (algorithm >= kNumAlgorithms) { |
| 97 debug("PublicKeyReadKeyb() called with invalid algorithm!\n"); | 175 VBDEBUG(("PublicKeyReadKeyb() called with invalid algorithm!\n")); |
| 98 return NULL; | 176 return NULL; |
| 99 } | 177 } |
| 100 if (version > 0xFFFF) { | 178 if (version > 0xFFFF) { |
| 101 /* Currently, TPM only supports 16-bit version */ | 179 /* Currently, TPM only supports 16-bit version */ |
| 102 debug("PublicKeyReadKeyb() called with invalid version!\n"); | 180 VBDEBUG(("PublicKeyReadKeyb() called with invalid version!\n")); |
| 103 return NULL; | 181 return NULL; |
| 104 } | 182 } |
| 105 | 183 |
| 106 key_data = ReadFile(filename, &key_size); | 184 key_data = ReadFile(filename, &key_size); |
| 107 if (!key_data) | 185 if (!key_data) |
| 108 return NULL; | 186 return NULL; |
| 109 | 187 |
| 110 if (RSAProcessedKeySize(algorithm) != key_size) { | 188 if (RSAProcessedKeySize(algorithm) != key_size) { |
| 111 debug("PublicKeyReadKeyb() wrong key size for algorithm\n"); | 189 VBDEBUG(("PublicKeyReadKeyb() wrong key size for algorithm\n")); |
| 112 Free(key_data); | 190 Free(key_data); |
| 113 return NULL; | 191 return NULL; |
| 114 } | 192 } |
| 115 | 193 |
| 116 key = PublicKeyAlloc(key_size, algorithm, version); | 194 key = PublicKeyAlloc(key_size, algorithm, version); |
| 117 if (!key) { | 195 if (!key) { |
| 118 Free(key_data); | 196 Free(key_data); |
| 119 return NULL; | 197 return NULL; |
| 120 } | 198 } |
| 121 Memcpy(GetPublicKeyData(key), key_data, key_size); | 199 Memcpy(GetPublicKeyData(key), key_data, key_size); |
| 122 | 200 |
| 123 Free(key_data); | 201 Free(key_data); |
| 124 return key; | 202 return key; |
| 125 } | 203 } |
| 126 | 204 |
| 127 | 205 |
| 128 VbPublicKey* PublicKeyRead(const char* filename) { | 206 VbPublicKey* PublicKeyRead(const char* filename) { |
| 129 VbPublicKey* key; | 207 VbPublicKey* key; |
| 130 uint64_t file_size; | 208 uint64_t file_size; |
| 131 | 209 |
| 132 key = (VbPublicKey*)ReadFile(filename, &file_size); | 210 key = (VbPublicKey*)ReadFile(filename, &file_size); |
| 133 if (!key) | 211 if (!key) |
| 134 return NULL; | 212 return NULL; |
| 135 | 213 |
| 136 do { | 214 do { |
| 137 /* Sanity-check key data */ | 215 /* Sanity-check key data */ |
| 138 if (0 != VerifyPublicKeyInside(key, file_size, key)) { | 216 if (0 != VerifyPublicKeyInside(key, file_size, key)) { |
| 139 debug("PublicKeyRead() not a VbPublicKey\n"); | 217 VBDEBUG(("PublicKeyRead() not a VbPublicKey\n")); |
| 140 break; | 218 break; |
| 141 } | 219 } |
| 142 if (key->algorithm >= kNumAlgorithms) { | 220 if (key->algorithm >= kNumAlgorithms) { |
| 143 debug("PublicKeyRead() invalid algorithm\n"); | 221 VBDEBUG(("PublicKeyRead() invalid algorithm\n")); |
| 144 break; | 222 break; |
| 145 } | 223 } |
| 146 if (key->key_version > 0xFFFF) { | 224 if (key->key_version > 0xFFFF) { |
| 147 debug("PublicKeyRead() invalid version\n"); | 225 VBDEBUG(("PublicKeyRead() invalid version\n")); |
| 148 break; /* Currently, TPM only supports 16-bit version */ | 226 break; /* Currently, TPM only supports 16-bit version */ |
| 149 } | 227 } |
| 150 if (RSAProcessedKeySize(key->algorithm) != key->key_size) { | 228 if (RSAProcessedKeySize(key->algorithm) != key->key_size) { |
| 151 debug("PublicKeyRead() wrong key size for algorithm\n"); | 229 VBDEBUG(("PublicKeyRead() wrong key size for algorithm\n")); |
| 152 break; | 230 break; |
| 153 } | 231 } |
| 154 | 232 |
| 155 /* Success */ | 233 /* Success */ |
| 156 return key; | 234 return key; |
| 157 | 235 |
| 158 } while(0); | 236 } while(0); |
| 159 | 237 |
| 160 /* Error */ | 238 /* Error */ |
| 161 Free(key); | 239 Free(key); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 174 if (0 != PublicKeyCopy(kcopy, key)) { | 252 if (0 != PublicKeyCopy(kcopy, key)) { |
| 175 Free(kcopy); | 253 Free(kcopy); |
| 176 return 1; | 254 return 1; |
| 177 } | 255 } |
| 178 | 256 |
| 179 /* Write the copy, then free it */ | 257 /* Write the copy, then free it */ |
| 180 rv = WriteFile(filename, kcopy, kcopy->key_offset + kcopy->key_size); | 258 rv = WriteFile(filename, kcopy, kcopy->key_offset + kcopy->key_size); |
| 181 Free(kcopy); | 259 Free(kcopy); |
| 182 return rv; | 260 return rv; |
| 183 } | 261 } |
| OLD | NEW |