xfrm_algo.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635
  1. /*
  2. * xfrm algorithm interface
  3. *
  4. * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License as published by the Free
  8. * Software Foundation; either version 2 of the License, or (at your option)
  9. * any later version.
  10. */
  11. #include <linux/module.h>
  12. #include <linux/kernel.h>
  13. #include <linux/pfkeyv2.h>
  14. #include <linux/crypto.h>
  15. #include <linux/scatterlist.h>
  16. #include <net/xfrm.h>
  17. #if defined(CONFIG_INET_AH) || defined(CONFIG_INET_AH_MODULE) || defined(CONFIG_INET6_AH) || defined(CONFIG_INET6_AH_MODULE)
  18. #include <net/ah.h>
  19. #endif
  20. #if defined(CONFIG_INET_ESP) || defined(CONFIG_INET_ESP_MODULE) || defined(CONFIG_INET6_ESP) || defined(CONFIG_INET6_ESP_MODULE)
  21. #include <net/esp.h>
  22. #endif
  23. #include <asm/scatterlist.h>
  24. /*
  25. * Algorithms supported by IPsec. These entries contain properties which
  26. * are used in key negotiation and xfrm processing, and are used to verify
  27. * that instantiated crypto transforms have correct parameters for IPsec
  28. * purposes.
  29. */
  30. static struct xfrm_algo_desc aalg_list[] = {
  31. {
  32. .name = "hmac(digest_null)",
  33. .compat = "digest_null",
  34. .uinfo = {
  35. .auth = {
  36. .icv_truncbits = 0,
  37. .icv_fullbits = 0,
  38. }
  39. },
  40. .desc = {
  41. .sadb_alg_id = SADB_X_AALG_NULL,
  42. .sadb_alg_ivlen = 0,
  43. .sadb_alg_minbits = 0,
  44. .sadb_alg_maxbits = 0
  45. }
  46. },
  47. {
  48. .name = "hmac(md5)",
  49. .compat = "md5",
  50. .uinfo = {
  51. .auth = {
  52. .icv_truncbits = 96,
  53. .icv_fullbits = 128,
  54. }
  55. },
  56. .desc = {
  57. .sadb_alg_id = SADB_AALG_MD5HMAC,
  58. .sadb_alg_ivlen = 0,
  59. .sadb_alg_minbits = 128,
  60. .sadb_alg_maxbits = 128
  61. }
  62. },
  63. {
  64. .name = "hmac(sha1)",
  65. .compat = "sha1",
  66. .uinfo = {
  67. .auth = {
  68. .icv_truncbits = 96,
  69. .icv_fullbits = 160,
  70. }
  71. },
  72. .desc = {
  73. .sadb_alg_id = SADB_AALG_SHA1HMAC,
  74. .sadb_alg_ivlen = 0,
  75. .sadb_alg_minbits = 160,
  76. .sadb_alg_maxbits = 160
  77. }
  78. },
  79. {
  80. .name = "hmac(sha256)",
  81. .compat = "sha256",
  82. .uinfo = {
  83. .auth = {
  84. .icv_truncbits = 96,
  85. .icv_fullbits = 256,
  86. }
  87. },
  88. .desc = {
  89. .sadb_alg_id = SADB_X_AALG_SHA2_256HMAC,
  90. .sadb_alg_ivlen = 0,
  91. .sadb_alg_minbits = 256,
  92. .sadb_alg_maxbits = 256
  93. }
  94. },
  95. {
  96. .name = "hmac(ripemd160)",
  97. .compat = "ripemd160",
  98. .uinfo = {
  99. .auth = {
  100. .icv_truncbits = 96,
  101. .icv_fullbits = 160,
  102. }
  103. },
  104. .desc = {
  105. .sadb_alg_id = SADB_X_AALG_RIPEMD160HMAC,
  106. .sadb_alg_ivlen = 0,
  107. .sadb_alg_minbits = 160,
  108. .sadb_alg_maxbits = 160
  109. }
  110. },
  111. {
  112. .name = "xcbc(aes)",
  113. .uinfo = {
  114. .auth = {
  115. .icv_truncbits = 96,
  116. .icv_fullbits = 128,
  117. }
  118. },
  119. .desc = {
  120. .sadb_alg_id = SADB_X_AALG_AES_XCBC_MAC,
  121. .sadb_alg_ivlen = 0,
  122. .sadb_alg_minbits = 128,
  123. .sadb_alg_maxbits = 128
  124. }
  125. },
  126. };
  127. static struct xfrm_algo_desc ealg_list[] = {
  128. {
  129. .name = "ecb(cipher_null)",
  130. .compat = "cipher_null",
  131. .uinfo = {
  132. .encr = {
  133. .blockbits = 8,
  134. .defkeybits = 0,
  135. }
  136. },
  137. .desc = {
  138. .sadb_alg_id = SADB_EALG_NULL,
  139. .sadb_alg_ivlen = 0,
  140. .sadb_alg_minbits = 0,
  141. .sadb_alg_maxbits = 0
  142. }
  143. },
  144. {
  145. .name = "cbc(des)",
  146. .compat = "des",
  147. .uinfo = {
  148. .encr = {
  149. .blockbits = 64,
  150. .defkeybits = 64,
  151. }
  152. },
  153. .desc = {
  154. .sadb_alg_id = SADB_EALG_DESCBC,
  155. .sadb_alg_ivlen = 8,
  156. .sadb_alg_minbits = 64,
  157. .sadb_alg_maxbits = 64
  158. }
  159. },
  160. {
  161. .name = "cbc(des3_ede)",
  162. .compat = "des3_ede",
  163. .uinfo = {
  164. .encr = {
  165. .blockbits = 64,
  166. .defkeybits = 192,
  167. }
  168. },
  169. .desc = {
  170. .sadb_alg_id = SADB_EALG_3DESCBC,
  171. .sadb_alg_ivlen = 8,
  172. .sadb_alg_minbits = 192,
  173. .sadb_alg_maxbits = 192
  174. }
  175. },
  176. {
  177. .name = "cbc(cast128)",
  178. .compat = "cast128",
  179. .uinfo = {
  180. .encr = {
  181. .blockbits = 64,
  182. .defkeybits = 128,
  183. }
  184. },
  185. .desc = {
  186. .sadb_alg_id = SADB_X_EALG_CASTCBC,
  187. .sadb_alg_ivlen = 8,
  188. .sadb_alg_minbits = 40,
  189. .sadb_alg_maxbits = 128
  190. }
  191. },
  192. {
  193. .name = "cbc(blowfish)",
  194. .compat = "blowfish",
  195. .uinfo = {
  196. .encr = {
  197. .blockbits = 64,
  198. .defkeybits = 128,
  199. }
  200. },
  201. .desc = {
  202. .sadb_alg_id = SADB_X_EALG_BLOWFISHCBC,
  203. .sadb_alg_ivlen = 8,
  204. .sadb_alg_minbits = 40,
  205. .sadb_alg_maxbits = 448
  206. }
  207. },
  208. {
  209. .name = "cbc(aes)",
  210. .compat = "aes",
  211. .uinfo = {
  212. .encr = {
  213. .blockbits = 128,
  214. .defkeybits = 128,
  215. }
  216. },
  217. .desc = {
  218. .sadb_alg_id = SADB_X_EALG_AESCBC,
  219. .sadb_alg_ivlen = 8,
  220. .sadb_alg_minbits = 128,
  221. .sadb_alg_maxbits = 256
  222. }
  223. },
  224. {
  225. .name = "cbc(serpent)",
  226. .compat = "serpent",
  227. .uinfo = {
  228. .encr = {
  229. .blockbits = 128,
  230. .defkeybits = 128,
  231. }
  232. },
  233. .desc = {
  234. .sadb_alg_id = SADB_X_EALG_SERPENTCBC,
  235. .sadb_alg_ivlen = 8,
  236. .sadb_alg_minbits = 128,
  237. .sadb_alg_maxbits = 256,
  238. }
  239. },
  240. {
  241. .name = "cbc(camellia)",
  242. .uinfo = {
  243. .encr = {
  244. .blockbits = 128,
  245. .defkeybits = 128,
  246. }
  247. },
  248. .desc = {
  249. .sadb_alg_id = SADB_X_EALG_CAMELLIACBC,
  250. .sadb_alg_ivlen = 8,
  251. .sadb_alg_minbits = 128,
  252. .sadb_alg_maxbits = 256
  253. }
  254. },
  255. {
  256. .name = "cbc(twofish)",
  257. .compat = "twofish",
  258. .uinfo = {
  259. .encr = {
  260. .blockbits = 128,
  261. .defkeybits = 128,
  262. }
  263. },
  264. .desc = {
  265. .sadb_alg_id = SADB_X_EALG_TWOFISHCBC,
  266. .sadb_alg_ivlen = 8,
  267. .sadb_alg_minbits = 128,
  268. .sadb_alg_maxbits = 256
  269. }
  270. },
  271. };
  272. static struct xfrm_algo_desc calg_list[] = {
  273. {
  274. .name = "deflate",
  275. .uinfo = {
  276. .comp = {
  277. .threshold = 90,
  278. }
  279. },
  280. .desc = { .sadb_alg_id = SADB_X_CALG_DEFLATE }
  281. },
  282. {
  283. .name = "lzs",
  284. .uinfo = {
  285. .comp = {
  286. .threshold = 90,
  287. }
  288. },
  289. .desc = { .sadb_alg_id = SADB_X_CALG_LZS }
  290. },
  291. {
  292. .name = "lzjh",
  293. .uinfo = {
  294. .comp = {
  295. .threshold = 50,
  296. }
  297. },
  298. .desc = { .sadb_alg_id = SADB_X_CALG_LZJH }
  299. },
  300. };
  301. static inline int aalg_entries(void)
  302. {
  303. return ARRAY_SIZE(aalg_list);
  304. }
  305. static inline int ealg_entries(void)
  306. {
  307. return ARRAY_SIZE(ealg_list);
  308. }
  309. static inline int calg_entries(void)
  310. {
  311. return ARRAY_SIZE(calg_list);
  312. }
  313. struct xfrm_algo_list {
  314. struct xfrm_algo_desc *algs;
  315. int entries;
  316. u32 type;
  317. u32 mask;
  318. };
  319. static const struct xfrm_algo_list xfrm_aalg_list = {
  320. .algs = aalg_list,
  321. .entries = ARRAY_SIZE(aalg_list),
  322. .type = CRYPTO_ALG_TYPE_HASH,
  323. .mask = CRYPTO_ALG_TYPE_HASH_MASK | CRYPTO_ALG_ASYNC,
  324. };
  325. static const struct xfrm_algo_list xfrm_ealg_list = {
  326. .algs = ealg_list,
  327. .entries = ARRAY_SIZE(ealg_list),
  328. .type = CRYPTO_ALG_TYPE_BLKCIPHER,
  329. .mask = CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC,
  330. };
  331. static const struct xfrm_algo_list xfrm_calg_list = {
  332. .algs = calg_list,
  333. .entries = ARRAY_SIZE(calg_list),
  334. .type = CRYPTO_ALG_TYPE_COMPRESS,
  335. .mask = CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC,
  336. };
  337. static struct xfrm_algo_desc *xfrm_find_algo(
  338. const struct xfrm_algo_list *algo_list,
  339. int match(const struct xfrm_algo_desc *entry, const void *data),
  340. const void *data, int probe)
  341. {
  342. struct xfrm_algo_desc *list = algo_list->algs;
  343. int i, status;
  344. for (i = 0; i < algo_list->entries; i++) {
  345. if (!match(list + i, data))
  346. continue;
  347. if (list[i].available)
  348. return &list[i];
  349. if (!probe)
  350. break;
  351. status = crypto_has_alg(list[i].name, algo_list->type,
  352. algo_list->mask);
  353. if (!status)
  354. break;
  355. list[i].available = status;
  356. return &list[i];
  357. }
  358. return NULL;
  359. }
  360. static int xfrm_alg_id_match(const struct xfrm_algo_desc *entry,
  361. const void *data)
  362. {
  363. return entry->desc.sadb_alg_id == (unsigned long)data;
  364. }
  365. struct xfrm_algo_desc *xfrm_aalg_get_byid(int alg_id)
  366. {
  367. return xfrm_find_algo(&xfrm_aalg_list, xfrm_alg_id_match,
  368. (void *)(unsigned long)alg_id, 1);
  369. }
  370. EXPORT_SYMBOL_GPL(xfrm_aalg_get_byid);
  371. struct xfrm_algo_desc *xfrm_ealg_get_byid(int alg_id)
  372. {
  373. return xfrm_find_algo(&xfrm_ealg_list, xfrm_alg_id_match,
  374. (void *)(unsigned long)alg_id, 1);
  375. }
  376. EXPORT_SYMBOL_GPL(xfrm_ealg_get_byid);
  377. struct xfrm_algo_desc *xfrm_calg_get_byid(int alg_id)
  378. {
  379. return xfrm_find_algo(&xfrm_calg_list, xfrm_alg_id_match,
  380. (void *)(unsigned long)alg_id, 1);
  381. }
  382. EXPORT_SYMBOL_GPL(xfrm_calg_get_byid);
  383. static int xfrm_alg_name_match(const struct xfrm_algo_desc *entry,
  384. const void *data)
  385. {
  386. const char *name = data;
  387. return name && (!strcmp(name, entry->name) ||
  388. (entry->compat && !strcmp(name, entry->compat)));
  389. }
  390. struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name, int probe)
  391. {
  392. return xfrm_find_algo(&xfrm_aalg_list, xfrm_alg_name_match, name,
  393. probe);
  394. }
  395. EXPORT_SYMBOL_GPL(xfrm_aalg_get_byname);
  396. struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name, int probe)
  397. {
  398. return xfrm_find_algo(&xfrm_ealg_list, xfrm_alg_name_match, name,
  399. probe);
  400. }
  401. EXPORT_SYMBOL_GPL(xfrm_ealg_get_byname);
  402. struct xfrm_algo_desc *xfrm_calg_get_byname(char *name, int probe)
  403. {
  404. return xfrm_find_algo(&xfrm_calg_list, xfrm_alg_name_match, name,
  405. probe);
  406. }
  407. EXPORT_SYMBOL_GPL(xfrm_calg_get_byname);
  408. struct xfrm_algo_desc *xfrm_aalg_get_byidx(unsigned int idx)
  409. {
  410. if (idx >= aalg_entries())
  411. return NULL;
  412. return &aalg_list[idx];
  413. }
  414. EXPORT_SYMBOL_GPL(xfrm_aalg_get_byidx);
  415. struct xfrm_algo_desc *xfrm_ealg_get_byidx(unsigned int idx)
  416. {
  417. if (idx >= ealg_entries())
  418. return NULL;
  419. return &ealg_list[idx];
  420. }
  421. EXPORT_SYMBOL_GPL(xfrm_ealg_get_byidx);
  422. /*
  423. * Probe for the availability of crypto algorithms, and set the available
  424. * flag for any algorithms found on the system. This is typically called by
  425. * pfkey during userspace SA add, update or register.
  426. */
  427. void xfrm_probe_algs(void)
  428. {
  429. #ifdef CONFIG_CRYPTO
  430. int i, status;
  431. BUG_ON(in_softirq());
  432. for (i = 0; i < aalg_entries(); i++) {
  433. status = crypto_has_hash(aalg_list[i].name, 0,
  434. CRYPTO_ALG_ASYNC);
  435. if (aalg_list[i].available != status)
  436. aalg_list[i].available = status;
  437. }
  438. for (i = 0; i < ealg_entries(); i++) {
  439. status = crypto_has_blkcipher(ealg_list[i].name, 0,
  440. CRYPTO_ALG_ASYNC);
  441. if (ealg_list[i].available != status)
  442. ealg_list[i].available = status;
  443. }
  444. for (i = 0; i < calg_entries(); i++) {
  445. status = crypto_has_comp(calg_list[i].name, 0,
  446. CRYPTO_ALG_ASYNC);
  447. if (calg_list[i].available != status)
  448. calg_list[i].available = status;
  449. }
  450. #endif
  451. }
  452. EXPORT_SYMBOL_GPL(xfrm_probe_algs);
  453. int xfrm_count_auth_supported(void)
  454. {
  455. int i, n;
  456. for (i = 0, n = 0; i < aalg_entries(); i++)
  457. if (aalg_list[i].available)
  458. n++;
  459. return n;
  460. }
  461. EXPORT_SYMBOL_GPL(xfrm_count_auth_supported);
  462. int xfrm_count_enc_supported(void)
  463. {
  464. int i, n;
  465. for (i = 0, n = 0; i < ealg_entries(); i++)
  466. if (ealg_list[i].available)
  467. n++;
  468. return n;
  469. }
  470. EXPORT_SYMBOL_GPL(xfrm_count_enc_supported);
  471. /* Move to common area: it is shared with AH. */
  472. int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc,
  473. int offset, int len, icv_update_fn_t icv_update)
  474. {
  475. int start = skb_headlen(skb);
  476. int i, copy = start - offset;
  477. int err;
  478. struct scatterlist sg;
  479. /* Checksum header. */
  480. if (copy > 0) {
  481. if (copy > len)
  482. copy = len;
  483. sg_set_page(&sg, virt_to_page(skb->data + offset));
  484. sg.offset = (unsigned long)(skb->data + offset) % PAGE_SIZE;
  485. sg.length = copy;
  486. err = icv_update(desc, &sg, copy);
  487. if (unlikely(err))
  488. return err;
  489. if ((len -= copy) == 0)
  490. return 0;
  491. offset += copy;
  492. }
  493. for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
  494. int end;
  495. BUG_TRAP(start <= offset + len);
  496. end = start + skb_shinfo(skb)->frags[i].size;
  497. if ((copy = end - offset) > 0) {
  498. skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
  499. if (copy > len)
  500. copy = len;
  501. sg_set_page(&sg, frag->page);
  502. sg.offset = frag->page_offset + offset-start;
  503. sg.length = copy;
  504. err = icv_update(desc, &sg, copy);
  505. if (unlikely(err))
  506. return err;
  507. if (!(len -= copy))
  508. return 0;
  509. offset += copy;
  510. }
  511. start = end;
  512. }
  513. if (skb_shinfo(skb)->frag_list) {
  514. struct sk_buff *list = skb_shinfo(skb)->frag_list;
  515. for (; list; list = list->next) {
  516. int end;
  517. BUG_TRAP(start <= offset + len);
  518. end = start + list->len;
  519. if ((copy = end - offset) > 0) {
  520. if (copy > len)
  521. copy = len;
  522. err = skb_icv_walk(list, desc, offset-start,
  523. copy, icv_update);
  524. if (unlikely(err))
  525. return err;
  526. if ((len -= copy) == 0)
  527. return 0;
  528. offset += copy;
  529. }
  530. start = end;
  531. }
  532. }
  533. BUG_ON(len);
  534. return 0;
  535. }
  536. EXPORT_SYMBOL_GPL(skb_icv_walk);
  537. #if defined(CONFIG_INET_ESP) || defined(CONFIG_INET_ESP_MODULE) || defined(CONFIG_INET6_ESP) || defined(CONFIG_INET6_ESP_MODULE)
  538. void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len)
  539. {
  540. if (tail != skb) {
  541. skb->data_len += len;
  542. skb->len += len;
  543. }
  544. return skb_put(tail, len);
  545. }
  546. EXPORT_SYMBOL_GPL(pskb_put);
  547. #endif