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