xref: /linux/net/xfrm/xfrm_algo.c (revision cbe0e415089636170aa6eb540ca4af5dc9842a60)
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(&xfrm_aalg_list, xfrm_alg_id_match,
714 			      (void *)(unsigned long)alg_id, 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(&xfrm_ealg_list, xfrm_alg_id_match,
721 			      (void *)(unsigned long)alg_id, 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(&xfrm_calg_list, xfrm_alg_id_match,
728 			      (void *)(unsigned long)alg_id, 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(&xfrm_aalg_list, xfrm_alg_name_match, 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(&xfrm_ealg_list, xfrm_alg_name_match, 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(&xfrm_calg_list, xfrm_alg_name_match, 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(&xfrm_aead_list, xfrm_aead_name_match, &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(aalg_list[i].name, 0, 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(ealg_list[i].name, 0, 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(calg_list[i].name, 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