| 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 * Functions for verifying a verified boot kernel image. | 5 * Functions for verifying a verified boot kernel image. |
| 6 * (Firmware portion) | 6 * (Firmware portion) |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 #include "kernel_image_fw.h" | 9 #include "kernel_image_fw.h" |
| 10 | 10 |
| 11 #include "cryptolib.h" | 11 #include "cryptolib.h" |
| 12 #include "rollback_index.h" | 12 #include "rollback_index.h" |
| 13 #include "utility.h" | 13 #include "utility.h" |
| 14 | 14 |
| 15 /* Macro to determine the size of a field structure in the KernelImage | 15 /* Macro to determine the size of a field structure in the KernelImage |
| 16 * structure. */ | 16 * structure. */ |
| 17 #define FIELD_LEN(field) (sizeof(((KernelImage*)0)->field)) | 17 #define FIELD_LEN(field) (sizeof(((KernelImage*)0)->field)) |
| 18 #define KERNEL_CONFIG_FIELD_LEN (FIELD_LEN(kernel_version) + FIELD_LEN(options.v
ersion) + \ | |
| 19 FIELD_LEN(options.cmd_line) + \ | |
| 20 FIELD_LEN(options.kernel_len) + \ | |
| 21 FIELD_LEN(options.kernel_load_addr) + \ | |
| 22 FIELD_LEN(options.kernel_entry_addr)) | |
| 23 | 18 |
| 24 char* kVerifyKernelErrors[VERIFY_KERNEL_MAX] = { | 19 char* kVerifyKernelErrors[VERIFY_KERNEL_MAX] = { |
| 25 "Success.", | 20 "Success.", |
| 26 "Invalid Image.", | 21 "Invalid Image.", |
| 27 "Kernel Key Signature Failed.", | 22 "Kernel Key Signature Failed.", |
| 28 "Invalid Kernel Verification Algorithm.", | 23 "Invalid Kernel Verification Algorithm.", |
| 29 "Config Signature Failed.", | 24 "Config Signature Failed.", |
| 30 "Kernel Signature Failed.", | 25 "Kernel Signature Failed.", |
| 31 "Wrong Kernel Magic.", | 26 "Wrong Kernel Magic.", |
| 32 }; | 27 }; |
| 33 | 28 |
| 29 uint64_t GetVblockHeaderSize(const uint8_t* vkernel_blob) { |
| 30 uint64_t len = 0; |
| 31 uint16_t firmware_sign_algorithm; |
| 32 uint16_t kernel_sign_algorithm; |
| 33 int algorithms_offset = (FIELD_LEN(magic) + |
| 34 FIELD_LEN(header_version) + |
| 35 FIELD_LEN(header_len)); |
| 36 if (SafeMemcmp(vkernel_blob, KERNEL_MAGIC, KERNEL_MAGIC_SIZE)) { |
| 37 debug("Not a valid verified boot kernel blob.\n"); |
| 38 return 0; |
| 39 } |
| 40 Memcpy(&firmware_sign_algorithm, |
| 41 vkernel_blob + algorithms_offset, |
| 42 sizeof(firmware_sign_algorithm)); |
| 43 Memcpy(&kernel_sign_algorithm, |
| 44 vkernel_blob + algorithms_offset + FIELD_LEN(kernel_sign_algorithm), |
| 45 sizeof(kernel_sign_algorithm)); |
| 46 if (firmware_sign_algorithm >= kNumAlgorithms) { |
| 47 debug("Invalid firmware signing algorithm.\n"); |
| 48 return 0; |
| 49 } |
| 50 if (kernel_sign_algorithm >= kNumAlgorithms) { |
| 51 debug("Invalid kernel signing algorithm.\n"); |
| 52 return 0; |
| 53 } |
| 54 len = algorithms_offset; /* magic, header length and version. */ |
| 55 len += (FIELD_LEN(firmware_sign_algorithm) + |
| 56 FIELD_LEN(kernel_sign_algorithm) + |
| 57 FIELD_LEN(kernel_key_version) + |
| 58 RSAProcessedKeySize(kernel_sign_algorithm) + /* kernel_sign_key */ |
| 59 FIELD_LEN(header_checksum) + |
| 60 siglen_map[firmware_sign_algorithm] + /* kernel_key_signature */ |
| 61 FIELD_LEN(kernel_version) + |
| 62 FIELD_LEN(kernel_len) + |
| 63 siglen_map[kernel_sign_algorithm] + /* config_signature */ |
| 64 siglen_map[kernel_sign_algorithm]); /* kernel_signature */ |
| 65 return len; |
| 66 } |
| 67 |
| 34 int VerifyKernelHeader(const uint8_t* firmware_key_blob, | 68 int VerifyKernelHeader(const uint8_t* firmware_key_blob, |
| 35 const uint8_t* header_blob, | 69 const uint8_t* header_blob, |
| 36 const int dev_mode, | 70 const int dev_mode, |
| 37 int* firmware_algorithm, | 71 int* firmware_algorithm, |
| 38 int* kernel_algorithm, | 72 int* kernel_algorithm, |
| 39 int* kernel_header_len) { | 73 int* kernel_header_len) { |
| 40 int kernel_sign_key_len; | 74 int kernel_sign_key_len; |
| 41 int firmware_sign_key_len; | 75 int firmware_sign_key_len; |
| 42 uint16_t header_version, header_len; | 76 uint16_t header_version, header_len; |
| 43 uint16_t firmware_sign_algorithm, kernel_sign_algorithm; | 77 uint16_t firmware_sign_algorithm, kernel_sign_algorithm; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 109 firmware_sign_algorithm)) | 143 firmware_sign_algorithm)) |
| 110 return VERIFY_KERNEL_KEY_SIGNATURE_FAILED; | 144 return VERIFY_KERNEL_KEY_SIGNATURE_FAILED; |
| 111 } | 145 } |
| 112 return 0; | 146 return 0; |
| 113 } | 147 } |
| 114 | 148 |
| 115 int VerifyKernelConfig(RSAPublicKey* kernel_sign_key, | 149 int VerifyKernelConfig(RSAPublicKey* kernel_sign_key, |
| 116 const uint8_t* config_blob, | 150 const uint8_t* config_blob, |
| 117 int algorithm, | 151 int algorithm, |
| 118 uint64_t* kernel_len) { | 152 uint64_t* kernel_len) { |
| 119 uint64_t len; | 153 int signature_len = siglen_map[algorithm]; |
| 120 if (!RSAVerifyBinary_f(NULL, kernel_sign_key, /* Key to use */ | 154 const uint8_t* config_signature = NULL; |
| 121 config_blob, /* Data to verify */ | 155 const uint8_t* kernel_config = NULL; |
| 122 KERNEL_CONFIG_FIELD_LEN, /* Length of data */ | 156 uint8_t* digest = NULL; |
| 123 config_blob + KERNEL_CONFIG_FIELD_LEN, /* Expected | 157 DigestContext ctx; |
| 124 * Signature */ | 158 |
| 125 algorithm)) | 159 config_signature = config_blob + (FIELD_LEN(kernel_version) + |
| 160 FIELD_LEN(kernel_len)); |
| 161 kernel_config = config_signature + 2 * signature_len; /* kernel and config |
| 162 * signature. */ |
| 163 /* Since the kernel config signature is computed over the kernel version, |
| 164 * kernel length and config, which does not form a contiguous region memory, |
| 165 * we calculate the message digest ourselves. */ |
| 166 DigestInit(&ctx, algorithm); |
| 167 DigestUpdate(&ctx, |
| 168 config_blob, |
| 169 FIELD_LEN(kernel_version) + FIELD_LEN(kernel_len)); |
| 170 DigestUpdate(&ctx, |
| 171 kernel_config, |
| 172 FIELD_LEN(kernel_config)); |
| 173 digest = DigestFinal(&ctx); |
| 174 if (!RSAVerifyBinaryWithDigest_f( |
| 175 NULL, kernel_sign_key, /* Key to use. */ |
| 176 digest, /* Digest of the Data to verify. */ |
| 177 config_signature, /* Expected signature. */ |
| 178 algorithm)) { |
| 179 Free(digest); |
| 126 return VERIFY_KERNEL_CONFIG_SIGNATURE_FAILED; | 180 return VERIFY_KERNEL_CONFIG_SIGNATURE_FAILED; |
| 127 | 181 } |
| 128 Memcpy(&len, | 182 Free(digest); |
| 129 config_blob + (FIELD_LEN(kernel_version) + FIELD_LEN(options.version) + | 183 Memcpy(kernel_len, |
| 130 FIELD_LEN(options.cmd_line)), | 184 config_blob + FIELD_LEN(kernel_version), |
| 131 sizeof(len)); | 185 FIELD_LEN(kernel_len)); |
| 132 *kernel_len = len; | |
| 133 return 0; | 186 return 0; |
| 134 } | 187 } |
| 135 | 188 |
| 136 int VerifyKernelData(RSAPublicKey* kernel_sign_key, | 189 int VerifyKernelData(RSAPublicKey* kernel_sign_key, |
| 137 const uint8_t* kernel_config_start, | 190 const uint8_t* config_blob, |
| 138 const uint8_t* kernel_data_start, | 191 const uint8_t* kernel_data, |
| 139 uint64_t kernel_len, | 192 uint64_t kernel_len, |
| 140 int algorithm) { | 193 int algorithm) { |
| 141 int signature_len = siglen_map[algorithm]; | 194 int signature_len = siglen_map[algorithm]; |
| 142 uint8_t* digest; | 195 const uint8_t* kernel_signature = NULL; |
| 196 const uint8_t* kernel_config = NULL; |
| 197 uint8_t* digest = NULL; |
| 143 DigestContext ctx; | 198 DigestContext ctx; |
| 144 | 199 |
| 145 /* Since the kernel signature is computed over the kernel version, options | 200 kernel_signature = config_blob + (FIELD_LEN(kernel_version) + |
| 146 * and data, which does not form a contiguous region of memory, we calculate | 201 FIELD_LEN(kernel_len) + |
| 147 * the message digest ourselves. */ | 202 signature_len); |
| 203 kernel_config = kernel_signature + signature_len; |
| 204 |
| 205 /* Since the kernel signature is computed over the kernel version, length, |
| 206 * config cmd line, and kernel image data, which does not form a contiguous |
| 207 * region of memory, we calculate the message digest ourselves. */ |
| 148 DigestInit(&ctx, algorithm); | 208 DigestInit(&ctx, algorithm); |
| 149 DigestUpdate(&ctx, kernel_config_start, KERNEL_CONFIG_FIELD_LEN); | 209 DigestUpdate(&ctx, |
| 150 DigestUpdate(&ctx, kernel_data_start + signature_len, kernel_len); | 210 config_blob, |
| 211 FIELD_LEN(kernel_version) + FIELD_LEN(kernel_len)); |
| 212 DigestUpdate(&ctx, kernel_config, |
| 213 FIELD_LEN(kernel_config)); |
| 214 DigestUpdate(&ctx, kernel_data, kernel_len); |
| 151 digest = DigestFinal(&ctx); | 215 digest = DigestFinal(&ctx); |
| 152 if (!RSAVerifyBinaryWithDigest_f( | 216 if (!RSAVerifyBinaryWithDigest_f( |
| 153 NULL, kernel_sign_key, /* Key to use. */ | 217 NULL, kernel_sign_key, /* Key to use. */ |
| 154 digest, /* Digest of the data to verify. */ | 218 digest, /* Digest of the data to verify. */ |
| 155 kernel_data_start, /* Expected Signature */ | 219 kernel_signature, /* Expected Signature */ |
| 156 algorithm)) { | 220 algorithm)) { |
| 157 Free(digest); | 221 Free(digest); |
| 158 return VERIFY_KERNEL_SIGNATURE_FAILED; | 222 return VERIFY_KERNEL_SIGNATURE_FAILED; |
| 159 } | 223 } |
| 160 Free(digest); | 224 Free(digest); |
| 161 return 0; | 225 return 0; |
| 162 } | 226 } |
| 163 | 227 |
| 164 int VerifyKernel(const uint8_t* firmware_key_blob, | 228 int VerifyKernel(const uint8_t* firmware_key_blob, |
| 165 const uint8_t* kernel_blob, | 229 const uint8_t* kernel_blob, |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 207 /* Only continue if config verification succeeds. */ | 271 /* Only continue if config verification succeeds. */ |
| 208 config_ptr = (header_ptr + header_len + kernel_key_signature_len); | 272 config_ptr = (header_ptr + header_len + kernel_key_signature_len); |
| 209 if ((error_code = VerifyKernelConfig(kernel_sign_key, config_ptr, | 273 if ((error_code = VerifyKernelConfig(kernel_sign_key, config_ptr, |
| 210 kernel_sign_algorithm, | 274 kernel_sign_algorithm, |
| 211 &kernel_len))) { | 275 &kernel_len))) { |
| 212 RSAPublicKeyFree(kernel_sign_key); | 276 RSAPublicKeyFree(kernel_sign_key); |
| 213 return error_code; /* AKA jump to recovery. */ | 277 return error_code; /* AKA jump to recovery. */ |
| 214 } | 278 } |
| 215 /* Only continue if kernel data verification succeeds. */ | 279 /* Only continue if kernel data verification succeeds. */ |
| 216 kernel_ptr = (config_ptr + | 280 kernel_ptr = (config_ptr + |
| 217 KERNEL_CONFIG_FIELD_LEN + /* Skip config block/signature. */ | 281 FIELD_LEN(kernel_version) + |
| 218 kernel_signature_len); | 282 FIELD_LEN(kernel_len) + |
| 283 2 * kernel_signature_len + /* config and kernel signature. */ |
| 284 FIELD_LEN(kernel_config)); |
| 219 | 285 |
| 220 if ((error_code = VerifyKernelData(kernel_sign_key, config_ptr, kernel_ptr, | 286 if ((error_code = VerifyKernelData(kernel_sign_key, /* Verification key */ |
| 221 kernel_len, | 287 config_ptr, /* Start of config block */ |
| 288 kernel_ptr, /* Start of kernel image */ |
| 289 kernel_len, /* Length of kernel image. */ |
| 222 kernel_sign_algorithm))) { | 290 kernel_sign_algorithm))) { |
| 223 RSAPublicKeyFree(kernel_sign_key); | 291 RSAPublicKeyFree(kernel_sign_key); |
| 224 return error_code; /* AKA jump to recovery. */ | 292 return error_code; /* AKA jump to recovery. */ |
| 225 } | 293 } |
| 226 RSAPublicKeyFree(kernel_sign_key); | 294 RSAPublicKeyFree(kernel_sign_key); |
| 227 return 0; /* Success! */ | 295 return 0; /* Success! */ |
| 228 } | 296 } |
| 229 | 297 |
| 230 uint32_t GetLogicalKernelVersion(uint8_t* kernel_blob) { | 298 uint32_t GetLogicalKernelVersion(uint8_t* kernel_blob) { |
| 231 uint8_t* kernel_ptr; | 299 uint8_t* kernel_ptr; |
| 232 uint16_t kernel_key_version; | 300 uint16_t kernel_key_version; |
| 233 uint16_t kernel_version; | 301 uint16_t kernel_version; |
| 234 uint16_t firmware_sign_algorithm; | 302 uint16_t firmware_sign_algorithm; |
| 235 uint16_t kernel_sign_algorithm; | 303 uint16_t kernel_sign_algorithm; |
| 236 int kernel_key_signature_len; | 304 int kernel_key_signature_len; |
| 237 int kernel_sign_key_len; | 305 int kernel_sign_key_len; |
| 238 kernel_ptr = kernel_blob + (FIELD_LEN(magic) + | 306 kernel_ptr = kernel_blob + (FIELD_LEN(magic) + |
| 239 FIELD_LEN(header_version) + | 307 FIELD_LEN(header_version) + |
| 240 FIELD_LEN(header_len)); | 308 FIELD_LEN(header_len)); |
| 241 Memcpy(&firmware_sign_algorithm, kernel_ptr, sizeof(firmware_sign_algorithm)); | 309 Memcpy(&firmware_sign_algorithm, kernel_ptr, sizeof(firmware_sign_algorithm)); |
| 242 kernel_ptr += FIELD_LEN(firmware_sign_algorithm); | 310 kernel_ptr += FIELD_LEN(firmware_sign_algorithm); |
| 243 Memcpy(&kernel_sign_algorithm, kernel_ptr, sizeof(kernel_sign_algorithm)); | 311 Memcpy(&kernel_sign_algorithm, kernel_ptr, sizeof(kernel_sign_algorithm)); |
| 244 kernel_ptr += FIELD_LEN(kernel_sign_algorithm); | 312 kernel_ptr += FIELD_LEN(kernel_sign_algorithm); |
| 245 Memcpy(&kernel_key_version, kernel_ptr, sizeof(kernel_key_version)); | 313 Memcpy(&kernel_key_version, kernel_ptr, sizeof(kernel_key_version)); |
| 246 | 314 |
| 247 if (firmware_sign_algorithm >= kNumAlgorithms) | 315 if (firmware_sign_algorithm >= kNumAlgorithms) |
| 248 return 0; | 316 return 0; |
| 249 if (kernel_sign_algorithm >= kNumAlgorithms) | 317 if (kernel_sign_algorithm >= kNumAlgorithms) |
| 250 return 0; | 318 return 0; |
| 319 |
| 251 kernel_key_signature_len = siglen_map[firmware_sign_algorithm]; | 320 kernel_key_signature_len = siglen_map[firmware_sign_algorithm]; |
| 252 kernel_sign_key_len = RSAProcessedKeySize(kernel_sign_algorithm); | 321 kernel_sign_key_len = RSAProcessedKeySize(kernel_sign_algorithm); |
| 253 kernel_ptr += (FIELD_LEN(kernel_key_version) + | 322 kernel_ptr += (FIELD_LEN(kernel_key_version) + |
| 254 kernel_sign_key_len + | 323 kernel_sign_key_len + |
| 255 FIELD_LEN(header_checksum) + | 324 FIELD_LEN(header_checksum) + |
| 256 kernel_key_signature_len); | 325 kernel_key_signature_len); |
| 257 Memcpy(&kernel_version, kernel_ptr, sizeof(kernel_version)); | 326 Memcpy(&kernel_version, kernel_ptr, sizeof(kernel_version)); |
| 258 return CombineUint16Pair(kernel_key_version, kernel_version); | 327 return CombineUint16Pair(kernel_key_version, kernel_version); |
| 259 } | 328 } |
| 260 | 329 |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 357 /* Lock Kernel TPM rollback indices from further writes. | 426 /* Lock Kernel TPM rollback indices from further writes. |
| 358 * TODO(gauravsh): Figure out if these can be combined into one | 427 * TODO(gauravsh): Figure out if these can be combined into one |
| 359 * 32-bit location since we seem to always use them together. This can help | 428 * 32-bit location since we seem to always use them together. This can help |
| 360 * us minimize the number of NVRAM writes/locks (which are limited over flash | 429 * us minimize the number of NVRAM writes/locks (which are limited over flash |
| 361 * memory lifetimes. | 430 * memory lifetimes. |
| 362 */ | 431 */ |
| 363 LockStoredVersion(KERNEL_KEY_VERSION); | 432 LockStoredVersion(KERNEL_KEY_VERSION); |
| 364 LockStoredVersion(KERNEL_VERSION); | 433 LockStoredVersion(KERNEL_VERSION); |
| 365 return kernel_to_boot; | 434 return kernel_to_boot; |
| 366 } | 435 } |
| OLD | NEW |