qcedev_fips.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. /* FIPS Known answer tests for QCEDEV / FIPS-non-FIPS separation .
  2. *
  3. * Copyright (c) 2014, The Linux Foundation. All rights reserved.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 and
  7. * only version 2 as published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. */
  15. #include <linux/mman.h>
  16. #include <linux/types.h>
  17. #include <linux/export.h>
  18. #include <linux/qcedev.h>
  19. #include "qcedevi.h"
  20. #include "qcedev_fips.h"
  21. /*
  22. * Initiate the session handle (like open /dev/qce)
  23. */
  24. static int _fips_initiate_qcedev_handle(struct qcedev_control *podev,
  25. struct qcedev_async_req *qcedev_areq)
  26. {
  27. struct qcedev_handle *handle;
  28. handle = kzalloc(sizeof(struct qcedev_handle), GFP_KERNEL);
  29. if (handle == NULL) {
  30. pr_err("Failed to allocate memory %ld\n", PTR_ERR(handle));
  31. return -ENOMEM;
  32. }
  33. handle->cntl = podev;
  34. qcedev_areq->handle = handle;
  35. return 0;
  36. }
  37. /*
  38. *Initiate QCEDEV request for sha/hmac
  39. */
  40. static
  41. int _fips_initiate_qcedev_async_req_sha(struct qcedev_async_req *qcedev_areq,
  42. struct scatterlist *fips_sg,
  43. int tv_index)
  44. {
  45. qcedev_areq->sha_op_req.alg =
  46. fips_test_vector_sha_hmac[tv_index].hash_alg;
  47. /* If HMAC setup key else make key length zero */
  48. if ((qcedev_areq->sha_op_req.alg == QCEDEV_ALG_SHA1_HMAC) ||
  49. (qcedev_areq->sha_op_req.alg == QCEDEV_ALG_SHA256_HMAC) ||
  50. (qcedev_areq->sha_op_req.alg == QCEDEV_ALG_AES_CMAC)) {
  51. qcedev_areq->sha_op_req.authkey =
  52. &fips_test_vector_sha_hmac[tv_index].key[0];
  53. qcedev_areq->sha_op_req.authklen =
  54. fips_test_vector_sha_hmac[tv_index].klen;
  55. } else
  56. qcedev_areq->sha_op_req.authklen = 0;
  57. /* Setup input and digest */
  58. qcedev_areq->sha_op_req.data[0].vaddr =
  59. &fips_test_vector_sha_hmac[tv_index].input[0];
  60. qcedev_areq->sha_op_req.data[0].len =
  61. fips_test_vector_sha_hmac[tv_index].ilen;
  62. qcedev_areq->sha_op_req.data_len =
  63. fips_test_vector_sha_hmac[tv_index].ilen;
  64. /* Setup sha context and other parameters */
  65. qcedev_areq->sha_op_req.entries = 1;
  66. qcedev_areq->op_type = QCEDEV_CRYPTO_OPER_SHA;
  67. memset(&qcedev_areq->handle->sha_ctxt, 0,
  68. sizeof(struct qcedev_sha_ctxt));
  69. qcedev_areq->handle->sha_ctxt.first_blk = 1;
  70. /* Initialize digest and digest length */
  71. memset(&qcedev_areq->sha_op_req.digest[0], 0, QCEDEV_MAX_SHA_DIGEST);
  72. qcedev_areq->sha_op_req.diglen =
  73. fips_test_vector_sha_hmac[tv_index].diglen;
  74. switch (qcedev_areq->sha_op_req.alg) {
  75. case QCEDEV_ALG_SHA1:
  76. case QCEDEV_ALG_SHA1_HMAC:
  77. memcpy(&qcedev_areq->handle->sha_ctxt.digest[0],
  78. &_std_init_vector_sha1_uint8[0],
  79. SHA1_DIGEST_SIZE);
  80. break;
  81. case QCEDEV_ALG_SHA256:
  82. case QCEDEV_ALG_SHA256_HMAC:
  83. memcpy(&qcedev_areq->handle->sha_ctxt.digest[0],
  84. &_std_init_vector_sha256_uint8[0],
  85. SHA256_DIGEST_SIZE);
  86. break;
  87. case QCEDEV_ALG_AES_CMAC:
  88. qcedev_areq->handle->sha_ctxt.diglen =
  89. fips_test_vector_sha_hmac[tv_index].diglen;
  90. break;
  91. default:
  92. pr_err(" _fips_initiate_qcedev_async_req_sha : Invalid algo");
  93. return -EINVAL;
  94. }
  95. qcedev_areq->handle->sha_ctxt.init_done = true;
  96. qcedev_areq->handle->sha_ctxt.trailing_buf_len =
  97. qcedev_areq->sha_op_req.data_len;
  98. memcpy(&qcedev_areq->handle->sha_ctxt.trailing_buf[0],
  99. fips_test_vector_sha_hmac[tv_index].input,
  100. fips_test_vector_sha_hmac[tv_index].ilen);
  101. qcedev_areq->handle->sha_ctxt.last_blk = 1;
  102. qcedev_areq->sha_req.sreq.nbytes = qcedev_areq->sha_op_req.data_len;
  103. qcedev_areq->sha_req.cookie = qcedev_areq->handle;
  104. qcedev_areq->sha_req.sreq.src = fips_sg;
  105. sg_set_buf(qcedev_areq->sha_req.sreq.src,
  106. &qcedev_areq->handle->sha_ctxt.trailing_buf[0],
  107. qcedev_areq->sha_op_req.data_len);
  108. sg_mark_end(qcedev_areq->sha_req.sreq.src);
  109. return 0;
  110. }
  111. /*
  112. * Clean up of sha context after request completion
  113. */
  114. static void _fips_clear_qcedev_handle(struct qcedev_sha_ctxt *sha_ctxt)
  115. {
  116. sha_ctxt->first_blk = 0;
  117. sha_ctxt->last_blk = 0;
  118. sha_ctxt->auth_data[0] = 0;
  119. sha_ctxt->auth_data[1] = 0;
  120. sha_ctxt->trailing_buf_len = 0;
  121. sha_ctxt->init_done = false;
  122. memset(&sha_ctxt->trailing_buf[0], 0, 64);
  123. }
  124. /*
  125. * Self test for SHA / HMAC
  126. */
  127. int _fips_qcedev_sha_selftest(struct qcedev_control *podev)
  128. {
  129. int ret = 0, tv_index, num_tv;
  130. struct qce_sha_req sreq;
  131. struct qcedev_async_req qcedev_areq;
  132. struct scatterlist fips_sg;
  133. /* Initiate handle */
  134. if (_fips_initiate_qcedev_handle(podev, &qcedev_areq))
  135. return -ENOMEM;
  136. num_tv = (sizeof(fips_test_vector_sha_hmac))/
  137. (sizeof(struct _fips_test_vector_sha_hmac));
  138. /* Tests one by one */
  139. for (tv_index = 0; tv_index < num_tv; tv_index++) {
  140. init_completion(&qcedev_areq.complete);
  141. /* Initiate the qcedev request */
  142. if (_fips_initiate_qcedev_async_req_sha(&qcedev_areq,
  143. &fips_sg, tv_index))
  144. return -EINVAL;
  145. podev->active_command = &qcedev_areq;
  146. /* Initiate qce hash request */
  147. sreq.qce_cb = qcedev_sha_req_cb;
  148. if (qcedev_areq.sha_op_req.alg != QCEDEV_ALG_AES_CMAC) {
  149. sreq.digest = &qcedev_areq.handle->sha_ctxt.digest[0];
  150. sreq.first_blk = qcedev_areq.handle->sha_ctxt.first_blk;
  151. sreq.last_blk = qcedev_areq.handle->sha_ctxt.last_blk;
  152. sreq.auth_data[0] =
  153. qcedev_areq.handle->sha_ctxt.auth_data[0];
  154. sreq.auth_data[1] =
  155. qcedev_areq.handle->sha_ctxt.auth_data[1];
  156. sreq.auth_data[2] =
  157. qcedev_areq.handle->sha_ctxt.auth_data[2];
  158. sreq.auth_data[3] =
  159. qcedev_areq.handle->sha_ctxt.auth_data[3];
  160. }
  161. sreq.size = qcedev_areq.sha_req.sreq.nbytes;
  162. sreq.src = qcedev_areq.sha_req.sreq.src;
  163. sreq.areq = (void *)&qcedev_areq.sha_req;
  164. sreq.flags = 0;
  165. switch (qcedev_areq.sha_op_req.alg) {
  166. case QCEDEV_ALG_SHA1:
  167. sreq.alg = QCE_HASH_SHA1;
  168. break;
  169. case QCEDEV_ALG_SHA256:
  170. sreq.alg = QCE_HASH_SHA256;
  171. break;
  172. case QCEDEV_ALG_SHA1_HMAC:
  173. sreq.alg = QCE_HASH_SHA1_HMAC;
  174. sreq.authkey = &qcedev_areq.sha_op_req.authkey[0];
  175. sreq.authklen = qcedev_areq.sha_op_req.authklen;
  176. break;
  177. case QCEDEV_ALG_SHA256_HMAC:
  178. sreq.alg = QCE_HASH_SHA256_HMAC;
  179. sreq.authkey =
  180. &qcedev_areq.sha_op_req.authkey[0];
  181. sreq.authklen =
  182. qcedev_areq.sha_op_req.authklen;
  183. break;
  184. case QCEDEV_ALG_AES_CMAC:
  185. sreq.alg = QCE_HASH_AES_CMAC;
  186. sreq.authkey =
  187. &qcedev_areq.sha_op_req.authkey[0];
  188. sreq.authklen =
  189. qcedev_areq.sha_op_req.authklen;
  190. break;
  191. default:
  192. ret = -EINVAL;
  193. goto handle_free;
  194. }
  195. /*qce call */
  196. ret = qce_process_sha_req(podev->qce, &sreq);
  197. if (ret == 0)
  198. wait_for_completion(&qcedev_areq.complete);
  199. else
  200. goto handle_free;
  201. /* Known answer test */
  202. if (memcmp(&qcedev_areq.handle->sha_ctxt.digest[0],
  203. fips_test_vector_sha_hmac[tv_index].digest,
  204. fips_test_vector_sha_hmac[tv_index].diglen)) {
  205. ret = -1;
  206. goto handle_free;
  207. }
  208. _fips_clear_qcedev_handle(&qcedev_areq.handle->sha_ctxt);
  209. }
  210. handle_free:
  211. kzfree(qcedev_areq.handle);
  212. return ret;
  213. }
  214. /*
  215. * Initiate QCEDEV request for cipher (Encryption/ Decryption requests)
  216. */
  217. static
  218. void _fips_initiate_qcedev_async_req_cipher(
  219. struct qcedev_async_req *qcedev_areq,
  220. enum qcedev_oper_enum qcedev_oper,
  221. struct scatterlist *fips_sg,
  222. uint8_t *k_align_src,
  223. int tv_index)
  224. {
  225. uint8_t *k_align_dst = k_align_src;
  226. /* Setup Key */
  227. memset(qcedev_areq->cipher_op_req.enckey, 0,
  228. fips_test_vector_cipher[tv_index].klen);
  229. memcpy(qcedev_areq->cipher_op_req.enckey,
  230. fips_test_vector_cipher[tv_index].key,
  231. fips_test_vector_cipher[tv_index].klen);
  232. qcedev_areq->cipher_op_req.encklen =
  233. fips_test_vector_cipher[tv_index].klen;
  234. /* Setup IV */
  235. memset(qcedev_areq->cipher_op_req.iv, 0,
  236. fips_test_vector_cipher[tv_index].ivlen);
  237. memcpy(qcedev_areq->cipher_op_req.iv,
  238. fips_test_vector_cipher[tv_index].iv,
  239. fips_test_vector_cipher[tv_index].ivlen);
  240. qcedev_areq->cipher_op_req.ivlen =
  241. fips_test_vector_cipher[tv_index].ivlen;
  242. /* Setup other parameters */
  243. qcedev_areq->cipher_op_req.byteoffset = 0;
  244. qcedev_areq->cipher_op_req.alg =
  245. fips_test_vector_cipher[tv_index].enc_alg;
  246. qcedev_areq->cipher_op_req.mode =
  247. fips_test_vector_cipher[tv_index].mode;
  248. qcedev_areq->cipher_op_req.use_pmem = 0;
  249. qcedev_areq->cipher_op_req.in_place_op = 1;
  250. qcedev_areq->cipher_op_req.entries = 1;
  251. qcedev_areq->cipher_op_req.op = qcedev_oper;
  252. qcedev_areq->op_type = QCEDEV_CRYPTO_OPER_CIPHER;
  253. /* Setup Input and output buffers */
  254. if (qcedev_oper == QCEDEV_OPER_ENC) {
  255. qcedev_areq->cipher_op_req.data_len =
  256. fips_test_vector_cipher[tv_index].pln_txt_len;
  257. qcedev_areq->cipher_op_req.vbuf.src[0].len =
  258. fips_test_vector_cipher[tv_index].pln_txt_len;
  259. } else {
  260. qcedev_areq->cipher_op_req.data_len =
  261. fips_test_vector_cipher[tv_index].enc_txt_len;
  262. qcedev_areq->cipher_op_req.vbuf.src[0].len =
  263. fips_test_vector_cipher[tv_index].enc_txt_len;
  264. }
  265. qcedev_areq->cipher_op_req.vbuf.src[0].vaddr =
  266. &k_align_src[0];
  267. qcedev_areq->cipher_op_req.vbuf.dst[0].vaddr =
  268. &k_align_dst[0];
  269. qcedev_areq->cipher_op_req.vbuf.dst[0].len =
  270. fips_test_vector_cipher[tv_index].enc_txt_len;
  271. qcedev_areq->cipher_req.creq.src = fips_sg;
  272. qcedev_areq->cipher_req.creq.dst = fips_sg;
  273. sg_set_buf(qcedev_areq->cipher_req.creq.src,
  274. k_align_src,
  275. qcedev_areq->cipher_op_req.data_len);
  276. sg_mark_end(qcedev_areq->cipher_req.creq.src);
  277. qcedev_areq->cipher_req.creq.nbytes =
  278. qcedev_areq->cipher_op_req.data_len;
  279. qcedev_areq->cipher_req.creq.info =
  280. qcedev_areq->cipher_op_req.iv;
  281. qcedev_areq->cipher_req.cookie = qcedev_areq->handle;
  282. }
  283. /*
  284. * Initiate QCE request for cipher (Encryption/ Decryption requests)
  285. */
  286. static int _fips_initiate_qce_req_cipher(struct qcedev_async_req *qcedev_areq,
  287. struct qce_req *creq,
  288. enum qce_cipher_dir_enum cipher_dir)
  289. {
  290. creq->dir = cipher_dir;
  291. creq->iv = &qcedev_areq->cipher_op_req.iv[0];
  292. creq->ivsize = qcedev_areq->cipher_op_req.ivlen;
  293. creq->enckey = &qcedev_areq->cipher_op_req.enckey[0];
  294. creq->encklen = qcedev_areq->cipher_op_req.encklen;
  295. creq->cryptlen = qcedev_areq->cipher_op_req.data_len;
  296. creq->op = QCE_REQ_ABLK_CIPHER;
  297. creq->qce_cb = qcedev_cipher_req_cb;
  298. creq->areq = (void *)&qcedev_areq->cipher_req;
  299. creq->flags = 0;
  300. switch (qcedev_areq->cipher_op_req.alg) {
  301. case QCEDEV_ALG_3DES:
  302. creq->alg = CIPHER_ALG_3DES;
  303. break;
  304. case QCEDEV_ALG_AES:
  305. creq->alg = CIPHER_ALG_AES;
  306. break;
  307. default:
  308. pr_err(" _fips_initiate_qce_req_cipher : Invalid algo");
  309. return -EINVAL;
  310. }
  311. switch (qcedev_areq->cipher_op_req.mode) {
  312. case QCEDEV_AES_MODE_CBC:
  313. case QCEDEV_DES_MODE_CBC:
  314. creq->mode = QCE_MODE_CBC;
  315. break;
  316. case QCEDEV_AES_MODE_ECB:
  317. case QCEDEV_DES_MODE_ECB:
  318. creq->mode = QCE_MODE_ECB;
  319. break;
  320. case QCEDEV_AES_MODE_CTR:
  321. creq->mode = QCE_MODE_CTR;
  322. break;
  323. case QCEDEV_AES_MODE_XTS:
  324. creq->mode = QCE_MODE_XTS;
  325. break;
  326. case QCEDEV_AES_MODE_CCM:
  327. creq->mode = QCE_MODE_CCM;
  328. break;
  329. default:
  330. pr_err(" _fips_initiate_qce_req_cipher : Invalid algo");
  331. return -EINVAL;
  332. }
  333. return 0;
  334. }
  335. /*
  336. * Self test for Cipher algorithms
  337. */
  338. int _fips_qcedev_cipher_selftest(struct qcedev_control *podev)
  339. {
  340. int ret = 0, tv_index = 0, num_tv;
  341. struct qcedev_async_req qcedev_areq;
  342. struct qce_req creq;
  343. struct scatterlist fips_sg;
  344. uint8_t *k_align_src = NULL;
  345. /* initiate handle */
  346. if (_fips_initiate_qcedev_handle(podev, &qcedev_areq))
  347. return -ENOMEM;
  348. num_tv = (sizeof(fips_test_vector_cipher)) /
  349. (sizeof(struct _fips_test_vector_cipher));
  350. /* tests one by one */
  351. for (tv_index = 0; tv_index < num_tv; tv_index++) {
  352. /* Allocate single buffer for in-place operation */
  353. k_align_src = kzalloc(QCE_MAX_OPER_DATA, GFP_KERNEL);
  354. if (k_align_src == NULL) {
  355. pr_err("qcedev: Failed to allocate memory for k_align_src %ld\n",
  356. PTR_ERR(k_align_src));
  357. kzfree(qcedev_areq.handle);
  358. return -ENOMEM;
  359. }
  360. /**************** Encryption Tests *****************/
  361. init_completion(&qcedev_areq.complete);
  362. memcpy(&k_align_src[0],
  363. fips_test_vector_cipher[tv_index].pln_txt,
  364. fips_test_vector_cipher[tv_index].pln_txt_len);
  365. /* Initiate qcedev request */
  366. _fips_initiate_qcedev_async_req_cipher(&qcedev_areq,
  367. QCEDEV_OPER_ENC, &fips_sg,
  368. k_align_src, tv_index);
  369. podev->active_command = &qcedev_areq;
  370. /* Initiate qce cipher request */
  371. if (_fips_initiate_qce_req_cipher(&qcedev_areq,
  372. &creq, QCE_ENCRYPT)) {
  373. ret = -EINVAL;
  374. kzfree(k_align_src);
  375. goto free_handle;
  376. }
  377. /* qce call */
  378. ret = qce_ablk_cipher_req(podev->qce, &creq);
  379. if (ret == 0)
  380. wait_for_completion(&qcedev_areq.complete);
  381. else {
  382. kzfree(k_align_src);
  383. goto free_handle;
  384. }
  385. /* Known answer test for encryption */
  386. if (memcmp(k_align_src,
  387. fips_test_vector_cipher[tv_index].enc_txt,
  388. fips_test_vector_cipher[tv_index].enc_txt_len)) {
  389. ret = -1;
  390. kzfree(k_align_src);
  391. goto free_handle;
  392. }
  393. /**************** Decryption Tests *****************/
  394. init_completion(&qcedev_areq.complete);
  395. memset(&k_align_src[0], 0,
  396. fips_test_vector_cipher[tv_index].pln_txt_len);
  397. memcpy(&k_align_src[0],
  398. fips_test_vector_cipher[tv_index].enc_txt,
  399. fips_test_vector_cipher[tv_index].enc_txt_len);
  400. /* Initiate qcedev request */
  401. _fips_initiate_qcedev_async_req_cipher(&qcedev_areq,
  402. QCEDEV_OPER_DEC, &fips_sg,
  403. k_align_src, tv_index);
  404. podev->active_command = &qcedev_areq;
  405. /*Initiate qce cipher request */
  406. if (_fips_initiate_qce_req_cipher(&qcedev_areq,
  407. &creq, QCE_DECRYPT)) {
  408. ret = -EINVAL;
  409. kzfree(k_align_src);
  410. goto free_handle;
  411. }
  412. /* qce call */
  413. ret = qce_ablk_cipher_req(podev->qce, &creq);
  414. if (ret == 0)
  415. wait_for_completion(&qcedev_areq.complete);
  416. else {
  417. kzfree(k_align_src);
  418. goto free_handle;
  419. }
  420. /* Known answer test for Decryption */
  421. if (memcmp(k_align_src,
  422. fips_test_vector_cipher[tv_index].pln_txt,
  423. fips_test_vector_cipher[tv_index].pln_txt_len)) {
  424. ret = -1;
  425. kzfree(k_align_src);
  426. goto free_handle;
  427. }
  428. podev->active_command = NULL;
  429. kzfree(k_align_src);
  430. }
  431. free_handle:
  432. kzfree(qcedev_areq.handle);
  433. return ret;
  434. }
  435. void fips_reg_drbg_callback(void *src)
  436. {
  437. drbg_call_back = src;
  438. }
  439. EXPORT_SYMBOL(fips_reg_drbg_callback);