1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * xfrm algorithm interface |
4 | * |
5 | * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> |
6 | */ |
7 | |
8 | #include <crypto/aead.h> |
9 | #include <crypto/hash.h> |
10 | #include <crypto/skcipher.h> |
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 IS_ENABLED(CONFIG_INET_ESP) || IS_ENABLED(CONFIG_INET6_ESP) |
18 | #include <net/esp.h> |
19 | #endif |
20 | |
21 | /* |
22 | * Algorithms supported by IPsec. These entries contain properties which |
23 | * are used in key negotiation and xfrm processing, and are used to verify |
24 | * that instantiated crypto transforms have correct parameters for IPsec |
25 | * purposes. |
26 | */ |
27 | static struct xfrm_algo_desc aead_list[] = { |
28 | { |
29 | .name = "rfc4106(gcm(aes))" , |
30 | |
31 | .uinfo = { |
32 | .aead = { |
33 | .geniv = "seqiv" , |
34 | .icv_truncbits = 64, |
35 | } |
36 | }, |
37 | |
38 | .pfkey_supported = 1, |
39 | |
40 | .desc = { |
41 | .sadb_alg_id = SADB_X_EALG_AES_GCM_ICV8, |
42 | .sadb_alg_ivlen = 8, |
43 | .sadb_alg_minbits = 128, |
44 | .sadb_alg_maxbits = 256 |
45 | } |
46 | }, |
47 | { |
48 | .name = "rfc4106(gcm(aes))" , |
49 | |
50 | .uinfo = { |
51 | .aead = { |
52 | .geniv = "seqiv" , |
53 | .icv_truncbits = 96, |
54 | } |
55 | }, |
56 | |
57 | .pfkey_supported = 1, |
58 | |
59 | .desc = { |
60 | .sadb_alg_id = SADB_X_EALG_AES_GCM_ICV12, |
61 | .sadb_alg_ivlen = 8, |
62 | .sadb_alg_minbits = 128, |
63 | .sadb_alg_maxbits = 256 |
64 | } |
65 | }, |
66 | { |
67 | .name = "rfc4106(gcm(aes))" , |
68 | |
69 | .uinfo = { |
70 | .aead = { |
71 | .geniv = "seqiv" , |
72 | .icv_truncbits = 128, |
73 | } |
74 | }, |
75 | |
76 | .pfkey_supported = 1, |
77 | |
78 | .desc = { |
79 | .sadb_alg_id = SADB_X_EALG_AES_GCM_ICV16, |
80 | .sadb_alg_ivlen = 8, |
81 | .sadb_alg_minbits = 128, |
82 | .sadb_alg_maxbits = 256 |
83 | } |
84 | }, |
85 | { |
86 | .name = "rfc4309(ccm(aes))" , |
87 | |
88 | .uinfo = { |
89 | .aead = { |
90 | .geniv = "seqiv" , |
91 | .icv_truncbits = 64, |
92 | } |
93 | }, |
94 | |
95 | .pfkey_supported = 1, |
96 | |
97 | .desc = { |
98 | .sadb_alg_id = SADB_X_EALG_AES_CCM_ICV8, |
99 | .sadb_alg_ivlen = 8, |
100 | .sadb_alg_minbits = 128, |
101 | .sadb_alg_maxbits = 256 |
102 | } |
103 | }, |
104 | { |
105 | .name = "rfc4309(ccm(aes))" , |
106 | |
107 | .uinfo = { |
108 | .aead = { |
109 | .geniv = "seqiv" , |
110 | .icv_truncbits = 96, |
111 | } |
112 | }, |
113 | |
114 | .pfkey_supported = 1, |
115 | |
116 | .desc = { |
117 | .sadb_alg_id = SADB_X_EALG_AES_CCM_ICV12, |
118 | .sadb_alg_ivlen = 8, |
119 | .sadb_alg_minbits = 128, |
120 | .sadb_alg_maxbits = 256 |
121 | } |
122 | }, |
123 | { |
124 | .name = "rfc4309(ccm(aes))" , |
125 | |
126 | .uinfo = { |
127 | .aead = { |
128 | .geniv = "seqiv" , |
129 | .icv_truncbits = 128, |
130 | } |
131 | }, |
132 | |
133 | .pfkey_supported = 1, |
134 | |
135 | .desc = { |
136 | .sadb_alg_id = SADB_X_EALG_AES_CCM_ICV16, |
137 | .sadb_alg_ivlen = 8, |
138 | .sadb_alg_minbits = 128, |
139 | .sadb_alg_maxbits = 256 |
140 | } |
141 | }, |
142 | { |
143 | .name = "rfc4543(gcm(aes))" , |
144 | |
145 | .uinfo = { |
146 | .aead = { |
147 | .geniv = "seqiv" , |
148 | .icv_truncbits = 128, |
149 | } |
150 | }, |
151 | |
152 | .pfkey_supported = 1, |
153 | |
154 | .desc = { |
155 | .sadb_alg_id = SADB_X_EALG_NULL_AES_GMAC, |
156 | .sadb_alg_ivlen = 8, |
157 | .sadb_alg_minbits = 128, |
158 | .sadb_alg_maxbits = 256 |
159 | } |
160 | }, |
161 | { |
162 | .name = "rfc7539esp(chacha20,poly1305)" , |
163 | |
164 | .uinfo = { |
165 | .aead = { |
166 | .geniv = "seqiv" , |
167 | .icv_truncbits = 128, |
168 | } |
169 | }, |
170 | |
171 | .pfkey_supported = 0, |
172 | }, |
173 | }; |
174 | |
175 | static struct xfrm_algo_desc aalg_list[] = { |
176 | { |
177 | .name = "digest_null" , |
178 | |
179 | .uinfo = { |
180 | .auth = { |
181 | .icv_truncbits = 0, |
182 | .icv_fullbits = 0, |
183 | } |
184 | }, |
185 | |
186 | .pfkey_supported = 1, |
187 | |
188 | .desc = { |
189 | .sadb_alg_id = SADB_X_AALG_NULL, |
190 | .sadb_alg_ivlen = 0, |
191 | .sadb_alg_minbits = 0, |
192 | .sadb_alg_maxbits = 0 |
193 | } |
194 | }, |
195 | { |
196 | .name = "hmac(md5)" , |
197 | .compat = "md5" , |
198 | |
199 | .uinfo = { |
200 | .auth = { |
201 | .icv_truncbits = 96, |
202 | .icv_fullbits = 128, |
203 | } |
204 | }, |
205 | |
206 | .pfkey_supported = 1, |
207 | |
208 | .desc = { |
209 | .sadb_alg_id = SADB_AALG_MD5HMAC, |
210 | .sadb_alg_ivlen = 0, |
211 | .sadb_alg_minbits = 128, |
212 | .sadb_alg_maxbits = 128 |
213 | } |
214 | }, |
215 | { |
216 | .name = "hmac(sha1)" , |
217 | .compat = "sha1" , |
218 | |
219 | .uinfo = { |
220 | .auth = { |
221 | .icv_truncbits = 96, |
222 | .icv_fullbits = 160, |
223 | } |
224 | }, |
225 | |
226 | .pfkey_supported = 1, |
227 | |
228 | .desc = { |
229 | .sadb_alg_id = SADB_AALG_SHA1HMAC, |
230 | .sadb_alg_ivlen = 0, |
231 | .sadb_alg_minbits = 160, |
232 | .sadb_alg_maxbits = 160 |
233 | } |
234 | }, |
235 | { |
236 | .name = "hmac(sha256)" , |
237 | .compat = "sha256" , |
238 | |
239 | .uinfo = { |
240 | .auth = { |
241 | .icv_truncbits = 96, |
242 | .icv_fullbits = 256, |
243 | } |
244 | }, |
245 | |
246 | .pfkey_supported = 1, |
247 | |
248 | .desc = { |
249 | .sadb_alg_id = SADB_X_AALG_SHA2_256HMAC, |
250 | .sadb_alg_ivlen = 0, |
251 | .sadb_alg_minbits = 256, |
252 | .sadb_alg_maxbits = 256 |
253 | } |
254 | }, |
255 | { |
256 | .name = "hmac(sha384)" , |
257 | |
258 | .uinfo = { |
259 | .auth = { |
260 | .icv_truncbits = 192, |
261 | .icv_fullbits = 384, |
262 | } |
263 | }, |
264 | |
265 | .pfkey_supported = 1, |
266 | |
267 | .desc = { |
268 | .sadb_alg_id = SADB_X_AALG_SHA2_384HMAC, |
269 | .sadb_alg_ivlen = 0, |
270 | .sadb_alg_minbits = 384, |
271 | .sadb_alg_maxbits = 384 |
272 | } |
273 | }, |
274 | { |
275 | .name = "hmac(sha512)" , |
276 | |
277 | .uinfo = { |
278 | .auth = { |
279 | .icv_truncbits = 256, |
280 | .icv_fullbits = 512, |
281 | } |
282 | }, |
283 | |
284 | .pfkey_supported = 1, |
285 | |
286 | .desc = { |
287 | .sadb_alg_id = SADB_X_AALG_SHA2_512HMAC, |
288 | .sadb_alg_ivlen = 0, |
289 | .sadb_alg_minbits = 512, |
290 | .sadb_alg_maxbits = 512 |
291 | } |
292 | }, |
293 | { |
294 | .name = "hmac(rmd160)" , |
295 | .compat = "rmd160" , |
296 | |
297 | .uinfo = { |
298 | .auth = { |
299 | .icv_truncbits = 96, |
300 | .icv_fullbits = 160, |
301 | } |
302 | }, |
303 | |
304 | .pfkey_supported = 1, |
305 | |
306 | .desc = { |
307 | .sadb_alg_id = SADB_X_AALG_RIPEMD160HMAC, |
308 | .sadb_alg_ivlen = 0, |
309 | .sadb_alg_minbits = 160, |
310 | .sadb_alg_maxbits = 160 |
311 | } |
312 | }, |
313 | { |
314 | .name = "xcbc(aes)" , |
315 | |
316 | .uinfo = { |
317 | .auth = { |
318 | .icv_truncbits = 96, |
319 | .icv_fullbits = 128, |
320 | } |
321 | }, |
322 | |
323 | .pfkey_supported = 1, |
324 | |
325 | .desc = { |
326 | .sadb_alg_id = SADB_X_AALG_AES_XCBC_MAC, |
327 | .sadb_alg_ivlen = 0, |
328 | .sadb_alg_minbits = 128, |
329 | .sadb_alg_maxbits = 128 |
330 | } |
331 | }, |
332 | { |
333 | /* rfc4494 */ |
334 | .name = "cmac(aes)" , |
335 | |
336 | .uinfo = { |
337 | .auth = { |
338 | .icv_truncbits = 96, |
339 | .icv_fullbits = 128, |
340 | } |
341 | }, |
342 | |
343 | .pfkey_supported = 0, |
344 | }, |
345 | { |
346 | .name = "hmac(sm3)" , |
347 | .compat = "sm3" , |
348 | |
349 | .uinfo = { |
350 | .auth = { |
351 | .icv_truncbits = 256, |
352 | .icv_fullbits = 256, |
353 | } |
354 | }, |
355 | |
356 | .pfkey_supported = 1, |
357 | |
358 | .desc = { |
359 | .sadb_alg_id = SADB_X_AALG_SM3_256HMAC, |
360 | .sadb_alg_ivlen = 0, |
361 | .sadb_alg_minbits = 256, |
362 | .sadb_alg_maxbits = 256 |
363 | } |
364 | }, |
365 | }; |
366 | |
367 | static struct xfrm_algo_desc ealg_list[] = { |
368 | { |
369 | .name = "ecb(cipher_null)" , |
370 | .compat = "cipher_null" , |
371 | |
372 | .uinfo = { |
373 | .encr = { |
374 | .blockbits = 8, |
375 | .defkeybits = 0, |
376 | } |
377 | }, |
378 | |
379 | .pfkey_supported = 1, |
380 | |
381 | .desc = { |
382 | .sadb_alg_id = SADB_EALG_NULL, |
383 | .sadb_alg_ivlen = 0, |
384 | .sadb_alg_minbits = 0, |
385 | .sadb_alg_maxbits = 0 |
386 | } |
387 | }, |
388 | { |
389 | .name = "cbc(des)" , |
390 | .compat = "des" , |
391 | |
392 | .uinfo = { |
393 | .encr = { |
394 | .geniv = "echainiv" , |
395 | .blockbits = 64, |
396 | .defkeybits = 64, |
397 | } |
398 | }, |
399 | |
400 | .pfkey_supported = 1, |
401 | |
402 | .desc = { |
403 | .sadb_alg_id = SADB_EALG_DESCBC, |
404 | .sadb_alg_ivlen = 8, |
405 | .sadb_alg_minbits = 64, |
406 | .sadb_alg_maxbits = 64 |
407 | } |
408 | }, |
409 | { |
410 | .name = "cbc(des3_ede)" , |
411 | .compat = "des3_ede" , |
412 | |
413 | .uinfo = { |
414 | .encr = { |
415 | .geniv = "echainiv" , |
416 | .blockbits = 64, |
417 | .defkeybits = 192, |
418 | } |
419 | }, |
420 | |
421 | .pfkey_supported = 1, |
422 | |
423 | .desc = { |
424 | .sadb_alg_id = SADB_EALG_3DESCBC, |
425 | .sadb_alg_ivlen = 8, |
426 | .sadb_alg_minbits = 192, |
427 | .sadb_alg_maxbits = 192 |
428 | } |
429 | }, |
430 | { |
431 | .name = "cbc(cast5)" , |
432 | .compat = "cast5" , |
433 | |
434 | .uinfo = { |
435 | .encr = { |
436 | .geniv = "echainiv" , |
437 | .blockbits = 64, |
438 | .defkeybits = 128, |
439 | } |
440 | }, |
441 | |
442 | .pfkey_supported = 1, |
443 | |
444 | .desc = { |
445 | .sadb_alg_id = SADB_X_EALG_CASTCBC, |
446 | .sadb_alg_ivlen = 8, |
447 | .sadb_alg_minbits = 40, |
448 | .sadb_alg_maxbits = 128 |
449 | } |
450 | }, |
451 | { |
452 | .name = "cbc(blowfish)" , |
453 | .compat = "blowfish" , |
454 | |
455 | .uinfo = { |
456 | .encr = { |
457 | .geniv = "echainiv" , |
458 | .blockbits = 64, |
459 | .defkeybits = 128, |
460 | } |
461 | }, |
462 | |
463 | .pfkey_supported = 1, |
464 | |
465 | .desc = { |
466 | .sadb_alg_id = SADB_X_EALG_BLOWFISHCBC, |
467 | .sadb_alg_ivlen = 8, |
468 | .sadb_alg_minbits = 40, |
469 | .sadb_alg_maxbits = 448 |
470 | } |
471 | }, |
472 | { |
473 | .name = "cbc(aes)" , |
474 | .compat = "aes" , |
475 | |
476 | .uinfo = { |
477 | .encr = { |
478 | .geniv = "echainiv" , |
479 | .blockbits = 128, |
480 | .defkeybits = 128, |
481 | } |
482 | }, |
483 | |
484 | .pfkey_supported = 1, |
485 | |
486 | .desc = { |
487 | .sadb_alg_id = SADB_X_EALG_AESCBC, |
488 | .sadb_alg_ivlen = 8, |
489 | .sadb_alg_minbits = 128, |
490 | .sadb_alg_maxbits = 256 |
491 | } |
492 | }, |
493 | { |
494 | .name = "cbc(serpent)" , |
495 | .compat = "serpent" , |
496 | |
497 | .uinfo = { |
498 | .encr = { |
499 | .geniv = "echainiv" , |
500 | .blockbits = 128, |
501 | .defkeybits = 128, |
502 | } |
503 | }, |
504 | |
505 | .pfkey_supported = 1, |
506 | |
507 | .desc = { |
508 | .sadb_alg_id = SADB_X_EALG_SERPENTCBC, |
509 | .sadb_alg_ivlen = 8, |
510 | .sadb_alg_minbits = 128, |
511 | .sadb_alg_maxbits = 256, |
512 | } |
513 | }, |
514 | { |
515 | .name = "cbc(camellia)" , |
516 | .compat = "camellia" , |
517 | |
518 | .uinfo = { |
519 | .encr = { |
520 | .geniv = "echainiv" , |
521 | .blockbits = 128, |
522 | .defkeybits = 128, |
523 | } |
524 | }, |
525 | |
526 | .pfkey_supported = 1, |
527 | |
528 | .desc = { |
529 | .sadb_alg_id = SADB_X_EALG_CAMELLIACBC, |
530 | .sadb_alg_ivlen = 8, |
531 | .sadb_alg_minbits = 128, |
532 | .sadb_alg_maxbits = 256 |
533 | } |
534 | }, |
535 | { |
536 | .name = "cbc(twofish)" , |
537 | .compat = "twofish" , |
538 | |
539 | .uinfo = { |
540 | .encr = { |
541 | .geniv = "echainiv" , |
542 | .blockbits = 128, |
543 | .defkeybits = 128, |
544 | } |
545 | }, |
546 | |
547 | .pfkey_supported = 1, |
548 | |
549 | .desc = { |
550 | .sadb_alg_id = SADB_X_EALG_TWOFISHCBC, |
551 | .sadb_alg_ivlen = 8, |
552 | .sadb_alg_minbits = 128, |
553 | .sadb_alg_maxbits = 256 |
554 | } |
555 | }, |
556 | { |
557 | .name = "rfc3686(ctr(aes))" , |
558 | |
559 | .uinfo = { |
560 | .encr = { |
561 | .geniv = "seqiv" , |
562 | .blockbits = 128, |
563 | .defkeybits = 160, /* 128-bit key + 32-bit nonce */ |
564 | } |
565 | }, |
566 | |
567 | .pfkey_supported = 1, |
568 | |
569 | .desc = { |
570 | .sadb_alg_id = SADB_X_EALG_AESCTR, |
571 | .sadb_alg_ivlen = 8, |
572 | .sadb_alg_minbits = 160, |
573 | .sadb_alg_maxbits = 288 |
574 | } |
575 | }, |
576 | { |
577 | .name = "cbc(sm4)" , |
578 | .compat = "sm4" , |
579 | |
580 | .uinfo = { |
581 | .encr = { |
582 | .geniv = "echainiv" , |
583 | .blockbits = 128, |
584 | .defkeybits = 128, |
585 | } |
586 | }, |
587 | |
588 | .pfkey_supported = 1, |
589 | |
590 | .desc = { |
591 | .sadb_alg_id = SADB_X_EALG_SM4CBC, |
592 | .sadb_alg_ivlen = 16, |
593 | .sadb_alg_minbits = 128, |
594 | .sadb_alg_maxbits = 256 |
595 | } |
596 | }, |
597 | }; |
598 | |
599 | static struct xfrm_algo_desc calg_list[] = { |
600 | { |
601 | .name = "deflate" , |
602 | .uinfo = { |
603 | .comp = { |
604 | .threshold = 90, |
605 | } |
606 | }, |
607 | .pfkey_supported = 1, |
608 | .desc = { .sadb_alg_id = SADB_X_CALG_DEFLATE } |
609 | }, |
610 | { |
611 | .name = "lzs" , |
612 | .uinfo = { |
613 | .comp = { |
614 | .threshold = 90, |
615 | } |
616 | }, |
617 | .pfkey_supported = 1, |
618 | .desc = { .sadb_alg_id = SADB_X_CALG_LZS } |
619 | }, |
620 | { |
621 | .name = "lzjh" , |
622 | .uinfo = { |
623 | .comp = { |
624 | .threshold = 50, |
625 | } |
626 | }, |
627 | .pfkey_supported = 1, |
628 | .desc = { .sadb_alg_id = SADB_X_CALG_LZJH } |
629 | }, |
630 | }; |
631 | |
632 | static inline int aalg_entries(void) |
633 | { |
634 | return ARRAY_SIZE(aalg_list); |
635 | } |
636 | |
637 | static inline int ealg_entries(void) |
638 | { |
639 | return ARRAY_SIZE(ealg_list); |
640 | } |
641 | |
642 | static inline int calg_entries(void) |
643 | { |
644 | return ARRAY_SIZE(calg_list); |
645 | } |
646 | |
647 | struct xfrm_algo_list { |
648 | int (*find)(const char *name, u32 type, u32 mask); |
649 | struct xfrm_algo_desc *algs; |
650 | int entries; |
651 | }; |
652 | |
653 | static const struct xfrm_algo_list xfrm_aead_list = { |
654 | .find = crypto_has_aead, |
655 | .algs = aead_list, |
656 | .entries = ARRAY_SIZE(aead_list), |
657 | }; |
658 | |
659 | static const struct xfrm_algo_list xfrm_aalg_list = { |
660 | .find = crypto_has_ahash, |
661 | .algs = aalg_list, |
662 | .entries = ARRAY_SIZE(aalg_list), |
663 | }; |
664 | |
665 | static const struct xfrm_algo_list xfrm_ealg_list = { |
666 | .find = crypto_has_skcipher, |
667 | .algs = ealg_list, |
668 | .entries = ARRAY_SIZE(ealg_list), |
669 | }; |
670 | |
671 | static const struct xfrm_algo_list xfrm_calg_list = { |
672 | .find = crypto_has_comp, |
673 | .algs = calg_list, |
674 | .entries = ARRAY_SIZE(calg_list), |
675 | }; |
676 | |
677 | static struct xfrm_algo_desc *xfrm_find_algo( |
678 | const struct xfrm_algo_list *algo_list, |
679 | int match(const struct xfrm_algo_desc *entry, const void *data), |
680 | const void *data, int probe) |
681 | { |
682 | struct xfrm_algo_desc *list = algo_list->algs; |
683 | int i, status; |
684 | |
685 | for (i = 0; i < algo_list->entries; i++) { |
686 | if (!match(list + i, data)) |
687 | continue; |
688 | |
689 | if (list[i].available) |
690 | return &list[i]; |
691 | |
692 | if (!probe) |
693 | break; |
694 | |
695 | status = algo_list->find(list[i].name, 0, 0); |
696 | if (!status) |
697 | break; |
698 | |
699 | list[i].available = status; |
700 | return &list[i]; |
701 | } |
702 | return NULL; |
703 | } |
704 | |
705 | static int xfrm_alg_id_match(const struct xfrm_algo_desc *entry, |
706 | const void *data) |
707 | { |
708 | return entry->desc.sadb_alg_id == (unsigned long)data; |
709 | } |
710 | |
711 | struct xfrm_algo_desc *xfrm_aalg_get_byid(int alg_id) |
712 | { |
713 | return xfrm_find_algo(algo_list: &xfrm_aalg_list, match: xfrm_alg_id_match, |
714 | data: (void *)(unsigned long)alg_id, probe: 1); |
715 | } |
716 | EXPORT_SYMBOL_GPL(xfrm_aalg_get_byid); |
717 | |
718 | struct xfrm_algo_desc *xfrm_ealg_get_byid(int alg_id) |
719 | { |
720 | return xfrm_find_algo(algo_list: &xfrm_ealg_list, match: xfrm_alg_id_match, |
721 | data: (void *)(unsigned long)alg_id, probe: 1); |
722 | } |
723 | EXPORT_SYMBOL_GPL(xfrm_ealg_get_byid); |
724 | |
725 | struct xfrm_algo_desc *xfrm_calg_get_byid(int alg_id) |
726 | { |
727 | return xfrm_find_algo(algo_list: &xfrm_calg_list, match: xfrm_alg_id_match, |
728 | data: (void *)(unsigned long)alg_id, probe: 1); |
729 | } |
730 | EXPORT_SYMBOL_GPL(xfrm_calg_get_byid); |
731 | |
732 | static int xfrm_alg_name_match(const struct xfrm_algo_desc *entry, |
733 | const void *data) |
734 | { |
735 | const char *name = data; |
736 | |
737 | return name && (!strcmp(name, entry->name) || |
738 | (entry->compat && !strcmp(name, entry->compat))); |
739 | } |
740 | |
741 | struct xfrm_algo_desc *xfrm_aalg_get_byname(const char *name, int probe) |
742 | { |
743 | return xfrm_find_algo(algo_list: &xfrm_aalg_list, match: xfrm_alg_name_match, data: name, |
744 | probe); |
745 | } |
746 | EXPORT_SYMBOL_GPL(xfrm_aalg_get_byname); |
747 | |
748 | struct xfrm_algo_desc *xfrm_ealg_get_byname(const char *name, int probe) |
749 | { |
750 | return xfrm_find_algo(algo_list: &xfrm_ealg_list, match: xfrm_alg_name_match, data: name, |
751 | probe); |
752 | } |
753 | EXPORT_SYMBOL_GPL(xfrm_ealg_get_byname); |
754 | |
755 | struct xfrm_algo_desc *xfrm_calg_get_byname(const char *name, int probe) |
756 | { |
757 | return xfrm_find_algo(algo_list: &xfrm_calg_list, match: xfrm_alg_name_match, data: name, |
758 | probe); |
759 | } |
760 | EXPORT_SYMBOL_GPL(xfrm_calg_get_byname); |
761 | |
762 | struct xfrm_aead_name { |
763 | const char *name; |
764 | int icvbits; |
765 | }; |
766 | |
767 | static int xfrm_aead_name_match(const struct xfrm_algo_desc *entry, |
768 | const void *data) |
769 | { |
770 | const struct xfrm_aead_name *aead = data; |
771 | const char *name = aead->name; |
772 | |
773 | return aead->icvbits == entry->uinfo.aead.icv_truncbits && name && |
774 | !strcmp(name, entry->name); |
775 | } |
776 | |
777 | struct xfrm_algo_desc *xfrm_aead_get_byname(const char *name, int icv_len, int probe) |
778 | { |
779 | struct xfrm_aead_name data = { |
780 | .name = name, |
781 | .icvbits = icv_len, |
782 | }; |
783 | |
784 | return xfrm_find_algo(algo_list: &xfrm_aead_list, match: xfrm_aead_name_match, data: &data, |
785 | probe); |
786 | } |
787 | EXPORT_SYMBOL_GPL(xfrm_aead_get_byname); |
788 | |
789 | struct xfrm_algo_desc *xfrm_aalg_get_byidx(unsigned int idx) |
790 | { |
791 | if (idx >= aalg_entries()) |
792 | return NULL; |
793 | |
794 | return &aalg_list[idx]; |
795 | } |
796 | EXPORT_SYMBOL_GPL(xfrm_aalg_get_byidx); |
797 | |
798 | struct xfrm_algo_desc *xfrm_ealg_get_byidx(unsigned int idx) |
799 | { |
800 | if (idx >= ealg_entries()) |
801 | return NULL; |
802 | |
803 | return &ealg_list[idx]; |
804 | } |
805 | EXPORT_SYMBOL_GPL(xfrm_ealg_get_byidx); |
806 | |
807 | /* |
808 | * Probe for the availability of crypto algorithms, and set the available |
809 | * flag for any algorithms found on the system. This is typically called by |
810 | * pfkey during userspace SA add, update or register. |
811 | */ |
812 | void xfrm_probe_algs(void) |
813 | { |
814 | int i, status; |
815 | |
816 | BUG_ON(in_softirq()); |
817 | |
818 | for (i = 0; i < aalg_entries(); i++) { |
819 | status = crypto_has_ahash(alg_name: aalg_list[i].name, type: 0, mask: 0); |
820 | if (aalg_list[i].available != status) |
821 | aalg_list[i].available = status; |
822 | } |
823 | |
824 | for (i = 0; i < ealg_entries(); i++) { |
825 | status = crypto_has_skcipher(alg_name: ealg_list[i].name, type: 0, mask: 0); |
826 | if (ealg_list[i].available != status) |
827 | ealg_list[i].available = status; |
828 | } |
829 | |
830 | for (i = 0; i < calg_entries(); i++) { |
831 | status = crypto_has_comp(alg_name: calg_list[i].name, type: 0, |
832 | CRYPTO_ALG_ASYNC); |
833 | if (calg_list[i].available != status) |
834 | calg_list[i].available = status; |
835 | } |
836 | } |
837 | EXPORT_SYMBOL_GPL(xfrm_probe_algs); |
838 | |
839 | int xfrm_count_pfkey_auth_supported(void) |
840 | { |
841 | int i, n; |
842 | |
843 | for (i = 0, n = 0; i < aalg_entries(); i++) |
844 | if (aalg_list[i].available && aalg_list[i].pfkey_supported) |
845 | n++; |
846 | return n; |
847 | } |
848 | EXPORT_SYMBOL_GPL(xfrm_count_pfkey_auth_supported); |
849 | |
850 | int xfrm_count_pfkey_enc_supported(void) |
851 | { |
852 | int i, n; |
853 | |
854 | for (i = 0, n = 0; i < ealg_entries(); i++) |
855 | if (ealg_list[i].available && ealg_list[i].pfkey_supported) |
856 | n++; |
857 | return n; |
858 | } |
859 | EXPORT_SYMBOL_GPL(xfrm_count_pfkey_enc_supported); |
860 | |
861 | MODULE_LICENSE("GPL" ); |
862 | |