123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347 |
- /*
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/slab.h>
- #include <linux/string.h>
- #include "fips_drbg.h"
- #include "ctr_drbg.h"
- #include "msm_rng.h"
- #include "msm_fips_selftest.h"
- #define CTRAES128_ENTROPY_BYTES (16)
- #define CTRAES128_NONCE_BYTES (8)
- #define CTRAES128_MAX_OUTPUT_BYTES (64)
- struct ctr_drbg_testcase_s {
- char *name;
- char *entropy_string;
- char *nonce_string;
- char *reseed_entropy_string;
- char *expected_string;
- };
- static struct ctr_drbg_testcase_s t0 = {
- .name = "use_pr_0",
- .entropy_string = "\x8f\xb9\x57\x3a\x54\x62\x53\xcd"
- "\xbf\x62\x15\xa1\x80\x5a\x41\x38",
- .nonce_string = "\x7c\x2c\xe6\x54\x02\xbc\xa6\x83",
- .reseed_entropy_string = "\xbc\x5a\xd8\x9a\xe1\x8c\x49\x1f"
- "\x90\xa2\xae\x9e\x7e\x2c\xf9\x9d",
- .expected_string = "\x07\x62\x82\xe8\x0e\x65\xd7\x70"
- "\x1a\x35\xb3\x44\x63\x68\xb6\x16"
- "\xf8\xd9\x62\x23\xb9\xb5\x11\x64"
- "\x23\xa3\xa2\x32\xc7\x2c\xea\xbf"
- "\x4a\xcc\xc4\x0a\xc6\x19\xd6\xaa"
- "\x68\xae\xdb\x8b\x26\x70\xb8\x07"
- "\xcc\xe9\x9f\xc2\x1b\x8f\xa5\x16"
- "\xef\x75\xb6\x8f\xc0\x6c\x87\xc7",
- };
- static struct ctr_drbg_testcase_s t1 = {
- .name = "use_pr_1",
- .entropy_string = "\xa3\x56\xf3\x9a\xce\x48\x59\xb1"
- "\xe1\x99\x49\x40\x22\x8e\xa4\xeb",
- .nonce_string = "\xff\x33\xe9\x51\x39\xf7\x67\xf1",
- .reseed_entropy_string = "\x66\x8f\x0f\xe2\xd8\xa9\xa9\x29"
- "\x20\xfc\xb9\xf3\x55\xd6\xc3\x4c",
- .expected_string = "\xa1\x06\x61\x65\x7b\x98\x0f\xac"
- "\xce\x77\x91\xde\x7f\x6f\xe6\x1e"
- "\x88\x15\xe5\xe2\x4c\xce\xb8\xa6"
- "\x63\xf2\xe8\x2f\x5b\xfb\x16\x92"
- "\x06\x2a\xf3\xa8\x59\x05\xe0\x5a"
- "\x92\x9a\x07\x65\xc7\x41\x29\x3a"
- "\x4b\x1d\x15\x3e\x02\x14\x7b\xdd"
- "\x74\x5e\xbd\x70\x07\x4d\x6c\x08",
- };
- static struct ctr_drbg_testcase_s *testlist[] = {
- &t0, &t1
- };
- static int allzeroP(void *p, size_t len)
- {
- size_t i;
- for (i = 0; i < len; ++i)
- if (((uint8_t *)p)[i] != 0)
- return 0;
- return 1;
- }
- /*
- * basic test. return value is error count.
- */
- int fips_ctraes128_df_known_answer_test(struct ctr_debg_test_inputs_s *tcase)
- {
- struct ctr_drbg_ctx_s ctx;
- enum ctr_drbg_status_t rv;
- if (tcase->observed_string_len > CTRAES128_MAX_OUTPUT_BYTES) {
- pr_debug("known answer test output is bigger than 64!\n");
- return 1;
- }
- memset(&ctx, 0, sizeof(ctx));
- ctx.continuous_test_started = 1;
- rv = ctr_drbg_instantiate(&ctx,
- tcase->entropy_string,
- 8 * CTRAES128_ENTROPY_BYTES,
- tcase->nonce_string,
- 8 * CTRAES128_NONCE_BYTES,
- 1<<19);
- if (rv != CTR_DRBG_SUCCESS) {
- pr_err("test instantiate failed with code %d\n", rv);
- return 1;
- }
- rv = ctr_drbg_reseed(&ctx,
- tcase->reseed_entropy_string,
- 8 * CTRAES128_ENTROPY_BYTES);
- if (rv != CTR_DRBG_SUCCESS) {
- pr_err("test reseed failed with code %d\n", rv);
- return 1;
- }
- rv = ctr_drbg_generate(&ctx,
- tcase->observed_string,
- tcase->observed_string_len * 8);
- if (rv != CTR_DRBG_SUCCESS) {
- pr_err("test generate (2) failed with code %d\n", rv);
- return 1;
- }
- rv = ctr_drbg_generate(&ctx,
- tcase->observed_string,
- tcase->observed_string_len * 8);
- if (rv != CTR_DRBG_SUCCESS) {
- pr_err("test generate (2) failed with code %d\n", rv);
- return 1;
- }
- ctr_drbg_uninstantiate(&ctx);
- if (!allzeroP(&ctx.seed, sizeof(ctx.seed))) {
- pr_err("test Final failed to zeroize the context\n");
- return 1;
- }
- pr_info("\n DRBG counter test done");
- return 0;
- }
- static int fips_drbg_healthcheck_sanitytest(void)
- {
- struct ctr_drbg_ctx_s *p_ctx = NULL;
- enum ctr_drbg_status_t rv = CTR_DRBG_SUCCESS;
- char entropy_string[MSM_ENTROPY_BUFFER_SIZE];
- char nonce[MSM_NONCE_BUFFER_SIZE];
- char buffer[32];
- pr_info("start DRBG health check sanity test.\n");
- p_ctx = kzalloc(sizeof(struct ctr_drbg_ctx_s), GFP_KERNEL);
- if (NULL == p_ctx) {
- rv = CTR_DRBG_GENERAL_ERROR;
- pr_err("p_ctx kzalloc fail\n");
- goto outbuf;
- }
- /*
- * test DRGB Instantiaion function error handling.
- * Sends a NULL pointer as DTR-DRBG context.
- */
- rv = ctr_drbg_instantiate(NULL,
- entropy_string,
- 8 * CTRAES128_ENTROPY_BYTES,
- nonce,
- 8 * CTRAES128_NONCE_BYTES,
- 1<<19);
- if (CTR_DRBG_SUCCESS == rv) {
- rv = CTR_DRBG_INVALID_ARG;
- pr_err("failed to handle NULL pointer of CTR context\n");
- goto outbuf;
- }
- /*
- * test DRGB Instantiaion function error handling.
- * Sends a NULL pointer as entropy input.
- */
- rv = ctr_drbg_instantiate(p_ctx,
- NULL,
- 8 * CTRAES128_ENTROPY_BYTES,
- nonce,
- 8 * CTRAES128_NONCE_BYTES,
- 1<<19);
- if (CTR_DRBG_SUCCESS == rv) {
- rv = CTR_DRBG_INVALID_ARG;
- pr_err("failed to handle NULL pointer of entropy string\n");
- goto outbuf;
- }
- rv = ctr_drbg_instantiate(p_ctx,
- entropy_string,
- 8 * CTRAES128_ENTROPY_BYTES,
- NULL,
- 8 * CTRAES128_NONCE_BYTES,
- 1<<19);
- if (CTR_DRBG_SUCCESS == rv) {
- rv = CTR_DRBG_INVALID_ARG;
- pr_err("failed to handle NULL pointer of nonce string\n");
- goto outbuf;
- }
- /*
- * test DRGB Instantiaion function error handling.
- * Sends very long seed length.
- */
- rv = ctr_drbg_instantiate(p_ctx,
- entropy_string,
- 8 * CTRAES128_ENTROPY_BYTES,
- nonce,
- 32 * CTRAES128_NONCE_BYTES,
- 1<<19);
- if (CTR_DRBG_SUCCESS == rv) {
- rv = CTR_DRBG_INVALID_ARG;
- pr_err("failed to handle incorrect seed size\n");
- goto outbuf;
- }
- rv = ctr_drbg_instantiate(p_ctx,
- entropy_string,
- 8 * CTRAES128_ENTROPY_BYTES,
- nonce,
- 8 * CTRAES128_NONCE_BYTES,
- 1<<19);
- if (CTR_DRBG_SUCCESS != rv) {
- pr_err("Instantiation failed to handle CTR-DRBG instance\n");
- goto outbuf;
- }
- /*
- * test DRGB generator function error handling.
- * set output string as NULL.
- */
- rv = ctr_drbg_generate(p_ctx, NULL, 256);
- if (CTR_DRBG_SUCCESS == rv) {
- pr_err("failed to handle incorrect buffer pointer\n");
- rv = CTR_DRBG_INVALID_ARG;
- goto outdrbg;
- }
- rv = ctr_drbg_generate(p_ctx, &buffer, 1 << 20);
- if (CTR_DRBG_SUCCESS == rv) {
- pr_err("failed to handle too long output length\n");
- rv = CTR_DRBG_INVALID_ARG;
- goto outdrbg;
- }
- rv = ctr_drbg_generate(p_ctx, &buffer, 177);
- if (CTR_DRBG_SUCCESS == rv) {
- pr_err("failed to handle incorrect output length\n");
- rv = CTR_DRBG_INVALID_ARG;
- goto outdrbg;
- }
- pr_info("DRBG health check sanity test passed.\n");
- rv = CTR_DRBG_SUCCESS;
- outdrbg:
- ctr_drbg_uninstantiate(p_ctx);
- outbuf:
- if (p_ctx)
- kzfree(p_ctx);
- p_ctx = NULL;
- memset(buffer, 0, 32);
- memset(nonce, 0, MSM_NONCE_BUFFER_SIZE);
- memset(entropy_string, 0, MSM_ENTROPY_BUFFER_SIZE);
- return rv;
- }
- int fips_self_test(void)
- {
- struct ctr_debg_test_inputs_s cavs_input;
- uint8_t entropy[CTRAES128_ENTROPY_BYTES];
- uint8_t nonce[CTRAES128_NONCE_BYTES];
- uint8_t reseed_entropy[CTRAES128_ENTROPY_BYTES];
- uint8_t expected[CTRAES128_MAX_OUTPUT_BYTES];
- uint8_t observed[CTRAES128_MAX_OUTPUT_BYTES];
- unsigned int i;
- int errors = 0;
- int ret;
- cavs_input.entropy_string = entropy;
- cavs_input.nonce_string = nonce;
- cavs_input.reseed_entropy_string = reseed_entropy;
- cavs_input.observed_string = observed;
- cavs_input.observed_string_len = CTRAES128_MAX_OUTPUT_BYTES;
- ret = fips_drbg_healthcheck_sanitytest();
- if (CTR_DRBG_SUCCESS != ret) {
- pr_err("DRBG health check fail\n");
- errors++;
- return errors;
- }
- for (i = 0;
- i < sizeof(testlist)/sizeof(struct ctr_drbg_testcase_s *);
- ++i) {
- memcpy(entropy,
- testlist[i]->entropy_string,
- CTRAES128_ENTROPY_BYTES);
- memcpy(nonce,
- testlist[i]->nonce_string,
- CTRAES128_NONCE_BYTES);
- memcpy(reseed_entropy,
- testlist[i]->reseed_entropy_string,
- CTRAES128_ENTROPY_BYTES);
- memcpy(expected,
- testlist[i]->expected_string,
- CTRAES128_MAX_OUTPUT_BYTES);
- pr_debug("starting test %s\n", testlist[i]->name);
- ret = fips_ctraes128_df_known_answer_test(&cavs_input);
- pr_debug("completed test %s\n\n", testlist[i]->name);
- if (0 != ret) {
- pr_debug("got error from drbg known answer test!\n");
- return 1;
- }
- if (memcmp(expected,
- cavs_input.observed_string,
- CTRAES128_MAX_OUTPUT_BYTES) != 0) {
- errors++;
- pr_info("%s: generate failed\n", testlist[i]->name);
- return 1;
- } else
- pr_info("%s: generate PASSED!\n", testlist[i]->name);
- }
- if (errors == 0)
- pr_debug("All tests passed\n");
- else
- pr_debug("%d tests failed\n", errors);
- return errors;
- }
|