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 api 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 "2rsa.h" 16 #include "2secdata.h" 17 18 #include "vb2_common.h" 19 20 #include "host_key2.h" 21 #include "host_signature2.h" 22 23 #include "test_common.h" 24 25 /* Common context for tests */ 26 static uint8_t workbuf[VB2_WORKBUF_RECOMMENDED_SIZE] 27 __attribute__ ((aligned (VB2_WORKBUF_ALIGN))); 28 static struct vb2_context ctx; 29 static struct vb2_shared_data *sd; 30 31 static const uint8_t mock_body[320] = "Mock body"; 32 static const int mock_body_size = sizeof(mock_body); 33 static const int mock_hash_alg = VB2_HASH_SHA256; 34 static int mock_sig_size; 35 36 static const struct vb2_guid test_guid[4] = { 37 {.raw = {0x11}}, 38 {.raw = {0x22}}, 39 {.raw = {0x33}}, 40 {.raw = {0x44}}, 41 }; 42 43 /* Mocked function data */ 44 45 static enum { 46 HWCRYPTO_DISABLED, 47 HWCRYPTO_ENABLED, 48 HWCRYPTO_FORBIDDEN, 49 } hwcrypto_state; 50 51 static struct vb2_digest_context hwcrypto_emulation_dc; 52 53 static int retval_hwcrypto; 54 static int retval_vb2_load_fw_keyblock; 55 static int retval_vb2_load_fw_preamble; 56 57 /* Type of test to reset for */ 58 enum reset_type { 59 FOR_MISC, 60 FOR_EXTEND_HASH, 61 FOR_CHECK_HASH, 62 }; 63 64 static void reset_common_data(enum reset_type t) 65 { 66 const struct vb2_private_key *hash_key; 67 struct vb2_fw_preamble *pre; 68 struct vb2_signature *sig; 69 uint32_t sig_offset; 70 71 int i; 72 73 memset(workbuf, 0xaa, sizeof(workbuf)); 74 75 memset(&ctx, 0, sizeof(ctx)); 76 ctx.workbuf = workbuf; 77 ctx.workbuf_size = sizeof(workbuf); 78 79 vb2_init_context(&ctx); 80 sd = vb2_get_sd(&ctx); 81 82 vb2_nv_init(&ctx); 83 84 vb2_secdata_create(&ctx); 85 vb2_secdata_init(&ctx); 86 87 memset(&hwcrypto_emulation_dc, 0, sizeof(hwcrypto_emulation_dc)); 88 retval_hwcrypto = VB2_SUCCESS; 89 retval_vb2_load_fw_keyblock = VB2_SUCCESS; 90 retval_vb2_load_fw_preamble = VB2_SUCCESS; 91 92 vb2_private_key_hash(&hash_key, mock_hash_alg); 93 94 sd->workbuf_preamble_offset = ctx.workbuf_used; 95 pre = (struct vb2_fw_preamble *) 96 (ctx.workbuf + sd->workbuf_preamble_offset); 97 pre->hash_count = 3; 98 pre->hash_offset = sig_offset = sizeof(*pre); 99 if (hwcrypto_state == HWCRYPTO_FORBIDDEN) 100 pre->flags = VB2_FIRMWARE_PREAMBLE_DISALLOW_HWCRYPTO; 101 else 102 pre->flags = 0; 103 104 for (i = 0; i < 3; i++) { 105 vb2_sign_data(&sig, mock_body, mock_body_size - 16 * i, 106 hash_key, NULL); 107 memcpy(&sig->guid, test_guid + i, sizeof(sig->guid)); 108 memcpy((uint8_t *)pre + sig_offset, sig, sig->c.total_size); 109 sig_offset += sig->c.total_size; 110 mock_sig_size = sig->c.total_size; 111 free(sig); 112 } 113 114 sd->workbuf_preamble_size = sig_offset; 115 ctx.workbuf_used = sd->workbuf_preamble_offset 116 + sd->workbuf_preamble_size; 117 118 if (t == FOR_EXTEND_HASH || t == FOR_CHECK_HASH) 119 vb2api_init_hash2(&ctx, test_guid, NULL); 120 121 if (t == FOR_CHECK_HASH) 122 vb2api_extend_hash(&ctx, mock_body, mock_body_size); 123 }; 124 125 /* Mocked functions */ 126 127 int vb2_load_fw_keyblock(struct vb2_context *ctx) 128 { 129 return retval_vb2_load_fw_keyblock; 130 } 131 132 int vb2_load_fw_preamble(struct vb2_context *ctx) 133 { 134 return retval_vb2_load_fw_preamble; 135 } 136 137 int vb2ex_hwcrypto_digest_init(enum vb2_hash_algorithm hash_alg, 138 uint32_t data_size) 139 { 140 vb2_digest_init(&hwcrypto_emulation_dc, hash_alg); 141 142 switch (hwcrypto_state) { 143 case HWCRYPTO_DISABLED: 144 return VB2_ERROR_EX_HWCRYPTO_UNSUPPORTED; 145 case HWCRYPTO_ENABLED: 146 if (hash_alg != mock_hash_alg) 147 return VB2_ERROR_SHA_INIT_ALGORITHM; 148 else 149 return retval_hwcrypto; 150 case HWCRYPTO_FORBIDDEN: 151 default: 152 return VB2_ERROR_UNKNOWN; 153 } 154 } 155 156 int vb2ex_hwcrypto_digest_extend(const uint8_t *buf, 157 uint32_t size) 158 { 159 vb2_digest_extend(&hwcrypto_emulation_dc, buf, size); 160 161 if (hwcrypto_state != HWCRYPTO_ENABLED) 162 return VB2_ERROR_UNKNOWN; 163 164 return retval_hwcrypto; 165 } 166 167 int vb2ex_hwcrypto_digest_finalize(uint8_t *digest, 168 uint32_t digest_size) 169 { 170 vb2_digest_finalize(&hwcrypto_emulation_dc, digest, digest_size); 171 172 if (hwcrypto_state != HWCRYPTO_ENABLED) 173 return VB2_ERROR_UNKNOWN; 174 175 return retval_hwcrypto; 176 } 177 178 /* Tests */ 179 180 static void phase3_tests(void) 181 { 182 reset_common_data(FOR_MISC); 183 TEST_SUCC(vb2api_fw_phase3(&ctx), "phase3 good"); 184 185 reset_common_data(FOR_MISC); 186 retval_vb2_load_fw_keyblock = VB2_ERROR_MOCK; 187 TEST_EQ(vb2api_fw_phase3(&ctx), VB2_ERROR_MOCK, "phase3 keyblock"); 188 TEST_EQ(vb2_nv_get(&ctx, VB2_NV_RECOVERY_REQUEST), 189 VB2_RECOVERY_RO_INVALID_RW, " recovery reason"); 190 191 reset_common_data(FOR_MISC); 192 retval_vb2_load_fw_preamble = VB2_ERROR_MOCK; 193 TEST_EQ(vb2api_fw_phase3(&ctx), VB2_ERROR_MOCK, "phase3 keyblock"); 194 TEST_EQ(vb2_nv_get(&ctx, VB2_NV_RECOVERY_REQUEST), 195 VB2_RECOVERY_RO_INVALID_RW, " recovery reason"); 196 } 197 198 static void init_hash_tests(void) 199 { 200 struct vb2_fw_preamble *pre; 201 struct vb2_signature *sig; 202 int wb_used_before; 203 uint32_t size; 204 205 reset_common_data(FOR_MISC); 206 pre = (struct vb2_fw_preamble *) 207 (ctx.workbuf + sd->workbuf_preamble_offset); 208 sig = (struct vb2_signature *)((uint8_t *)pre + pre->hash_offset); 209 210 wb_used_before = ctx.workbuf_used; 211 TEST_SUCC(vb2api_init_hash2(&ctx, test_guid, &size), 212 "init hash good"); 213 TEST_EQ(sd->workbuf_hash_offset, 214 (wb_used_before + (VB2_WORKBUF_ALIGN - 1)) & 215 ~(VB2_WORKBUF_ALIGN - 1), 216 "hash context offset"); 217 TEST_EQ(sd->workbuf_hash_size, sizeof(struct vb2_digest_context), 218 "hash context size"); 219 TEST_EQ(ctx.workbuf_used, 220 sd->workbuf_hash_offset + sd->workbuf_hash_size, 221 "hash uses workbuf"); 222 TEST_EQ(sd->hash_tag, 223 sd->workbuf_preamble_offset + pre->hash_offset, 224 "hash signature offset"); 225 TEST_EQ(sd->hash_remaining_size, mock_body_size, "hash remaining"); 226 227 wb_used_before = ctx.workbuf_used; 228 TEST_SUCC(vb2api_init_hash2(&ctx, test_guid + 2, NULL), 229 "init hash again"); 230 TEST_EQ(ctx.workbuf_used, wb_used_before, "init hash reuses context"); 231 TEST_EQ(sd->hash_tag, 232 sd->workbuf_preamble_offset + pre->hash_offset + 233 2 * mock_sig_size, 234 "hash signature offset 2"); 235 236 reset_common_data(FOR_MISC); 237 TEST_EQ(vb2api_init_hash2(&ctx, test_guid + 3, &size), 238 VB2_ERROR_API_INIT_HASH_GUID, "init hash invalid guid"); 239 240 reset_common_data(FOR_MISC); 241 sd->workbuf_preamble_size = 0; 242 TEST_EQ(vb2api_init_hash2(&ctx, test_guid, &size), 243 VB2_ERROR_API_INIT_HASH_PREAMBLE, "init hash preamble"); 244 245 reset_common_data(FOR_MISC); 246 ctx.workbuf_used = 247 ctx.workbuf_size - sizeof(struct vb2_digest_context) + 8; 248 TEST_EQ(vb2api_init_hash2(&ctx, test_guid, &size), 249 VB2_ERROR_API_INIT_HASH_WORKBUF, "init hash workbuf"); 250 251 reset_common_data(FOR_MISC); 252 sig->hash_alg = VB2_HASH_INVALID; 253 TEST_EQ(vb2api_init_hash2(&ctx, test_guid, &size), 254 VB2_ERROR_SHA_INIT_ALGORITHM, "init hash algorithm"); 255 256 if (hwcrypto_state == HWCRYPTO_ENABLED) { 257 reset_common_data(FOR_MISC); 258 retval_hwcrypto = VB2_ERROR_MOCK; 259 TEST_EQ(vb2api_init_hash2(&ctx, test_guid, &size), 260 VB2_ERROR_MOCK, "init hash use hwcrypto"); 261 } 262 } 263 264 static void extend_hash_tests(void) 265 { 266 struct vb2_digest_context *dc; 267 268 reset_common_data(FOR_EXTEND_HASH); 269 TEST_SUCC(vb2api_extend_hash(&ctx, mock_body, 32), 270 "hash extend good"); 271 TEST_EQ(sd->hash_remaining_size, mock_body_size - 32, 272 "hash extend remaining"); 273 TEST_SUCC(vb2api_extend_hash(&ctx, mock_body, mock_body_size - 32), 274 "hash extend again"); 275 TEST_EQ(sd->hash_remaining_size, 0, "hash extend remaining 2"); 276 277 reset_common_data(FOR_EXTEND_HASH); 278 sd->workbuf_hash_size = 0; 279 TEST_EQ(vb2api_extend_hash(&ctx, mock_body, mock_body_size), 280 VB2_ERROR_API_EXTEND_HASH_WORKBUF, "hash extend no workbuf"); 281 282 reset_common_data(FOR_EXTEND_HASH); 283 TEST_EQ(vb2api_extend_hash(&ctx, mock_body, mock_body_size + 1), 284 VB2_ERROR_API_EXTEND_HASH_SIZE, "hash extend too much"); 285 286 reset_common_data(FOR_EXTEND_HASH); 287 TEST_EQ(vb2api_extend_hash(&ctx, mock_body, 0), 288 VB2_ERROR_API_EXTEND_HASH_SIZE, "hash extend empty"); 289 290 if (hwcrypto_state == HWCRYPTO_ENABLED) { 291 reset_common_data(FOR_EXTEND_HASH); 292 retval_hwcrypto = VB2_ERROR_MOCK; 293 TEST_EQ(vb2api_extend_hash(&ctx, mock_body, mock_body_size), 294 VB2_ERROR_MOCK, "hash extend use hwcrypto"); 295 } else { 296 reset_common_data(FOR_EXTEND_HASH); 297 dc = (struct vb2_digest_context *) 298 (ctx.workbuf + sd->workbuf_hash_offset); 299 dc->hash_alg = VB2_HASH_INVALID; 300 TEST_EQ(vb2api_extend_hash(&ctx, mock_body, mock_body_size), 301 VB2_ERROR_SHA_EXTEND_ALGORITHM, "hash extend fail"); 302 } 303 } 304 305 static void check_hash_tests(void) 306 { 307 struct vb2_fw_preamble *pre; 308 struct vb2_signature *sig; 309 struct vb2_digest_context *dc; 310 311 reset_common_data(FOR_CHECK_HASH); 312 pre = (struct vb2_fw_preamble *) 313 (ctx.workbuf + sd->workbuf_preamble_offset); 314 sig = (struct vb2_signature *)((uint8_t *)pre + pre->hash_offset); 315 dc = (struct vb2_digest_context *) 316 (ctx.workbuf + sd->workbuf_hash_offset); 317 318 TEST_SUCC(vb2api_check_hash(&ctx), "check hash good"); 319 320 reset_common_data(FOR_CHECK_HASH); 321 sd->hash_tag = 0; 322 TEST_EQ(vb2api_check_hash(&ctx), 323 VB2_ERROR_API_CHECK_HASH_TAG, "check hash tag"); 324 325 reset_common_data(FOR_CHECK_HASH); 326 sd->workbuf_hash_size = 0; 327 TEST_EQ(vb2api_check_hash(&ctx), 328 VB2_ERROR_API_CHECK_HASH_WORKBUF, "check hash no workbuf"); 329 330 reset_common_data(FOR_CHECK_HASH); 331 sd->hash_remaining_size = 1; 332 TEST_EQ(vb2api_check_hash(&ctx), 333 VB2_ERROR_API_CHECK_HASH_SIZE, "check hash size"); 334 335 reset_common_data(FOR_CHECK_HASH); 336 ctx.workbuf_used = ctx.workbuf_size; 337 TEST_EQ(vb2api_check_hash(&ctx), 338 VB2_ERROR_API_CHECK_HASH_WORKBUF_DIGEST, "check hash workbuf"); 339 340 reset_common_data(FOR_CHECK_HASH); 341 *((uint8_t *)sig + sig->sig_offset) ^= 0x55; 342 TEST_EQ(vb2api_check_hash(&ctx), 343 VB2_ERROR_API_CHECK_HASH_SIG, "check hash sig"); 344 345 if (hwcrypto_state == HWCRYPTO_ENABLED) { 346 reset_common_data(FOR_CHECK_HASH); 347 retval_hwcrypto = VB2_ERROR_MOCK; 348 TEST_EQ(vb2api_check_hash(&ctx), 349 VB2_ERROR_MOCK, "check hash use hwcrypto"); 350 } else { 351 reset_common_data(FOR_CHECK_HASH); 352 dc->hash_alg = VB2_HASH_INVALID; 353 *((uint8_t *)sig + sig->sig_offset) ^= 0x55; 354 TEST_EQ(vb2api_check_hash(&ctx), 355 VB2_ERROR_SHA_FINALIZE_ALGORITHM, "check hash finaliz"); 356 } 357 } 358 359 int main(int argc, char* argv[]) 360 { 361 phase3_tests(); 362 363 fprintf(stderr, "Running hash API tests without hwcrypto support...\n"); 364 hwcrypto_state = HWCRYPTO_DISABLED; 365 init_hash_tests(); 366 extend_hash_tests(); 367 check_hash_tests(); 368 369 fprintf(stderr, "Running hash API tests with hwcrypto support...\n"); 370 hwcrypto_state = HWCRYPTO_ENABLED; 371 init_hash_tests(); 372 extend_hash_tests(); 373 check_hash_tests(); 374 375 fprintf(stderr, "Running hash API tests with forbidden hwcrypto...\n"); 376 hwcrypto_state = HWCRYPTO_FORBIDDEN; 377 init_hash_tests(); 378 extend_hash_tests(); 379 check_hash_tests(); 380 381 return gTestSuccess ? 0 : 255; 382 } 383