PageRenderTime 78ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/drivers/crypto/cavium/nitrox/nitrox_algs.c

https://gitlab.com/oyvholm/linux
C | 458 lines | 391 code | 52 blank | 15 comment | 16 complexity | 5b897d24e23bf5b8af8101c72db316b9 MD5 | raw file
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/crypto.h>
  3. #include <linux/kernel.h>
  4. #include <linux/module.h>
  5. #include <linux/printk.h>
  6. #include <crypto/aes.h>
  7. #include <crypto/skcipher.h>
  8. #include <crypto/ctr.h>
  9. #include <crypto/des.h>
  10. #include <crypto/xts.h>
  11. #include "nitrox_dev.h"
  12. #include "nitrox_common.h"
  13. #include "nitrox_req.h"
  14. #define PRIO 4001
  15. struct nitrox_cipher {
  16. const char *name;
  17. enum flexi_cipher value;
  18. };
  19. /**
  20. * supported cipher list
  21. */
  22. static const struct nitrox_cipher flexi_cipher_table[] = {
  23. { "null", CIPHER_NULL },
  24. { "cbc(des3_ede)", CIPHER_3DES_CBC },
  25. { "ecb(des3_ede)", CIPHER_3DES_ECB },
  26. { "cbc(aes)", CIPHER_AES_CBC },
  27. { "ecb(aes)", CIPHER_AES_ECB },
  28. { "cfb(aes)", CIPHER_AES_CFB },
  29. { "rfc3686(ctr(aes))", CIPHER_AES_CTR },
  30. { "xts(aes)", CIPHER_AES_XTS },
  31. { "cts(cbc(aes))", CIPHER_AES_CBC_CTS },
  32. { NULL, CIPHER_INVALID }
  33. };
  34. static enum flexi_cipher flexi_cipher_type(const char *name)
  35. {
  36. const struct nitrox_cipher *cipher = flexi_cipher_table;
  37. while (cipher->name) {
  38. if (!strcmp(cipher->name, name))
  39. break;
  40. cipher++;
  41. }
  42. return cipher->value;
  43. }
  44. static int flexi_aes_keylen(int keylen)
  45. {
  46. int aes_keylen;
  47. switch (keylen) {
  48. case AES_KEYSIZE_128:
  49. aes_keylen = 1;
  50. break;
  51. case AES_KEYSIZE_192:
  52. aes_keylen = 2;
  53. break;
  54. case AES_KEYSIZE_256:
  55. aes_keylen = 3;
  56. break;
  57. default:
  58. aes_keylen = -EINVAL;
  59. break;
  60. }
  61. return aes_keylen;
  62. }
  63. static int nitrox_skcipher_init(struct crypto_skcipher *tfm)
  64. {
  65. struct nitrox_crypto_ctx *nctx = crypto_skcipher_ctx(tfm);
  66. void *fctx;
  67. /* get the first device */
  68. nctx->ndev = nitrox_get_first_device();
  69. if (!nctx->ndev)
  70. return -ENODEV;
  71. /* allocate nitrox crypto context */
  72. fctx = crypto_alloc_context(nctx->ndev);
  73. if (!fctx) {
  74. nitrox_put_device(nctx->ndev);
  75. return -ENOMEM;
  76. }
  77. nctx->u.ctx_handle = (uintptr_t)fctx;
  78. crypto_skcipher_set_reqsize(tfm, crypto_skcipher_reqsize(tfm) +
  79. sizeof(struct nitrox_kcrypt_request));
  80. return 0;
  81. }
  82. static void nitrox_skcipher_exit(struct crypto_skcipher *tfm)
  83. {
  84. struct nitrox_crypto_ctx *nctx = crypto_skcipher_ctx(tfm);
  85. /* free the nitrox crypto context */
  86. if (nctx->u.ctx_handle) {
  87. struct flexi_crypto_context *fctx = nctx->u.fctx;
  88. memset(&fctx->crypto, 0, sizeof(struct crypto_keys));
  89. memset(&fctx->auth, 0, sizeof(struct auth_keys));
  90. crypto_free_context((void *)fctx);
  91. }
  92. nitrox_put_device(nctx->ndev);
  93. nctx->u.ctx_handle = 0;
  94. nctx->ndev = NULL;
  95. }
  96. static inline int nitrox_skcipher_setkey(struct crypto_skcipher *cipher,
  97. int aes_keylen, const u8 *key,
  98. unsigned int keylen)
  99. {
  100. struct crypto_tfm *tfm = crypto_skcipher_tfm(cipher);
  101. struct nitrox_crypto_ctx *nctx = crypto_tfm_ctx(tfm);
  102. struct flexi_crypto_context *fctx;
  103. enum flexi_cipher cipher_type;
  104. const char *name;
  105. name = crypto_tfm_alg_name(tfm);
  106. cipher_type = flexi_cipher_type(name);
  107. if (unlikely(cipher_type == CIPHER_INVALID)) {
  108. pr_err("unsupported cipher: %s\n", name);
  109. return -EINVAL;
  110. }
  111. /* fill crypto context */
  112. fctx = nctx->u.fctx;
  113. fctx->flags = 0;
  114. fctx->w0.cipher_type = cipher_type;
  115. fctx->w0.aes_keylen = aes_keylen;
  116. fctx->w0.iv_source = IV_FROM_DPTR;
  117. fctx->flags = cpu_to_be64(*(u64 *)&fctx->w0);
  118. /* copy the key to context */
  119. memcpy(fctx->crypto.u.key, key, keylen);
  120. return 0;
  121. }
  122. static int nitrox_aes_setkey(struct crypto_skcipher *cipher, const u8 *key,
  123. unsigned int keylen)
  124. {
  125. int aes_keylen;
  126. aes_keylen = flexi_aes_keylen(keylen);
  127. if (aes_keylen < 0) {
  128. crypto_skcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
  129. return -EINVAL;
  130. }
  131. return nitrox_skcipher_setkey(cipher, aes_keylen, key, keylen);
  132. }
  133. static void nitrox_skcipher_callback(struct skcipher_request *skreq,
  134. int err)
  135. {
  136. if (err) {
  137. pr_err_ratelimited("request failed status 0x%0x\n", err);
  138. err = -EINVAL;
  139. }
  140. skcipher_request_complete(skreq, err);
  141. }
  142. static int nitrox_skcipher_crypt(struct skcipher_request *skreq, bool enc)
  143. {
  144. struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(skreq);
  145. struct nitrox_crypto_ctx *nctx = crypto_skcipher_ctx(cipher);
  146. struct nitrox_kcrypt_request *nkreq = skcipher_request_ctx(skreq);
  147. int ivsize = crypto_skcipher_ivsize(cipher);
  148. struct se_crypto_request *creq;
  149. creq = &nkreq->creq;
  150. creq->flags = skreq->base.flags;
  151. creq->gfp = (skreq->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
  152. GFP_KERNEL : GFP_ATOMIC;
  153. /* fill the request */
  154. creq->ctrl.value = 0;
  155. creq->opcode = FLEXI_CRYPTO_ENCRYPT_HMAC;
  156. creq->ctrl.s.arg = (enc ? ENCRYPT : DECRYPT);
  157. /* param0: length of the data to be encrypted */
  158. creq->gph.param0 = cpu_to_be16(skreq->cryptlen);
  159. creq->gph.param1 = 0;
  160. /* param2: encryption data offset */
  161. creq->gph.param2 = cpu_to_be16(ivsize);
  162. creq->gph.param3 = 0;
  163. creq->ctx_handle = nctx->u.ctx_handle;
  164. creq->ctrl.s.ctxl = sizeof(struct flexi_crypto_context);
  165. /* copy the iv */
  166. memcpy(creq->iv, skreq->iv, ivsize);
  167. creq->ivsize = ivsize;
  168. creq->src = skreq->src;
  169. creq->dst = skreq->dst;
  170. nkreq->nctx = nctx;
  171. nkreq->skreq = skreq;
  172. /* send the crypto request */
  173. return nitrox_process_se_request(nctx->ndev, creq,
  174. nitrox_skcipher_callback, skreq);
  175. }
  176. static int nitrox_aes_encrypt(struct skcipher_request *skreq)
  177. {
  178. return nitrox_skcipher_crypt(skreq, true);
  179. }
  180. static int nitrox_aes_decrypt(struct skcipher_request *skreq)
  181. {
  182. return nitrox_skcipher_crypt(skreq, false);
  183. }
  184. static int nitrox_3des_setkey(struct crypto_skcipher *cipher,
  185. const u8 *key, unsigned int keylen)
  186. {
  187. if (keylen != DES3_EDE_KEY_SIZE) {
  188. crypto_skcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
  189. return -EINVAL;
  190. }
  191. return nitrox_skcipher_setkey(cipher, 0, key, keylen);
  192. }
  193. static int nitrox_3des_encrypt(struct skcipher_request *skreq)
  194. {
  195. return nitrox_skcipher_crypt(skreq, true);
  196. }
  197. static int nitrox_3des_decrypt(struct skcipher_request *skreq)
  198. {
  199. return nitrox_skcipher_crypt(skreq, false);
  200. }
  201. static int nitrox_aes_xts_setkey(struct crypto_skcipher *cipher,
  202. const u8 *key, unsigned int keylen)
  203. {
  204. struct crypto_tfm *tfm = crypto_skcipher_tfm(cipher);
  205. struct nitrox_crypto_ctx *nctx = crypto_tfm_ctx(tfm);
  206. struct flexi_crypto_context *fctx;
  207. int aes_keylen, ret;
  208. ret = xts_check_key(tfm, key, keylen);
  209. if (ret)
  210. return ret;
  211. keylen /= 2;
  212. aes_keylen = flexi_aes_keylen(keylen);
  213. if (aes_keylen < 0) {
  214. crypto_skcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
  215. return -EINVAL;
  216. }
  217. fctx = nctx->u.fctx;
  218. /* copy KEY2 */
  219. memcpy(fctx->auth.u.key2, (key + keylen), keylen);
  220. return nitrox_skcipher_setkey(cipher, aes_keylen, key, keylen);
  221. }
  222. static int nitrox_aes_ctr_rfc3686_setkey(struct crypto_skcipher *cipher,
  223. const u8 *key, unsigned int keylen)
  224. {
  225. struct crypto_tfm *tfm = crypto_skcipher_tfm(cipher);
  226. struct nitrox_crypto_ctx *nctx = crypto_tfm_ctx(tfm);
  227. struct flexi_crypto_context *fctx;
  228. int aes_keylen;
  229. if (keylen < CTR_RFC3686_NONCE_SIZE)
  230. return -EINVAL;
  231. fctx = nctx->u.fctx;
  232. memcpy(fctx->crypto.iv, key + (keylen - CTR_RFC3686_NONCE_SIZE),
  233. CTR_RFC3686_NONCE_SIZE);
  234. keylen -= CTR_RFC3686_NONCE_SIZE;
  235. aes_keylen = flexi_aes_keylen(keylen);
  236. if (aes_keylen < 0) {
  237. crypto_skcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
  238. return -EINVAL;
  239. }
  240. return nitrox_skcipher_setkey(cipher, aes_keylen, key, keylen);
  241. }
  242. static struct skcipher_alg nitrox_skciphers[] = { {
  243. .base = {
  244. .cra_name = "cbc(aes)",
  245. .cra_driver_name = "n5_cbc(aes)",
  246. .cra_priority = PRIO,
  247. .cra_flags = CRYPTO_ALG_ASYNC,
  248. .cra_blocksize = AES_BLOCK_SIZE,
  249. .cra_ctxsize = sizeof(struct nitrox_crypto_ctx),
  250. .cra_alignmask = 0,
  251. .cra_module = THIS_MODULE,
  252. },
  253. .min_keysize = AES_MIN_KEY_SIZE,
  254. .max_keysize = AES_MAX_KEY_SIZE,
  255. .ivsize = AES_BLOCK_SIZE,
  256. .setkey = nitrox_aes_setkey,
  257. .encrypt = nitrox_aes_encrypt,
  258. .decrypt = nitrox_aes_decrypt,
  259. .init = nitrox_skcipher_init,
  260. .exit = nitrox_skcipher_exit,
  261. }, {
  262. .base = {
  263. .cra_name = "ecb(aes)",
  264. .cra_driver_name = "n5_ecb(aes)",
  265. .cra_priority = PRIO,
  266. .cra_flags = CRYPTO_ALG_ASYNC,
  267. .cra_blocksize = AES_BLOCK_SIZE,
  268. .cra_ctxsize = sizeof(struct nitrox_crypto_ctx),
  269. .cra_alignmask = 0,
  270. .cra_module = THIS_MODULE,
  271. },
  272. .min_keysize = AES_MIN_KEY_SIZE,
  273. .max_keysize = AES_MAX_KEY_SIZE,
  274. .ivsize = AES_BLOCK_SIZE,
  275. .setkey = nitrox_aes_setkey,
  276. .encrypt = nitrox_aes_encrypt,
  277. .decrypt = nitrox_aes_decrypt,
  278. .init = nitrox_skcipher_init,
  279. .exit = nitrox_skcipher_exit,
  280. }, {
  281. .base = {
  282. .cra_name = "cfb(aes)",
  283. .cra_driver_name = "n5_cfb(aes)",
  284. .cra_priority = PRIO,
  285. .cra_flags = CRYPTO_ALG_ASYNC,
  286. .cra_blocksize = AES_BLOCK_SIZE,
  287. .cra_ctxsize = sizeof(struct nitrox_crypto_ctx),
  288. .cra_alignmask = 0,
  289. .cra_module = THIS_MODULE,
  290. },
  291. .min_keysize = AES_MIN_KEY_SIZE,
  292. .max_keysize = AES_MAX_KEY_SIZE,
  293. .ivsize = AES_BLOCK_SIZE,
  294. .setkey = nitrox_aes_setkey,
  295. .encrypt = nitrox_aes_encrypt,
  296. .decrypt = nitrox_aes_decrypt,
  297. .init = nitrox_skcipher_init,
  298. .exit = nitrox_skcipher_exit,
  299. }, {
  300. .base = {
  301. .cra_name = "xts(aes)",
  302. .cra_driver_name = "n5_xts(aes)",
  303. .cra_priority = PRIO,
  304. .cra_flags = CRYPTO_ALG_ASYNC,
  305. .cra_blocksize = AES_BLOCK_SIZE,
  306. .cra_ctxsize = sizeof(struct nitrox_crypto_ctx),
  307. .cra_alignmask = 0,
  308. .cra_module = THIS_MODULE,
  309. },
  310. .min_keysize = 2 * AES_MIN_KEY_SIZE,
  311. .max_keysize = 2 * AES_MAX_KEY_SIZE,
  312. .ivsize = AES_BLOCK_SIZE,
  313. .setkey = nitrox_aes_xts_setkey,
  314. .encrypt = nitrox_aes_encrypt,
  315. .decrypt = nitrox_aes_decrypt,
  316. .init = nitrox_skcipher_init,
  317. .exit = nitrox_skcipher_exit,
  318. }, {
  319. .base = {
  320. .cra_name = "rfc3686(ctr(aes))",
  321. .cra_driver_name = "n5_rfc3686(ctr(aes))",
  322. .cra_priority = PRIO,
  323. .cra_flags = CRYPTO_ALG_ASYNC,
  324. .cra_blocksize = 1,
  325. .cra_ctxsize = sizeof(struct nitrox_crypto_ctx),
  326. .cra_alignmask = 0,
  327. .cra_module = THIS_MODULE,
  328. },
  329. .min_keysize = AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
  330. .max_keysize = AES_MAX_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
  331. .ivsize = CTR_RFC3686_IV_SIZE,
  332. .init = nitrox_skcipher_init,
  333. .exit = nitrox_skcipher_exit,
  334. .setkey = nitrox_aes_ctr_rfc3686_setkey,
  335. .encrypt = nitrox_aes_encrypt,
  336. .decrypt = nitrox_aes_decrypt,
  337. }, {
  338. .base = {
  339. .cra_name = "cts(cbc(aes))",
  340. .cra_driver_name = "n5_cts(cbc(aes))",
  341. .cra_priority = PRIO,
  342. .cra_flags = CRYPTO_ALG_ASYNC,
  343. .cra_blocksize = AES_BLOCK_SIZE,
  344. .cra_ctxsize = sizeof(struct nitrox_crypto_ctx),
  345. .cra_alignmask = 0,
  346. .cra_type = &crypto_ablkcipher_type,
  347. .cra_module = THIS_MODULE,
  348. },
  349. .min_keysize = AES_MIN_KEY_SIZE,
  350. .max_keysize = AES_MAX_KEY_SIZE,
  351. .ivsize = AES_BLOCK_SIZE,
  352. .setkey = nitrox_aes_setkey,
  353. .encrypt = nitrox_aes_encrypt,
  354. .decrypt = nitrox_aes_decrypt,
  355. .init = nitrox_skcipher_init,
  356. .exit = nitrox_skcipher_exit,
  357. }, {
  358. .base = {
  359. .cra_name = "cbc(des3_ede)",
  360. .cra_driver_name = "n5_cbc(des3_ede)",
  361. .cra_priority = PRIO,
  362. .cra_flags = CRYPTO_ALG_ASYNC,
  363. .cra_blocksize = DES3_EDE_BLOCK_SIZE,
  364. .cra_ctxsize = sizeof(struct nitrox_crypto_ctx),
  365. .cra_alignmask = 0,
  366. .cra_module = THIS_MODULE,
  367. },
  368. .min_keysize = DES3_EDE_KEY_SIZE,
  369. .max_keysize = DES3_EDE_KEY_SIZE,
  370. .ivsize = DES3_EDE_BLOCK_SIZE,
  371. .setkey = nitrox_3des_setkey,
  372. .encrypt = nitrox_3des_encrypt,
  373. .decrypt = nitrox_3des_decrypt,
  374. .init = nitrox_skcipher_init,
  375. .exit = nitrox_skcipher_exit,
  376. }, {
  377. .base = {
  378. .cra_name = "ecb(des3_ede)",
  379. .cra_driver_name = "n5_ecb(des3_ede)",
  380. .cra_priority = PRIO,
  381. .cra_flags = CRYPTO_ALG_ASYNC,
  382. .cra_blocksize = DES3_EDE_BLOCK_SIZE,
  383. .cra_ctxsize = sizeof(struct nitrox_crypto_ctx),
  384. .cra_alignmask = 0,
  385. .cra_module = THIS_MODULE,
  386. },
  387. .min_keysize = DES3_EDE_KEY_SIZE,
  388. .max_keysize = DES3_EDE_KEY_SIZE,
  389. .ivsize = DES3_EDE_BLOCK_SIZE,
  390. .setkey = nitrox_3des_setkey,
  391. .encrypt = nitrox_3des_encrypt,
  392. .decrypt = nitrox_3des_decrypt,
  393. .init = nitrox_skcipher_init,
  394. .exit = nitrox_skcipher_exit,
  395. }
  396. };
  397. int nitrox_crypto_register(void)
  398. {
  399. return crypto_register_skciphers(nitrox_skciphers,
  400. ARRAY_SIZE(nitrox_skciphers));
  401. }
  402. void nitrox_crypto_unregister(void)
  403. {
  404. crypto_unregister_skciphers(nitrox_skciphers,
  405. ARRAY_SIZE(nitrox_skciphers));
  406. }