static void test_changed(struct vb2_context *ctx, int changed, const char *why) { if (changed) TEST_NEQ(ctx->flags & VB2_CONTEXT_NVDATA_CHANGED, 0, why); else TEST_EQ(ctx->flags & VB2_CONTEXT_NVDATA_CHANGED, 0, why); };
static void VerifyDigestTest(const VbPublicKey *public_key, const VbPrivateKey *private_key) { const uint8_t test_data[] = "This is some other test data to sign."; VbSignature *sig; RSAPublicKey *rsa; uint8_t *digest; sig = CalculateSignature(test_data, sizeof(test_data), private_key); rsa = PublicKeyToRSA(public_key); digest = DigestBuf(test_data, sizeof(test_data), (int)public_key->algorithm); TEST_NEQ(sig && rsa && digest, 0, "VerifyData() prerequisites"); if (!sig || !rsa || !digest) return; TEST_EQ(VerifyDigest(digest, sig, rsa), 0, "VerifyDigest() ok"); GetSignatureData(sig)[0] ^= 0x5A; TEST_EQ(VerifyDigest(digest, sig, rsa), 1, "VerifyDigest() wrong sig"); sig->sig_size = 1; TEST_EQ(VerifyDigest(digest, sig, rsa), 1, "VerifyDigest() sig size"); RSAPublicKeyFree(rsa); free(sig); VbExFree(digest); }
void test_sensor_find(char* name, struct sensors_sensor *psensor) { TEST_CODE(); psensor = sensors_find(name); TEST_NEQ(psensor, NULL); }
static void recovery_tests(void) { /* No recovery */ reset_common_data(); vb2_check_recovery(&cc); TEST_EQ(sd->recovery_reason, 0, "No recovery reason"); TEST_EQ(sd->flags & VB2_SD_FLAG_MANUAL_RECOVERY, 0, "Not manual recovery"); TEST_EQ(cc.flags & VB2_CONTEXT_RECOVERY_MODE, 0, "Not recovery mode"); /* From request */ reset_common_data(); vb2_nv_set(&cc, VB2_NV_RECOVERY_REQUEST, 3); vb2_check_recovery(&cc); TEST_EQ(sd->recovery_reason, 3, "Recovery reason from request"); TEST_EQ(vb2_nv_get(&cc, VB2_NV_RECOVERY_REQUEST), 0, "NV cleared"); TEST_EQ(sd->flags & VB2_SD_FLAG_MANUAL_RECOVERY, 0, "Not manual recovery"); TEST_NEQ(cc.flags & VB2_CONTEXT_RECOVERY_MODE, 0, "Recovery mode"); /* From request, but already failed */ reset_common_data(); vb2_nv_set(&cc, VB2_NV_RECOVERY_REQUEST, 4); sd->recovery_reason = 5; vb2_check_recovery(&cc); TEST_EQ(sd->recovery_reason, 5, "Recovery reason already failed"); TEST_EQ(vb2_nv_get(&cc, VB2_NV_RECOVERY_REQUEST), 0, "NV still cleared"); /* Override */ reset_common_data(); sd->recovery_reason = 6; cc.flags |= VB2_CONTEXT_FORCE_RECOVERY_MODE; vb2_check_recovery(&cc); TEST_EQ(sd->recovery_reason, VB2_RECOVERY_RO_MANUAL, "Recovery reason forced"); TEST_NEQ(sd->flags & VB2_SD_FLAG_MANUAL_RECOVERY, 0, "SD flag set"); }
static void test_verify_keyblock(const struct vb2_public_key *public_key, const struct vb2_private_key *private_key, const struct vb2_packed_key *data_key) { uint8_t workbuf[VB2_KEY_BLOCK_VERIFY_WORKBUF_BYTES] __attribute__ ((aligned (VB2_WORKBUF_ALIGN))); struct vb2_workbuf wb; struct vb2_keyblock *hdr; struct vb2_keyblock *h; uint32_t hsize; vb2_workbuf_init(&wb, workbuf, sizeof(workbuf)); hdr = vb2_create_keyblock(data_key, private_key, 0x1234); TEST_NEQ((size_t)hdr, 0, "vb2_verify_keyblock() prerequisites"); if (!hdr) return; hsize = hdr->keyblock_size; h = (struct vb2_keyblock *)malloc(hsize + 2048); memcpy(h, hdr, hsize); TEST_SUCC(vb2_verify_keyblock(h, hsize, public_key, &wb), "vb2_verify_keyblock() ok using key"); /* Failures in keyblock check also cause verify to fail */ memcpy(h, hdr, hsize); TEST_EQ(vb2_verify_keyblock(h, hsize - 1, public_key, &wb), VB2_ERROR_KEYBLOCK_SIZE, "vb2_verify_keyblock() check"); /* Check signature */ memcpy(h, hdr, hsize); h->keyblock_signature.sig_size--; resign_keyblock(h, private_key); TEST_EQ(vb2_verify_keyblock(h, hsize, public_key, &wb), VB2_ERROR_KEYBLOCK_SIG_INVALID, "vb2_verify_keyblock() sig too small"); memcpy(h, hdr, hsize); ((uint8_t *)vb2_packed_key_data(&h->data_key))[0] ^= 0x34; TEST_EQ(vb2_verify_keyblock(h, hsize, public_key, &wb), VB2_ERROR_KEYBLOCK_SIG_INVALID, "vb2_verify_keyblock() sig mismatch"); /* * TODO: verify parser can support a bigger header (i.e., one where * data_key.key_offset is bigger than expected). */ free(h); free(hdr); }
/* Test displaying debug info */ static void DebugInfoTest(void) { char hwid[VB_REGION_HWID_LEN]; int i; /* Recovery string should be non-null for any code */ for (i = 0; i < 0x100; i++) TEST_PTR_NEQ(RecoveryReasonString(i), NULL, "Non-null reason"); /* HWID should come from the gbb */ ResetMocks(); VbRegionReadHWID(&cparams, hwid, sizeof(hwid)); TEST_EQ(strcmp(hwid, "Test HWID"), 0, "HWID"); VbApiKernelFree(&cparams); ResetMocks(); cparams.gbb_size = 0; VbRegionReadHWID(&cparams, hwid, sizeof(hwid)); TEST_EQ(strcmp(hwid, "{INVALID}"), 0, "HWID bad gbb"); VbApiKernelFree(&cparams); ResetMocks(); cparams.gbb->hwid_size = 0; VbRegionReadHWID(&cparams, hwid, sizeof(hwid)); TEST_EQ(strcmp(hwid, "{INVALID}"), 0, "HWID missing"); VbApiKernelFree(&cparams); ResetMocks(); cparams.gbb->hwid_offset = cparams.gbb_size + 1; VbRegionReadHWID(&cparams, hwid, sizeof(hwid)); TEST_EQ(strcmp(hwid, "{INVALID}"), 0, "HWID past end"); VbApiKernelFree(&cparams); ResetMocks(); cparams.gbb->hwid_size = cparams.gbb_size; VbRegionReadHWID(&cparams, hwid, sizeof(hwid)); TEST_EQ(strcmp(hwid, "{INVALID}"), 0, "HWID overflow"); VbApiKernelFree(&cparams); /* Display debug info */ ResetMocks(); VbDisplayDebugInfo(&cparams, &vnc); TEST_NEQ(*debug_info, '\0', "Some debug info was displayed"); VbApiKernelFree(&cparams); }
/* Test display key checking */ static void DisplayKeyTest(void) { uint32_t u; ResetMocks(); VbCheckDisplayKey(&cparams, 'q', &vnc); TEST_EQ(*debug_info, '\0', "DisplayKey q = does nothing"); VbApiKernelFree(&cparams); ResetMocks(); VbCheckDisplayKey(&cparams, '\t', &vnc); TEST_NEQ(*debug_info, '\0', "DisplayKey tab = display"); VbApiKernelFree(&cparams); /* Toggle localization */ ResetMocks(); VbNvSet(&vnc, VBNV_LOCALIZATION_INDEX, 0); VbNvTeardown(&vnc); VbCheckDisplayKey(&cparams, VB_KEY_DOWN, &vnc); VbNvGet(&vnc, VBNV_LOCALIZATION_INDEX, &u); TEST_EQ(u, 2, "DisplayKey up"); VbCheckDisplayKey(&cparams, VB_KEY_LEFT, &vnc); VbNvGet(&vnc, VBNV_LOCALIZATION_INDEX, &u); TEST_EQ(u, 1, "DisplayKey left"); VbCheckDisplayKey(&cparams, VB_KEY_RIGHT, &vnc); VbNvGet(&vnc, VBNV_LOCALIZATION_INDEX, &u); TEST_EQ(u, 2, "DisplayKey right"); VbCheckDisplayKey(&cparams, VB_KEY_UP, &vnc); VbNvGet(&vnc, VBNV_LOCALIZATION_INDEX, &u); TEST_EQ(u, 0, "DisplayKey up"); VbApiKernelFree(&cparams); /* Reset localization if localization count is invalid */ ResetMocks(); VbNvSet(&vnc, VBNV_LOCALIZATION_INDEX, 1); VbNvTeardown(&vnc); bhdr->signature[0] ^= 0x5a; VbCheckDisplayKey(&cparams, VB_KEY_UP, &vnc); VbNvGet(&vnc, VBNV_LOCALIZATION_INDEX, &u); TEST_EQ(u, 0, "DisplayKey invalid"); VbApiKernelFree(&cparams); }
/* Test displaying debug info */ static void DebugInfoTest(void) { char hwid[256]; int i; /* Recovery string should be non-null for any code */ for (i = 0; i < 0x100; i++) TEST_PTR_NEQ(RecoveryReasonString(i), NULL, "Non-null reason"); /* HWID should come from the gbb */ ResetMocks(); VbGbbReadHWID(&ctx, hwid, sizeof(hwid)); TEST_EQ(strcmp(hwid, "Test HWID"), 0, "HWID"); ResetMocks(); sd->gbb_size = 0; VbGbbReadHWID(&ctx, hwid, sizeof(hwid)); TEST_EQ(strcmp(hwid, "{INVALID}"), 0, "HWID bad gbb"); ResetMocks(); sd->gbb->hwid_size = 0; VbGbbReadHWID(&ctx, hwid, sizeof(hwid)); TEST_EQ(strcmp(hwid, "{INVALID}"), 0, "HWID missing"); ResetMocks(); sd->gbb->hwid_offset = sd->gbb_size + 1; VbGbbReadHWID(&ctx, hwid, sizeof(hwid)); TEST_EQ(strcmp(hwid, "{INVALID}"), 0, "HWID past end"); ResetMocks(); sd->gbb->hwid_size = sd->gbb_size; VbGbbReadHWID(&ctx, hwid, sizeof(hwid)); TEST_EQ(strcmp(hwid, "{INVALID}"), 0, "HWID overflow"); /* Display debug info */ ResetMocks(); VbDisplayDebugInfo(&ctx); TEST_NEQ(*debug_info, '\0', "Some debug info was displayed"); }
static void VerifyPublicKeyToRSA(const VbPublicKey *orig_key) { RSAPublicKey *rsa; VbPublicKey *key = PublicKeyAlloc(orig_key->key_size, 0, 0); PublicKeyCopy(key, orig_key); key->algorithm = kNumAlgorithms; TEST_EQ((size_t)PublicKeyToRSA(key), 0, "PublicKeyToRSA() invalid algorithm"); PublicKeyCopy(key, orig_key); key->key_size -= 1; TEST_EQ((size_t)PublicKeyToRSA(key), 0, "PublicKeyToRSA() invalid size"); rsa = PublicKeyToRSA(orig_key); TEST_NEQ((size_t)rsa, 0, "PublicKeyToRSA() ok"); if (rsa) { TEST_EQ((int)rsa->algorithm, (int)key->algorithm, "PublicKeyToRSA() algorithm"); RSAPublicKeyFree(rsa); } }
/* Test display key checking */ static void DisplayKeyTest(void) { ResetMocks(); VbCheckDisplayKey(&ctx, 'q', NULL); TEST_EQ(*debug_info, '\0', "DisplayKey q = does nothing"); ResetMocks(); VbCheckDisplayKey(&ctx, '\t', NULL); TEST_NEQ(*debug_info, '\0', "DisplayKey tab = display"); /* Toggle localization */ ResetMocks(); vb2_nv_set(&ctx, VB2_NV_LOCALIZATION_INDEX, 0); VbCheckDisplayKey(&ctx, VB_KEY_DOWN, NULL); TEST_EQ(vb2_nv_get(&ctx, VB2_NV_LOCALIZATION_INDEX), 2, "DisplayKey up"); VbCheckDisplayKey(&ctx, VB_KEY_LEFT, NULL); vb2_nv_get(&ctx, VB2_NV_LOCALIZATION_INDEX); TEST_EQ(vb2_nv_get(&ctx, VB2_NV_LOCALIZATION_INDEX), 1, "DisplayKey left"); VbCheckDisplayKey(&ctx, VB_KEY_RIGHT, NULL); vb2_nv_get(&ctx, VB2_NV_LOCALIZATION_INDEX); TEST_EQ(vb2_nv_get(&ctx, VB2_NV_LOCALIZATION_INDEX), 2, "DisplayKey right"); VbCheckDisplayKey(&ctx, VB_KEY_UP, NULL); vb2_nv_get(&ctx, VB2_NV_LOCALIZATION_INDEX); TEST_EQ(vb2_nv_get(&ctx, VB2_NV_LOCALIZATION_INDEX), 0, "DisplayKey up"); /* Reset localization if localization count is invalid */ ResetMocks(); vb2_nv_set(&ctx, VB2_NV_LOCALIZATION_INDEX, 1); mock_localization_count = 0xffffffff; VbCheckDisplayKey(&ctx, VB_KEY_UP, NULL); TEST_EQ(vb2_nv_get(&ctx, VB2_NV_LOCALIZATION_INDEX), 0, "DisplayKey invalid"); }
static void test_verify_keyblock(const VbPublicKey *public_key, const VbPrivateKey *private_key, const VbPublicKey *data_key) { uint8_t workbuf[VB2_KEY_BLOCK_VERIFY_WORKBUF_BYTES] __attribute__ ((aligned (VB2_WORKBUF_ALIGN))); struct vb2_workbuf wb; struct vb2_public_key key; struct vb2_keyblock *hdr; struct vb2_keyblock *h; uint32_t hsize; vb2_workbuf_init(&wb, workbuf, sizeof(workbuf)); /* Unpack public key */ TEST_SUCC(vb2_unpack_key(&key, (uint8_t *)public_key, public_key->key_offset + public_key->key_size), "vb2_verify_keyblock public key"); hdr = (struct vb2_keyblock *) KeyBlockCreate(data_key, private_key, 0x1234); TEST_NEQ((size_t)hdr, 0, "vb2_verify_keyblock() prerequisites"); if (!hdr) return; hsize = hdr->keyblock_size; h = (struct vb2_keyblock *)malloc(hsize + 2048); Memcpy(h, hdr, hsize); TEST_SUCC(vb2_verify_keyblock(h, hsize, &key, &wb), "vb2_verify_keyblock() ok using key"); Memcpy(h, hdr, hsize); TEST_EQ(vb2_verify_keyblock(h, hsize - 1, &key, &wb), VB2_ERROR_KEYBLOCK_SIZE, "vb2_verify_keyblock() size--"); /* Buffer is allowed to be bigger than keyblock */ Memcpy(h, hdr, hsize); TEST_SUCC(vb2_verify_keyblock(h, hsize + 1, &key, &wb), "vb2_verify_keyblock() size++"); Memcpy(h, hdr, hsize); h->magic[0] &= 0x12; TEST_EQ(vb2_verify_keyblock(h, hsize, &key, &wb), VB2_ERROR_KEYBLOCK_MAGIC, "vb2_verify_keyblock() magic"); /* Care about major version but not minor */ Memcpy(h, hdr, hsize); h->header_version_major++; resign_keyblock(h, private_key); TEST_EQ(vb2_verify_keyblock(h, hsize, &key, &wb), VB2_ERROR_KEYBLOCK_HEADER_VERSION, "vb2_verify_keyblock() major++"); Memcpy(h, hdr, hsize); h->header_version_major--; resign_keyblock(h, private_key); TEST_EQ(vb2_verify_keyblock(h, hsize, &key, &wb), VB2_ERROR_KEYBLOCK_HEADER_VERSION, "vb2_verify_keyblock() major--"); Memcpy(h, hdr, hsize); h->header_version_minor++; resign_keyblock(h, private_key); TEST_SUCC(vb2_verify_keyblock(h, hsize, &key, &wb), "vb2_verify_keyblock() minor++"); Memcpy(h, hdr, hsize); h->header_version_minor--; resign_keyblock(h, private_key); TEST_SUCC(vb2_verify_keyblock(h, hsize, &key, &wb), "vb2_verify_keyblock() minor--"); /* Check signature */ Memcpy(h, hdr, hsize); h->keyblock_signature.sig_offset = hsize; resign_keyblock(h, private_key); TEST_EQ(vb2_verify_keyblock(h, hsize, &key, &wb), VB2_ERROR_KEYBLOCK_SIG_OUTSIDE, "vb2_verify_keyblock() sig off end"); Memcpy(h, hdr, hsize); h->keyblock_signature.sig_size--; resign_keyblock(h, private_key); TEST_EQ(vb2_verify_keyblock(h, hsize, &key, &wb), VB2_ERROR_KEYBLOCK_SIG_INVALID, "vb2_verify_keyblock() sig too small"); Memcpy(h, hdr, hsize); ((uint8_t *)vb2_packed_key_data(&h->data_key))[0] ^= 0x34; TEST_EQ(vb2_verify_keyblock(h, hsize, &key, &wb), VB2_ERROR_KEYBLOCK_SIG_INVALID, "vb2_verify_keyblock() sig mismatch"); Memcpy(h, hdr, hsize); h->keyblock_signature.data_size = h->keyblock_size + 1; TEST_EQ(vb2_verify_keyblock(h, hsize, &key, &wb), VB2_ERROR_KEYBLOCK_SIGNED_TOO_MUCH, "vb2_verify_keyblock() sig data past end of block"); /* Check that we signed header and data key */ Memcpy(h, hdr, hsize); h->keyblock_signature.data_size = 4; h->data_key.key_offset = 0; h->data_key.key_size = 0; resign_keyblock(h, private_key); TEST_EQ(vb2_verify_keyblock(h, hsize, &key, &wb), VB2_ERROR_KEYBLOCK_SIGNED_TOO_LITTLE, "vb2_verify_keyblock() didn't sign header"); Memcpy(h, hdr, hsize); h->data_key.key_offset = hsize; resign_keyblock(h, private_key); TEST_EQ(vb2_verify_keyblock(h, hsize, &key, &wb), VB2_ERROR_KEYBLOCK_DATA_KEY_OUTSIDE, "vb2_verify_keyblock() data key off end"); /* Corner cases for error checking */ TEST_EQ(vb2_verify_keyblock(NULL, 4, &key, &wb), VB2_ERROR_KEYBLOCK_TOO_SMALL_FOR_HEADER, "vb2_verify_keyblock size too small"); /* * TODO: verify parser can support a bigger header (i.e., one where * data_key.key_offset is bigger than expected). */ free(h); free(hdr); }
static void VbNvStorageTest(void) { VbNvField* vnf; VbNvContext c; uint8_t goodcrc; uint32_t data; memset(&c, 0xA6, sizeof(c)); /* Open with invalid data should set defaults */ TEST_EQ(VbNvSetup(&c), 0, "VbNvSetup()"); TEST_EQ(c.raw[0], 0x70, "VbNvSetup() reset header byte"); /* Close then regenerates the CRC */ TEST_EQ(VbNvTeardown(&c), 0, "VbNvTeardown()"); TEST_NEQ(c.raw[15], 0, "VbNvTeardown() CRC"); TEST_EQ(c.raw_changed, 1, "VbNvTeardown() changed"); goodcrc = c.raw[15]; /* Another open-close pair should not cause further changes */ VbNvSetup(&c); VbNvTeardown(&c); TEST_EQ(c.raw_changed, 0, "VbNvTeardown() didn't change"); TEST_EQ(c.raw[15], goodcrc, "VbNvTeardown() CRC same"); /* Perturbing the header should force defaults */ c.raw[0] ^= 0x40; VbNvSetup(&c); TEST_EQ(c.raw[0], 0x70, "VbNvSetup() reset header byte again"); /* Close then regenerates the CRC */ VbNvTeardown(&c); TEST_EQ(c.raw_changed, 1, "VbNvTeardown() changed again"); TEST_EQ(c.raw[15], goodcrc, "VbNvTeardown() CRC same again"); /* So should perturbing some other byte */ TEST_EQ(c.raw[11], 0, "Kernel byte starts at 0"); c.raw[11] = 12; VbNvSetup(&c); TEST_EQ(c.raw[11], 0, "VbNvSetup() reset kernel byte"); /* Close then regenerates the CRC */ VbNvTeardown(&c); TEST_EQ(c.raw_changed, 1, "VbNvTeardown() changed again"); TEST_EQ(c.raw[15], goodcrc, "VbNvTeardown() CRC same again"); /* Clear the kernel and firmware flags */ VbNvSetup(&c); TEST_EQ(VbNvGet(&c, VBNV_FIRMWARE_SETTINGS_RESET, &data), 0, "Get firmware settings reset"); TEST_EQ(data, 1, "Firmware settings are reset"); TEST_EQ(VbNvSet(&c, VBNV_FIRMWARE_SETTINGS_RESET, 0), 0, "Clear firmware settings reset"); VbNvGet(&c, VBNV_FIRMWARE_SETTINGS_RESET, &data); TEST_EQ(data, 0, "Firmware settings are clear"); TEST_EQ(VbNvGet(&c, VBNV_KERNEL_SETTINGS_RESET, &data), 0, "Get kernel settings reset"); TEST_EQ(data, 1, "Kernel settings are reset"); TEST_EQ(VbNvSet(&c, VBNV_KERNEL_SETTINGS_RESET, 0), 0, "Clear kernel settings reset"); VbNvGet(&c, VBNV_KERNEL_SETTINGS_RESET, &data); TEST_EQ(data, 0, "Kernel settings are clear"); TEST_EQ(c.raw[0], 0x40, "Header byte now just has the header bit"); VbNvTeardown(&c); /* That should have changed the CRC */ TEST_NEQ(c.raw[15], goodcrc, "VbNvTeardown() CRC changed due to flags clear"); /* Test explicitly setting the reset flags again */ VbNvSetup(&c); VbNvSet(&c, VBNV_FIRMWARE_SETTINGS_RESET, 1); VbNvGet(&c, VBNV_FIRMWARE_SETTINGS_RESET, &data); TEST_EQ(data, 1, "Firmware settings forced reset"); VbNvSet(&c, VBNV_FIRMWARE_SETTINGS_RESET, 0); VbNvSet(&c, VBNV_KERNEL_SETTINGS_RESET, 1); VbNvGet(&c, VBNV_KERNEL_SETTINGS_RESET, &data); TEST_EQ(data, 1, "Kernel settings forced reset"); VbNvSet(&c, VBNV_KERNEL_SETTINGS_RESET, 0); VbNvTeardown(&c); /* Get/set an invalid field */ VbNvSetup(&c); TEST_EQ(VbNvGet(&c, -1, &data), 1, "Get invalid setting"); TEST_EQ(VbNvSet(&c, -1, 0), 1, "Set invalid setting"); VbNvTeardown(&c); /* Test other fields */ VbNvSetup(&c); for (vnf = nvfields; vnf->desc; vnf++) { TEST_EQ(VbNvGet(&c, vnf->param, &data), 0, vnf->desc); TEST_EQ(data, vnf->default_value, vnf->desc); TEST_EQ(VbNvSet(&c, vnf->param, vnf->test_value), 0, vnf->desc); TEST_EQ(VbNvGet(&c, vnf->param, &data), 0, vnf->desc); TEST_EQ(data, vnf->test_value, vnf->desc); TEST_EQ(VbNvSet(&c, vnf->param, vnf->test_value2), 0, vnf->desc); TEST_EQ(VbNvGet(&c, vnf->param, &data), 0, vnf->desc); TEST_EQ(data, vnf->test_value2, vnf->desc); } VbNvTeardown(&c); /* None of those changes should have caused a reset to defaults */ VbNvSetup(&c); VbNvGet(&c, VBNV_FIRMWARE_SETTINGS_RESET, &data); TEST_EQ(data, 0, "Firmware settings are still clear"); VbNvGet(&c, VBNV_KERNEL_SETTINGS_RESET, &data); TEST_EQ(data, 0, "Kernel settings are still clear"); VbNvTeardown(&c); /* Verify writing identical settings doesn't cause the CRC to regenerate */ VbNvSetup(&c); TEST_EQ(c.regenerate_crc, 0, "No regen CRC on open"); for (vnf = nvfields; vnf->desc; vnf++) TEST_EQ(VbNvSet(&c, vnf->param, vnf->test_value2), 0, vnf->desc); TEST_EQ(c.regenerate_crc, 0, "No regen CRC if data not changed"); VbNvTeardown(&c); TEST_EQ(c.raw_changed, 0, "No raw change if data not changed"); /* Test out-of-range fields mapping to defaults */ VbNvSetup(&c); VbNvSet(&c, VBNV_TRY_B_COUNT, 16); VbNvGet(&c, VBNV_TRY_B_COUNT, &data); TEST_EQ(data, 15, "Try b count out of range"); VbNvSet(&c, VBNV_RECOVERY_REQUEST, 0x101); VbNvGet(&c, VBNV_RECOVERY_REQUEST, &data); TEST_EQ(data, VBNV_RECOVERY_LEGACY, "Recovery request out of range"); VbNvSet(&c, VBNV_LOCALIZATION_INDEX, 0x102); VbNvGet(&c, VBNV_LOCALIZATION_INDEX, &data); TEST_EQ(data, 0, "Localization index out of range"); VbNvTeardown(&c); }
static void dev_switch_tests(void) { uint32_t v; /* Normal mode */ reset_common_data(); TEST_SUCC(vb2_check_dev_switch(&cc), "dev mode off"); TEST_EQ(sd->flags & VB2_SD_DEV_MODE_ENABLED, 0, "sd not in dev"); TEST_EQ(cc.flags & VB2_CONTEXT_DEVELOPER_MODE, 0, "ctx not in dev"); TEST_EQ(mock_tpm_clear_called, 0, "no tpm clear"); /* Dev mode */ reset_common_data(); vb2_secdata_set(&cc, VB2_SECDATA_FLAGS, (VB2_SECDATA_FLAG_DEV_MODE | VB2_SECDATA_FLAG_LAST_BOOT_DEVELOPER)); TEST_SUCC(vb2_check_dev_switch(&cc), "dev mode on"); TEST_NEQ(sd->flags & VB2_SD_DEV_MODE_ENABLED, 0, "sd in dev"); TEST_NEQ(cc.flags & VB2_CONTEXT_DEVELOPER_MODE, 0, "ctx in dev"); TEST_EQ(mock_tpm_clear_called, 0, "no tpm clear"); /* Any normal mode boot clears dev boot flags */ reset_common_data(); vb2_nv_set(&cc, VB2_NV_DEV_BOOT_USB, 1); vb2_nv_set(&cc, VB2_NV_DEV_BOOT_LEGACY, 1); vb2_nv_set(&cc, VB2_NV_DEV_BOOT_SIGNED_ONLY, 1); vb2_nv_set(&cc, VB2_NV_DEV_BOOT_FASTBOOT_FULL_CAP, 1); vb2_nv_set(&cc, VB2_NV_FASTBOOT_UNLOCK_IN_FW, 1); TEST_SUCC(vb2_check_dev_switch(&cc), "dev mode off"); TEST_EQ(vb2_nv_get(&cc, VB2_NV_DEV_BOOT_USB), 0, "cleared dev boot usb"); TEST_EQ(vb2_nv_get(&cc, VB2_NV_DEV_BOOT_LEGACY), 0, "cleared dev boot legacy"); TEST_EQ(vb2_nv_get(&cc, VB2_NV_DEV_BOOT_SIGNED_ONLY), 0, "cleared dev boot signed only"); TEST_EQ(vb2_nv_get(&cc, VB2_NV_DEV_BOOT_FASTBOOT_FULL_CAP), 0, "cleared dev boot fastboot full cap"); TEST_EQ(vb2_nv_get(&cc, VB2_NV_FASTBOOT_UNLOCK_IN_FW), 0, "cleared dev boot fastboot unlock in fw"); /* Normal-dev transition clears TPM */ reset_common_data(); vb2_secdata_set(&cc, VB2_SECDATA_FLAGS, VB2_SECDATA_FLAG_DEV_MODE); TEST_SUCC(vb2_check_dev_switch(&cc), "to dev mode"); TEST_EQ(mock_tpm_clear_called, 1, "tpm clear"); vb2_secdata_get(&cc, VB2_SECDATA_FLAGS, &v); TEST_EQ(v, (VB2_SECDATA_FLAG_DEV_MODE | VB2_SECDATA_FLAG_LAST_BOOT_DEVELOPER), "last boot developer now"); /* Dev-normal transition clears TPM too */ reset_common_data(); vb2_secdata_set(&cc, VB2_SECDATA_FLAGS, VB2_SECDATA_FLAG_LAST_BOOT_DEVELOPER); TEST_SUCC(vb2_check_dev_switch(&cc), "from dev mode"); TEST_EQ(mock_tpm_clear_called, 1, "tpm clear"); vb2_secdata_get(&cc, VB2_SECDATA_FLAGS, &v); TEST_EQ(v, 0, "last boot not developer now"); /* Disable dev mode */ reset_common_data(); vb2_secdata_set(&cc, VB2_SECDATA_FLAGS, (VB2_SECDATA_FLAG_DEV_MODE | VB2_SECDATA_FLAG_LAST_BOOT_DEVELOPER)); vb2_nv_set(&cc, VB2_NV_DISABLE_DEV_REQUEST, 1); TEST_SUCC(vb2_check_dev_switch(&cc), "disable dev request"); TEST_EQ(sd->flags & VB2_SD_DEV_MODE_ENABLED, 0, "sd not in dev"); TEST_EQ(vb2_nv_get(&cc, VB2_NV_DISABLE_DEV_REQUEST), 0, "request cleared"); /* Force enabled by gbb */ reset_common_data(); sd->gbb_flags |= VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON; TEST_SUCC(vb2_check_dev_switch(&cc), "dev on via gbb"); TEST_NEQ(sd->flags & VB2_SD_DEV_MODE_ENABLED, 0, "sd in dev"); vb2_secdata_get(&cc, VB2_SECDATA_FLAGS, &v); TEST_EQ(v, VB2_SECDATA_FLAG_LAST_BOOT_DEVELOPER, "doesn't set dev on in secdata but does set last boot dev"); TEST_EQ(mock_tpm_clear_called, 1, "tpm clear"); /* Force enabled by ctx flag */ reset_common_data(); cc.flags |= VB2_CONTEXT_FORCE_DEVELOPER_MODE; TEST_SUCC(vb2_check_dev_switch(&cc), "dev on via ctx flag"); TEST_NEQ(sd->flags & VB2_SD_DEV_MODE_ENABLED, 0, "sd in dev"); vb2_secdata_get(&cc, VB2_SECDATA_FLAGS, &v); TEST_EQ(v, VB2_SECDATA_FLAG_LAST_BOOT_DEVELOPER, "doesn't set dev on in secdata but does set last boot dev"); TEST_EQ(mock_tpm_clear_called, 1, "tpm clear"); /* Simulate clear owner failure */ reset_common_data(); vb2_secdata_set(&cc, VB2_SECDATA_FLAGS, VB2_SECDATA_FLAG_LAST_BOOT_DEVELOPER); mock_tpm_clear_retval = VB2_ERROR_EX_TPM_CLEAR_OWNER; TEST_EQ(vb2_check_dev_switch(&cc), VB2_ERROR_EX_TPM_CLEAR_OWNER, "tpm clear fail"); TEST_EQ(mock_tpm_clear_called, 1, "tpm clear"); vb2_secdata_get(&cc, VB2_SECDATA_FLAGS, &v); TEST_EQ(v, VB2_SECDATA_FLAG_LAST_BOOT_DEVELOPER, "last boot still developer"); TEST_EQ(vb2_nv_get(&cc, VB2_NV_RECOVERY_REQUEST), VB2_RECOVERY_TPM_CLEAR_OWNER, "requests recovery"); TEST_EQ(vb2_nv_get(&cc, VB2_NV_RECOVERY_SUBCODE), (uint8_t)VB2_ERROR_EX_TPM_CLEAR_OWNER, "recovery subcode"); }
static void test_check_keyblock(const struct vb2_public_key *public_key, const struct vb2_private_key *private_key, const struct vb2_packed_key *data_key) { struct vb2_keyblock *hdr; struct vb2_keyblock *h; struct vb2_signature *sig; uint32_t hsize; hdr = vb2_create_keyblock(data_key, private_key, 0x1234); TEST_NEQ((size_t)hdr, 0, "vb2_verify_keyblock() prerequisites"); if (!hdr) return; hsize = hdr->keyblock_size; h = (struct vb2_keyblock *)malloc(hsize + 2048); sig = &h->keyblock_signature; memcpy(h, hdr, hsize); TEST_SUCC(vb2_check_keyblock(h, hsize, sig), "vb2_check_keyblock() ok"); memcpy(h, hdr, hsize); TEST_EQ(vb2_check_keyblock(h, hsize - 1, sig), VB2_ERROR_KEYBLOCK_SIZE, "vb2_check_keyblock() size--"); /* Buffer is allowed to be bigger than keyblock */ memcpy(h, hdr, hsize); TEST_SUCC(vb2_check_keyblock(h, hsize + 1, sig), "vb2_check_keyblock() size++"); memcpy(h, hdr, hsize); h->magic[0] &= 0x12; TEST_EQ(vb2_check_keyblock(h, hsize, sig), VB2_ERROR_KEYBLOCK_MAGIC, "vb2_check_keyblock() magic"); /* Care about major version but not minor */ memcpy(h, hdr, hsize); h->header_version_major++; resign_keyblock(h, private_key); TEST_EQ(vb2_check_keyblock(h, hsize, sig), VB2_ERROR_KEYBLOCK_HEADER_VERSION, "vb2_check_keyblock() major++"); memcpy(h, hdr, hsize); h->header_version_major--; resign_keyblock(h, private_key); TEST_EQ(vb2_check_keyblock(h, hsize, sig), VB2_ERROR_KEYBLOCK_HEADER_VERSION, "vb2_check_keyblock() major--"); memcpy(h, hdr, hsize); h->header_version_minor++; resign_keyblock(h, private_key); TEST_SUCC(vb2_check_keyblock(h, hsize, sig), "vb2_check_keyblock() minor++"); memcpy(h, hdr, hsize); h->header_version_minor--; resign_keyblock(h, private_key); TEST_SUCC(vb2_check_keyblock(h, hsize, sig), "vb2_check_keyblock() minor--"); /* Check signature */ memcpy(h, hdr, hsize); h->keyblock_signature.sig_offset = hsize; resign_keyblock(h, private_key); TEST_EQ(vb2_check_keyblock(h, hsize, sig), VB2_ERROR_KEYBLOCK_SIG_OUTSIDE, "vb2_check_keyblock() sig off end"); memcpy(h, hdr, hsize); h->keyblock_signature.data_size = h->keyblock_size + 1; TEST_EQ(vb2_check_keyblock(h, hsize, sig), VB2_ERROR_KEYBLOCK_SIGNED_TOO_MUCH, "vb2_check_keyblock() sig data past end of block"); /* Check that we signed header and data key */ memcpy(h, hdr, hsize); h->keyblock_signature.data_size = 4; h->data_key.key_offset = 0; h->data_key.key_size = 0; resign_keyblock(h, private_key); TEST_EQ(vb2_check_keyblock(h, hsize, sig), VB2_ERROR_KEYBLOCK_SIGNED_TOO_LITTLE, "vb2_check_keyblock() didn't sign header"); memcpy(h, hdr, hsize); h->data_key.key_offset = hsize; resign_keyblock(h, private_key); TEST_EQ(vb2_check_keyblock(h, hsize, sig), VB2_ERROR_KEYBLOCK_DATA_KEY_OUTSIDE, "vb2_check_keyblock() data key off end"); /* Corner cases for error checking */ TEST_EQ(vb2_check_keyblock(NULL, 4, sig), VB2_ERROR_KEYBLOCK_TOO_SMALL_FOR_HEADER, "vb2_check_keyblock size too small"); /* * TODO: verify parser can support a bigger header (i.e., one where * data_key.key_offset is bigger than expected). */ free(h); free(hdr); }
int socket_api_test_echo_server_stream(socket_stack_t stack, socket_address_family_t af, const char* local_addr, uint16_t port) { struct socket s; struct socket cs; struct socket_addr addr; socket_error_t err; const struct socket_api *api = socket_get_api(stack); server_socket = &s; client_socket = &cs; mbed::Timeout to; mbed::Ticker ticker; // Create the socket TEST_CLEAR(); if (!TEST_NEQ(api, NULL)) { // Test cannot continue without API. TEST_RETURN(); } err = api->init(); if (!TEST_EQ(err, SOCKET_ERROR_NONE)) { TEST_RETURN(); } // Zero the socket implementation s.impl = NULL; // Create a socket err = api->create(&s, af, SOCKET_STREAM, &server_cb); if (!TEST_EQ(err, SOCKET_ERROR_NONE)) { TEST_RETURN(); } err = api->str2addr(&s, &addr, local_addr); if (!TEST_EQ(err, SOCKET_ERROR_NONE)) { TEST_RETURN(); } // start the TCP timer uint32_t interval_ms = api->periodic_interval(&s); TEST_NEQ(interval_ms, 0); uint32_t interval_us = interval_ms * 1000; socket_api_handler_t periodic_task = api->periodic_task(&s); if (TEST_NEQ(periodic_task, NULL)) { ticker.attach_us(periodic_task, interval_us); } err = api->bind(&s, &addr, port); if (!TEST_EQ(err, SOCKET_ERROR_NONE)) { TEST_RETURN(); } void *data = malloc(SOCKET_SENDBUF_MAXSIZE); if(!TEST_NEQ(data, NULL)) { TEST_RETURN(); } // Tell the host test to try and connect TEST_PRINT(">>> EC,%s,%d\r\n", local_addr, port); bool quit = false; // For several iterations while (!quit) { timedout = false; server_event_done = false; incoming = false; to.attach(onTimeout, SOCKET_TEST_SERVER_TIMEOUT); // Listen for incoming connections err = api->start_listen(&s, 0); if (!TEST_EQ(err, SOCKET_ERROR_NONE)) { TEST_EXIT(); } // Reset the state of client_rx_done client_rx_done = false; // Wait for a connect event while (!timedout && !incoming) { __WFI(); } if (TEST_EQ(timedout,0)) { to.detach(); } else { TEST_EXIT(); } if(!TEST_EQ(server_event.event, SOCKET_EVENT_ACCEPT)) { TEST_PRINT("Event: %d\r\n",(int)client_event.event); continue; } // Stop listening server_event_done = false; // err = api->stop_listen(&s); // TEST_EQ(err, SOCKET_ERROR_NONE); // Accept an incoming connection cs.impl = server_event.i.a.newimpl; cs.family = s.family; cs.stack = s.stack; err = api->accept(&cs, client_cb); if(!TEST_EQ(err, SOCKET_ERROR_NONE)) { continue; } to.attach(onTimeout, SOCKET_TEST_SERVER_TIMEOUT); // Client should test for successive connections being rejected // Until Client disconnects while (client_event.event != SOCKET_EVENT_ERROR && client_event.event != SOCKET_EVENT_DISCONNECT) { // Wait for a read event while (!client_event_done && !client_rx_done && !timedout) { __WFI(); } if (!TEST_EQ(client_event_done, false)) { client_event_done = false; continue; } // Reset the state of client_rx_done client_rx_done = false; // Receive some data size_t len = SOCKET_SENDBUF_MAXSIZE; err = api->recv(&cs, data, &len); if (!TEST_NEQ(err, SOCKET_ERROR_WOULD_BLOCK)) { TEST_PRINT("Rx Would Block\r\n"); continue; } if (!TEST_EQ(err, SOCKET_ERROR_NONE)) { TEST_PRINT("err: (%d) %s\r\n", err, socket_strerror(err)); break; } // Check if the server should halt if (strncmp((const char *)data, "quit", 4) == 0) { quit = true; break; } // Send some data err = api->send(&cs, data, len); if (!TEST_EQ(err, SOCKET_ERROR_NONE)) { break; } } to.detach(); TEST_NEQ(timedout, true); // Close client socket err = api->close(&cs); TEST_EQ(err, SOCKET_ERROR_NONE); } err = api->stop_listen(&s); TEST_EQ(err, SOCKET_ERROR_NONE); test_exit: ticker.detach(); TEST_PRINT(">>> KILL,EC\r\n"); free(data); // Destroy server socket TEST_RETURN(); }
int test_socket_stack_registry() { unsigned int i; socket_error_t err = SOCKET_ERROR_NONE; printf("Testing stack registry...\n"); TEST_CLEAR(); // Try to register a stack marked as Uninitialized expect_fail_api.stack = SOCKET_STACK_UNINIT; expect_fail_api.version = SOCKET_ABSTRACTION_LAYER_VERSION; err = socket_register_stack((&expect_fail_api)); TEST_NEQ(err,SOCKET_ERROR_NONE); // Register a NULL socket api memset(&expect_fail_api, 0, sizeof(struct socket_api)); expect_fail_api.version = SOCKET_ABSTRACTION_LAYER_VERSION; err = socket_register_stack(&expect_fail_api); TEST_NEQ(err,SOCKET_ERROR_NONE); // Register a socket api with one zeroed API. memset(&expect_fail_api, 1, sizeof(struct socket_api)); expect_fail_api.version = SOCKET_ABSTRACTION_LAYER_VERSION; expect_fail_api.create = NULL; expect_fail_api.stack = static_cast<socket_stack_t>(SOCKET_STACK_UNINIT + 1); err = socket_register_stack(&expect_fail_api); TEST_NEQ(err,SOCKET_ERROR_NONE); // Register a socket api with the version set wrong memset(&expect_fail_api, 1, sizeof(struct socket_api)); expect_fail_api.version = 0; expect_fail_api.stack = static_cast<socket_stack_t>(SOCKET_STACK_UNINIT + 1); err = socket_register_stack(&expect_fail_api); TEST_NEQ(err,SOCKET_ERROR_NONE); // Register two of the same socket api's memset(&test_api[0], 1, sizeof(struct socket_api)); memset(&expect_fail_api, 1, sizeof(struct socket_api)); test_api[0].stack = static_cast<socket_stack_t>(SOCKET_STACK_UNINIT + 1); test_api[0].version = SOCKET_ABSTRACTION_LAYER_VERSION; expect_fail_api.stack = static_cast<socket_stack_t>(SOCKET_STACK_UNINIT + 1); expect_fail_api.version = SOCKET_ABSTRACTION_LAYER_VERSION; err = socket_register_stack(&test_api[0]); TEST_EQ(err,SOCKET_ERROR_NONE); err = socket_register_stack(&expect_fail_api); TEST_NEQ(err,SOCKET_ERROR_NONE); // Register the same stack again, but with the stack ID changed test_api[0].stack = static_cast<socket_stack_t>(static_cast<uint32_t>(test_api[0].stack) + 1); test_api[0].version = SOCKET_ABSTRACTION_LAYER_VERSION; err = socket_register_stack(&test_api[0]); TEST_NEQ(err,SOCKET_ERROR_NONE); test_api[0].stack = static_cast<socket_stack_t>(static_cast<uint32_t>(test_api[0].stack) - 1); // Try to register a stack outside the accepted range expect_fail_api.stack = SOCKET_STACK_MAX; expect_fail_api.version = SOCKET_ABSTRACTION_LAYER_VERSION; err = socket_register_stack(&expect_fail_api); TEST_NEQ(err,SOCKET_ERROR_NONE); // One stack is already registered // Try to register the maximum number of stacks for (i = 1; i < SOCKET_MAX_STACKS; i++) { socket_stack_t stack = static_cast<socket_stack_t>(SOCKET_STACK_UNINIT + 1 + i); memset (&test_api[i],1,sizeof(struct socket_api)); test_api[i].stack = stack; test_api[i].version = SOCKET_ABSTRACTION_LAYER_VERSION; err = socket_register_stack(&test_api[i]); TEST_EQ(err,SOCKET_ERROR_NONE); } // Then register one more. expect_fail_api.stack = static_cast<socket_stack_t>(SOCKET_MAX_STACKS + 1); expect_fail_api.version = SOCKET_ABSTRACTION_LAYER_VERSION; err = socket_register_stack(&expect_fail_api); TEST_NEQ(err,SOCKET_ERROR_NONE); // Extract an uninit socket api const struct socket_api *papi; papi = socket_get_api(SOCKET_STACK_UNINIT); TEST_EQ(papi, NULL); if (SOCKET_MAX_STACKS < SOCKET_STACK_MAX - 1) { // Get a valid, but unregistered stack papi = socket_get_api(static_cast<socket_stack_t>(SOCKET_STACK_MAX - 1)); TEST_EQ(papi, NULL); } // Verify all registered stacks for (i = 0; i < SOCKET_MAX_STACKS; i++) { socket_stack_t stack = static_cast<socket_stack_t>(SOCKET_STACK_UNINIT + 1 + i); papi = socket_get_api(stack); TEST_EQ(papi, &test_api[i]); } return test_pass_global; }
/** * Test send-command functions */ static void SendCommandTest(void) { ResetMocks(); TEST_EQ(TlclStartup(), 0, "SaveState"); TEST_EQ(calls[0].req_cmd, TPM_ORD_Startup, " cmd"); ResetMocks(); TEST_EQ(TlclSaveState(), 0, "SaveState"); TEST_EQ(calls[0].req_cmd, TPM_ORD_SaveState, " cmd"); ResetMocks(); TEST_EQ(TlclResume(), 0, "Resume"); TEST_EQ(calls[0].req_cmd, TPM_ORD_Startup, " cmd"); ResetMocks(); TEST_EQ(TlclSelfTestFull(), 0, "SelfTestFull"); TEST_EQ(calls[0].req_cmd, TPM_ORD_SelfTestFull, " cmd"); ResetMocks(); TEST_EQ(TlclContinueSelfTest(), 0, "ContinueSelfTest"); TEST_EQ(calls[0].req_cmd, TPM_ORD_ContinueSelfTest, " cmd"); ResetMocks(); TEST_EQ(TlclAssertPhysicalPresence(), 0, "AssertPhysicalPresence"); TEST_EQ(calls[0].req_cmd, TSC_ORD_PhysicalPresence, " cmd"); ResetMocks(); TEST_EQ(TlclPhysicalPresenceCMDEnable(), 0, "PhysicalPresenceCMDEnable"); TEST_EQ(calls[0].req_cmd, TSC_ORD_PhysicalPresence, " cmd"); ResetMocks(); TEST_EQ(TlclFinalizePhysicalPresence(), 0, "FinalizePhysicalPresence"); TEST_EQ(calls[0].req_cmd, TSC_ORD_PhysicalPresence, " cmd"); ResetMocks(); TEST_EQ(TlclAssertPhysicalPresenceResult(), 0, "AssertPhysicalPresenceResult"); TEST_EQ(calls[0].req_cmd, TSC_ORD_PhysicalPresence, " cmd"); ResetMocks(); TEST_EQ(TlclLockPhysicalPresence(), 0, "LockPhysicalPresence"); TEST_EQ(calls[0].req_cmd, TSC_ORD_PhysicalPresence, " cmd"); ResetMocks(); TEST_EQ(TlclIsOwned(), 0, "IsOwned"); TEST_EQ(calls[0].req_cmd, TPM_ORD_ReadPubek, " cmd"); ResetMocks(); calls[0].retval = VBERROR_SIMULATED; TEST_NEQ(TlclIsOwned(), 0, "IsOwned"); ResetMocks(); TEST_EQ(TlclForceClear(), 0, "ForceClear"); TEST_EQ(calls[0].req_cmd, TPM_ORD_ForceClear, " cmd"); ResetMocks(); TEST_EQ(TlclSetEnable(), 0, "SetEnable"); TEST_EQ(calls[0].req_cmd, TPM_ORD_PhysicalEnable, " cmd"); ResetMocks(); TEST_EQ(TlclClearEnable(), 0, "ClearEnable"); TEST_EQ(calls[0].req_cmd, TPM_ORD_PhysicalDisable, " cmd"); ResetMocks(); TEST_EQ(TlclSetDeactivated(0), 0, "SetDeactivated"); TEST_EQ(calls[0].req_cmd, TPM_ORD_PhysicalSetDeactivated, " cmd"); }
/*---------------------------------------------------------------------------*/ PROCESS_THREAD(coffee_test_process, ev, data) { int fd_write, n, i; static int cnt = 0; uint8_t buffer[FILE_SIZE]; clock_time_t now; unsigned short now_fine; static uint32_t time_start, time_stop; printf("###########################################################\n"); PROCESS_BEGIN(); printf("process running\n"); // wait for 5 sec etimer_set(&et, CLOCK_SECOND * 5); PROCESS_YIELD_UNTIL(etimer_expired(&et)); #if (COFFEE_DEVICE == 6) int initialized = 0, i; SDCARD_POWER_ON(); //--- Detecting devices and partitions TEST_EQUALS(diskio_detect_devices(), DISKIO_SUCCESS); info = diskio_devices(); for (i = 0; i < DISKIO_MAX_DEVICES; i++) { if ((info + i)->type == (DISKIO_DEVICE_TYPE_SD_CARD | DISKIO_DEVICE_TYPE_PARTITION)) { info += i; initialized = 1; break; } } TEST_EQUALS(initialized, 1); diskio_set_default_device(info); #endif printf("fomartting...\n"); TEST_EQUALS(cfs_coffee_format(), 0); //printf("test starting\n"); do { now_fine = clock_time(); now = clock_seconds(); } while (now_fine != clock_time()); time_start = ((unsigned long)now)*CLOCK_SECOND + now_fine%CLOCK_SECOND; while(1) { // Shortest possible pause PROCESS_PAUSE(); // Determine the filename char b_file[8]; sprintf(b_file,"%u.b", cnt); // Set the file size printf("Reserving '%s'...\n", b_file); TEST_EQUALS(cfs_coffee_reserve(b_file, FILE_SIZE), 0); // And open it printf("Opening '%s'...\n", b_file); fd_write = cfs_open(b_file, CFS_WRITE); TEST_NEQ(fd_write, -1); // fill buffer for(i=0; i<FILE_SIZE; i++) { buffer[i] = cnt % 0xFF; } // Open was successful, write has to be successful too since the size has been reserved printf("Writing'%s'...\n", b_file); n = cfs_write(fd_write, buffer, FILE_SIZE); cfs_close(fd_write); TEST_EQUALS(n, FILE_SIZE); printf("%s written\n", b_file); if( cnt >= FILES_IN_STORAGE ) { int fd_read; // Figure out the filename char r_file[8]; sprintf(r_file,"%u.b", cnt - FILES_IN_STORAGE); // Open the bundle file printf("Reopening '%s'...\n", r_file); fd_read = cfs_open(r_file, CFS_READ); if(fd_read == -1) { // Could not open file printf("############# STORAGE: could not open file %s\n", r_file); fail(); } memset(buffer, 0, FILE_SIZE); // And now read the bundle back from flash printf("Reading '%s'...\n", b_file); if (cfs_read(fd_read, buffer, FILE_SIZE) == -1){ printf("############# STORAGE: cfs_read error\n"); cfs_close(fd_read); fail(); } cfs_close(fd_read); for(i=0; i<FILE_SIZE; i++) { if( buffer[i] != (cnt - FILES_IN_STORAGE) % 0xFF ) { printf("############# STORAGE: verify error\n"); fail(); } } if( cfs_remove(r_file) == -1 ) { printf("############# STORAGE: unable to remove %s\n", r_file); fail(); } printf("%s deleted\n", r_file); } cnt ++; if( cnt >= 10 ) { do { now_fine = clock_time(); now = clock_seconds(); } while (now_fine != clock_time()); time_stop = ((unsigned long)now)*CLOCK_SECOND + now_fine%CLOCK_SECOND; TEST_REPORT("data written", FILE_SIZE*cnt*CLOCK_SECOND, time_stop-time_start, "bytes/s"); TEST_PASS(); watchdog_stop(); while(1); } } PROCESS_END(); }
static void nv_storage_test(void) { struct nv_field *vnf; uint8_t goodcrc; uint8_t workbuf[VB2_WORKBUF_RECOMMENDED_SIZE] __attribute__ ((aligned (VB2_WORKBUF_ALIGN))); struct vb2_context c = { .flags = 0, .workbuf = workbuf, .workbuf_size = sizeof(workbuf), }; struct vb2_shared_data *sd = vb2_get_sd(&c); memset(c.nvdata, 0xA6, sizeof(c.nvdata)); vb2_init_context(&c); /* Init with invalid data should set defaults and regenerate CRC */ vb2_nv_init(&c); TEST_EQ(c.nvdata[0], 0x70, "vb2_nv_init() reset header byte"); TEST_NEQ(c.nvdata[15], 0, "vb2_nv_init() CRC"); TEST_EQ(sd->status, VB2_SD_STATUS_NV_INIT | VB2_SD_STATUS_NV_REINIT, "vb2_nv_init() status changed"); test_changed(&c, 1, "vb2_nv_init() reset changed"); goodcrc = c.nvdata[15]; TEST_SUCC(vb2_nv_check_crc(&c), "vb2_nv_check_crc() good"); /* Another init should not cause further changes */ c.flags = 0; sd->status = 0; vb2_nv_init(&c); test_changed(&c, 0, "vb2_nv_init() didn't re-reset"); TEST_EQ(c.nvdata[15], goodcrc, "vb2_nv_init() CRC same"); TEST_EQ(sd->status, VB2_SD_STATUS_NV_INIT, "vb2_nv_init() status same"); /* Perturbing the header should force defaults */ c.nvdata[0] ^= 0x40; TEST_EQ(vb2_nv_check_crc(&c), VB2_ERROR_NV_HEADER, "vb2_nv_check_crc() bad header"); vb2_nv_init(&c); TEST_EQ(c.nvdata[0], 0x70, "vb2_nv_init() reset header byte again"); test_changed(&c, 1, "vb2_nv_init() corrupt changed"); TEST_EQ(c.nvdata[15], goodcrc, "vb2_nv_init() CRC same again"); /* So should perturbing some other byte */ TEST_EQ(c.nvdata[11], 0, "Kernel byte starts at 0"); c.nvdata[11] = 12; TEST_EQ(vb2_nv_check_crc(&c), VB2_ERROR_NV_CRC, "vb2_nv_check_crc() bad CRC"); vb2_nv_init(&c); TEST_EQ(c.nvdata[11], 0, "vb2_nv_init() reset kernel byte"); test_changed(&c, 1, "vb2_nv_init() corrupt elsewhere changed"); TEST_EQ(c.nvdata[15], goodcrc, "vb2_nv_init() CRC same again"); /* Clear the kernel and firmware flags */ vb2_nv_init(&c); TEST_EQ(vb2_nv_get(&c, VB2_NV_FIRMWARE_SETTINGS_RESET), 1, "Firmware settings are reset"); vb2_nv_set(&c, VB2_NV_FIRMWARE_SETTINGS_RESET, 0); TEST_EQ(vb2_nv_get(&c, VB2_NV_FIRMWARE_SETTINGS_RESET), 0, "Firmware settings are clear"); TEST_EQ(vb2_nv_get(&c, VB2_NV_KERNEL_SETTINGS_RESET), 1, "Kernel settings are reset"); vb2_nv_set(&c, VB2_NV_KERNEL_SETTINGS_RESET, 0); TEST_EQ(vb2_nv_get(&c, VB2_NV_KERNEL_SETTINGS_RESET), 0, "Kernel settings are clear"); TEST_EQ(c.nvdata[0], 0x40, "Header byte now just has the header bit"); /* That should have changed the CRC */ TEST_NEQ(c.nvdata[15], goodcrc, "vb2_nv_init() CRC changed due to flags clear"); /* Test explicitly setting the reset flags again */ vb2_nv_init(&c); vb2_nv_set(&c, VB2_NV_FIRMWARE_SETTINGS_RESET, 1); TEST_EQ(vb2_nv_get(&c, VB2_NV_FIRMWARE_SETTINGS_RESET), 1, "Firmware settings forced reset"); vb2_nv_set(&c, VB2_NV_FIRMWARE_SETTINGS_RESET, 0); vb2_nv_set(&c, VB2_NV_KERNEL_SETTINGS_RESET, 1); TEST_EQ(vb2_nv_get(&c, VB2_NV_KERNEL_SETTINGS_RESET), 1, "Kernel settings forced reset"); vb2_nv_set(&c, VB2_NV_KERNEL_SETTINGS_RESET, 0); /* Get/set an invalid field */ vb2_nv_init(&c); vb2_nv_set(&c, -1, 1); TEST_EQ(vb2_nv_get(&c, -1), 0, "Get invalid setting"); /* Test other fields */ vb2_nv_init(&c); for (vnf = nvfields; vnf->desc; vnf++) { TEST_EQ(vb2_nv_get(&c, vnf->param), vnf->default_value, vnf->desc); vb2_nv_set(&c, vnf->param, vnf->test_value); TEST_EQ(vb2_nv_get(&c, vnf->param), vnf->test_value, vnf->desc); vb2_nv_set(&c, vnf->param, vnf->test_value2); TEST_EQ(vb2_nv_get(&c, vnf->param), vnf->test_value2, vnf->desc); } /* None of those changes should have caused a reset to defaults */ vb2_nv_init(&c); TEST_EQ(vb2_nv_get(&c, VB2_NV_FIRMWARE_SETTINGS_RESET), 0, "Firmware settings are still clear"); TEST_EQ(vb2_nv_get(&c, VB2_NV_KERNEL_SETTINGS_RESET), 0, "Kernel settings are still clear"); /* Writing identical settings doesn't cause the CRC to regenerate */ c.flags = 0; vb2_nv_init(&c); test_changed(&c, 0, "No regen CRC on open"); for (vnf = nvfields; vnf->desc; vnf++) vb2_nv_set(&c, vnf->param, vnf->test_value2); test_changed(&c, 0, "No regen CRC if data not changed"); /* Test out-of-range fields mapping to defaults or failing */ vb2_nv_init(&c); vb2_nv_set(&c, VB2_NV_TRY_COUNT, 16); TEST_EQ(vb2_nv_get(&c, VB2_NV_TRY_COUNT), 15, "Try b count out of range"); vb2_nv_set(&c, VB2_NV_RECOVERY_REQUEST, 0x101); TEST_EQ(vb2_nv_get(&c, VB2_NV_RECOVERY_REQUEST), VB2_RECOVERY_LEGACY, "Recovery request out of range"); vb2_nv_set(&c, VB2_NV_LOCALIZATION_INDEX, 0x102); TEST_EQ(vb2_nv_get(&c, VB2_NV_LOCALIZATION_INDEX), 0, "Localization index out of range"); vb2_nv_set(&c, VB2_NV_FW_RESULT, VB2_FW_RESULT_UNKNOWN + 1); vb2_nv_set(&c, VB2_NV_FW_RESULT, VB2_FW_RESULT_UNKNOWN + 100); TEST_EQ(vb2_nv_get(&c, VB2_NV_FW_RESULT), VB2_FW_RESULT_UNKNOWN, "Firmware result out of range"); } int main(int argc, char* argv[]) { nv_storage_test(); return gTestSuccess ? 0 : 255; }
static void select_slot_tests(void) { /* Slot A */ reset_common_data(); TEST_SUCC(vb2_select_fw_slot(&cc), "select slot A"); TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_RESULT), VB2_FW_RESULT_UNKNOWN, "result unknown"); TEST_NEQ(sd->status & VB2_SD_STATUS_CHOSE_SLOT, 0, "chose slot"); TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_TRIED), 0, "tried A"); TEST_EQ(sd->fw_slot, 0, "selected A"); TEST_EQ(cc.flags & VB2_CONTEXT_FW_SLOT_B, 0, "didn't choose B"); /* Slot B */ reset_common_data(); vb2_nv_set(&cc, VB2_NV_TRY_NEXT, 1); TEST_SUCC(vb2_select_fw_slot(&cc), "select slot B"); TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_RESULT), VB2_FW_RESULT_UNKNOWN, "result unknown"); TEST_NEQ(sd->status & VB2_SD_STATUS_CHOSE_SLOT, 0, "chose slot"); TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_TRIED), 1, "tried B"); TEST_EQ(sd->fw_slot, 1, "selected B"); TEST_NEQ(cc.flags & VB2_CONTEXT_FW_SLOT_B, 0, "ctx says choose B"); /* Slot A ran out of tries */ reset_common_data(); vb2_nv_set(&cc, VB2_NV_FW_RESULT, VB2_FW_RESULT_TRYING); TEST_SUCC(vb2_select_fw_slot(&cc), "select slot A out of tries"); TEST_EQ(vb2_nv_get(&cc, VB2_NV_TRY_NEXT), 1, "try B next"); TEST_NEQ(sd->status & VB2_SD_STATUS_CHOSE_SLOT, 0, "chose slot"); TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_TRIED), 1, "tried B"); TEST_EQ(sd->fw_slot, 1, "selected B"); TEST_NEQ(cc.flags & VB2_CONTEXT_FW_SLOT_B, 0, "ctx says choose B"); /* Slot A ran out of tries, even with nofail active */ reset_common_data(); cc.flags |= VB2_CONTEXT_NOFAIL_BOOT; vb2_nv_set(&cc, VB2_NV_FW_RESULT, VB2_FW_RESULT_TRYING); TEST_SUCC(vb2_select_fw_slot(&cc), "select slot A out of tries"); TEST_EQ(vb2_nv_get(&cc, VB2_NV_TRY_NEXT), 1, "try B next"); TEST_NEQ(sd->status & VB2_SD_STATUS_CHOSE_SLOT, 0, "chose slot"); TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_TRIED), 1, "tried B"); TEST_EQ(sd->fw_slot, 1, "selected B"); TEST_NEQ(cc.flags & VB2_CONTEXT_FW_SLOT_B, 0, "ctx says choose B"); /* Slot A used up a try */ reset_common_data(); vb2_nv_set(&cc, VB2_NV_TRY_COUNT, 3); TEST_SUCC(vb2_select_fw_slot(&cc), "try slot A"); TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_RESULT), VB2_FW_RESULT_TRYING, "result trying"); TEST_NEQ(sd->status & VB2_SD_STATUS_CHOSE_SLOT, 0, "chose slot"); TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_TRIED), 0, "tried A"); TEST_EQ(sd->fw_slot, 0, "selected A"); TEST_EQ(cc.flags & VB2_CONTEXT_FW_SLOT_B, 0, "didn't choose B"); TEST_EQ(vb2_nv_get(&cc, VB2_NV_TRY_COUNT), 2, "tries decremented"); /* Slot A failed, but nofail active */ reset_common_data(); cc.flags |= VB2_CONTEXT_NOFAIL_BOOT; vb2_nv_set(&cc, VB2_NV_TRY_COUNT, 3); TEST_SUCC(vb2_select_fw_slot(&cc), "try slot A"); TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_RESULT), VB2_FW_RESULT_TRYING, "result trying"); TEST_NEQ(sd->status & VB2_SD_STATUS_CHOSE_SLOT, 0, "chose slot"); TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_TRIED), 0, "tried A"); TEST_EQ(sd->fw_slot, 0, "selected A"); TEST_EQ(cc.flags & VB2_CONTEXT_FW_SLOT_B, 0, "didn't choose B"); TEST_EQ(vb2_nv_get(&cc, VB2_NV_TRY_COUNT), 3, "tries not decremented"); /* Tried/result get copied to the previous fields */ reset_common_data(); vb2_nv_set(&cc, VB2_NV_FW_TRIED, 0); vb2_nv_set(&cc, VB2_NV_FW_RESULT, VB2_FW_RESULT_SUCCESS); vb2_select_fw_slot(&cc); TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_PREV_TRIED), 0, "prev A"); TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_PREV_RESULT), VB2_FW_RESULT_SUCCESS, "prev success"); reset_common_data(); vb2_nv_set(&cc, VB2_NV_FW_TRIED, 1); vb2_nv_set(&cc, VB2_NV_FW_RESULT, VB2_FW_RESULT_FAILURE); vb2_select_fw_slot(&cc); TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_PREV_TRIED), 1, "prev B"); TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_PREV_RESULT), VB2_FW_RESULT_FAILURE, "prev failure"); }
int socket_api_test_connect_close(socket_stack_t stack, socket_address_family_t af, const char* server, uint16_t port) { struct socket s; int pfi; socket_error_t err; const struct socket_api * api = socket_get_api(stack); struct socket_addr addr; ConnectCloseSock = &s; TEST_CLEAR(); if (!TEST_NEQ(api, NULL)) { // Test cannot continue without API. TEST_RETURN(); } err = api->init(); if (!TEST_EQ(err, SOCKET_ERROR_NONE)) { TEST_RETURN(); } // Create a socket for each protocol family for (pfi = SOCKET_PROTO_UNINIT+1; pfi < SOCKET_PROTO_MAX; pfi++) { socket_proto_family_t pf = static_cast<socket_proto_family_t>(pfi); // Zero the implementation s.impl = NULL; err = api->create(&s, af, pf, &connect_close_handler); // catch expected failing cases TEST_EQ(err, SOCKET_ERROR_NONE); if (!TEST_NEQ(s.impl, NULL)) { continue; } // Tell the host launch a server TEST_PRINT(">>> ES,%d\r\n", pf); // connect to a remote host err = api->str2addr(&s, &addr, server); TEST_EQ(err, SOCKET_ERROR_NONE); timedout = 0; connected = 0; mbed::Timeout to; to.attach(onTimeout, SOCKET_TEST_TIMEOUT); err = api->connect(&s, &addr, port); TEST_EQ(err, SOCKET_ERROR_NONE); if (err!=SOCKET_ERROR_NONE) { printf("err = %d\r\n", err); } switch (pf) { case SOCKET_DGRAM: while ((!api->is_connected(&s)) && (!timedout)) { __WFI(); } break; case SOCKET_STREAM: while (!connected && !timedout) { __WFI(); } break; default: break; } to.detach(); TEST_EQ(timedout, 0); // close the connection timedout = 0; closed = 0; to.attach(onTimeout, SOCKET_TEST_TIMEOUT); err = api->close(&s); TEST_EQ(err, SOCKET_ERROR_NONE); if (err!=SOCKET_ERROR_NONE) { printf("err = %d\r\n", err); } switch (pf) { case SOCKET_DGRAM: while ((api->is_connected(&s)) && (!timedout)) { __WFI(); } break; case SOCKET_STREAM: while (!closed && !timedout) { __WFI(); } break; default: break; } to.detach(); TEST_EQ(timedout, 0); // Tell the host to kill the server TEST_PRINT(">>> KILL ES\r\n"); // Destroy the socket err = api->destroy(&s); TEST_EQ(err, SOCKET_ERROR_NONE); } TEST_RETURN(); }
int socket_api_test_echo_client_connected(socket_stack_t stack, socket_address_family_t af, socket_proto_family_t pf, bool connect, const char* server, uint16_t port) { struct socket s; socket_error_t err; const struct socket_api *api = socket_get_api(stack); client_socket = &s; mbed::Timeout to; // Create the socket TEST_CLEAR(); TEST_PRINT("\r\n%s af: %d, pf: %d, connect: %d, server: %s:%d\r\n",__func__, (int) af, (int) pf, (int) connect, server, (int) port); if (!TEST_NEQ(api, NULL)) { // Test cannot continue without API. TEST_RETURN(); } err = api->init(); if (!TEST_EQ(err, SOCKET_ERROR_NONE)) { TEST_RETURN(); } struct socket_addr addr; // Resolve the host address err = blocking_resolve(stack, af, server, &addr); if (!TEST_EQ(err, SOCKET_ERROR_NONE)) { TEST_RETURN(); } // Tell the host launch a server TEST_PRINT(">>> ES,%d\r\n", pf); // Allocate a data buffer for tx/rx void *data = malloc(SOCKET_SENDBUF_MAXSIZE); // Zero the socket implementation s.impl = NULL; // Create a socket err = api->create(&s, af, pf, &client_cb); if (!TEST_EQ(err, SOCKET_ERROR_NONE)) { TEST_EXIT(); } // Connect to a host if (connect) { client_event_done = false; timedout = 0; to.attach(onTimeout, SOCKET_TEST_TIMEOUT); err = api->connect(&s, &addr, port); if (!TEST_EQ(err, SOCKET_ERROR_NONE)) { TEST_EXIT(); } // Override event for dgrams. if (pf == SOCKET_DGRAM) { client_event.event = SOCKET_EVENT_CONNECT; client_event_done = true; } // Wait for onConnect while (!timedout && !client_event_done) { __WFI(); } // Make sure that the correct event occurred if (!TEST_EQ(client_event.event, SOCKET_EVENT_CONNECT)) { TEST_EXIT(); } to.detach(); } // For several iterations for (size_t i = 0; i < SOCKET_SENDBUF_ITERATIONS; i++) { // Fill some data into a buffer const size_t nWords = SOCKET_SENDBUF_BLOCKSIZE * (1 << i) / sizeof(uint16_t); for (size_t j = 0; j < nWords; j++) { *((uint16_t*) data + j) = j; } // Send the data client_tx_done = false; client_rx_done = false; timedout = 0; to.attach(onTimeout, SOCKET_TEST_TIMEOUT); if(connect) { err = api->send(&s, data, nWords * sizeof(uint16_t)); } else { err = api->send_to(&s, data, nWords * sizeof(uint16_t), &addr, port); } if (!TEST_EQ(err, SOCKET_ERROR_NONE)) { TEST_PRINT("Failed to send %u bytes\r\n", nWords * sizeof(uint16_t)); } else { size_t tx_bytes = 0; do { // Wait for the onSent callback while (!timedout && !client_tx_done) { __WFI(); } if (!TEST_EQ(timedout,0)) { break; } if (!TEST_NEQ(client_tx_info.sentbytes, 0)) { break; } tx_bytes += client_tx_info.sentbytes; if (tx_bytes < nWords * sizeof(uint16_t)) { client_tx_done = false; continue; } to.detach(); TEST_EQ(tx_bytes, nWords * sizeof(uint16_t)); break; } while (1); } timedout = 0; to.attach(onTimeout, SOCKET_TEST_TIMEOUT); memset(data, 0, nWords * sizeof(uint16_t)); // Wait for the onReadable callback size_t rx_bytes = 0; do { while (!timedout && !client_rx_done) { __WFI(); } if (!TEST_EQ(timedout,0)) { break; } size_t len = SOCKET_SENDBUF_MAXSIZE - rx_bytes; // Receive data if (connect) { err = api->recv(&s, (void*) ((uintptr_t) data + rx_bytes), &len); } else { struct socket_addr rxaddr; uint16_t rxport = 0; // addr may contain unused data in the storage element. memcpy(&rxaddr, &addr, sizeof(rxaddr)); // Receive from... err = api->recv_from(&s, (void*) ((uintptr_t) data + rx_bytes), &len, &rxaddr, &rxport); int rc = memcmp(&rxaddr.ipv6be, &addr.ipv6be, sizeof(rxaddr.ipv6be)); if(!TEST_EQ(rc, 0)) { TEST_PRINT("Spurious receive packet\r\n"); } TEST_EQ(rxport, port); } if (!TEST_EQ(err, SOCKET_ERROR_NONE)) { break; } rx_bytes += len; if (rx_bytes < nWords * sizeof(uint16_t)) { client_rx_done = false; continue; } to.detach(); break; } while (1); if(!TEST_EQ(rx_bytes, nWords * sizeof(uint16_t))) { TEST_PRINT("Expected %u, got %u\r\n", nWords * sizeof(uint16_t), rx_bytes); } // Validate that the two buffers are the same bool match = true; size_t j; for (j = 0; match && j < nWords; j++) { match = (*((uint16_t*) data + j) == j); } if(!TEST_EQ(match, true)) { TEST_PRINT("Mismatch in %u byte packet at offset %u\r\n", nWords * sizeof(uint16_t), j * sizeof(uint16_t)); } } if (connect) { // close the socket client_event_done = false; timedout = 0; to.attach(onTimeout, SOCKET_TEST_TIMEOUT); err = api->close(&s); TEST_EQ(err, SOCKET_ERROR_NONE); // Override event for dgrams. if (pf == SOCKET_DGRAM) { client_event.event = SOCKET_EVENT_DISCONNECT; client_event_done = true; } // wait for onClose while (!timedout && !client_event_done) { __WFI(); } if (TEST_EQ(timedout,0)) { to.detach(); } // Make sure that the correct event occurred TEST_EQ(client_event.event, SOCKET_EVENT_DISCONNECT); } // destroy the socket err = api->destroy(&s); TEST_EQ(err, SOCKET_ERROR_NONE); test_exit: TEST_PRINT(">>> KILL,ES\r\n"); free(data); TEST_RETURN(); }
static void VerifyKernelPreambleTest(const VbPublicKey *public_key, const VbPrivateKey *private_key) { VbKernelPreambleHeader *hdr; VbKernelPreambleHeader *h; RSAPublicKey *rsa; unsigned hsize; /* Create a dummy signature */ VbSignature *body_sig = SignatureAlloc(56, 78); rsa = PublicKeyToRSA(public_key); hdr = CreateKernelPreamble(0x1234, 0x100000, 0x300000, 0x4000, body_sig, 0, 0, 0, 0, private_key); TEST_NEQ(hdr && rsa, 0, "VerifyKernelPreamble() prerequisites"); if (!hdr) return; hsize = (unsigned) hdr->preamble_size; h = (VbKernelPreambleHeader *)malloc(hsize + 16384); TEST_EQ(VerifyKernelPreamble(hdr, hsize, rsa), 0, "VerifyKernelPreamble() ok using key"); TEST_NEQ(VerifyKernelPreamble(hdr, hsize - 1, rsa), 0, "VerifyKernelPreamble() size--"); TEST_NEQ(VerifyKernelPreamble(hdr, 4, rsa), 0, "VerifyKernelPreamble() size tiny"); TEST_EQ(VerifyKernelPreamble(hdr, hsize + 1, rsa), 0, "VerifyKernelPreamble() size++"); /* Care about major version but not minor */ Memcpy(h, hdr, hsize); h->header_version_major++; ReSignKernelPreamble(h, private_key); TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0, "VerifyKernelPreamble() major++"); Memcpy(h, hdr, hsize); h->header_version_major--; ReSignKernelPreamble(h, private_key); TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0, "VerifyKernelPreamble() major--"); Memcpy(h, hdr, hsize); h->header_version_minor++; ReSignKernelPreamble(h, private_key); TEST_EQ(VerifyKernelPreamble(h, hsize, rsa), 0, "VerifyKernelPreamble() minor++"); Memcpy(h, hdr, hsize); h->header_version_minor--; ReSignKernelPreamble(h, private_key); TEST_EQ(VerifyKernelPreamble(h, hsize, rsa), 0, "VerifyKernelPreamble() minor--"); /* Check signature */ Memcpy(h, hdr, hsize); h->preamble_signature.sig_offset = hsize; ReSignKernelPreamble(h, private_key); TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0, "VerifyKernelPreamble() sig off end"); Memcpy(h, hdr, hsize); h->preamble_signature.sig_size--; ReSignKernelPreamble(h, private_key); TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0, "VerifyKernelPreamble() sig too small"); Memcpy(h, hdr, hsize); GetSignatureData(&h->body_signature)[0] ^= 0x34; TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0, "VerifyKernelPreamble() sig mismatch"); /* Check that we signed header and body sig */ Memcpy(h, hdr, hsize); h->preamble_signature.data_size = 4; h->body_signature.sig_offset = 0; h->body_signature.sig_size = 0; ReSignKernelPreamble(h, private_key); TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0, "VerifyKernelPreamble() didn't sign header"); Memcpy(h, hdr, hsize); h->body_signature.sig_offset = hsize; ReSignKernelPreamble(h, private_key); TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0, "VerifyKernelPreamble() body sig off end"); /* TODO: verify parser can support a bigger header. */ free(h); RSAPublicKeyFree(rsa); free(hdr); }
int socket_api_test_create_destroy(socket_stack_t stack, socket_address_family_t disable_family) { struct socket s; int afi, pfi; socket_error_t err; const struct socket_api * api = socket_get_api(stack); TEST_CLEAR(); if (!TEST_NEQ(api, NULL)) { // Test cannot continue without API. return 0; } err = api->init(); if (!TEST_EQ(err, SOCKET_ERROR_NONE)) { return 0; } // Create a socket for each address family for (afi = SOCKET_AF_UNINIT; afi <= SOCKET_AF_MAX; afi++) { socket_address_family_t af = static_cast<socket_address_family_t>(afi); // Create a socket for each protocol family for (pfi = SOCKET_PROTO_UNINIT; pfi <= SOCKET_PROTO_MAX; pfi++) { socket_proto_family_t pf = static_cast<socket_proto_family_t>(pfi); // Zero the implementation s.impl = NULL; err = api->create(&s, af, pf, &create_test_handler); // catch expected failing cases if (af == SOCKET_AF_UNINIT || af == SOCKET_AF_MAX || pf == SOCKET_PROTO_UNINIT || pf == SOCKET_PROTO_MAX || af == disable_family) { TEST_NEQ(err, SOCKET_ERROR_NONE); continue; } TEST_EQ(err, SOCKET_ERROR_NONE); if (!TEST_NEQ(s.impl, NULL)) { continue; } // Destroy the socket; err = api->destroy(&s); TEST_EQ(err, SOCKET_ERROR_NONE); // Zero the implementation s.impl = NULL; // Create a socket with a NULL handler err = api->create(&s, af, pf, NULL); TEST_NEQ(err, SOCKET_ERROR_NONE); TEST_EQ(s.impl, NULL); // A NULL impl is not explicitly an exception since it can be zeroed during disconnect // Destroy the socket err = api->destroy(&s); TEST_EQ(err, SOCKET_ERROR_NONE); // Try destroying a socket that hasn't been created s.impl = NULL; err = api->destroy(&s); TEST_EQ(err, SOCKET_ERROR_NONE); /* * Because the allocator is stack-dependent, there is no way to test for a * memory leak in a portable way */ } } TEST_RETURN(); }
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"); }