| 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 "vboot_firmware.h" | 9 #include "vboot_firmware.h" |
| 10 | 10 |
| 11 #include "load_firmware_fw.h" | 11 #include "load_firmware_fw.h" |
| 12 #include "rollback_index.h" | 12 #include "rollback_index.h" |
| 13 #include "utility.h" | 13 #include "utility.h" |
| 14 #include "vboot_common.h" | 14 #include "vboot_common.h" |
| 15 | 15 |
| 16 /* Static variables for UpdateFirmwareBodyHash(). It's less than |
| 17 * optimal to have static variables in a library, but in UEFI the |
| 18 * caller is deep inside a different firmware stack and doesn't have a |
| 19 * good way to pass the params struct back to us. */ |
| 20 static DigestContext ctx; |
| 21 static uint64_t body_size_accum = 0; |
| 22 static int inside_load_firmware = 0; |
| 16 | 23 |
| 17 void UpdateFirmwareBodyHash2(uint8_t* data, uint64_t size) { | 24 void UpdateFirmwareBodyHash2(uint8_t* data, uint64_t size) { |
| 18 /* TODO: actually update the hash. */ | 25 |
| 26 if (!inside_load_firmware) { |
| 27 debug("UpdateFirmwareBodyHash() called outside LoadFirmware()\n"); |
| 28 return; |
| 29 } |
| 30 |
| 31 DigestUpdate(&ctx, data, size); |
| 32 body_size_accum += size; |
| 19 } | 33 } |
| 20 | 34 |
| 21 | 35 |
| 22 int LoadFirmware2(LoadFirmwareParams* params) { | 36 int LoadFirmware2(LoadFirmwareParams* params) { |
| 23 | 37 |
| 24 VbPublicKey* root_key = (VbPublicKey*)params->firmware_root_key_blob; | 38 VbPublicKey* root_key = (VbPublicKey*)params->firmware_root_key_blob; |
| 25 | 39 |
| 26 uint16_t tpm_key_version = 0; | 40 uint16_t tpm_key_version = 0; |
| 27 uint16_t tpm_fw_version = 0; | 41 uint16_t tpm_fw_version = 0; |
| 28 uint64_t lowest_key_version = 0xFFFF; | 42 uint64_t lowest_key_version = 0xFFFF; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 49 | 63 |
| 50 /* Loop over indices */ | 64 /* Loop over indices */ |
| 51 for (index = 0; index < 2; index++) { | 65 for (index = 0; index < 2; index++) { |
| 52 VbKeyBlockHeader* key_block; | 66 VbKeyBlockHeader* key_block; |
| 53 uint64_t vblock_size; | 67 uint64_t vblock_size; |
| 54 VbFirmwarePreambleHeader* preamble; | 68 VbFirmwarePreambleHeader* preamble; |
| 55 RSAPublicKey* data_key; | 69 RSAPublicKey* data_key; |
| 56 uint64_t key_version; | 70 uint64_t key_version; |
| 57 uint8_t* body_data; | 71 uint8_t* body_data; |
| 58 uint64_t body_size; | 72 uint64_t body_size; |
| 73 uint8_t* body_digest; |
| 59 | 74 |
| 60 /* Verify the key block */ | 75 /* Verify the key block */ |
| 61 if (0 == index) { | 76 if (0 == index) { |
| 62 key_block = (VbKeyBlockHeader*)params->verification_block_0; | 77 key_block = (VbKeyBlockHeader*)params->verification_block_0; |
| 63 vblock_size = params->verification_size_0; | 78 vblock_size = params->verification_size_0; |
| 64 } else { | 79 } else { |
| 65 key_block = (VbKeyBlockHeader*)params->verification_block_1; | 80 key_block = (VbKeyBlockHeader*)params->verification_block_1; |
| 66 vblock_size = params->verification_size_1; | 81 vblock_size = params->verification_size_1; |
| 67 } | 82 } |
| 68 if ((0 != KeyBlockVerify(key_block, vblock_size, root_key))) | 83 if ((0 != KeyBlockVerify(key_block, vblock_size, root_key))) |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 105 lowest_fw_version = preamble->firmware_version; | 120 lowest_fw_version = preamble->firmware_version; |
| 106 } | 121 } |
| 107 | 122 |
| 108 /* If we already have good firmware, no need to read another one; | 123 /* If we already have good firmware, no need to read another one; |
| 109 * we only needed to look at the versions to check for | 124 * we only needed to look at the versions to check for |
| 110 * rollback. */ | 125 * rollback. */ |
| 111 if (-1 != good_index) | 126 if (-1 != good_index) |
| 112 continue; | 127 continue; |
| 113 | 128 |
| 114 /* Read the firmware data */ | 129 /* Read the firmware data */ |
| 115 /* TODO: should set up hash for UpdateFirmwareBodyHash(). */ | 130 DigestInit(&ctx, data_key->algorithm); |
| 131 body_size_accum = 0; |
| 132 inside_load_firmware = 1; |
| 116 body_data = GetFirmwareBody(index, &body_size); | 133 body_data = GetFirmwareBody(index, &body_size); |
| 117 if (!body_data || (body_size != preamble->body_signature.data_size)) { | 134 inside_load_firmware = 0; |
| 135 body_digest = DigestFinal(&ctx); |
| 136 if (!body_data || (body_size != preamble->body_signature.data_size) || |
| 137 (body_size_accum != body_size)) { |
| 118 RSAPublicKeyFree(data_key); | 138 RSAPublicKeyFree(data_key); |
| 139 Free(body_digest); |
| 119 continue; | 140 continue; |
| 120 } | 141 } |
| 121 | 142 |
| 122 /* Verify firmware data */ | 143 /* Verify firmware data */ |
| 123 /* TODO: should use hash from UpdateFirmwareBodyHash() rather than | 144 if (0 != VerifyDigest(body_digest, &preamble->body_signature, data_key)) { |
| 124 * recalculating it in VerifyData(). */ | |
| 125 if (0 != VerifyData(body_data, &preamble->body_signature, data_key)) { | |
| 126 RSAPublicKeyFree(data_key); | 145 RSAPublicKeyFree(data_key); |
| 146 Free(body_digest); |
| 127 continue; | 147 continue; |
| 128 } | 148 } |
| 129 | 149 |
| 130 /* Done with the data key, so can free it now */ | 150 /* Done with the digest and data key, so can free them now */ |
| 131 RSAPublicKeyFree(data_key); | 151 RSAPublicKeyFree(data_key); |
| 152 Free(body_digest); |
| 132 | 153 |
| 133 /* If we're still here, the firmware is valid. */ | 154 /* If we're still here, the firmware is valid. */ |
| 134 /* Save the first good firmware we find; that's the one we'll boot */ | 155 /* Save the first good firmware we find; that's the one we'll boot */ |
| 135 if (-1 == good_index) { | 156 if (-1 == good_index) { |
| 136 good_index = index; | 157 good_index = index; |
| 137 params->firmware_index = index; | 158 params->firmware_index = index; |
| 138 params->kernel_sign_key_blob = &preamble->kernel_subkey; | 159 params->kernel_sign_key_blob = &preamble->kernel_subkey; |
| 139 params->kernel_sign_key_size = (preamble->kernel_subkey.key_offset + | 160 params->kernel_sign_key_size = (preamble->kernel_subkey.key_offset + |
| 140 preamble->kernel_subkey.key_size); | 161 preamble->kernel_subkey.key_size); |
| 141 | 162 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 165 /* Lock Firmware TPM rollback indices from further writes. In | 186 /* Lock Firmware TPM rollback indices from further writes. In |
| 166 * this design, this is done by setting the globalLock bit, which | 187 * this design, this is done by setting the globalLock bit, which |
| 167 * is cleared only by TPM_Init at reboot. */ | 188 * is cleared only by TPM_Init at reboot. */ |
| 168 if (0 != LockFirmwareVersions()) | 189 if (0 != LockFirmwareVersions()) |
| 169 return LOAD_FIRMWARE_RECOVERY; | 190 return LOAD_FIRMWARE_RECOVERY; |
| 170 } | 191 } |
| 171 | 192 |
| 172 /* If we're still here, no good firmware, so go to recovery mode. */ | 193 /* If we're still here, no good firmware, so go to recovery mode. */ |
| 173 return LOAD_FIRMWARE_RECOVERY; | 194 return LOAD_FIRMWARE_RECOVERY; |
| 174 } | 195 } |
| OLD | NEW |