static int test_uninstantiate(void) { u8_t entropy[32] = {0}; /* value not important */ TCCtrPrng_t ctx; size_t words; size_t i; int rc; rc = tc_ctr_prng_init(&ctx, entropy, sizeof(entropy), 0, 0); if (rc != TC_CRYPTO_SUCCESS) { rc = TC_FAIL; goto exit_test; } tc_ctr_prng_uninstantiate(&ctx); /* show that state has been zeroised */ for (i = 0; i < sizeof(ctx.V); i++) { if (ctx.V[i] != 0) { rc = TC_FAIL; goto exit_test; } } words = sizeof(ctx.key.words) / sizeof(ctx.key.words[0]); for (i = 0; i < words; i++) { if (ctx.key.words[i] != 0) { rc = TC_FAIL; goto exit_test; } } if (ctx.reseedCount != 0) { rc = TC_FAIL; goto exit_test; } rc = TC_PASS; exit_test: return rc; }
static int32_t test_uninstantiate(void) { uint32_t i; int32_t result = TC_PASS; uint8_t entropy[32U] = {0U}; /* value not important */ TCCtrPrng_t ctx; (void)tc_ctr_prng_init(&ctx, entropy, sizeof entropy, 0, 0U); tc_ctr_prng_uninstantiate(&ctx); /* show that state has been zeroised */ for (i = 0U; i < sizeof ctx.V; i++) { if (0U != ctx.V[i]) { TC_ERROR("CTR PRNG uninstantiate tests failed\n"); result = TC_FAIL; break; } } for (i = 0U; i < sizeof ctx.key.words / sizeof ctx.key.words[0]; i++) { if (0U != ctx.key.words[i]) { TC_ERROR("CTR PRNG uninstantiate tests failed\n"); result = TC_FAIL; break; } } if (0U != ctx.reseedCount) { TC_ERROR("CTR PRNG uninstantiate tests failed\n"); result = TC_FAIL; } return result; }
static int test_robustness(void) { u8_t entropy[32] = {0}; /* value not important */ u8_t output[32]; TCCtrPrng_t ctx; int rc; /* show that the CTR PRNG is robust to invalid inputs */ tc_ctr_prng_uninstantiate(0); rc = tc_ctr_prng_generate(&ctx, 0, 0, 0, 0); if (rc != TC_CRYPTO_FAIL) { rc = TC_FAIL; goto exit_test; } rc = tc_ctr_prng_generate(0, 0, 0, output, sizeof(output)); if (rc != TC_CRYPTO_FAIL) { rc = TC_FAIL; goto exit_test; } rc = tc_ctr_prng_generate(0, 0, 0, 0, 0); if (rc != TC_CRYPTO_FAIL) { rc = TC_FAIL; goto exit_test; } rc = tc_ctr_prng_reseed(&ctx, 0, 0, 0, 0); if (rc != TC_CRYPTO_FAIL) { rc = TC_FAIL; goto exit_test; } /* too little entropy */ rc = tc_ctr_prng_reseed(&ctx, entropy, sizeof(entropy) - 1, 0, 0); if (rc != TC_CRYPTO_FAIL) { rc = TC_FAIL; goto exit_test; } rc = tc_ctr_prng_reseed(0, entropy, sizeof(entropy), 0, 0); if (rc != TC_CRYPTO_FAIL) { rc = TC_FAIL; goto exit_test; } rc = tc_ctr_prng_reseed(0, 0, 0, 0, 0); if (rc != TC_CRYPTO_FAIL) { rc = TC_FAIL; goto exit_test; } rc = tc_ctr_prng_init(&ctx, 0, 0, 0, 0); if (rc != TC_CRYPTO_FAIL) { rc = TC_FAIL; goto exit_test; } /* too little entropy */ rc = tc_ctr_prng_init(&ctx, entropy, sizeof(entropy) - 1, 0, 0); if (rc != TC_CRYPTO_FAIL) { rc = TC_FAIL; goto exit_test; } rc = tc_ctr_prng_init(0, entropy, sizeof(entropy), 0, 0); if (rc != TC_CRYPTO_FAIL) { rc = TC_FAIL; goto exit_test; } rc = tc_ctr_prng_init(0, 0, 0, 0, 0); if (rc != TC_CRYPTO_FAIL) { rc = TC_FAIL; goto exit_test; } rc = TC_PASS; exit_test: return rc; }
static int test_reseed(void) { u8_t expectedV1[] = {0x7E, 0xE3, 0xA0, 0xCB, 0x6D, 0x5C, 0x4B, 0xC2, 0x4B, 0x7E, 0x3C, 0x48, 0x88, 0xC3, 0x69, 0x70}; u8_t expectedV2[] = {0x5E, 0xC1, 0x84, 0xED, 0x45, 0x76, 0x67, 0xEC, 0x7B, 0x4C, 0x08, 0x7E, 0xB0, 0xF9, 0x55, 0x4E}; u8_t extra_input[32] = {0}; u8_t entropy[32] = {0}; /* value not important */ u8_t output[32]; TCCtrPrng_t ctx; u32_t i; int rc; rc = tc_ctr_prng_init(&ctx, entropy, sizeof(entropy), 0, 0U); if (rc != TC_CRYPTO_SUCCESS) { rc = TC_FAIL; goto exit_test; } /* force internal state to max allowed count */ ctx.reseedCount = 0x1000000000000ULL; rc = tc_ctr_prng_generate(&ctx, 0, 0, output, sizeof(output)); if (rc != TC_CRYPTO_SUCCESS) { rc = TC_FAIL; goto exit_test; } /* expect further attempts to fail due to reaching reseed threshold */ rc = tc_ctr_prng_generate(&ctx, 0, 0, output, sizeof(output)); if (rc != TC_CTR_PRNG_RESEED_REQ) { rc = TC_FAIL; goto exit_test; } /* reseed and confirm generate works again * make entropy different from original value - not really important * for the purpose of this test */ memset(entropy, 0xFF, sizeof(entropy)); rc = tc_ctr_prng_reseed(&ctx, entropy, sizeof(entropy), extra_input, sizeof(extra_input)); if (rc != TC_CRYPTO_SUCCESS) { rc = TC_FAIL; goto exit_test; } rc = tc_ctr_prng_generate(&ctx, 0, 0, output, sizeof(output)); if (rc != TC_CRYPTO_SUCCESS) { rc = TC_FAIL; goto exit_test; } /* confirm entropy and additional_input are being used correctly * first, entropy only */ memset(&ctx, 0x0, sizeof(ctx)); for (i = 0; i < sizeof(entropy); i++) { entropy[i] = i; } rc = tc_ctr_prng_reseed(&ctx, entropy, sizeof(entropy), 0, 0); if (rc != 1) { rc = TC_FAIL; goto exit_test; } if (memcmp(ctx.V, expectedV1, sizeof(expectedV1))) { rc = TC_FAIL; goto exit_test; } /* now, entropy and additional_input */ memset(&ctx, 0x00, sizeof(ctx)); for (i = 0; i < sizeof(extra_input); i++) { extra_input[i] = i * 2; } rc = tc_ctr_prng_reseed(&ctx, entropy, sizeof(entropy), extra_input, sizeof(extra_input)); if (rc != 1) { rc = TC_FAIL; goto exit_test; } if (memcmp(ctx.V, expectedV2, sizeof(expectedV2))) { rc = TC_FAIL; goto exit_test; } rc = TC_PASS; exit_test: return rc; }
static int test_prng_vector(struct prng_vector *v) { TCCtrPrng_t ctx; u8_t entropy[MAX_BIN_SIZE]; u8_t expected[MAX_BIN_SIZE]; u8_t output[MAX_BIN_SIZE]; u8_t *personal = NULL; u8_t *extra1 = NULL; u8_t *extra2 = NULL; int extra1_len = 0; int extra2_len = 0; int plen = 0; int ent_len; int exp_len; int rc; hex_str_to_num(entropy, v->entropy); hex_str_to_num(expected, v->expected); ent_len = strlen(v->entropy) / 2; exp_len = strlen(v->expected) / 2; if (v->personal != 0) { personal = per; hex_str_to_num(personal, v->personal); plen = strlen(v->personal) / 2; } if (v->extra1 != 0) { extra1 = ai1; hex_str_to_num(extra1, v->extra1); extra1_len = strlen(v->extra1) / 2; } if (v->extra2 != 0) { extra2 = ai2; hex_str_to_num(extra2, v->extra2); extra2_len = strlen(v->extra2) / 2; } rc = tc_ctr_prng_init(&ctx, entropy, ent_len, personal, plen); if (rc != TC_CRYPTO_SUCCESS) { rc = TC_FAIL; goto exit_test; } rc = tc_ctr_prng_generate(&ctx, extra1, extra1_len, output, exp_len); if (rc != TC_CRYPTO_SUCCESS) { rc = TC_FAIL; goto exit_test; } rc = tc_ctr_prng_generate(&ctx, extra2, extra2_len, output, exp_len); if (rc != TC_CRYPTO_SUCCESS) { rc = TC_FAIL; goto exit_test; } rc = memcmp(output, expected, exp_len); if (rc != 0) { rc = TC_FAIL; goto exit_test; } rc = TC_PASS; exit_test: return rc; }
static int32_t test_robustness(void) { int32_t result = TC_PASS; int32_t ret; uint8_t entropy[32U] = {0U}; /* value not important */ uint8_t output[32]; TCCtrPrng_t ctx; /* show that the CTR PRNG is robust to invalid inputs */ tc_ctr_prng_uninstantiate(0); ret = tc_ctr_prng_generate(&ctx, 0, 0, 0, 0); if (0 != ret) { result = TC_FAIL; goto exitTest; } ret = tc_ctr_prng_generate(0, 0, 0, output, sizeof output); if (0 != ret) { result = TC_FAIL; goto exitTest; } ret = tc_ctr_prng_generate(0, 0, 0, 0, 0); if (0 != ret) { result = TC_FAIL; goto exitTest; } ret = tc_ctr_prng_reseed(&ctx, 0, 0, 0, 0); if (0 != ret) { result = TC_FAIL; goto exitTest; } /* too little entropy */ ret = tc_ctr_prng_reseed(&ctx, entropy, (sizeof entropy) - 1U, 0, 0); if (0 != ret) { result = TC_FAIL; goto exitTest; } ret = tc_ctr_prng_reseed(0, entropy, sizeof entropy, 0, 0); if (0 != ret) { result = TC_FAIL; goto exitTest; } ret = tc_ctr_prng_reseed(0, 0, 0, 0, 0); if (0 != ret) { result = TC_FAIL; goto exitTest; } ret = tc_ctr_prng_init(&ctx, 0, 0, 0, 0); if (0 != ret) { result = TC_FAIL; goto exitTest; } /* too little entropy */ ret = tc_ctr_prng_init(&ctx, entropy, (sizeof entropy) - 1U, 0, 0); if (0 != ret) { result = TC_FAIL; goto exitTest; } ret = tc_ctr_prng_init(0, entropy, sizeof entropy, 0, 0); if (0 != ret) { result = TC_FAIL; goto exitTest; } ret = tc_ctr_prng_init(0, 0, 0, 0, 0); if (0 != ret) { result = TC_FAIL; goto exitTest; } exitTest: if (TC_FAIL == result) { TC_ERROR("CTR PRNG reseed tests failed\n"); } return result; }
static int32_t test_reseed(void) { int32_t result = TC_PASS; uint8_t entropy[32U] = {0U}; /* value not important */ uint8_t additional_input[32] = {0U}; uint8_t output[32]; TCCtrPrng_t ctx; int32_t ret; uint32_t i; (void)tc_ctr_prng_init(&ctx, entropy, sizeof entropy, 0, 0U); /* force internal state to max allowed count */ ctx.reseedCount = 0x1000000000000ULL; ret = tc_ctr_prng_generate(&ctx, 0, 0, output, sizeof output); if (1 != ret) { result = TC_FAIL; goto exitTest; } /* expect further attempts to fail due to reaching reseed threshold */ ret = tc_ctr_prng_generate(&ctx, 0, 0, output, sizeof output); if (-1 != ret) { result = TC_FAIL; goto exitTest; } /* reseed and confirm generate works again */ /* make entropy different from original value - not really important for the purpose of this test */ memset(entropy, 0xFF, sizeof entropy); ret = tc_ctr_prng_reseed(&ctx, entropy, sizeof entropy, additional_input, sizeof additional_input); if (1 != ret) { result = TC_FAIL; goto exitTest; } ret = tc_ctr_prng_generate(&ctx, 0, 0, output, sizeof output); if (1 != ret) { result = TC_FAIL; goto exitTest; } /* confirm entropy and additional_input are being used correctly */ /* first, entropy only */ memset(&ctx, 0x0, sizeof ctx); for (i = 0U; i < sizeof entropy; i++) { entropy[i] = i; } ret = tc_ctr_prng_reseed(&ctx, entropy, sizeof entropy, 0, 0U); if (1 != ret) { result = TC_FAIL; goto exitTest; } { uint8_t expectedV[] = {0x7EU, 0xE3U, 0xA0U, 0xCBU, 0x6DU, 0x5CU, 0x4BU, 0xC2U, 0x4BU, 0x7EU, 0x3CU, 0x48U, 0x88U, 0xC3U, 0x69U, 0x70U}; for (i = 0U; i < sizeof expectedV; i++) { if (ctx.V[i] != expectedV[i]) { result = TC_FAIL; goto exitTest; } } } /* now, entropy and additional_input */ memset(&ctx, 0x0, sizeof ctx); for (i = 0U; i < sizeof additional_input; i++) { additional_input[i] = i * 2U; } ret = tc_ctr_prng_reseed(&ctx, entropy, sizeof entropy, additional_input, sizeof additional_input); if (1 != ret) { result = TC_FAIL; goto exitTest; } { uint8_t expectedV[] = {0x5EU, 0xC1U, 0x84U, 0xEDU, 0x45U, 0x76U, 0x67U, 0xECU, 0x7BU, 0x4CU, 0x08U, 0x7EU, 0xB0U, 0xF9U, 0x55U, 0x4EU}; for (i = 0U; i < sizeof expectedV; i++) { if (ctx.V[i] != expectedV[i]) { result = TC_FAIL; goto exitTest; } } } exitTest: if (TC_FAIL == result) { TC_ERROR("CTR PRNG reseed tests failed\n"); } return result; }
static uint32_t executePRNG_TestVector(PRNG_Vector vector, uint32_t idx) { uint32_t result = TC_PASS; uint8_t * entropy = hexStringToBytes(vector.entropyString); uint32_t entropylen = strlen(vector.entropyString) / 2U; uint8_t * expected = hexStringToBytes(vector.expectedString); uint32_t expectedlen = strlen(vector.expectedString) / 2U; uint8_t * personalization = 0; uint32_t plen = 0U; uint8_t * additional_input1 = 0; uint32_t additionallen1 = 0U; uint8_t * additional_input2 = 0; uint32_t additionallen2 = 0U; uint8_t * output = (uint8_t *)malloc(expectedlen); uint32_t i; TCCtrPrng_t ctx; if (0 != vector.personalizationString) { personalization = hexStringToBytes(vector.personalizationString); plen = strlen(vector.personalizationString) / 2U; } if (0 != vector.additionalInputString1) { additional_input1 = hexStringToBytes(vector.additionalInputString1); additionallen1 = strlen(vector.additionalInputString1) / 2U; } if (0 != vector.additionalInputString2) { additional_input2 = hexStringToBytes(vector.additionalInputString2); additionallen2 = strlen(vector.additionalInputString2) / 2U; } (void)tc_ctr_prng_init(&ctx, entropy, entropylen, personalization, plen); (void)tc_ctr_prng_generate(&ctx, additional_input1, additionallen1, output, expectedlen); (void)tc_ctr_prng_generate(&ctx, additional_input2, additionallen2, output, expectedlen); for (i = 0U; i < expectedlen; i++) { if (output[i] != expected[i]) { TC_ERROR("CTR PRNG test #%d failed\n", idx); result = TC_FAIL; break; } } free(entropy); free(expected); free(personalization); free(additional_input1); free(additional_input2); free(output); return result; }