msm_fips_selftest.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. /*
  2. * Copyright (c) 2014, The Linux Foundation. All rights reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2 and
  6. * only version 2 as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. */
  13. #include <linux/kernel.h>
  14. #include <linux/module.h>
  15. #include <linux/slab.h>
  16. #include <linux/string.h>
  17. #include "fips_drbg.h"
  18. #include "ctr_drbg.h"
  19. #include "msm_rng.h"
  20. #include "msm_fips_selftest.h"
  21. #define CTRAES128_ENTROPY_BYTES (16)
  22. #define CTRAES128_NONCE_BYTES (8)
  23. #define CTRAES128_MAX_OUTPUT_BYTES (64)
  24. struct ctr_drbg_testcase_s {
  25. char *name;
  26. char *entropy_string;
  27. char *nonce_string;
  28. char *reseed_entropy_string;
  29. char *expected_string;
  30. };
  31. static struct ctr_drbg_testcase_s t0 = {
  32. .name = "use_pr_0",
  33. .entropy_string = "\x8f\xb9\x57\x3a\x54\x62\x53\xcd"
  34. "\xbf\x62\x15\xa1\x80\x5a\x41\x38",
  35. .nonce_string = "\x7c\x2c\xe6\x54\x02\xbc\xa6\x83",
  36. .reseed_entropy_string = "\xbc\x5a\xd8\x9a\xe1\x8c\x49\x1f"
  37. "\x90\xa2\xae\x9e\x7e\x2c\xf9\x9d",
  38. .expected_string = "\x07\x62\x82\xe8\x0e\x65\xd7\x70"
  39. "\x1a\x35\xb3\x44\x63\x68\xb6\x16"
  40. "\xf8\xd9\x62\x23\xb9\xb5\x11\x64"
  41. "\x23\xa3\xa2\x32\xc7\x2c\xea\xbf"
  42. "\x4a\xcc\xc4\x0a\xc6\x19\xd6\xaa"
  43. "\x68\xae\xdb\x8b\x26\x70\xb8\x07"
  44. "\xcc\xe9\x9f\xc2\x1b\x8f\xa5\x16"
  45. "\xef\x75\xb6\x8f\xc0\x6c\x87\xc7",
  46. };
  47. static struct ctr_drbg_testcase_s t1 = {
  48. .name = "use_pr_1",
  49. .entropy_string = "\xa3\x56\xf3\x9a\xce\x48\x59\xb1"
  50. "\xe1\x99\x49\x40\x22\x8e\xa4\xeb",
  51. .nonce_string = "\xff\x33\xe9\x51\x39\xf7\x67\xf1",
  52. .reseed_entropy_string = "\x66\x8f\x0f\xe2\xd8\xa9\xa9\x29"
  53. "\x20\xfc\xb9\xf3\x55\xd6\xc3\x4c",
  54. .expected_string = "\xa1\x06\x61\x65\x7b\x98\x0f\xac"
  55. "\xce\x77\x91\xde\x7f\x6f\xe6\x1e"
  56. "\x88\x15\xe5\xe2\x4c\xce\xb8\xa6"
  57. "\x63\xf2\xe8\x2f\x5b\xfb\x16\x92"
  58. "\x06\x2a\xf3\xa8\x59\x05\xe0\x5a"
  59. "\x92\x9a\x07\x65\xc7\x41\x29\x3a"
  60. "\x4b\x1d\x15\x3e\x02\x14\x7b\xdd"
  61. "\x74\x5e\xbd\x70\x07\x4d\x6c\x08",
  62. };
  63. static struct ctr_drbg_testcase_s *testlist[] = {
  64. &t0, &t1
  65. };
  66. static int allzeroP(void *p, size_t len)
  67. {
  68. size_t i;
  69. for (i = 0; i < len; ++i)
  70. if (((uint8_t *)p)[i] != 0)
  71. return 0;
  72. return 1;
  73. }
  74. /*
  75. * basic test. return value is error count.
  76. */
  77. int fips_ctraes128_df_known_answer_test(struct ctr_debg_test_inputs_s *tcase)
  78. {
  79. struct ctr_drbg_ctx_s ctx;
  80. enum ctr_drbg_status_t rv;
  81. if (tcase->observed_string_len > CTRAES128_MAX_OUTPUT_BYTES) {
  82. pr_debug("known answer test output is bigger than 64!\n");
  83. return 1;
  84. }
  85. memset(&ctx, 0, sizeof(ctx));
  86. ctx.continuous_test_started = 1;
  87. rv = ctr_drbg_instantiate(&ctx,
  88. tcase->entropy_string,
  89. 8 * CTRAES128_ENTROPY_BYTES,
  90. tcase->nonce_string,
  91. 8 * CTRAES128_NONCE_BYTES,
  92. 1<<19);
  93. if (rv != CTR_DRBG_SUCCESS) {
  94. pr_err("test instantiate failed with code %d\n", rv);
  95. return 1;
  96. }
  97. rv = ctr_drbg_reseed(&ctx,
  98. tcase->reseed_entropy_string,
  99. 8 * CTRAES128_ENTROPY_BYTES);
  100. if (rv != CTR_DRBG_SUCCESS) {
  101. pr_err("test reseed failed with code %d\n", rv);
  102. return 1;
  103. }
  104. rv = ctr_drbg_generate(&ctx,
  105. tcase->observed_string,
  106. tcase->observed_string_len * 8);
  107. if (rv != CTR_DRBG_SUCCESS) {
  108. pr_err("test generate (2) failed with code %d\n", rv);
  109. return 1;
  110. }
  111. rv = ctr_drbg_generate(&ctx,
  112. tcase->observed_string,
  113. tcase->observed_string_len * 8);
  114. if (rv != CTR_DRBG_SUCCESS) {
  115. pr_err("test generate (2) failed with code %d\n", rv);
  116. return 1;
  117. }
  118. ctr_drbg_uninstantiate(&ctx);
  119. if (!allzeroP(&ctx.seed, sizeof(ctx.seed))) {
  120. pr_err("test Final failed to zeroize the context\n");
  121. return 1;
  122. }
  123. pr_info("\n DRBG counter test done");
  124. return 0;
  125. }
  126. static int fips_drbg_healthcheck_sanitytest(void)
  127. {
  128. struct ctr_drbg_ctx_s *p_ctx = NULL;
  129. enum ctr_drbg_status_t rv = CTR_DRBG_SUCCESS;
  130. char entropy_string[MSM_ENTROPY_BUFFER_SIZE];
  131. char nonce[MSM_NONCE_BUFFER_SIZE];
  132. char buffer[32];
  133. pr_info("start DRBG health check sanity test.\n");
  134. p_ctx = kzalloc(sizeof(struct ctr_drbg_ctx_s), GFP_KERNEL);
  135. if (NULL == p_ctx) {
  136. rv = CTR_DRBG_GENERAL_ERROR;
  137. pr_err("p_ctx kzalloc fail\n");
  138. goto outbuf;
  139. }
  140. /*
  141. * test DRGB Instantiaion function error handling.
  142. * Sends a NULL pointer as DTR-DRBG context.
  143. */
  144. rv = ctr_drbg_instantiate(NULL,
  145. entropy_string,
  146. 8 * CTRAES128_ENTROPY_BYTES,
  147. nonce,
  148. 8 * CTRAES128_NONCE_BYTES,
  149. 1<<19);
  150. if (CTR_DRBG_SUCCESS == rv) {
  151. rv = CTR_DRBG_INVALID_ARG;
  152. pr_err("failed to handle NULL pointer of CTR context\n");
  153. goto outbuf;
  154. }
  155. /*
  156. * test DRGB Instantiaion function error handling.
  157. * Sends a NULL pointer as entropy input.
  158. */
  159. rv = ctr_drbg_instantiate(p_ctx,
  160. NULL,
  161. 8 * CTRAES128_ENTROPY_BYTES,
  162. nonce,
  163. 8 * CTRAES128_NONCE_BYTES,
  164. 1<<19);
  165. if (CTR_DRBG_SUCCESS == rv) {
  166. rv = CTR_DRBG_INVALID_ARG;
  167. pr_err("failed to handle NULL pointer of entropy string\n");
  168. goto outbuf;
  169. }
  170. rv = ctr_drbg_instantiate(p_ctx,
  171. entropy_string,
  172. 8 * CTRAES128_ENTROPY_BYTES,
  173. NULL,
  174. 8 * CTRAES128_NONCE_BYTES,
  175. 1<<19);
  176. if (CTR_DRBG_SUCCESS == rv) {
  177. rv = CTR_DRBG_INVALID_ARG;
  178. pr_err("failed to handle NULL pointer of nonce string\n");
  179. goto outbuf;
  180. }
  181. /*
  182. * test DRGB Instantiaion function error handling.
  183. * Sends very long seed length.
  184. */
  185. rv = ctr_drbg_instantiate(p_ctx,
  186. entropy_string,
  187. 8 * CTRAES128_ENTROPY_BYTES,
  188. nonce,
  189. 32 * CTRAES128_NONCE_BYTES,
  190. 1<<19);
  191. if (CTR_DRBG_SUCCESS == rv) {
  192. rv = CTR_DRBG_INVALID_ARG;
  193. pr_err("failed to handle incorrect seed size\n");
  194. goto outbuf;
  195. }
  196. rv = ctr_drbg_instantiate(p_ctx,
  197. entropy_string,
  198. 8 * CTRAES128_ENTROPY_BYTES,
  199. nonce,
  200. 8 * CTRAES128_NONCE_BYTES,
  201. 1<<19);
  202. if (CTR_DRBG_SUCCESS != rv) {
  203. pr_err("Instantiation failed to handle CTR-DRBG instance\n");
  204. goto outbuf;
  205. }
  206. /*
  207. * test DRGB generator function error handling.
  208. * set output string as NULL.
  209. */
  210. rv = ctr_drbg_generate(p_ctx, NULL, 256);
  211. if (CTR_DRBG_SUCCESS == rv) {
  212. pr_err("failed to handle incorrect buffer pointer\n");
  213. rv = CTR_DRBG_INVALID_ARG;
  214. goto outdrbg;
  215. }
  216. rv = ctr_drbg_generate(p_ctx, &buffer, 1 << 20);
  217. if (CTR_DRBG_SUCCESS == rv) {
  218. pr_err("failed to handle too long output length\n");
  219. rv = CTR_DRBG_INVALID_ARG;
  220. goto outdrbg;
  221. }
  222. rv = ctr_drbg_generate(p_ctx, &buffer, 177);
  223. if (CTR_DRBG_SUCCESS == rv) {
  224. pr_err("failed to handle incorrect output length\n");
  225. rv = CTR_DRBG_INVALID_ARG;
  226. goto outdrbg;
  227. }
  228. pr_info("DRBG health check sanity test passed.\n");
  229. rv = CTR_DRBG_SUCCESS;
  230. outdrbg:
  231. ctr_drbg_uninstantiate(p_ctx);
  232. outbuf:
  233. if (p_ctx)
  234. kzfree(p_ctx);
  235. p_ctx = NULL;
  236. memset(buffer, 0, 32);
  237. memset(nonce, 0, MSM_NONCE_BUFFER_SIZE);
  238. memset(entropy_string, 0, MSM_ENTROPY_BUFFER_SIZE);
  239. return rv;
  240. }
  241. int fips_self_test(void)
  242. {
  243. struct ctr_debg_test_inputs_s cavs_input;
  244. uint8_t entropy[CTRAES128_ENTROPY_BYTES];
  245. uint8_t nonce[CTRAES128_NONCE_BYTES];
  246. uint8_t reseed_entropy[CTRAES128_ENTROPY_BYTES];
  247. uint8_t expected[CTRAES128_MAX_OUTPUT_BYTES];
  248. uint8_t observed[CTRAES128_MAX_OUTPUT_BYTES];
  249. unsigned int i;
  250. int errors = 0;
  251. int ret;
  252. cavs_input.entropy_string = entropy;
  253. cavs_input.nonce_string = nonce;
  254. cavs_input.reseed_entropy_string = reseed_entropy;
  255. cavs_input.observed_string = observed;
  256. cavs_input.observed_string_len = CTRAES128_MAX_OUTPUT_BYTES;
  257. ret = fips_drbg_healthcheck_sanitytest();
  258. if (CTR_DRBG_SUCCESS != ret) {
  259. pr_err("DRBG health check fail\n");
  260. errors++;
  261. return errors;
  262. }
  263. for (i = 0;
  264. i < sizeof(testlist)/sizeof(struct ctr_drbg_testcase_s *);
  265. ++i) {
  266. memcpy(entropy,
  267. testlist[i]->entropy_string,
  268. CTRAES128_ENTROPY_BYTES);
  269. memcpy(nonce,
  270. testlist[i]->nonce_string,
  271. CTRAES128_NONCE_BYTES);
  272. memcpy(reseed_entropy,
  273. testlist[i]->reseed_entropy_string,
  274. CTRAES128_ENTROPY_BYTES);
  275. memcpy(expected,
  276. testlist[i]->expected_string,
  277. CTRAES128_MAX_OUTPUT_BYTES);
  278. pr_debug("starting test %s\n", testlist[i]->name);
  279. ret = fips_ctraes128_df_known_answer_test(&cavs_input);
  280. pr_debug("completed test %s\n\n", testlist[i]->name);
  281. if (0 != ret) {
  282. pr_debug("got error from drbg known answer test!\n");
  283. return 1;
  284. }
  285. if (memcmp(expected,
  286. cavs_input.observed_string,
  287. CTRAES128_MAX_OUTPUT_BYTES) != 0) {
  288. errors++;
  289. pr_info("%s: generate failed\n", testlist[i]->name);
  290. return 1;
  291. } else
  292. pr_info("%s: generate PASSED!\n", testlist[i]->name);
  293. }
  294. if (errors == 0)
  295. pr_debug("All tests passed\n");
  296. else
  297. pr_debug("%d tests failed\n", errors);
  298. return errors;
  299. }