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