| OLD | NEW |
| (Empty) |
| 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 | |
| 3 * found in the LICENSE file. | |
| 4 * | |
| 5 * Functions for verifying a verified boot kernel image. | |
| 6 * (Firmware portion) | |
| 7 */ | |
| 8 | |
| 9 #include "kernel_image_fw.h" | |
| 10 | |
| 11 #include "cryptolib.h" | |
| 12 #include "rollback_index.h" | |
| 13 #include "stateful_util.h" | |
| 14 #include "utility.h" | |
| 15 | |
| 16 /* Macro to determine the size of a field structure in the KernelImage | |
| 17 * structure. */ | |
| 18 #define FIELD_LEN(field) (sizeof(((KernelImage*)0)->field)) | |
| 19 | |
| 20 char* kVerifyKernelErrors[VERIFY_KERNEL_MAX] = { | |
| 21 "Success.", | |
| 22 "Invalid Image.", | |
| 23 "Kernel Key Signature Failed.", | |
| 24 "Invalid Kernel Verification Algorithm.", | |
| 25 "Preamble Signature Failed.", | |
| 26 "Kernel Signature Failed.", | |
| 27 "Wrong Kernel Magic.", | |
| 28 }; | |
| 29 | |
| 30 inline uint64_t GetKernelPreambleLen(int algorithm) { | |
| 31 return (FIELD_LEN(kernel_version) + | |
| 32 FIELD_LEN(kernel_len) + | |
| 33 FIELD_LEN(bootloader_offset) + | |
| 34 FIELD_LEN(bootloader_size) + | |
| 35 FIELD_LEN(padded_header_size) + | |
| 36 siglen_map[algorithm]); | |
| 37 } | |
| 38 | |
| 39 uint64_t GetVblockHeaderSize(const uint8_t* vkernel_blob) { | |
| 40 uint64_t len = 0; | |
| 41 uint16_t firmware_sign_algorithm; | |
| 42 uint16_t kernel_sign_algorithm; | |
| 43 int algorithms_offset = (FIELD_LEN(magic) + | |
| 44 FIELD_LEN(header_version) + | |
| 45 FIELD_LEN(header_len)); | |
| 46 if (SafeMemcmp(vkernel_blob, KERNEL_MAGIC, KERNEL_MAGIC_SIZE)) { | |
| 47 debug("Not a valid verified boot kernel blob.\n"); | |
| 48 return 0; | |
| 49 } | |
| 50 Memcpy(&firmware_sign_algorithm, | |
| 51 vkernel_blob + algorithms_offset, | |
| 52 sizeof(firmware_sign_algorithm)); | |
| 53 Memcpy(&kernel_sign_algorithm, | |
| 54 vkernel_blob + algorithms_offset + FIELD_LEN(kernel_sign_algorithm), | |
| 55 sizeof(kernel_sign_algorithm)); | |
| 56 if (firmware_sign_algorithm >= kNumAlgorithms) { | |
| 57 debug("Invalid firmware signing algorithm.\n"); | |
| 58 return 0; | |
| 59 } | |
| 60 if (kernel_sign_algorithm >= kNumAlgorithms) { | |
| 61 debug("Invalid kernel signing algorithm.\n"); | |
| 62 return 0; | |
| 63 } | |
| 64 len = algorithms_offset; /* magic, header length and version. */ | |
| 65 len += (FIELD_LEN(firmware_sign_algorithm) + | |
| 66 FIELD_LEN(kernel_sign_algorithm) + | |
| 67 FIELD_LEN(kernel_key_version) + | |
| 68 RSAProcessedKeySize(kernel_sign_algorithm) + /* kernel_sign_key */ | |
| 69 FIELD_LEN(header_checksum) + | |
| 70 siglen_map[firmware_sign_algorithm] + /* kernel_key_signature */ | |
| 71 GetKernelPreambleLen(kernel_sign_algorithm) + | |
| 72 siglen_map[kernel_sign_algorithm]); /* preamble_signature */ | |
| 73 return len; | |
| 74 } | |
| 75 | |
| 76 int VerifyKernelKeyHeader(const uint8_t* firmware_key_blob, | |
| 77 const uint8_t* header_blob, | |
| 78 const int dev_mode, | |
| 79 int* firmware_algorithm, | |
| 80 int* kernel_algorithm, | |
| 81 int* kernel_header_len) { | |
| 82 int kernel_sign_key_len; | |
| 83 int firmware_sign_key_len; | |
| 84 uint16_t header_version, header_len; | |
| 85 uint16_t firmware_sign_algorithm, kernel_sign_algorithm; | |
| 86 uint8_t* header_checksum = NULL; | |
| 87 | |
| 88 /* Base Offset for the header_checksum field. Actual offset is | |
| 89 * this + kernel_sign_key_len. */ | |
| 90 int base_header_checksum_offset = (FIELD_LEN(header_version) + | |
| 91 FIELD_LEN(header_len) + | |
| 92 FIELD_LEN(firmware_sign_algorithm) + | |
| 93 FIELD_LEN(kernel_sign_algorithm) + | |
| 94 FIELD_LEN(kernel_key_version)); | |
| 95 | |
| 96 Memcpy(&header_version, header_blob, sizeof(header_version)); | |
| 97 Memcpy(&header_len, header_blob + FIELD_LEN(header_version), | |
| 98 sizeof(header_len)); | |
| 99 Memcpy(&firmware_sign_algorithm, | |
| 100 header_blob + (FIELD_LEN(header_version) + | |
| 101 FIELD_LEN(header_len)), | |
| 102 sizeof(firmware_sign_algorithm)); | |
| 103 Memcpy(&kernel_sign_algorithm, | |
| 104 header_blob + (FIELD_LEN(header_version) + | |
| 105 FIELD_LEN(header_len) + | |
| 106 FIELD_LEN(firmware_sign_algorithm)), | |
| 107 sizeof(kernel_sign_algorithm)); | |
| 108 | |
| 109 /* TODO(gauravsh): Make this return two different error types depending | |
| 110 * on whether the firmware or kernel signing algorithm is invalid. */ | |
| 111 if (firmware_sign_algorithm >= kNumAlgorithms) | |
| 112 return VERIFY_KERNEL_INVALID_ALGORITHM; | |
| 113 if (kernel_sign_algorithm >= kNumAlgorithms) | |
| 114 return VERIFY_KERNEL_INVALID_ALGORITHM; | |
| 115 | |
| 116 *firmware_algorithm = (int) firmware_sign_algorithm; | |
| 117 *kernel_algorithm = (int) kernel_sign_algorithm; | |
| 118 kernel_sign_key_len = RSAProcessedKeySize(kernel_sign_algorithm); | |
| 119 firmware_sign_key_len = RSAProcessedKeySize(firmware_sign_algorithm); | |
| 120 | |
| 121 | |
| 122 /* Verify if header len is correct? */ | |
| 123 if (header_len != (base_header_checksum_offset + | |
| 124 kernel_sign_key_len + | |
| 125 FIELD_LEN(header_checksum))) { | |
| 126 debug("VerifyKernelKeyHeader: Header length mismatch\n"); | |
| 127 return VERIFY_KERNEL_INVALID_IMAGE; | |
| 128 } | |
| 129 *kernel_header_len = (int) header_len; | |
| 130 | |
| 131 /* Verify if the hash of the header is correct. */ | |
| 132 header_checksum = DigestBuf(header_blob, | |
| 133 header_len - FIELD_LEN(header_checksum), | |
| 134 SHA512_DIGEST_ALGORITHM); | |
| 135 if (SafeMemcmp(header_checksum, | |
| 136 header_blob + (base_header_checksum_offset + | |
| 137 kernel_sign_key_len), | |
| 138 FIELD_LEN(header_checksum))) { | |
| 139 Free(header_checksum); | |
| 140 debug("VerifyKernelKeyHeader: Invalid header hash\n"); | |
| 141 return VERIFY_KERNEL_INVALID_IMAGE; | |
| 142 } | |
| 143 Free(header_checksum); | |
| 144 | |
| 145 /* Verify kernel key signature unless we are in dev mode. */ | |
| 146 if (!dev_mode) { | |
| 147 if (!RSAVerifyBinary_f(firmware_key_blob, NULL, /* Key to use */ | |
| 148 header_blob, /* Data to verify */ | |
| 149 header_len, /* Length of data */ | |
| 150 header_blob + header_len, /* Expected Signature */ | |
| 151 firmware_sign_algorithm)) | |
| 152 return VERIFY_KERNEL_KEY_SIGNATURE_FAILED; | |
| 153 } | |
| 154 return 0; | |
| 155 } | |
| 156 | |
| 157 int VerifyKernelPreamble(RSAPublicKey* kernel_sign_key, | |
| 158 const uint8_t* preamble_blob, | |
| 159 int algorithm, | |
| 160 uint64_t* kernel_len) { | |
| 161 int preamble_len = GetKernelPreambleLen(algorithm); | |
| 162 if (!RSAVerifyBinary_f(NULL, kernel_sign_key, /* Key to use */ | |
| 163 preamble_blob, /* Data to verify */ | |
| 164 preamble_len, /* Length of data */ | |
| 165 preamble_blob + preamble_len, /* Expected Signature */ | |
| 166 algorithm)) | |
| 167 return VERIFY_KERNEL_PREAMBLE_SIGNATURE_FAILED; | |
| 168 Memcpy(kernel_len, | |
| 169 preamble_blob + FIELD_LEN(kernel_version), | |
| 170 FIELD_LEN(kernel_len)); | |
| 171 return 0; | |
| 172 } | |
| 173 | |
| 174 int VerifyKernelData(RSAPublicKey* kernel_sign_key, | |
| 175 const uint8_t* kernel_signature, | |
| 176 const uint8_t* kernel_data, | |
| 177 uint64_t kernel_len, | |
| 178 int algorithm) { | |
| 179 | |
| 180 if (!RSAVerifyBinary_f(NULL, kernel_sign_key, /* Key to use */ | |
| 181 kernel_data, /* Data to verify */ | |
| 182 kernel_len, /* Length of data */ | |
| 183 kernel_signature, /* Expected Signature */ | |
| 184 algorithm)) | |
| 185 return VERIFY_KERNEL_SIGNATURE_FAILED; | |
| 186 return 0; | |
| 187 } | |
| 188 | |
| 189 int VerifyKernelHeader(const uint8_t* firmware_key_blob, | |
| 190 const uint8_t* kernel_header_blob, | |
| 191 uint64_t kernel_header_blob_len, | |
| 192 const int dev_mode, | |
| 193 KernelImage* image, | |
| 194 RSAPublicKey** kernel_sign_key) { | |
| 195 int error_code; | |
| 196 int firmware_sign_algorithm; /* Firmware signing key algorithm. */ | |
| 197 int kernel_sign_algorithm; /* Kernel signing key algorithm. */ | |
| 198 int kernel_sign_key_len, kernel_key_signature_len, kernel_signature_len, | |
| 199 header_len; | |
| 200 uint64_t kernel_len; | |
| 201 const uint8_t* header_ptr = NULL; /* Pointer to key header. */ | |
| 202 const uint8_t* preamble_ptr = NULL; /* Pointer to start of preamble. */ | |
| 203 MemcpyState st; | |
| 204 | |
| 205 /* Note: All the offset calculations are based on struct KernelImage which | |
| 206 * is defined in include/kernel_image_fw.h. */ | |
| 207 st.remaining_buf = (void *)kernel_header_blob; | |
| 208 st.remaining_len = kernel_header_blob_len; | |
| 209 st.overrun = 0; | |
| 210 | |
| 211 /* Clear destination image struct */ | |
| 212 Memset(image, 0, sizeof(KernelImage)); | |
| 213 | |
| 214 /* Read and compare magic bytes. */ | |
| 215 StatefulMemcpy(&st, &image->magic, KERNEL_MAGIC_SIZE); | |
| 216 if (SafeMemcmp(image->magic, KERNEL_MAGIC, KERNEL_MAGIC_SIZE)) { | |
| 217 return VERIFY_KERNEL_WRONG_MAGIC; | |
| 218 } | |
| 219 StatefulMemcpy(&st, &image->header_version, FIELD_LEN(header_version)); | |
| 220 StatefulMemcpy(&st, &image->header_len, FIELD_LEN(header_len)); | |
| 221 StatefulMemcpy(&st, &image->firmware_sign_algorithm, | |
| 222 FIELD_LEN(firmware_sign_algorithm)); | |
| 223 StatefulMemcpy(&st, &image->kernel_sign_algorithm, | |
| 224 FIELD_LEN(kernel_sign_algorithm)); | |
| 225 | |
| 226 header_ptr = kernel_header_blob + KERNEL_MAGIC_SIZE; | |
| 227 | |
| 228 /* Only continue if header verification succeeds. */ | |
| 229 if ((error_code = VerifyKernelKeyHeader(firmware_key_blob, header_ptr, | |
| 230 dev_mode, | |
| 231 &firmware_sign_algorithm, | |
| 232 &kernel_sign_algorithm, | |
| 233 &header_len))) { | |
| 234 debug("VerifyKernelHeader: Kernel Key Header verification failed.\n"); | |
| 235 return error_code; /* AKA jump to recovery. */ | |
| 236 } | |
| 237 | |
| 238 /* Read pre-processed public half of the kernel signing key. */ | |
| 239 kernel_sign_key_len = RSAProcessedKeySize(kernel_sign_algorithm); | |
| 240 StatefulMemcpy(&st, &image->kernel_key_version, | |
| 241 FIELD_LEN(kernel_key_version)); | |
| 242 image->kernel_sign_key = (uint8_t*)st.remaining_buf; | |
| 243 StatefulSkip(&st, kernel_sign_key_len); | |
| 244 StatefulMemcpy(&st, image->header_checksum, FIELD_LEN(header_checksum)); | |
| 245 | |
| 246 /* Parse signing key into RSAPublicKey structure since it is | |
| 247 * required multiple times. */ | |
| 248 *kernel_sign_key = RSAPublicKeyFromBuf(image->kernel_sign_key, | |
| 249 kernel_sign_key_len); | |
| 250 kernel_signature_len = siglen_map[kernel_sign_algorithm]; | |
| 251 kernel_key_signature_len = siglen_map[firmware_sign_algorithm]; | |
| 252 image->kernel_key_signature = (uint8_t*)st.remaining_buf; | |
| 253 StatefulSkip(&st, kernel_key_signature_len); | |
| 254 | |
| 255 /* Only continue if preamble verification succeeds. */ | |
| 256 /* TODO: should pass the remaining len into VerifyKernelPreamble() */ | |
| 257 preamble_ptr = (const uint8_t*)st.remaining_buf; | |
| 258 if ((error_code = VerifyKernelPreamble(*kernel_sign_key, preamble_ptr, | |
| 259 kernel_sign_algorithm, | |
| 260 &kernel_len))) { | |
| 261 RSAPublicKeyFree(*kernel_sign_key); | |
| 262 *kernel_sign_key = NULL; | |
| 263 return error_code; /* AKA jump to recovery. */ | |
| 264 } | |
| 265 | |
| 266 /* Copy preamble fields */ | |
| 267 StatefulMemcpy(&st, &image->kernel_version, FIELD_LEN(kernel_version)); | |
| 268 StatefulMemcpy(&st, &image->kernel_len, FIELD_LEN(kernel_len)); | |
| 269 StatefulMemcpy(&st, &image->bootloader_offset, FIELD_LEN(bootloader_offset)); | |
| 270 StatefulMemcpy(&st, &image->bootloader_size, FIELD_LEN(bootloader_size)); | |
| 271 StatefulMemcpy(&st, &image->padded_header_size, | |
| 272 FIELD_LEN(padded_header_size)); | |
| 273 image->kernel_signature = (uint8_t*)st.remaining_buf; | |
| 274 StatefulSkip(&st, kernel_signature_len); | |
| 275 image->preamble_signature = (uint8_t*)st.remaining_buf; | |
| 276 | |
| 277 return 0; | |
| 278 } | |
| 279 | |
| 280 int VerifyKernel(const uint8_t* firmware_key_blob, | |
| 281 const uint8_t* kernel_blob, | |
| 282 const int dev_mode) { | |
| 283 int error_code; | |
| 284 int firmware_sign_algorithm; /* Firmware signing key algorithm. */ | |
| 285 int kernel_sign_algorithm; /* Kernel Signing key algorithm. */ | |
| 286 RSAPublicKey* kernel_sign_key; | |
| 287 int kernel_sign_key_len, kernel_key_signature_len, kernel_signature_len, | |
| 288 header_len; | |
| 289 uint64_t kernel_len; | |
| 290 const uint8_t* header_ptr; /* Pointer to header. */ | |
| 291 const uint8_t* kernel_sign_key_ptr; /* Pointer to signing key. */ | |
| 292 const uint8_t* preamble_ptr; /* Pointer to kernel preamble block. */ | |
| 293 const uint8_t* kernel_ptr; /* Pointer to kernel signature/data. */ | |
| 294 const uint8_t* kernel_signature; | |
| 295 | |
| 296 /* Note: All the offset calculations are based on struct FirmwareImage which | |
| 297 * is defined in include/firmware_image.h. */ | |
| 298 | |
| 299 /* Compare magic bytes. */ | |
| 300 if (SafeMemcmp(kernel_blob, KERNEL_MAGIC, KERNEL_MAGIC_SIZE)) { | |
| 301 debug("VerifyKernel: Kernel magic bytes not found.\n"); | |
| 302 return VERIFY_KERNEL_WRONG_MAGIC; | |
| 303 } | |
| 304 header_ptr = kernel_blob + KERNEL_MAGIC_SIZE; | |
| 305 | |
| 306 /* Only continue if header verification succeeds. */ | |
| 307 if ((error_code = VerifyKernelKeyHeader(firmware_key_blob, header_ptr, dev_mod
e, | |
| 308 &firmware_sign_algorithm, | |
| 309 &kernel_sign_algorithm, &header_len)))
{ | |
| 310 debug("VerifyKernel: Kernel header verification failed.\n"); | |
| 311 return error_code; /* AKA jump to recovery. */ | |
| 312 } | |
| 313 /* Parse signing key into RSAPublicKey structure since it is required multiple | |
| 314 * times. */ | |
| 315 kernel_sign_key_len = RSAProcessedKeySize(kernel_sign_algorithm); | |
| 316 kernel_sign_key_ptr = header_ptr + (FIELD_LEN(header_version) + | |
| 317 FIELD_LEN(header_len) + | |
| 318 FIELD_LEN(firmware_sign_algorithm) + | |
| 319 FIELD_LEN(kernel_sign_algorithm) + | |
| 320 FIELD_LEN(kernel_key_version)); | |
| 321 kernel_sign_key = RSAPublicKeyFromBuf(kernel_sign_key_ptr, | |
| 322 kernel_sign_key_len); | |
| 323 kernel_signature_len = siglen_map[kernel_sign_algorithm]; | |
| 324 kernel_key_signature_len = siglen_map[firmware_sign_algorithm]; | |
| 325 | |
| 326 /* Only continue if preamble verification succeeds. */ | |
| 327 preamble_ptr = (header_ptr + header_len + kernel_key_signature_len); | |
| 328 if ((error_code = VerifyKernelPreamble(kernel_sign_key, preamble_ptr, | |
| 329 kernel_sign_algorithm, | |
| 330 &kernel_len))) { | |
| 331 debug("VerifyKernel: Kernel preamble verification failed.\n"); | |
| 332 RSAPublicKeyFree(kernel_sign_key); | |
| 333 return error_code; /* AKA jump to recovery. */ | |
| 334 } | |
| 335 /* Only continue if kernel data verification succeeds. */ | |
| 336 kernel_ptr = (preamble_ptr + | |
| 337 GetKernelPreambleLen(kernel_sign_algorithm) + | |
| 338 kernel_signature_len); /* preamble signature. */ | |
| 339 kernel_signature = kernel_ptr - 2 * kernel_signature_len; /* end of kernel | |
| 340 * preamble. */ | |
| 341 | |
| 342 if ((error_code = VerifyKernelData(kernel_sign_key, /* Verification key */ | |
| 343 kernel_signature, /* kernel signature */ | |
| 344 kernel_ptr, /* Start of kernel data */ | |
| 345 kernel_len, /* Length of kernel data. */ | |
| 346 kernel_sign_algorithm))) { | |
| 347 RSAPublicKeyFree(kernel_sign_key); | |
| 348 return error_code; /* AKA jump to recovery. */ | |
| 349 } | |
| 350 RSAPublicKeyFree(kernel_sign_key); | |
| 351 return 0; /* Success! */ | |
| 352 } | |
| 353 | |
| 354 uint32_t GetLogicalKernelVersion(uint8_t* kernel_blob) { | |
| 355 uint8_t* kernel_ptr; | |
| 356 uint16_t kernel_key_version; | |
| 357 uint16_t kernel_version; | |
| 358 uint16_t firmware_sign_algorithm; | |
| 359 uint16_t kernel_sign_algorithm; | |
| 360 int kernel_key_signature_len; | |
| 361 int kernel_sign_key_len; | |
| 362 kernel_ptr = kernel_blob + (FIELD_LEN(magic) + | |
| 363 FIELD_LEN(header_version) + | |
| 364 FIELD_LEN(header_len)); | |
| 365 Memcpy(&firmware_sign_algorithm, kernel_ptr, sizeof(firmware_sign_algorithm)); | |
| 366 kernel_ptr += FIELD_LEN(firmware_sign_algorithm); | |
| 367 Memcpy(&kernel_sign_algorithm, kernel_ptr, sizeof(kernel_sign_algorithm)); | |
| 368 kernel_ptr += FIELD_LEN(kernel_sign_algorithm); | |
| 369 Memcpy(&kernel_key_version, kernel_ptr, sizeof(kernel_key_version)); | |
| 370 | |
| 371 if (firmware_sign_algorithm >= kNumAlgorithms) | |
| 372 return 0; | |
| 373 if (kernel_sign_algorithm >= kNumAlgorithms) | |
| 374 return 0; | |
| 375 | |
| 376 kernel_key_signature_len = siglen_map[firmware_sign_algorithm]; | |
| 377 kernel_sign_key_len = RSAProcessedKeySize(kernel_sign_algorithm); | |
| 378 kernel_ptr += (FIELD_LEN(kernel_key_version) + | |
| 379 kernel_sign_key_len + | |
| 380 FIELD_LEN(header_checksum) + | |
| 381 kernel_key_signature_len); | |
| 382 Memcpy(&kernel_version, kernel_ptr, sizeof(kernel_version)); | |
| 383 return CombineUint16Pair(kernel_key_version, kernel_version); | |
| 384 } | |
| OLD | NEW |