| 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 * High-level firmware API for loading and verifying rewritable firmware. | 5 * High-level firmware API for loading and verifying rewritable firmware. |
| 6 * (Firmware portion) | 6 * (Firmware portion) |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 #include "load_firmware_fw.h" | 9 #include "load_firmware_fw.h" |
| 10 #include "rollback_index.h" | 10 #include "rollback_index.h" |
| (...skipping 18 matching lines...) Expand all Loading... |
| 29 DigestUpdate(&lfi->body_digest_context, data, size); | 29 DigestUpdate(&lfi->body_digest_context, data, size); |
| 30 lfi->body_size_accum += size; | 30 lfi->body_size_accum += size; |
| 31 } | 31 } |
| 32 | 32 |
| 33 | 33 |
| 34 int LoadFirmware(LoadFirmwareParams* params) { | 34 int LoadFirmware(LoadFirmwareParams* params) { |
| 35 | 35 |
| 36 VbPublicKey* root_key = (VbPublicKey*)params->firmware_root_key_blob; | 36 VbPublicKey* root_key = (VbPublicKey*)params->firmware_root_key_blob; |
| 37 VbLoadFirmwareInternal* lfi; | 37 VbLoadFirmwareInternal* lfi; |
| 38 | 38 |
| 39 uint16_t tpm_key_version = 0; | 39 uint32_t tpm_version = 0; |
| 40 uint16_t tpm_fw_version = 0; | 40 uint64_t lowest_version = 0xFFFFFFFF; |
| 41 uint64_t lowest_key_version = 0xFFFF; | |
| 42 uint64_t lowest_fw_version = 0xFFFF; | |
| 43 uint32_t status; | 41 uint32_t status; |
| 44 int good_index = -1; | 42 int good_index = -1; |
| 45 int index; | 43 int index; |
| 46 | 44 |
| 47 /* Clear output params in case we fail */ | 45 /* Clear output params in case we fail */ |
| 48 params->firmware_index = 0; | 46 params->firmware_index = 0; |
| 49 | 47 |
| 50 VBDEBUG(("LoadFirmware started...\n")); | 48 VBDEBUG(("LoadFirmware started...\n")); |
| 51 | 49 |
| 52 if (params->kernel_sign_key_size < sizeof(VbPublicKey)) { | 50 if (params->kernel_sign_key_size < sizeof(VbPublicKey)) { |
| 53 VBDEBUG(("Kernel sign key buffer too small\n")); | 51 VBDEBUG(("Kernel sign key buffer too small\n")); |
| 54 return LOAD_FIRMWARE_RECOVERY; | 52 return LOAD_FIRMWARE_RECOVERY; |
| 55 } | 53 } |
| 56 | 54 |
| 57 /* Must have a root key */ | 55 /* Must have a root key */ |
| 58 if (!root_key) { | 56 if (!root_key) { |
| 59 VBDEBUG(("No root key\n")); | 57 VBDEBUG(("No root key\n")); |
| 60 return LOAD_FIRMWARE_RECOVERY; | 58 return LOAD_FIRMWARE_RECOVERY; |
| 61 } | 59 } |
| 62 | 60 |
| 63 /* Initialize the TPM and read rollback indices. */ | 61 /* Initialize the TPM and read rollback indices. */ |
| 64 status = RollbackFirmwareSetup(params->boot_flags & BOOT_FLAG_DEVELOPER, | 62 status = RollbackFirmwareSetup(params->boot_flags & BOOT_FLAG_DEVELOPER, |
| 65 &tpm_key_version, &tpm_fw_version); | 63 &tpm_version); |
| 66 if (0 != status) { | 64 if (0 != status) { |
| 67 VBDEBUG(("Unable to setup TPM and read stored versions.\n")); | 65 VBDEBUG(("Unable to setup TPM and read stored versions.\n")); |
| 68 return (status == TPM_E_MUST_REBOOT ? | 66 return (status == TPM_E_MUST_REBOOT ? |
| 69 LOAD_FIRMWARE_REBOOT : LOAD_FIRMWARE_RECOVERY); | 67 LOAD_FIRMWARE_REBOOT : LOAD_FIRMWARE_RECOVERY); |
| 70 } | 68 } |
| 71 | 69 |
| 72 /* Allocate our internal data */ | 70 /* Allocate our internal data */ |
| 73 lfi = (VbLoadFirmwareInternal*)Malloc(sizeof(VbLoadFirmwareInternal)); | 71 lfi = (VbLoadFirmwareInternal*)Malloc(sizeof(VbLoadFirmwareInternal)); |
| 74 if (!lfi) | 72 if (!lfi) |
| 75 return LOAD_FIRMWARE_RECOVERY; | 73 return LOAD_FIRMWARE_RECOVERY; |
| 76 params->load_firmware_internal = (uint8_t*)lfi; | 74 params->load_firmware_internal = (uint8_t*)lfi; |
| 77 | 75 |
| 78 /* Loop over indices */ | 76 /* Loop over indices */ |
| 79 for (index = 0; index < 2; index++) { | 77 for (index = 0; index < 2; index++) { |
| 80 VbKeyBlockHeader* key_block; | 78 VbKeyBlockHeader* key_block; |
| 81 uint64_t vblock_size; | 79 uint64_t vblock_size; |
| 82 VbFirmwarePreambleHeader* preamble; | 80 VbFirmwarePreambleHeader* preamble; |
| 83 RSAPublicKey* data_key; | 81 RSAPublicKey* data_key; |
| 84 uint64_t key_version; | 82 uint64_t key_version; |
| 83 uint64_t combined_version; |
| 85 uint8_t* body_digest; | 84 uint8_t* body_digest; |
| 86 | 85 |
| 87 /* Verify the key block */ | 86 /* Verify the key block */ |
| 88 if (0 == index) { | 87 if (0 == index) { |
| 89 key_block = (VbKeyBlockHeader*)params->verification_block_0; | 88 key_block = (VbKeyBlockHeader*)params->verification_block_0; |
| 90 vblock_size = params->verification_size_0; | 89 vblock_size = params->verification_size_0; |
| 91 } else { | 90 } else { |
| 92 key_block = (VbKeyBlockHeader*)params->verification_block_1; | 91 key_block = (VbKeyBlockHeader*)params->verification_block_1; |
| 93 vblock_size = params->verification_size_1; | 92 vblock_size = params->verification_size_1; |
| 94 } | 93 } |
| 95 if ((0 != KeyBlockVerify(key_block, vblock_size, root_key))) { | 94 if ((0 != KeyBlockVerify(key_block, vblock_size, root_key))) { |
| 96 VBDEBUG(("Key block verification failed.\n")); | 95 VBDEBUG(("Key block verification failed.\n")); |
| 97 continue; | 96 continue; |
| 98 } | 97 } |
| 99 | 98 |
| 100 /* Check for rollback of key version. */ | 99 /* Check for rollback of key version. */ |
| 101 key_version = key_block->data_key.key_version; | 100 key_version = key_block->data_key.key_version; |
| 102 if (key_version < tpm_key_version) { | 101 if (key_version < (tpm_version >> 16)) { |
| 103 VBDEBUG(("Key rollback detected.\n")); | 102 VBDEBUG(("Key rollback detected.\n")); |
| 104 continue; | 103 continue; |
| 105 } | 104 } |
| 106 | 105 |
| 107 /* Get the key for preamble/data verification from the key block. */ | 106 /* Get the key for preamble/data verification from the key block. */ |
| 108 data_key = PublicKeyToRSA(&key_block->data_key); | 107 data_key = PublicKeyToRSA(&key_block->data_key); |
| 109 if (!data_key) { | 108 if (!data_key) { |
| 110 VBDEBUG(("Unable to parse data key.\n")); | 109 VBDEBUG(("Unable to parse data key.\n")); |
| 111 continue; | 110 continue; |
| 112 } | 111 } |
| 113 | 112 |
| 114 /* Verify the preamble, which follows the key block. */ | 113 /* Verify the preamble, which follows the key block. */ |
| 115 preamble = (VbFirmwarePreambleHeader*)((uint8_t*)key_block + | 114 preamble = (VbFirmwarePreambleHeader*)((uint8_t*)key_block + |
| 116 key_block->key_block_size); | 115 key_block->key_block_size); |
| 117 if ((0 != VerifyFirmwarePreamble(preamble, | 116 if ((0 != VerifyFirmwarePreamble(preamble, |
| 118 vblock_size - key_block->key_block_size, | 117 vblock_size - key_block->key_block_size, |
| 119 data_key))) { | 118 data_key))) { |
| 120 VBDEBUG(("Preamble verfication failed.\n")); | 119 VBDEBUG(("Preamble verfication failed.\n")); |
| 121 RSAPublicKeyFree(data_key); | 120 RSAPublicKeyFree(data_key); |
| 122 continue; | 121 continue; |
| 123 } | 122 } |
| 124 | 123 |
| 125 /* Check for rollback of firmware version. */ | 124 /* Check for rollback of firmware version. */ |
| 126 if (key_version == tpm_key_version && | 125 combined_version = ((key_version << 16) | |
| 127 preamble->firmware_version < tpm_fw_version) { | 126 (preamble->firmware_version & 0xFFFF)); |
| 127 if (combined_version < tpm_version) { |
| 128 VBDEBUG(("Firmware version rollback detected.\n")); | 128 VBDEBUG(("Firmware version rollback detected.\n")); |
| 129 RSAPublicKeyFree(data_key); | 129 RSAPublicKeyFree(data_key); |
| 130 continue; | 130 continue; |
| 131 } | 131 } |
| 132 | 132 |
| 133 /* Check for lowest key version from a valid header. */ | 133 /* Check for lowest key version from a valid header. */ |
| 134 if (lowest_key_version > key_version) { | 134 if (lowest_version > combined_version) |
| 135 lowest_key_version = key_version; | 135 lowest_version = combined_version; |
| 136 lowest_fw_version = preamble->firmware_version; | |
| 137 } | |
| 138 else if (lowest_key_version == key_version && | |
| 139 lowest_fw_version > preamble->firmware_version) { | |
| 140 lowest_fw_version = preamble->firmware_version; | |
| 141 } | |
| 142 | 136 |
| 143 /* If we already have good firmware, no need to read another one; | 137 /* If we already have good firmware, no need to read another one; |
| 144 * we only needed to look at the versions to check for | 138 * we only needed to look at the versions to check for |
| 145 * rollback. */ | 139 * rollback. */ |
| 146 if (-1 != good_index) | 140 if (-1 != good_index) |
| 147 continue; | 141 continue; |
| 148 | 142 |
| 149 /* Read the firmware data */ | 143 /* Read the firmware data */ |
| 150 DigestInit(&lfi->body_digest_context, data_key->algorithm); | 144 DigestInit(&lfi->body_digest_context, data_key->algorithm); |
| 151 lfi->body_size_accum = 0; | 145 lfi->body_size_accum = 0; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 195 | 189 |
| 196 /* Save the good index, now that we're sure we can actually use | 190 /* Save the good index, now that we're sure we can actually use |
| 197 * this firmware. That's the one we'll boot. */ | 191 * this firmware. That's the one we'll boot. */ |
| 198 good_index = index; | 192 good_index = index; |
| 199 params->firmware_index = index; | 193 params->firmware_index = index; |
| 200 | 194 |
| 201 /* If the good firmware's key version is the same as the tpm, | 195 /* If the good firmware's key version is the same as the tpm, |
| 202 * then the TPM doesn't need updating; we can stop now. | 196 * then the TPM doesn't need updating; we can stop now. |
| 203 * Otherwise, we'll check all the other headers to see if they | 197 * Otherwise, we'll check all the other headers to see if they |
| 204 * contain a newer key. */ | 198 * contain a newer key. */ |
| 205 if (key_version == tpm_key_version && | 199 if (combined_version == tpm_version) |
| 206 preamble->firmware_version == tpm_fw_version) | |
| 207 break; | 200 break; |
| 208 } | 201 } |
| 209 } | 202 } |
| 210 | 203 |
| 211 /* Free internal data */ | 204 /* Free internal data */ |
| 212 Free(lfi); | 205 Free(lfi); |
| 213 params->load_firmware_internal = NULL; | 206 params->load_firmware_internal = NULL; |
| 214 | 207 |
| 215 /* Handle finding good firmware */ | 208 /* Handle finding good firmware */ |
| 216 if (good_index >= 0) { | 209 if (good_index >= 0) { |
| 217 | 210 |
| 218 /* Update TPM if necessary */ | 211 /* Update TPM if necessary */ |
| 219 if ((lowest_key_version > tpm_key_version) || | 212 if (lowest_version > tpm_version) { |
| 220 (lowest_key_version == tpm_key_version && | 213 status = RollbackFirmwareWrite((uint32_t)lowest_version); |
| 221 lowest_fw_version > tpm_fw_version)) { | |
| 222 | |
| 223 status = RollbackFirmwareWrite((uint16_t)lowest_key_version, | |
| 224 (uint16_t)lowest_fw_version); | |
| 225 if (0 != status) { | 214 if (0 != status) { |
| 226 VBDEBUG(("Unable to write stored versions.\n")); | 215 VBDEBUG(("Unable to write stored versions.\n")); |
| 227 return (status == TPM_E_MUST_REBOOT ? | 216 return (status == TPM_E_MUST_REBOOT ? |
| 228 LOAD_FIRMWARE_REBOOT : LOAD_FIRMWARE_RECOVERY); | 217 LOAD_FIRMWARE_REBOOT : LOAD_FIRMWARE_RECOVERY); |
| 229 } | 218 } |
| 230 } | 219 } |
| 231 | 220 |
| 232 /* Lock firmware versions in TPM */ | 221 /* Lock firmware versions in TPM */ |
| 233 status = RollbackFirmwareLock(); | 222 status = RollbackFirmwareLock(); |
| 234 if (0 != status) { | 223 if (0 != status) { |
| 235 VBDEBUG(("Unable to lock firmware versions.\n")); | 224 VBDEBUG(("Unable to lock firmware versions.\n")); |
| 236 return (status == TPM_E_MUST_REBOOT ? | 225 return (status == TPM_E_MUST_REBOOT ? |
| 237 LOAD_FIRMWARE_REBOOT : LOAD_FIRMWARE_RECOVERY); | 226 LOAD_FIRMWARE_REBOOT : LOAD_FIRMWARE_RECOVERY); |
| 238 } | 227 } |
| 239 | 228 |
| 240 /* Success */ | 229 /* Success */ |
| 241 VBDEBUG(("Will boot firmware index %d\n", (int)params->firmware_index)); | 230 VBDEBUG(("Will boot firmware index %d\n", (int)params->firmware_index)); |
| 242 return LOAD_FIRMWARE_SUCCESS; | 231 return LOAD_FIRMWARE_SUCCESS; |
| 243 } | 232 } |
| 244 | 233 |
| 245 /* If we're still here, no good firmware, so go to recovery mode. */ | 234 /* If we're still here, no good firmware, so go to recovery mode. */ |
| 246 VBDEBUG(("Alas, no good firmware.\n")); | 235 VBDEBUG(("Alas, no good firmware.\n")); |
| 247 return LOAD_FIRMWARE_RECOVERY; | 236 return LOAD_FIRMWARE_RECOVERY; |
| 248 } | 237 } |
| OLD | NEW |