1 /* Copyright (c) 2014 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 * Misc functions which need access to vb2_context but are not public APIs 6 */ 7 8 #include "2sysincludes.h" 9 #include "2api.h" 10 #include "2misc.h" 11 #include "2nvstorage.h" 12 #include "2secdata.h" 13 #include "2sha.h" 14 #include "2rsa.h" 15 #include "vb2_common.h" 16 17 int vb2_load_fw_keyblock(struct vb2_context *ctx) 18 { 19 struct vb2_shared_data *sd = vb2_get_sd(ctx); 20 struct vb2_workbuf wb; 21 22 uint8_t *key_data; 23 uint32_t key_size; 24 struct vb2_packed_key *packed_key; 25 struct vb2_public_key root_key; 26 27 struct vb2_keyblock *kb; 28 uint32_t block_size; 29 30 int rv; 31 32 vb2_workbuf_from_ctx(ctx, &wb); 33 34 /* Read the root key */ 35 key_size = sd->gbb_rootkey_size; 36 key_data = vb2_workbuf_alloc(&wb, key_size); 37 if (!key_data) 38 return VB2_ERROR_FW_KEYBLOCK_WORKBUF_ROOT_KEY; 39 40 rv = vb2ex_read_resource(ctx, VB2_RES_GBB, sd->gbb_rootkey_offset, 41 key_data, key_size); 42 if (rv) 43 return rv; 44 45 /* Unpack the root key */ 46 rv = vb2_unpack_key(&root_key, key_data, key_size); 47 if (rv) 48 return rv; 49 50 /* Load the firmware keyblock header after the root key */ 51 kb = vb2_workbuf_alloc(&wb, sizeof(*kb)); 52 if (!kb) 53 return VB2_ERROR_FW_KEYBLOCK_WORKBUF_HEADER; 54 55 rv = vb2ex_read_resource(ctx, VB2_RES_FW_VBLOCK, 0, kb, sizeof(*kb)); 56 if (rv) 57 return rv; 58 59 block_size = kb->keyblock_size; 60 61 /* 62 * Load the entire keyblock, now that we know how big it is. Note that 63 * we're loading the entire keyblock instead of just the piece after 64 * the header. That means we re-read the header. But that's a tiny 65 * amount of data, and it makes the code much more straightforward. 66 */ 67 kb = vb2_workbuf_realloc(&wb, sizeof(*kb), block_size); 68 if (!kb) 69 return VB2_ERROR_FW_KEYBLOCK_WORKBUF; 70 71 rv = vb2ex_read_resource(ctx, VB2_RES_FW_VBLOCK, 0, kb, block_size); 72 if (rv) 73 return rv; 74 75 /* Verify the keyblock */ 76 rv = vb2_verify_keyblock(kb, block_size, &root_key, &wb); 77 if (rv) { 78 vb2_fail(ctx, VB2_RECOVERY_FW_KEYBLOCK, rv); 79 return rv; 80 } 81 82 /* Key version is the upper 16 bits of the composite firmware version */ 83 if (kb->data_key.key_version > 0xffff) 84 rv = VB2_ERROR_FW_KEYBLOCK_VERSION_RANGE; 85 if (!rv && kb->data_key.key_version < (sd->fw_version_secdata >> 16)) 86 rv = VB2_ERROR_FW_KEYBLOCK_VERSION_ROLLBACK; 87 if (rv) { 88 vb2_fail(ctx, VB2_RECOVERY_FW_KEY_ROLLBACK, rv); 89 return rv; 90 } 91 92 sd->fw_version = kb->data_key.key_version << 16; 93 94 /* 95 * Save the data key in the work buffer. This overwrites the root key 96 * we read above. That's ok, because now that we have the data key we 97 * no longer need the root key. 98 */ 99 packed_key = (struct vb2_packed_key *)key_data; 100 101 packed_key->algorithm = kb->data_key.algorithm; 102 packed_key->key_version = kb->data_key.key_version; 103 packed_key->key_size = kb->data_key.key_size; 104 105 /* 106 * Use memmove() instead of memcpy(). In theory, the destination will 107 * never overlap because with the source because the root key is likely 108 * to be at least as large as the data key, but there's no harm here in 109 * being paranoid. 110 */ 111 memmove(key_data + packed_key->key_offset, 112 (uint8_t*)&kb->data_key + kb->data_key.key_offset, 113 packed_key->key_size); 114 115 /* Save the packed key offset and size */ 116 sd->workbuf_data_key_offset = vb2_offset_of(ctx->workbuf, key_data); 117 sd->workbuf_data_key_size = 118 packed_key->key_offset + packed_key->key_size; 119 120 /* Preamble follows the keyblock in the vblock */ 121 sd->vblock_preamble_offset = kb->keyblock_size; 122 123 /* Data key will persist in the workbuf after we return */ 124 ctx->workbuf_used = sd->workbuf_data_key_offset + 125 sd->workbuf_data_key_size; 126 127 return VB2_SUCCESS; 128 } 129 130 int vb2_load_fw_preamble(struct vb2_context *ctx) 131 { 132 struct vb2_shared_data *sd = vb2_get_sd(ctx); 133 struct vb2_workbuf wb; 134 135 uint8_t *key_data = ctx->workbuf + sd->workbuf_data_key_offset; 136 uint32_t key_size = sd->workbuf_data_key_size; 137 struct vb2_public_key data_key; 138 139 /* Preamble goes in the next unused chunk of work buffer */ 140 struct vb2_fw_preamble *pre; 141 uint32_t pre_size; 142 143 int rv; 144 145 vb2_workbuf_from_ctx(ctx, &wb); 146 147 /* Unpack the firmware data key */ 148 if (!sd->workbuf_data_key_size) 149 return VB2_ERROR_FW_PREAMBLE2_DATA_KEY; 150 151 rv = vb2_unpack_key(&data_key, key_data, key_size); 152 if (rv) 153 return rv; 154 155 /* Load the firmware preamble header */ 156 pre = vb2_workbuf_alloc(&wb, sizeof(*pre)); 157 if (!pre) 158 return VB2_ERROR_FW_PREAMBLE2_WORKBUF_HEADER; 159 160 rv = vb2ex_read_resource(ctx, VB2_RES_FW_VBLOCK, 161 sd->vblock_preamble_offset, 162 pre, sizeof(*pre)); 163 if (rv) 164 return rv; 165 166 pre_size = pre->preamble_size; 167 168 /* Load the entire firmware preamble, now that we know how big it is */ 169 pre = vb2_workbuf_realloc(&wb, sizeof(*pre), pre_size); 170 if (!pre) 171 return VB2_ERROR_FW_PREAMBLE2_WORKBUF; 172 173 rv = vb2ex_read_resource(ctx, VB2_RES_FW_VBLOCK, 174 sd->vblock_preamble_offset, 175 pre, pre_size); 176 if (rv) 177 return rv; 178 179 /* Work buffer now contains the data subkey data and the preamble */ 180 181 /* Verify the preamble */ 182 rv = vb2_verify_fw_preamble(pre, pre_size, &data_key, &wb); 183 if (rv) { 184 vb2_fail(ctx, VB2_RECOVERY_FW_PREAMBLE, rv); 185 return rv; 186 } 187 188 /* 189 * Firmware version is the lower 16 bits of the composite firmware 190 * version. 191 */ 192 if (pre->firmware_version > 0xffff) 193 rv = VB2_ERROR_FW_PREAMBLE_VERSION_RANGE; 194 /* Combine with the key version from vb2_load_fw_keyblock() */ 195 sd->fw_version |= pre->firmware_version; 196 if (!rv && sd->fw_version < sd->fw_version_secdata) 197 rv = VB2_ERROR_FW_PREAMBLE_VERSION_ROLLBACK; 198 if (rv) { 199 vb2_fail(ctx, VB2_RECOVERY_FW_ROLLBACK, rv); 200 return rv; 201 } 202 203 /* 204 * If this is a newer version than in secure storage, and we 205 * successfully booted the same slot last boot, roll forward the 206 * version in secure storage. 207 */ 208 if (sd->fw_version > sd->fw_version_secdata && 209 sd->last_fw_slot == sd->fw_slot && 210 sd->last_fw_result == VB2_FW_RESULT_SUCCESS) { 211 212 sd->fw_version_secdata = sd->fw_version; 213 rv = vb2_secdata_set(ctx, VB2_SECDATA_VERSIONS, sd->fw_version); 214 if (rv) 215 return rv; 216 } 217 218 /* Keep track of where we put the preamble */ 219 sd->workbuf_preamble_offset = vb2_offset_of(ctx->workbuf, pre); 220 sd->workbuf_preamble_size = pre_size; 221 222 /* Preamble will persist in work buffer after we return */ 223 ctx->workbuf_used = sd->workbuf_preamble_offset + pre_size; 224 225 return VB2_SUCCESS; 226 } 227