/* Test StatefulSkip */ static void StatefulSkipTest(void) { MemcpyState s; char buf[128]; /* Small skip */ StatefulInit(&s, buf, 128); TEST_PTR_EQ(&s, StatefulSkip(&s, 5), "StatefulSkip(5) retval"); TEST_EQ(128 - 5, s.remaining_len, "StatefulSkip(5) len"); TEST_PTR_EQ(buf + 5, s.remaining_buf, "StatefulSkip(5) buf"); TEST_EQ(0, s.overrun, "StatefulSkip(5) overrun"); /* Use entire buffer */ StatefulInit(&s, buf, 128); TEST_PTR_EQ(&s, StatefulSkip(&s, 128), "StatefulSkip(all) retval"); TEST_EQ(0, s.remaining_len, "StatefulSkip(all) len"); TEST_PTR_EQ(buf + 128, s.remaining_buf, "StatefulSkip(all) buf"); TEST_EQ(0, s.overrun, "StatefulSkip(all) overrun"); /* Zero-length skip is ok (but meaningless) */ TEST_PTR_EQ(&s, StatefulSkip(&s, 0), "StatefulSkip(0) retval"); TEST_EQ(0, s.remaining_len, "StatefulSkip(0) len"); TEST_PTR_EQ(buf + 128, s.remaining_buf, "StatefulSkip(0) buf"); TEST_EQ(0, s.overrun, "StatefulSkip(0) overrun"); /* Can't use even one byte past that */ TEST_PTR_EQ(NULL, StatefulSkip(&s, 1), "StatefulSkip(+1) retval"); TEST_EQ(0, s.remaining_len, "StatefulSkip(+1) len"); TEST_EQ(1, s.overrun, "StatefulSkip(+1) overrun"); /* Overrun */ StatefulInit(&s, buf, 128); TEST_PTR_EQ(NULL, StatefulSkip(&s, 256), "StatefulSkip(256) retval"); TEST_EQ(1, s.overrun, "StatefulSkip(256) overrun"); /* Once overrun, always overrun, even if we now ask for a small skip */ TEST_PTR_EQ(NULL, StatefulSkip(&s, 1), "StatefulSkip(256+1) retval"); TEST_EQ(1, s.overrun, "StatefulSkip(256+1) overrun"); /* Overrun with potential wraparound */ StatefulInit(&s, buf, 128); TEST_PTR_EQ(NULL, StatefulSkip(&s, -1), "StatefulSkip(-1) retval"); TEST_EQ(1, s.overrun, "StatefulSkip(-1) overrun"); }
static void VbRegionReadTest(void) { /* Should read GBB */ ResetMocks(); TEST_TRUE(1, "Normal call"); TEST_EQ(VbSelectFirmware(&cparams, &fparams), VBERROR_SUCCESS, " Success"); TEST_EQ(mock_seen_region, 1 << VB_REGION_GBB, " GBB region"); TEST_PTR_EQ(cparams.gbb, NULL, " GBB free"); ResetMocks(); TEST_EQ(VbSelectAndLoadKernel(&cparams, &kparams), VBERROR_NO_DISK_FOUND, "Kernel"); TEST_PTR_EQ(cparams.gbb, NULL, " GBB free"); TEST_PTR_EQ(cparams.bmp, NULL, " BMP free"); ResetMocks(); shared->flags |= VBSD_BOOT_DEV_SWITCH_ON; TEST_EQ(VbSelectAndLoadKernel(&cparams, &kparams), VBERROR_NO_DISK_FOUND, "Kernel"); }
/* Test StatefulInit */ static void StatefulInitTest(void) { MemcpyState s; char buf[128]; memset(&s, 0, sizeof(s)); s.overrun = 1; StatefulInit(&s, buf, 128); TEST_EQ(0, s.overrun, "StatefulInit() overrun"); TEST_EQ(128, s.remaining_len, "StatefulInit() len"); TEST_PTR_EQ(buf, s.remaining_buf, "StatefulInit() buf"); }
static void VbTryLoadKernelTest(void) { int i; int num_tests = sizeof(test) / sizeof(test[0]); for (i = 0; i < num_tests; i++) { printf("Test case: %s ...\n", test[i].name); ResetMocks(i); TEST_EQ(VbTryLoadKernel(0, &lkparams, test[i].want_flags), t->expected_return_val, " return value"); TEST_EQ(got_recovery_request_val, t->expected_recovery_request_val, " recovery_request"); if (t->expected_to_find_disk != DONT_CARE) { TEST_PTR_EQ(got_find_disk, t->expected_to_find_disk, " find disk"); TEST_PTR_EQ(got_load_disk, t->expected_to_load_disk, " load disk"); } TEST_EQ(got_external_mismatch, 0, " external GPT errors"); } }
/** * Test assorted tlcl functions */ static void TlclTest(void) { uint8_t buf[32], buf2[32]; ResetMocks(); TEST_EQ(TlclLibInit(), VBERROR_SUCCESS, "Init"); ResetMocks(); mock_retval = VBERROR_SIMULATED; TEST_EQ(TlclLibInit(), mock_retval, "Init bad"); ResetMocks(); TEST_EQ(TlclLibClose(), VBERROR_SUCCESS, "Close"); ResetMocks(); mock_retval = VBERROR_SIMULATED; TEST_EQ(TlclLibClose(), mock_retval, "Close bad"); ResetMocks(); ToTpmUint32(buf + 2, 123); TEST_EQ(TlclPacketSize(buf), 123, "TlclPacketSize"); ResetMocks(); ToTpmUint32(buf + 2, 10); TEST_EQ(TlclSendReceive(buf, buf2, sizeof(buf2)), 0, "SendReceive"); TEST_PTR_EQ(calls[0].req, buf, "SendReceive req ptr"); TEST_EQ(calls[0].req_size, 10, "SendReceive size"); ResetMocks(); calls[0].retval = VBERROR_SIMULATED; ToTpmUint32(buf + 2, 10); TEST_EQ(TlclSendReceive(buf, buf2, sizeof(buf2)), VBERROR_SIMULATED, "SendReceive fail"); ResetMocks(); SetResponse(0, 123, 10); ToTpmUint32(buf + 2, 10); TEST_EQ(TlclSendReceive(buf, buf2, sizeof(buf2)), 123, "SendReceive error response"); // TODO: continue self test (if needed or doing) // TODO: then retry doing self test }
static void keyblock_tests(const char *keys_dir) { struct vb2_public_key *pubk2048, *pubk4096, *pubk8192, pubkhash; struct vb2_private_key *prik4096, *prik8192; struct vb2_packed_key *pak, *pakgood; struct vb2_keyblock *kb; const struct vb2_private_key *prikhash; const struct vb2_private_key *prik[2]; char fname[1024]; const char test_desc[] = "Test keyblock"; uint8_t workbuf[VB2_KEY_BLOCK_VERIFY_WORKBUF_BYTES] __attribute__ ((aligned (VB2_WORKBUF_ALIGN))); struct vb2_workbuf wb; vb2_workbuf_init(&wb, workbuf, sizeof(workbuf)); /* Read keys */ sprintf(fname, "%s/key_rsa2048.keyb", keys_dir); TEST_SUCC(vb2_public_key_read_keyb(&pubk2048, fname), "Read public key 2"); vb2_public_key_set_desc(pubk2048, "Test RSA2048 public key"); pubk2048->hash_alg = VB2_HASH_SHA256; sprintf(fname, "%s/key_rsa4096.keyb", keys_dir); TEST_SUCC(vb2_public_key_read_keyb(&pubk4096, fname), "Read public key 1"); vb2_public_key_set_desc(pubk4096, "Test RSA4096 public key"); pubk4096->hash_alg = VB2_HASH_SHA256; sprintf(fname, "%s/key_rsa8192.keyb", keys_dir); TEST_SUCC(vb2_public_key_read_keyb(&pubk8192, fname), "Read public key 2"); vb2_public_key_set_desc(pubk8192, "Test RSA8192 public key"); pubk8192->hash_alg = VB2_HASH_SHA512; sprintf(fname, "%s/key_rsa4096.pem", keys_dir); TEST_SUCC(vb2_private_key_read_pem(&prik4096, fname), "Read private key 2"); vb2_private_key_set_desc(prik4096, "Test RSA4096 private key"); prik4096->sig_alg = VB2_SIG_RSA4096; prik4096->hash_alg = VB2_HASH_SHA256; sprintf(fname, "%s/key_rsa8192.pem", keys_dir); TEST_SUCC(vb2_private_key_read_pem(&prik8192, fname), "Read private key 1"); vb2_private_key_set_desc(prik8192, "Test RSA8192 private key"); prik8192->sig_alg = VB2_SIG_RSA8192; prik8192->hash_alg = VB2_HASH_SHA512; TEST_SUCC(vb2_private_key_hash(&prikhash, VB2_HASH_SHA512), "Create private hash key"); TEST_SUCC(vb2_public_key_hash(&pubkhash, VB2_HASH_SHA512), "Create public hash key"); TEST_SUCC(vb2_public_key_pack(&pakgood, pubk2048), "Test packed key"); /* Sign a keyblock with one key */ prik[0] = prik4096; TEST_SUCC(vb2_keyblock_create(&kb, pubk2048, prik, 1, 0x1234, NULL), "Keyblock single"); TEST_PTR_NEQ(kb, NULL, " kb_ptr"); TEST_SUCC(vb2_verify_keyblock(kb, kb->c.total_size, pubk4096, &wb), " verify"); TEST_EQ(strcmp(vb2_common_desc(kb), pubk2048->desc), 0, " desc"); TEST_EQ(kb->flags, 0x1234, " flags"); pak = (struct vb2_packed_key *)((uint8_t *)kb + kb->key_offset); TEST_EQ(0, memcmp(pak, pakgood, pakgood->c.total_size), " data key"); free(kb); /* Sign a keyblock with two keys */ prik[0] = prik8192; prik[1] = prikhash; TEST_SUCC(vb2_keyblock_create(&kb, pubk4096, prik, 2, 0, test_desc), "Keyblock multiple"); TEST_SUCC(vb2_verify_keyblock(kb, kb->c.total_size, pubk8192, &wb), " verify 1"); TEST_SUCC(vb2_verify_keyblock(kb, kb->c.total_size, &pubkhash, &wb), " verify 2"); TEST_EQ(strcmp(vb2_common_desc(kb), test_desc), 0, " desc"); TEST_EQ(kb->flags, 0, " flags"); free(kb); /* Test errors */ prik[0] = prik8192; prik8192->hash_alg = VB2_HASH_INVALID; TEST_EQ(vb2_keyblock_create(&kb, pubk4096, prik, 1, 0, NULL), VB2_KEYBLOCK_CREATE_SIG_SIZE, "Keyblock bad sig size"); TEST_PTR_EQ(kb, NULL, " kb_ptr"); prik[0] = prik4096; pubk4096->sig_alg = VB2_SIG_INVALID; TEST_EQ(vb2_keyblock_create(&kb, pubk4096, prik, 1, 0, NULL), VB2_KEYBLOCK_CREATE_DATA_KEY, "Keyblock bad data key"); /* Free keys */ free(pakgood); vb2_public_key_free(pubk2048); vb2_public_key_free(pubk4096); vb2_public_key_free(pubk8192); vb2_private_key_free(prik4096); vb2_private_key_free(prik8192); }
/* Test StatefulMemset_r */ static void StatefulMemset_rTest(void) { MemcpyState s; char buf[129]; char want[129]; memset(want, 0, sizeof(want)); memset(buf, 0, sizeof(buf)); /* Small sets */ StatefulInit(&s, buf, 128); TEST_PTR_EQ(&s, StatefulMemset_r(&s, 'A', 5), "StatefulMemset_r(5) retval"); TEST_EQ(128 - 5, s.remaining_len, "StatefulMemset_r(5) len"); TEST_PTR_EQ(buf + 5, s.remaining_buf, "StatefulMemset_r(5) buf"); /* Using strcmp() is a convenient way to check that we didn't * overwrite the 0-byte following what we expected to set. */ TEST_EQ(0, strcmp("AAAAA", buf), "StatefulMemset_r(5) contents"); TEST_EQ(0, s.overrun, "StatefulMemset_r(5) overrun"); TEST_PTR_EQ(&s, StatefulMemset_r(&s, 'B', 3), "StatefulMemset_r(3) retval"); TEST_EQ(0, strcmp("AAAAABBB", buf), "StatefulMemset_r(3) contents"); /* Use entire buffer */ StatefulInit(&s, buf, 128); TEST_PTR_EQ(&s, StatefulMemset_r(&s, 'C', 128), "StatefulMemset_r(all) retval"); TEST_EQ(0, s.remaining_len, "StatefulMemset_r(all) len"); TEST_PTR_EQ(buf + 128, s.remaining_buf, "StatefulMemset_r(all) buf"); TEST_EQ(0, s.overrun, "StatefulMemset_r(all) overrun"); memset(want, 'C', 128); TEST_EQ(0, memcmp(want, buf, sizeof(want)), "StatefulMemset_r(all) contents"); /* Zero-length set is ok (but meaningless) */ TEST_PTR_EQ(&s, StatefulMemset_r(&s, 'D', 0), "StatefulMemset_r(0) retval"); TEST_EQ(0, s.remaining_len, "StatefulMemset_r(0) len"); TEST_PTR_EQ(buf + 128, s.remaining_buf, "StatefulMemset_r(0) buf"); TEST_EQ(0, s.overrun, "StatefulMemset_r(0) overrun"); TEST_EQ(0, memcmp(want, buf, sizeof(want)), "StatefulMemset_r(0) contents"); /* Can't use even one byte past that */ TEST_PTR_EQ(NULL, StatefulMemset_r(&s, 'E', 1), "StatefulMemset_r(+1) retval"); TEST_EQ(0, s.remaining_len, "StatefulMemset_r(+1) len"); TEST_EQ(1, s.overrun, "StatefulMemset_r(+1) overrun"); TEST_EQ(0, memcmp(want, buf, sizeof(want)), "StatefulMemset_r(+1) contents"); /* Overrun */ StatefulInit(&s, buf, 128); TEST_PTR_EQ(NULL, StatefulMemset_r(&s, 'F', 256), "StatefulMemset_r(256) retval"); TEST_EQ(1, s.overrun, "StatefulMemset_r(256) overrun"); /* Once overrun, always overrun, even if we now ask for a small skip */ TEST_PTR_EQ(NULL, StatefulMemset_r(&s, 'G', 1), "StatefulMemset_r(256+1) retval"); TEST_EQ(1, s.overrun, "StatefulMemset_r(256+1) overrun"); TEST_EQ(0, memcmp(want, buf, sizeof(want)), "StatefulMemset_r(+1) contents"); /* Overrun with potential wraparound */ StatefulInit(&s, buf, 128); TEST_PTR_EQ(NULL, StatefulMemset_r(&s, 'H', -1), "StatefulMemset_r(-1) retval"); TEST_EQ(1, s.overrun, "StatefulMemset_r(-1) overrun"); TEST_EQ(0, memcmp(want, buf, sizeof(want)), "StatefulMemset_r(+1) contents"); }
/* Test StatefulMemcpy */ static void StatefulMemcpyTest(void) { MemcpyState s; char buf[129]; char want[129]; char* src1 = "ThisIsATest"; char* src2 = "ThisIsOnlyATest"; memset(want, 0, sizeof(want)); memset(buf, 0, sizeof(buf)); /* Small copies */ StatefulInit(&s, src1, 12); TEST_PTR_EQ(buf, StatefulMemcpy(&s, buf, 6), "StatefulMemcpy(6) retval"); TEST_EQ(6, s.remaining_len, "StatefulMemcpy(6) len"); TEST_PTR_EQ(src1 + 6, s.remaining_buf, "StatefulMemcpy(6) buf"); /* Using strcmp() is a convenient way to check that we didn't * overwrite the 0-byte following what we expected to copy. */ TEST_EQ(0, strcmp("ThisIs", buf), "StatefulMemcpy(6) contents"); TEST_EQ(0, s.overrun, "StatefulMemcpy(6) overrun"); TEST_PTR_EQ(buf, StatefulMemcpy(&s, buf, 5), "StatefulMemcpy(5) retval"); /* Note that we shouldn't have copied the last byte out of the * stateful buffer, so we don't overwrite the last character of the * string that was in buf. */ TEST_EQ(0, strcmp("ATests", buf), "StatefulMemcpy(5) contents"); /* Use entire buffer */ memset(buf, 1, sizeof(buf)); StatefulInit(&s, src2, 16); TEST_PTR_EQ(buf, StatefulMemcpy(&s, buf, 16), "StatefulMemcpy(all) retval"); TEST_EQ(0, s.remaining_len, "StatefulMemcpy(all) len"); TEST_PTR_EQ(src2 + 16, s.remaining_buf, "StatefulMemcpy(all) buf"); TEST_EQ(0, s.overrun, "StatefulMemcpy(all) overrun"); TEST_EQ(0, strcmp(src2, buf), "StatefulMemcpy(all) contents"); /* Zero-length copy is ok (but meaningless) */ TEST_PTR_EQ(buf, StatefulMemcpy(&s, buf, 0), "StatefulMemcpy(0) retval"); TEST_EQ(0, s.remaining_len, "StatefulMemcpy(0) len"); TEST_PTR_EQ(src2 + 16, s.remaining_buf, "StatefulMemcpy(0) buf"); TEST_EQ(0, s.overrun, "StatefulMemcpy(0) overrun"); TEST_EQ(0, strcmp(src2, buf), "StatefulMemcpy(0) contents"); /* Can't use even one byte past that */ TEST_PTR_EQ(NULL, StatefulMemcpy(&s, buf, 1), "StatefulMemcpy(+1) retval"); TEST_EQ(0, s.remaining_len, "StatefulMemcpy(+1) len"); TEST_EQ(1, s.overrun, "StatefulMemcpy(+1) overrun"); TEST_EQ(0, strcmp(src2, buf), "StatefulMemcpy(+1) contents"); /* Overrun */ memset(buf, 0, sizeof(buf)); StatefulInit(&s, "Small", 5); TEST_PTR_EQ(NULL, StatefulMemcpy(&s, buf, 9), "StatefulMemcpy(9) retval"); TEST_EQ(1, s.overrun, "StatefulMemcpy(9) overrun"); /* Once overrun, always overrun, even if we now ask for a small skip */ TEST_PTR_EQ(NULL, StatefulMemcpy(&s, buf, 4), "StatefulMemcpy(9+1) retval"); TEST_EQ(1, s.overrun, "StatefulMemcpy(9+1) overrun"); TEST_EQ(0, memcmp(want, buf, sizeof(want)), "StatefulMemcpy(+1) contents"); /* Overrun with potential wraparound */ StatefulInit(&s, "Larger", 6); TEST_PTR_EQ(NULL, StatefulMemcpy(&s, buf, -1), "StatefulMemcpy(-1) retval"); TEST_EQ(1, s.overrun, "StatefulMemcpy(-1) overrun"); TEST_EQ(0, memcmp(want, buf, sizeof(want)), "StatefulMemcpy(+1) contents"); }
/* Test StatefulMemcpy_r */ static void StatefulMemcpy_rTest(void) { MemcpyState s; char buf[129]; char want[129]; char* src1 = "Doogie"; char* src2 = "Howserrr"; char* src3 = "WholeBuffr"; memset(want, 0, sizeof(want)); memset(buf, 0, sizeof(buf)); /* Small copies */ StatefulInit(&s, buf, 128); TEST_PTR_EQ(src1, StatefulMemcpy_r(&s, src1, 6), "StatefulMemcpy_r(6) retval"); TEST_EQ(128 - 6, s.remaining_len, "StatefulMemcpy_r(6) len"); TEST_PTR_EQ(buf + 6, s.remaining_buf, "StatefulMemcpy_r(6) buf"); /* Using strcmp() is a convenient way to check that we didn't * overwrite the 0-byte following what we expected to copy. */ TEST_EQ(0, strcmp("Doogie", buf), "StatefulMemcpy_r(6) contents"); TEST_EQ(0, s.overrun, "StatefulMemcpy_r(6) overrun"); TEST_PTR_EQ(src2, StatefulMemcpy_r(&s, src2, 8), "StatefulMemcpy_r(8) retval"); TEST_EQ(0, strcmp("DoogieHowserrr", buf), "StatefulMemcpy_r(8) contents"); /* Use entire buffer */ memset(buf, 42, sizeof(buf)); StatefulInit(&s, buf, 10); TEST_PTR_EQ(src3, StatefulMemcpy_r(&s, src3, 10), "StatefulMemcpy_r(all) retval"); TEST_EQ(0, s.remaining_len, "StatefulMemcpy_r(all) len"); TEST_PTR_EQ(buf + 10, s.remaining_buf, "StatefulMemcpy_r(all) buf"); TEST_EQ(0, s.overrun, "StatefulMemcpy_r(all) overrun"); TEST_EQ(0, memcmp(src3, buf, 10), "StatefulMemcpy_r(all) contents"); TEST_EQ(42, buf[10], "StatefulMemcpy_r(all) contents+1"); /* Zero-length copy is ok (but meaningless) */ TEST_PTR_EQ(src1, StatefulMemcpy_r(&s, src1, 0), "StatefulMemcpy_r(0) retval"); TEST_EQ(0, s.remaining_len, "StatefulMemcpy_r(0) len"); TEST_PTR_EQ(buf + 10, s.remaining_buf, "StatefulMemcpy_r(0) buf"); TEST_EQ(0, s.overrun, "StatefulMemcpy_r(0) overrun"); TEST_EQ(42, buf[10], "StatefulMemcpy_r(0) contents+1"); /* Can't use even one byte past that */ TEST_PTR_EQ(NULL, StatefulMemcpy_r(&s, src1, 1), "StatefulMemcpy_r(+1) retval"); TEST_EQ(0, s.remaining_len, "StatefulMemcpy_r(+1) len"); TEST_EQ(1, s.overrun, "StatefulMemcpy_r(+1) overrun"); TEST_EQ(42, buf[10], "StatefulMemcpy_r(+1) contents"); /* Overrun */ memset(buf, 0, sizeof(buf)); StatefulInit(&s, buf, 8); TEST_PTR_EQ(NULL, StatefulMemcpy_r(&s, "MoreThan8", 9), "StatefulMemcpy_r(9) retval"); TEST_EQ(1, s.overrun, "StatefulMemcpy_r(9) overrun"); /* Once overrun, always overrun, even if we now ask for a small skip */ TEST_PTR_EQ(NULL, StatefulMemcpy_r(&s, "Less", 4), "StatefulMemcpy_r(9+1) retval"); TEST_EQ(1, s.overrun, "StatefulMemcpy_r(9+1) overrun"); TEST_EQ(0, memcmp(want, buf, sizeof(want)), "StatefulMemcpy_r(+1) contents"); /* Overrun with potential wraparound */ StatefulInit(&s, buf, 128); TEST_PTR_EQ(NULL, StatefulMemcpy_r(&s, "FOO", -1), "StatefulMemcpy_r(-1) retval"); TEST_EQ(1, s.overrun, "StatefulMemcpy_r(-1) overrun"); TEST_EQ(0, memcmp(want, buf, sizeof(want)), "StatefulMemcpy_r(+1) contents"); }
static void init_context_tests(void) { /* Use our own context struct so we can re-init it */ struct vb2_context c = { .workbuf = workbuf, .workbuf_size = sizeof(workbuf), }; reset_common_data(); TEST_SUCC(vb2_init_context(&c), "Init context good"); TEST_EQ(c.workbuf_used, sizeof(struct vb2_shared_data), "Init vbsd"); /* Don't re-init if used is non-zero */ c.workbuf_used = 200; TEST_SUCC(vb2_init_context(&c), "Re-init context good"); TEST_EQ(c.workbuf_used, 200, "Didn't re-init"); /* Handle workbuf errors */ c.workbuf_used = 0; c.workbuf_size = sizeof(struct vb2_shared_data) - 1; TEST_EQ(vb2_init_context(&c), VB2_ERROR_INITCTX_WORKBUF_SMALL, "Init too small"); c.workbuf_size = sizeof(workbuf); /* Handle workbuf unaligned */ c.workbuf++; TEST_EQ(vb2_init_context(&c), VB2_ERROR_INITCTX_WORKBUF_ALIGN, "Init unaligned"); } static void misc_tests(void) { struct vb2_workbuf wb; reset_common_data(); cc.workbuf_used = 16; vb2_workbuf_from_ctx(&cc, &wb); TEST_PTR_EQ(wb.buf, workbuf + 16, "vb_workbuf_from_ctx() buf"); TEST_EQ(wb.size, cc.workbuf_size - 16, "vb_workbuf_from_ctx() size"); } static void gbb_tests(void) { struct vb2_gbb_header gbb = { .signature = {'$', 'G', 'B', 'B'}, .major_version = VB2_GBB_MAJOR_VER, .minor_version = VB2_GBB_MINOR_VER, .header_size = sizeof(struct vb2_gbb_header), .flags = 0x1234, .rootkey_offset = 240, .rootkey_size = 1040, }; struct vb2_gbb_header gbbdest; TEST_EQ(sizeof(struct vb2_gbb_header), EXPECTED_VB2_GBB_HEADER_SIZE, "sizeof(struct vb2_gbb_header)"); reset_common_data(); /* Good contents */ mock_resource_index = VB2_RES_GBB; mock_resource_ptr = &gbb; mock_resource_size = sizeof(gbb); TEST_SUCC(vb2_read_gbb_header(&cc, &gbbdest), "read gbb header good"); TEST_SUCC(memcmp(&gbb, &gbbdest, sizeof(gbb)), "read gbb contents"); mock_resource_index = VB2_RES_GBB + 1; TEST_EQ(vb2_read_gbb_header(&cc, &gbbdest), VB2_ERROR_EX_READ_RESOURCE_INDEX, "read gbb header missing"); mock_resource_index = VB2_RES_GBB; gbb.signature[0]++; TEST_EQ(vb2_read_gbb_header(&cc, &gbbdest), VB2_ERROR_GBB_MAGIC, "read gbb header bad magic"); gbb.signature[0]--; gbb.major_version = VB2_GBB_MAJOR_VER + 1; TEST_EQ(vb2_read_gbb_header(&cc, &gbbdest), VB2_ERROR_GBB_VERSION, "read gbb header major version"); gbb.major_version = VB2_GBB_MAJOR_VER; gbb.minor_version = VB2_GBB_MINOR_VER + 1; TEST_SUCC(vb2_read_gbb_header(&cc, &gbbdest), "read gbb header minor++"); gbb.minor_version = 1; TEST_EQ(vb2_read_gbb_header(&cc, &gbbdest), VB2_ERROR_GBB_TOO_OLD, "read gbb header 1.1 fails"); gbb.minor_version = 0; TEST_EQ(vb2_read_gbb_header(&cc, &gbbdest), VB2_ERROR_GBB_TOO_OLD, "read gbb header 1.0 fails"); gbb.minor_version = VB2_GBB_MINOR_VER; gbb.header_size--; TEST_EQ(vb2_read_gbb_header(&cc, &gbbdest), VB2_ERROR_GBB_HEADER_SIZE, "read gbb header size"); TEST_EQ(vb2_fw_parse_gbb(&cc), VB2_ERROR_GBB_HEADER_SIZE, "parse gbb failure"); gbb.header_size++; /* Parse GBB */ TEST_SUCC(vb2_fw_parse_gbb(&cc), "parse gbb"); TEST_EQ(sd->gbb_flags, gbb.flags, "gbb flags"); TEST_EQ(sd->gbb_rootkey_offset, gbb.rootkey_offset, "rootkey offset"); TEST_EQ(sd->gbb_rootkey_size, gbb.rootkey_size, "rootkey size"); /* Workbuf failure */ reset_common_data(); cc.workbuf_used = cc.workbuf_size - 4; TEST_EQ(vb2_fw_parse_gbb(&cc), VB2_ERROR_GBB_WORKBUF, "parse gbb no workbuf"); } static void fail_tests(void) { /* Early fail (before even NV init) */ reset_common_data(); sd->status &= ~VB2_SD_STATUS_NV_INIT; vb2_fail(&cc, 1, 2); TEST_NEQ(sd->status & VB2_SD_STATUS_NV_INIT, 0, "vb2_fail inits NV"); TEST_EQ(vb2_nv_get(&cc, VB2_NV_RECOVERY_REQUEST), 1, "vb2_fail request"); TEST_EQ(vb2_nv_get(&cc, VB2_NV_RECOVERY_SUBCODE), 2, "vb2_fail subcode"); /* Repeated fail doesn't overwrite the error code */ vb2_fail(&cc, 3, 4); TEST_EQ(vb2_nv_get(&cc, VB2_NV_RECOVERY_REQUEST), 1, "vb2_fail repeat"); TEST_EQ(vb2_nv_get(&cc, VB2_NV_RECOVERY_SUBCODE), 2, "vb2_fail repeat2"); /* Fail with other slot good doesn't trigger recovery */ reset_common_data(); vb2_nv_set(&cc, VB2_NV_TRY_COUNT, 3); vb2_nv_set(&cc, VB2_NV_FW_RESULT, VB2_FW_RESULT_UNKNOWN); sd->status |= VB2_SD_STATUS_CHOSE_SLOT; sd->fw_slot = 0; sd->last_fw_slot = 1; sd->last_fw_result = VB2_FW_RESULT_UNKNOWN; vb2_fail(&cc, 5, 6); TEST_EQ(vb2_nv_get(&cc, VB2_NV_RECOVERY_REQUEST), 0, "vb2_failover"); TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_RESULT), VB2_FW_RESULT_FAILURE, "vb2_fail this fw"); TEST_EQ(vb2_nv_get(&cc, VB2_NV_TRY_COUNT), 0, "vb2_fail use up tries"); TEST_EQ(vb2_nv_get(&cc, VB2_NV_TRY_NEXT), 1, "vb2_fail try other slot"); /* Fail with other slot already failing triggers recovery */ reset_common_data(); sd->status |= VB2_SD_STATUS_CHOSE_SLOT; sd->fw_slot = 1; sd->last_fw_slot = 0; sd->last_fw_result = VB2_FW_RESULT_FAILURE; vb2_fail(&cc, 7, 8); TEST_EQ(vb2_nv_get(&cc, VB2_NV_RECOVERY_REQUEST), 7, "vb2_fail both slots bad"); TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_RESULT), VB2_FW_RESULT_FAILURE, "vb2_fail this fw"); TEST_EQ(vb2_nv_get(&cc, VB2_NV_TRY_NEXT), 0, "vb2_fail try other slot"); }