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 * Tests for misc library, new-style structs 6 */ 7 8 #include <stdio.h> 9 10 #include "2sysincludes.h" 11 #include "2api.h" 12 #include "2common.h" 13 #include "2misc.h" 14 #include "2nvstorage.h" 15 #include "2secdata.h" 16 17 #include "vb2_common.h" 18 19 #include "test_common.h" 20 21 /* Common context for tests */ 22 static uint8_t workbuf[VB2_WORKBUF_RECOMMENDED_SIZE] 23 __attribute__ ((aligned (VB2_WORKBUF_ALIGN))); 24 static struct vb2_context ctx; 25 static struct vb2_shared_data *sd; 26 27 /* Mocked function data */ 28 29 static struct { 30 struct vb2_gbb_header h; 31 struct vb2_packed_key rootkey; 32 char rootkey_data[32]; 33 } mock_gbb; 34 35 static struct { 36 /* Keyblock */ 37 struct { 38 struct vb2_keyblock kb; 39 struct vb2_packed_key data_key; 40 char data_key_data[16]; 41 uint8_t kbdata[128]; 42 } k; 43 /* Preamble follows keyblock */ 44 struct { 45 struct vb2_fw_preamble pre; 46 uint8_t predata[128]; 47 } p; 48 } mock_vblock; 49 50 static int mock_read_res_fail_on_call; 51 static int mock_unpack_key_retval; 52 static int mock_verify_keyblock_retval; 53 static int mock_verify_preamble_retval; 54 55 /* Type of test to reset for */ 56 enum reset_type { 57 FOR_KEYBLOCK, 58 FOR_PREAMBLE 59 }; 60 61 static void reset_common_data(enum reset_type t) 62 { 63 struct vb2_keyblock *kb = &mock_vblock.k.kb; 64 struct vb2_packed_key *dk = &mock_vblock.k.data_key; 65 struct vb2_fw_preamble *pre = &mock_vblock.p.pre; 66 67 memset(workbuf, 0xaa, sizeof(workbuf)); 68 69 memset(&ctx, 0, sizeof(ctx)); 70 ctx.workbuf = workbuf; 71 ctx.workbuf_size = sizeof(workbuf); 72 73 vb2_init_context(&ctx); 74 sd = vb2_get_sd(&ctx); 75 76 vb2_nv_init(&ctx); 77 78 vb2_secdata_create(&ctx); 79 vb2_secdata_init(&ctx); 80 81 mock_read_res_fail_on_call = 0; 82 mock_unpack_key_retval = VB2_SUCCESS; 83 mock_verify_keyblock_retval = VB2_SUCCESS; 84 mock_verify_preamble_retval = VB2_SUCCESS; 85 86 /* Set up mock data for verifying keyblock */ 87 sd->fw_version_secdata = 0x20002; 88 vb2_secdata_set(&ctx, VB2_SECDATA_VERSIONS, sd->fw_version_secdata); 89 90 sd->gbb_rootkey_offset = vb2_offset_of(&mock_gbb, &mock_gbb.rootkey); 91 sd->gbb_rootkey_size = sizeof(mock_gbb.rootkey_data); 92 sd->last_fw_result = VB2_FW_RESULT_SUCCESS; 93 94 mock_gbb.rootkey.sig_alg = VB2_SIG_RSA8192; 95 mock_gbb.rootkey.key_offset = 96 vb2_offset_of(&mock_gbb.rootkey, 97 &mock_gbb.rootkey_data); 98 mock_gbb.rootkey.key_size = sizeof(mock_gbb.rootkey_data); 99 100 kb->c.total_size = sizeof(mock_vblock.k); 101 kb->key_offset = vb2_offset_of(&mock_vblock.k.kb, 102 &mock_vblock.k.data_key); 103 104 dk->c.fixed_size = sizeof(mock_vblock.k.data_key); 105 dk->sig_alg = VB2_SIG_RSA4096; 106 dk->key_version = 2; 107 dk->key_offset = dk->c.fixed_size; 108 dk->key_size = sizeof(mock_vblock.k.data_key_data); 109 dk->c.total_size = dk->key_offset + dk->key_size; 110 strcpy(mock_vblock.k.data_key_data, "data key data!!"); 111 112 pre->c.total_size = sizeof(mock_vblock.p); 113 pre->fw_version = 2; 114 115 /* If verifying preamble, verify keyblock first to set up data key */ 116 if (t == FOR_PREAMBLE) 117 vb2_load_fw_keyblock(&ctx); 118 }; 119 120 /* Mocked functions */ 121 122 int vb2ex_read_resource(struct vb2_context *ctx, 123 enum vb2_resource_index index, 124 uint32_t offset, 125 void *buf, 126 uint32_t size) 127 { 128 uint8_t *rptr; 129 uint32_t rsize; 130 131 if (--mock_read_res_fail_on_call == 0) 132 return VB2_ERROR_EX_READ_RESOURCE_INDEX; 133 134 switch(index) { 135 case VB2_RES_GBB: 136 rptr = (uint8_t *)&mock_gbb; 137 rsize = sizeof(mock_gbb); 138 break; 139 case VB2_RES_FW_VBLOCK: 140 rptr = (uint8_t *)&mock_vblock; 141 rsize = sizeof(mock_vblock); 142 break; 143 default: 144 return VB2_ERROR_EX_READ_RESOURCE_INDEX; 145 } 146 147 if (offset > rsize || offset + size > rsize) 148 return VB2_ERROR_EX_READ_RESOURCE_SIZE; 149 150 memcpy(buf, rptr + offset, size); 151 return VB2_SUCCESS; 152 } 153 154 int vb2_unpack_key(struct vb2_public_key *key, 155 const uint8_t *buf, 156 uint32_t size) 157 { 158 return mock_unpack_key_retval; 159 } 160 161 int vb2_verify_keyblock(struct vb2_keyblock *block, 162 uint32_t size, 163 const struct vb2_public_key *key, 164 const struct vb2_workbuf *wb) 165 { 166 return mock_verify_keyblock_retval; 167 } 168 169 int vb2_verify_fw_preamble(struct vb2_fw_preamble *preamble, 170 uint32_t size, 171 const struct vb2_public_key *key, 172 const struct vb2_workbuf *wb) 173 { 174 return mock_verify_preamble_retval; 175 } 176 177 /* Tests */ 178 179 static void load_keyblock_tests(void) 180 { 181 struct vb2_keyblock *kb = &mock_vblock.k.kb; 182 struct vb2_packed_key *dk = &mock_vblock.k.data_key; 183 struct vb2_packed_key *k; 184 int wb_used_before; 185 186 /* Test successful call */ 187 reset_common_data(FOR_KEYBLOCK); 188 wb_used_before = ctx.workbuf_used; 189 TEST_SUCC(vb2_load_fw_keyblock(&ctx), "keyblock verify"); 190 TEST_EQ(sd->fw_version, 0x20000, "keyblock version"); 191 TEST_EQ(sd->vblock_preamble_offset, sizeof(mock_vblock.k), 192 "preamble offset"); 193 TEST_EQ(sd->workbuf_data_key_offset, 194 (wb_used_before + (VB2_WORKBUF_ALIGN - 1)) & 195 ~(VB2_WORKBUF_ALIGN - 1), 196 "keyblock data key offset"); 197 TEST_EQ(ctx.workbuf_used, 198 sd->workbuf_data_key_offset + sd->workbuf_data_key_size, 199 "workbuf used"); 200 201 /* Make sure data key was properly saved */ 202 k = (struct vb2_packed_key *)(ctx.workbuf + 203 sd->workbuf_data_key_offset); 204 TEST_EQ(k->sig_alg, VB2_SIG_RSA4096, "data key algorithm"); 205 TEST_EQ(k->key_version, 2, "data key version"); 206 TEST_EQ(k->key_size, sizeof(mock_vblock.k.data_key_data), 207 "data key size"); 208 TEST_EQ(memcmp(ctx.workbuf + sd->workbuf_data_key_offset + 209 k->key_offset, mock_vblock.k.data_key_data, 210 sizeof(mock_vblock.k.data_key_data)), 211 0, "data key data"); 212 TEST_EQ(ctx.workbuf_used, 213 sd->workbuf_data_key_offset + sd->workbuf_data_key_size, 214 "workbuf used after"); 215 216 /* Test failures */ 217 reset_common_data(FOR_KEYBLOCK); 218 ctx.workbuf_used = ctx.workbuf_size - sd->gbb_rootkey_size + 8; 219 TEST_EQ(vb2_load_fw_keyblock(&ctx), 220 VB2_ERROR_FW_KEYBLOCK_WORKBUF_ROOT_KEY, 221 "keyblock not enough workbuf for root key"); 222 223 reset_common_data(FOR_KEYBLOCK); 224 sd->gbb_rootkey_size = sizeof(mock_gbb); 225 TEST_EQ(vb2_load_fw_keyblock(&ctx), 226 VB2_ERROR_EX_READ_RESOURCE_SIZE, 227 "keyblock read root key"); 228 229 reset_common_data(FOR_KEYBLOCK); 230 mock_unpack_key_retval = VB2_ERROR_UNPACK_KEY_SIG_ALGORITHM; 231 TEST_EQ(vb2_load_fw_keyblock(&ctx), 232 VB2_ERROR_UNPACK_KEY_SIG_ALGORITHM, 233 "keyblock unpack root key"); 234 235 reset_common_data(FOR_KEYBLOCK); 236 ctx.workbuf_used = ctx.workbuf_size - sd->gbb_rootkey_size - 8; 237 TEST_EQ(vb2_load_fw_keyblock(&ctx), 238 VB2_ERROR_READ_RESOURCE_OBJECT_BUF, 239 "keyblock not enough workbuf for header"); 240 241 reset_common_data(FOR_KEYBLOCK); 242 mock_read_res_fail_on_call = 2; 243 TEST_EQ(vb2_load_fw_keyblock(&ctx), 244 VB2_ERROR_EX_READ_RESOURCE_INDEX, 245 "keyblock read keyblock header"); 246 247 reset_common_data(FOR_KEYBLOCK); 248 ctx.workbuf_used = ctx.workbuf_size - sd->gbb_rootkey_size 249 - sizeof(struct vb2_keyblock); 250 TEST_EQ(vb2_load_fw_keyblock(&ctx), 251 VB2_ERROR_READ_RESOURCE_OBJECT_BUF, 252 "keyblock not enough workbuf for entire keyblock"); 253 254 reset_common_data(FOR_KEYBLOCK); 255 kb->c.total_size = sizeof(mock_vblock) + 1; 256 TEST_EQ(vb2_load_fw_keyblock(&ctx), 257 VB2_ERROR_EX_READ_RESOURCE_SIZE, 258 "keyblock read keyblock"); 259 260 reset_common_data(FOR_KEYBLOCK); 261 mock_verify_keyblock_retval = VB2_ERROR_KEYBLOCK_MAGIC; 262 TEST_EQ(vb2_load_fw_keyblock(&ctx), 263 VB2_ERROR_KEYBLOCK_MAGIC, 264 "keyblock verify keyblock"); 265 266 reset_common_data(FOR_KEYBLOCK); 267 dk->key_version = 0x10000; 268 TEST_EQ(vb2_load_fw_keyblock(&ctx), 269 VB2_ERROR_FW_KEYBLOCK_VERSION_RANGE, 270 "keyblock version range"); 271 272 reset_common_data(FOR_KEYBLOCK); 273 dk->key_version = 1; 274 TEST_EQ(vb2_load_fw_keyblock(&ctx), 275 VB2_ERROR_FW_KEYBLOCK_VERSION_ROLLBACK, 276 "keyblock rollback"); 277 } 278 279 static void load_preamble_tests(void) 280 { 281 struct vb2_fw_preamble *pre = &mock_vblock.p.pre; 282 int data_key_offset_before; 283 uint32_t v; 284 285 /* Test successful call */ 286 reset_common_data(FOR_PREAMBLE); 287 data_key_offset_before = sd->workbuf_data_key_offset; 288 TEST_SUCC(vb2_load_fw_preamble(&ctx), "preamble good"); 289 TEST_EQ(sd->fw_version, 0x20002, "combined version"); 290 TEST_EQ(sd->workbuf_preamble_offset, data_key_offset_before, 291 "preamble offset"); 292 TEST_EQ(sd->workbuf_preamble_size, pre->c.total_size, "preamble size"); 293 TEST_EQ(ctx.workbuf_used, 294 sd->workbuf_preamble_offset + sd->workbuf_preamble_size, 295 "workbuf used"); 296 TEST_EQ(sd->workbuf_data_key_offset, 0, "data key offset gone"); 297 TEST_EQ(sd->workbuf_data_key_size, 0, "data key size gone"); 298 299 /* Expected failures */ 300 reset_common_data(FOR_PREAMBLE); 301 sd->workbuf_data_key_size = 0; 302 TEST_EQ(vb2_load_fw_preamble(&ctx), 303 VB2_ERROR_FW_PREAMBLE2_DATA_KEY, 304 "preamble no data key"); 305 306 reset_common_data(FOR_PREAMBLE); 307 mock_unpack_key_retval = VB2_ERROR_UNPACK_KEY_HASH_ALGORITHM; 308 TEST_EQ(vb2_load_fw_preamble(&ctx), 309 VB2_ERROR_UNPACK_KEY_HASH_ALGORITHM, 310 "preamble unpack data key"); 311 312 reset_common_data(FOR_PREAMBLE); 313 ctx.workbuf_used = ctx.workbuf_size 314 - sizeof(struct vb2_fw_preamble) + 8; 315 TEST_EQ(vb2_load_fw_preamble(&ctx), 316 VB2_ERROR_READ_RESOURCE_OBJECT_BUF, 317 "preamble not enough workbuf for header"); 318 319 reset_common_data(FOR_PREAMBLE); 320 sd->vblock_preamble_offset = sizeof(mock_vblock); 321 TEST_EQ(vb2_load_fw_preamble(&ctx), 322 VB2_ERROR_EX_READ_RESOURCE_SIZE, 323 "preamble read header"); 324 325 reset_common_data(FOR_PREAMBLE); 326 ctx.workbuf_used = ctx.workbuf_size - sizeof(mock_vblock.p) + 8; 327 TEST_EQ(vb2_load_fw_preamble(&ctx), 328 VB2_ERROR_READ_RESOURCE_OBJECT_BUF, 329 "preamble not enough workbuf"); 330 331 reset_common_data(FOR_PREAMBLE); 332 pre->c.total_size = sizeof(mock_vblock); 333 TEST_EQ(vb2_load_fw_preamble(&ctx), 334 VB2_ERROR_EX_READ_RESOURCE_SIZE, 335 "preamble read full"); 336 337 reset_common_data(FOR_PREAMBLE); 338 mock_verify_preamble_retval = VB2_ERROR_PREAMBLE_SIG_INVALID; 339 TEST_EQ(vb2_load_fw_preamble(&ctx), 340 VB2_ERROR_PREAMBLE_SIG_INVALID, 341 "preamble verify"); 342 343 reset_common_data(FOR_PREAMBLE); 344 pre->fw_version = 0x10000; 345 TEST_EQ(vb2_load_fw_preamble(&ctx), 346 VB2_ERROR_FW_PREAMBLE_VERSION_RANGE, 347 "preamble version range"); 348 349 reset_common_data(FOR_PREAMBLE); 350 pre->fw_version = 1; 351 TEST_EQ(vb2_load_fw_preamble(&ctx), 352 VB2_ERROR_FW_PREAMBLE_VERSION_ROLLBACK, 353 "preamble version rollback"); 354 355 reset_common_data(FOR_PREAMBLE); 356 pre->fw_version = 3; 357 TEST_SUCC(vb2_load_fw_preamble(&ctx), 358 "preamble version roll forward"); 359 vb2_secdata_get(&ctx, VB2_SECDATA_VERSIONS, &v); 360 TEST_EQ(v, 0x20003, "roll forward"); 361 362 /* Newer version without result success doesn't roll forward */ 363 reset_common_data(FOR_PREAMBLE); 364 pre->fw_version = 3; 365 sd->last_fw_result = VB2_FW_RESULT_UNKNOWN; 366 TEST_SUCC(vb2_load_fw_preamble(&ctx), 367 "preamble version no roll forward 1"); 368 vb2_secdata_get(&ctx, VB2_SECDATA_VERSIONS, &v); 369 TEST_EQ(v, 0x20002, "no roll forward"); 370 371 /* Newer version with success but for other slot doesn't roll forward */ 372 reset_common_data(FOR_PREAMBLE); 373 pre->fw_version = 3; 374 sd->last_fw_slot = 1; 375 TEST_SUCC(vb2_load_fw_preamble(&ctx), 376 "preamble version no roll forward 2"); 377 vb2_secdata_get(&ctx, VB2_SECDATA_VERSIONS, &v); 378 TEST_EQ(v, 0x20002, "no roll forward"); 379 } 380 381 int main(int argc, char* argv[]) 382 { 383 load_keyblock_tests(); 384 load_preamble_tests(); 385 386 return gTestSuccess ? 0 : 255; 387 } 388