| 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 | 16 /* Static variables for UpdateFirmwareBodyHash(). It's less than |
| 17 * optimal to have static variables in a library, but in UEFI the | 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 | 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. */ | 19 * good way to pass the params struct back to us. */ |
| 20 static DigestContext ctx; | 20 typedef struct VbLoadFirmwareInternal { |
| 21 static uint64_t body_size_accum = 0; | 21 DigestContext ctx; |
| 22 static int inside_load_firmware = 0; | 22 uint64_t body_size_accum; |
| 23 } VbLoadFirmwareInternal; |
| 23 | 24 |
| 24 void UpdateFirmwareBodyHash2(uint8_t* data, uint64_t size) { | |
| 25 | 25 |
| 26 if (!inside_load_firmware) { | 26 void UpdateFirmwareBodyHash(LoadFirmwareParams* params, |
| 27 debug("UpdateFirmwareBodyHash() called outside LoadFirmware()\n"); | 27 uint8_t* data, uint64_t size) { |
| 28 return; | 28 VbLoadFirmwareInternal* lfi = |
| 29 } | 29 (VbLoadFirmwareInternal*)params->load_firmware_internal; |
| 30 | 30 |
| 31 DigestUpdate(&ctx, data, size); | 31 DigestUpdate(&lfi->ctx, data, size); |
| 32 body_size_accum += size; | 32 lfi->body_size_accum += size; |
| 33 } | 33 } |
| 34 | 34 |
| 35 | 35 |
| 36 int LoadFirmware2(LoadFirmwareParams* params) { | 36 int LoadFirmware2(LoadFirmwareParams* params) { |
| 37 | 37 |
| 38 VbPublicKey* root_key = (VbPublicKey*)params->firmware_root_key_blob; | 38 VbPublicKey* root_key = (VbPublicKey*)params->firmware_root_key_blob; |
| 39 VbLoadFirmwareInternal* lfi; |
| 39 | 40 |
| 40 uint16_t tpm_key_version = 0; | 41 uint16_t tpm_key_version = 0; |
| 41 uint16_t tpm_fw_version = 0; | 42 uint16_t tpm_fw_version = 0; |
| 42 uint64_t lowest_key_version = 0xFFFF; | 43 uint64_t lowest_key_version = 0xFFFF; |
| 43 uint64_t lowest_fw_version = 0xFFFF; | 44 uint64_t lowest_fw_version = 0xFFFF; |
| 44 int good_index = -1; | 45 int good_index = -1; |
| 45 int index; | 46 int index; |
| 46 | 47 |
| 47 /* Clear output params in case we fail */ | 48 /* Clear output params in case we fail */ |
| 48 params->firmware_index = 0; | 49 params->firmware_index = 0; |
| 49 params->kernel_sign_key_blob = NULL; | 50 params->kernel_sign_key_blob = NULL; |
| 50 params->kernel_sign_key_size = 0; | 51 params->kernel_sign_key_size = 0; |
| 51 | 52 |
| 52 /* Must have a root key */ | 53 /* Must have a root key */ |
| 53 if (!root_key) | 54 if (!root_key) |
| 54 return LOAD_FIRMWARE_RECOVERY; | 55 return LOAD_FIRMWARE_RECOVERY; |
| 55 | 56 |
| 56 /* Initialize the TPM and read rollback indices. */ | 57 /* Initialize the TPM and read rollback indices. */ |
| 57 /* TODO: fix SetupTPM parameter */ | 58 /* TODO: fix SetupTPM parameter */ |
| 58 if (0 != SetupTPM(0, 0) ) | 59 if (0 != SetupTPM(0, 0) ) |
| 59 return LOAD_FIRMWARE_RECOVERY; | 60 return LOAD_FIRMWARE_RECOVERY; |
| 60 if (0 != GetStoredVersions(FIRMWARE_VERSIONS, | 61 if (0 != GetStoredVersions(FIRMWARE_VERSIONS, |
| 61 &tpm_key_version, &tpm_fw_version)) | 62 &tpm_key_version, &tpm_fw_version)) |
| 62 return LOAD_FIRMWARE_RECOVERY; | 63 return LOAD_FIRMWARE_RECOVERY; |
| 63 | 64 |
| 65 /* Allocate our internal data */ |
| 66 lfi = (VbLoadFirmwareInternal*)Malloc(sizeof(VbLoadFirmwareInternal)); |
| 67 if (!lfi) |
| 68 return LOAD_FIRMWARE_RECOVERY; |
| 69 params->load_firmware_internal = lfi; |
| 70 |
| 64 /* Loop over indices */ | 71 /* Loop over indices */ |
| 65 for (index = 0; index < 2; index++) { | 72 for (index = 0; index < 2; index++) { |
| 66 VbKeyBlockHeader* key_block; | 73 VbKeyBlockHeader* key_block; |
| 67 uint64_t vblock_size; | 74 uint64_t vblock_size; |
| 68 VbFirmwarePreambleHeader* preamble; | 75 VbFirmwarePreambleHeader* preamble; |
| 69 RSAPublicKey* data_key; | 76 RSAPublicKey* data_key; |
| 70 uint64_t key_version; | 77 uint64_t key_version; |
| 71 uint8_t* body_data; | |
| 72 uint64_t body_size; | |
| 73 uint8_t* body_digest; | 78 uint8_t* body_digest; |
| 74 | 79 |
| 75 /* Verify the key block */ | 80 /* Verify the key block */ |
| 76 if (0 == index) { | 81 if (0 == index) { |
| 77 key_block = (VbKeyBlockHeader*)params->verification_block_0; | 82 key_block = (VbKeyBlockHeader*)params->verification_block_0; |
| 78 vblock_size = params->verification_size_0; | 83 vblock_size = params->verification_size_0; |
| 79 } else { | 84 } else { |
| 80 key_block = (VbKeyBlockHeader*)params->verification_block_1; | 85 key_block = (VbKeyBlockHeader*)params->verification_block_1; |
| 81 vblock_size = params->verification_size_1; | 86 vblock_size = params->verification_size_1; |
| 82 } | 87 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 120 lowest_fw_version = preamble->firmware_version; | 125 lowest_fw_version = preamble->firmware_version; |
| 121 } | 126 } |
| 122 | 127 |
| 123 /* If we already have good firmware, no need to read another one; | 128 /* If we already have good firmware, no need to read another one; |
| 124 * we only needed to look at the versions to check for | 129 * we only needed to look at the versions to check for |
| 125 * rollback. */ | 130 * rollback. */ |
| 126 if (-1 != good_index) | 131 if (-1 != good_index) |
| 127 continue; | 132 continue; |
| 128 | 133 |
| 129 /* Read the firmware data */ | 134 /* Read the firmware data */ |
| 130 DigestInit(&ctx, data_key->algorithm); | 135 DigestInit(&lfi->ctx, data_key->algorithm); |
| 131 body_size_accum = 0; | 136 lfi->body_size_accum = 0; |
| 132 inside_load_firmware = 1; | 137 if ((0 != GetFirmwareBody(params, index)) || |
| 133 body_data = GetFirmwareBody(index, &body_size); | 138 (lfi->body_size_accum != 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)) { | |
| 138 RSAPublicKeyFree(data_key); | 139 RSAPublicKeyFree(data_key); |
| 139 Free(body_digest); | |
| 140 continue; | 140 continue; |
| 141 } | 141 } |
| 142 | 142 |
| 143 /* Verify firmware data */ | 143 /* Verify firmware data */ |
| 144 body_digest = DigestFinal(&lfi->ctx); |
| 144 if (0 != VerifyDigest(body_digest, &preamble->body_signature, data_key)) { | 145 if (0 != VerifyDigest(body_digest, &preamble->body_signature, data_key)) { |
| 145 RSAPublicKeyFree(data_key); | 146 RSAPublicKeyFree(data_key); |
| 146 Free(body_digest); | 147 Free(body_digest); |
| 147 continue; | 148 continue; |
| 148 } | 149 } |
| 149 | 150 |
| 150 /* Done with the digest and data key, so can free them now */ | 151 /* Done with the digest and data key, so can free them now */ |
| 151 RSAPublicKeyFree(data_key); | 152 RSAPublicKeyFree(data_key); |
| 152 Free(body_digest); | 153 Free(body_digest); |
| 153 | 154 |
| 154 /* If we're still here, the firmware is valid. */ | 155 /* If we're still here, the firmware is valid. */ |
| 155 /* Save the first good firmware we find; that's the one we'll boot */ | 156 /* Save the first good firmware we find; that's the one we'll boot */ |
| 156 if (-1 == good_index) { | 157 if (-1 == good_index) { |
| 158 VbPublicKey *kdest = (VbPublicKey*)params->kernel_sign_key_blob; |
| 159 |
| 160 /* Copy the kernel sign key blob into the destination buffer */ |
| 161 PublicKeyInit(kdest, (uint8_t*)(kdest + 1), |
| 162 (params->kernel_sign_key_size - sizeof(VbPublicKey))); |
| 163 |
| 164 if (0 != PublicKeyCopy(kdest, &preamble->kernel_subkey)) |
| 165 continue; /* The firmware signature was good, but the public |
| 166 * key was bigger that the caller can handle. */ |
| 167 |
| 168 /* Save the key size we actually used */ |
| 169 params->kernel_sign_key_size = kdest->key_offset + kdest->key_size; |
| 170 |
| 171 /* Save the good index, now that we're sure we can actually use |
| 172 * this firmware. */ |
| 157 good_index = index; | 173 good_index = index; |
| 158 params->firmware_index = index; | 174 params->firmware_index = index; |
| 159 params->kernel_sign_key_blob = &preamble->kernel_subkey; | |
| 160 params->kernel_sign_key_size = (preamble->kernel_subkey.key_offset + | |
| 161 preamble->kernel_subkey.key_size); | |
| 162 | 175 |
| 163 /* If the good firmware's key version is the same as the tpm, | 176 /* If the good firmware's key version is the same as the tpm, |
| 164 * then the TPM doesn't need updating; we can stop now. | 177 * then the TPM doesn't need updating; we can stop now. |
| 165 * Otherwise, we'll check all the other headers to see if they | 178 * Otherwise, we'll check all the other headers to see if they |
| 166 * contain a newer key. */ | 179 * contain a newer key. */ |
| 167 if (key_version == tpm_key_version && | 180 if (key_version == tpm_key_version && |
| 168 preamble->firmware_version == tpm_fw_version) | 181 preamble->firmware_version == tpm_fw_version) |
| 169 break; | 182 break; |
| 170 } | 183 } |
| 171 } | 184 } |
| 172 | 185 |
| 186 /* Free internal data */ |
| 187 Free(lfi); |
| 188 params->load_firmware_internal = NULL; |
| 189 |
| 173 /* Handle finding good firmware */ | 190 /* Handle finding good firmware */ |
| 174 if (good_index >= 0) { | 191 if (good_index >= 0) { |
| 175 | 192 |
| 176 /* Update TPM if necessary */ | 193 /* Update TPM if necessary */ |
| 177 if ((lowest_key_version > tpm_key_version) || | 194 if ((lowest_key_version > tpm_key_version) || |
| 178 (lowest_key_version == tpm_key_version && | 195 (lowest_key_version == tpm_key_version && |
| 179 lowest_fw_version > tpm_fw_version)) { | 196 lowest_fw_version > tpm_fw_version)) { |
| 180 if (0 != WriteStoredVersions(FIRMWARE_VERSIONS, | 197 if (0 != WriteStoredVersions(FIRMWARE_VERSIONS, |
| 181 lowest_key_version, | 198 lowest_key_version, |
| 182 lowest_fw_version)) | 199 lowest_fw_version)) |
| 183 return LOAD_FIRMWARE_RECOVERY; | 200 return LOAD_FIRMWARE_RECOVERY; |
| 184 } | 201 } |
| 185 | 202 |
| 186 /* Lock Firmware TPM rollback indices from further writes. In | 203 /* Lock Firmware TPM rollback indices from further writes. In |
| 187 * this design, this is done by setting the globalLock bit, which | 204 * this design, this is done by setting the globalLock bit, which |
| 188 * is cleared only by TPM_Init at reboot. */ | 205 * is cleared only by TPM_Init at reboot. */ |
| 189 if (0 != LockFirmwareVersions()) | 206 if (0 != LockFirmwareVersions()) |
| 190 return LOAD_FIRMWARE_RECOVERY; | 207 return LOAD_FIRMWARE_RECOVERY; |
| 191 } | 208 } |
| 192 | 209 |
| 193 /* If we're still here, no good firmware, so go to recovery mode. */ | 210 /* If we're still here, no good firmware, so go to recovery mode. */ |
| 194 return LOAD_FIRMWARE_RECOVERY; | 211 return LOAD_FIRMWARE_RECOVERY; |
| 195 } | 212 } |
| OLD | NEW |