xref: /linux/net/xfrm/xfrm_algo.c (revision 0fc8f6200d2313278fbf4539bbab74677c685531)
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/acompress.h>
9 #include <crypto/aead.h>
10 #include <crypto/hash.h>
11 #include <crypto/skcipher.h>
12 #include <linux/module.h>
13 #include <linux/kernel.h>
14 #include <linux/pfkeyv2.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 = "xcbc(aes)",
295 
296 	.uinfo = {
297 		.auth = {
298 			.icv_truncbits = 96,
299 			.icv_fullbits = 128,
300 		}
301 	},
302 
303 	.pfkey_supported = 1,
304 
305 	.desc = {
306 		.sadb_alg_id = SADB_X_AALG_AES_XCBC_MAC,
307 		.sadb_alg_ivlen = 0,
308 		.sadb_alg_minbits = 128,
309 		.sadb_alg_maxbits = 128
310 	}
311 },
312 {
313 	/* rfc4494 */
314 	.name = "cmac(aes)",
315 
316 	.uinfo = {
317 		.auth = {
318 			.icv_truncbits = 96,
319 			.icv_fullbits = 128,
320 		}
321 	},
322 
323 	.pfkey_supported = 0,
324 },
325 {
326 	.name = "hmac(sm3)",
327 	.compat = "sm3",
328 
329 	.uinfo = {
330 		.auth = {
331 			.icv_truncbits = 256,
332 			.icv_fullbits = 256,
333 		}
334 	},
335 
336 	.pfkey_supported = 1,
337 
338 	.desc = {
339 		.sadb_alg_id = SADB_X_AALG_SM3_256HMAC,
340 		.sadb_alg_ivlen = 0,
341 		.sadb_alg_minbits = 256,
342 		.sadb_alg_maxbits = 256
343 	}
344 },
345 };
346 
347 static struct xfrm_algo_desc ealg_list[] = {
348 {
349 	.name = "ecb(cipher_null)",
350 	.compat = "cipher_null",
351 
352 	.uinfo = {
353 		.encr = {
354 			.blockbits = 8,
355 			.defkeybits = 0,
356 		}
357 	},
358 
359 	.pfkey_supported = 1,
360 
361 	.desc = {
362 		.sadb_alg_id =	SADB_EALG_NULL,
363 		.sadb_alg_ivlen = 0,
364 		.sadb_alg_minbits = 0,
365 		.sadb_alg_maxbits = 0
366 	}
367 },
368 {
369 	.name = "cbc(des)",
370 	.compat = "des",
371 
372 	.uinfo = {
373 		.encr = {
374 			.geniv = "echainiv",
375 			.blockbits = 64,
376 			.defkeybits = 64,
377 		}
378 	},
379 
380 	.pfkey_supported = 1,
381 
382 	.desc = {
383 		.sadb_alg_id = SADB_EALG_DESCBC,
384 		.sadb_alg_ivlen = 8,
385 		.sadb_alg_minbits = 64,
386 		.sadb_alg_maxbits = 64
387 	}
388 },
389 {
390 	.name = "cbc(des3_ede)",
391 	.compat = "des3_ede",
392 
393 	.uinfo = {
394 		.encr = {
395 			.geniv = "echainiv",
396 			.blockbits = 64,
397 			.defkeybits = 192,
398 		}
399 	},
400 
401 	.pfkey_supported = 1,
402 
403 	.desc = {
404 		.sadb_alg_id = SADB_EALG_3DESCBC,
405 		.sadb_alg_ivlen = 8,
406 		.sadb_alg_minbits = 192,
407 		.sadb_alg_maxbits = 192
408 	}
409 },
410 {
411 	.name = "cbc(cast5)",
412 	.compat = "cast5",
413 
414 	.uinfo = {
415 		.encr = {
416 			.geniv = "echainiv",
417 			.blockbits = 64,
418 			.defkeybits = 128,
419 		}
420 	},
421 
422 	.pfkey_supported = 1,
423 
424 	.desc = {
425 		.sadb_alg_id = SADB_X_EALG_CASTCBC,
426 		.sadb_alg_ivlen = 8,
427 		.sadb_alg_minbits = 40,
428 		.sadb_alg_maxbits = 128
429 	}
430 },
431 {
432 	.name = "cbc(blowfish)",
433 	.compat = "blowfish",
434 
435 	.uinfo = {
436 		.encr = {
437 			.geniv = "echainiv",
438 			.blockbits = 64,
439 			.defkeybits = 128,
440 		}
441 	},
442 
443 	.pfkey_supported = 1,
444 
445 	.desc = {
446 		.sadb_alg_id = SADB_X_EALG_BLOWFISHCBC,
447 		.sadb_alg_ivlen = 8,
448 		.sadb_alg_minbits = 40,
449 		.sadb_alg_maxbits = 448
450 	}
451 },
452 {
453 	.name = "cbc(aes)",
454 	.compat = "aes",
455 
456 	.uinfo = {
457 		.encr = {
458 			.geniv = "echainiv",
459 			.blockbits = 128,
460 			.defkeybits = 128,
461 		}
462 	},
463 
464 	.pfkey_supported = 1,
465 
466 	.desc = {
467 		.sadb_alg_id = SADB_X_EALG_AESCBC,
468 		.sadb_alg_ivlen = 8,
469 		.sadb_alg_minbits = 128,
470 		.sadb_alg_maxbits = 256
471 	}
472 },
473 {
474 	.name = "cbc(serpent)",
475 	.compat = "serpent",
476 
477 	.uinfo = {
478 		.encr = {
479 			.geniv = "echainiv",
480 			.blockbits = 128,
481 			.defkeybits = 128,
482 		}
483 	},
484 
485 	.pfkey_supported = 1,
486 
487 	.desc = {
488 		.sadb_alg_id = SADB_X_EALG_SERPENTCBC,
489 		.sadb_alg_ivlen = 8,
490 		.sadb_alg_minbits = 128,
491 		.sadb_alg_maxbits = 256,
492 	}
493 },
494 {
495 	.name = "cbc(camellia)",
496 	.compat = "camellia",
497 
498 	.uinfo = {
499 		.encr = {
500 			.geniv = "echainiv",
501 			.blockbits = 128,
502 			.defkeybits = 128,
503 		}
504 	},
505 
506 	.pfkey_supported = 1,
507 
508 	.desc = {
509 		.sadb_alg_id = SADB_X_EALG_CAMELLIACBC,
510 		.sadb_alg_ivlen = 8,
511 		.sadb_alg_minbits = 128,
512 		.sadb_alg_maxbits = 256
513 	}
514 },
515 {
516 	.name = "cbc(twofish)",
517 	.compat = "twofish",
518 
519 	.uinfo = {
520 		.encr = {
521 			.geniv = "echainiv",
522 			.blockbits = 128,
523 			.defkeybits = 128,
524 		}
525 	},
526 
527 	.pfkey_supported = 1,
528 
529 	.desc = {
530 		.sadb_alg_id = SADB_X_EALG_TWOFISHCBC,
531 		.sadb_alg_ivlen = 8,
532 		.sadb_alg_minbits = 128,
533 		.sadb_alg_maxbits = 256
534 	}
535 },
536 {
537 	.name = "rfc3686(ctr(aes))",
538 
539 	.uinfo = {
540 		.encr = {
541 			.geniv = "seqiv",
542 			.blockbits = 128,
543 			.defkeybits = 160, /* 128-bit key + 32-bit nonce */
544 		}
545 	},
546 
547 	.pfkey_supported = 1,
548 
549 	.desc = {
550 		.sadb_alg_id = SADB_X_EALG_AESCTR,
551 		.sadb_alg_ivlen	= 8,
552 		.sadb_alg_minbits = 160,
553 		.sadb_alg_maxbits = 288
554 	}
555 },
556 {
557 	.name = "cbc(sm4)",
558 	.compat = "sm4",
559 
560 	.uinfo = {
561 		.encr = {
562 			.geniv = "echainiv",
563 			.blockbits = 128,
564 			.defkeybits = 128,
565 		}
566 	},
567 
568 	.pfkey_supported = 1,
569 
570 	.desc = {
571 		.sadb_alg_id = SADB_X_EALG_SM4CBC,
572 		.sadb_alg_ivlen	= 16,
573 		.sadb_alg_minbits = 128,
574 		.sadb_alg_maxbits = 256
575 	}
576 },
577 };
578 
579 static struct xfrm_algo_desc calg_list[] = {
580 {
581 	.name = "deflate",
582 	.uinfo = {
583 		.comp = {
584 			.threshold = 90,
585 		}
586 	},
587 	.pfkey_supported = 1,
588 	.desc = { .sadb_alg_id = SADB_X_CALG_DEFLATE }
589 },
590 {
591 	.name = "lzs",
592 	.uinfo = {
593 		.comp = {
594 			.threshold = 90,
595 		}
596 	},
597 	.pfkey_supported = 1,
598 	.desc = { .sadb_alg_id = SADB_X_CALG_LZS }
599 },
600 {
601 	.name = "lzjh",
602 	.uinfo = {
603 		.comp = {
604 			.threshold = 50,
605 		}
606 	},
607 	.pfkey_supported = 1,
608 	.desc = { .sadb_alg_id = SADB_X_CALG_LZJH }
609 },
610 };
611 
612 static inline int aalg_entries(void)
613 {
614 	return ARRAY_SIZE(aalg_list);
615 }
616 
617 static inline int ealg_entries(void)
618 {
619 	return ARRAY_SIZE(ealg_list);
620 }
621 
622 static inline int calg_entries(void)
623 {
624 	return ARRAY_SIZE(calg_list);
625 }
626 
627 struct xfrm_algo_list {
628 	int (*find)(const char *name, u32 type, u32 mask);
629 	struct xfrm_algo_desc *algs;
630 	int entries;
631 };
632 
633 static const struct xfrm_algo_list xfrm_aead_list = {
634 	.find = crypto_has_aead,
635 	.algs = aead_list,
636 	.entries = ARRAY_SIZE(aead_list),
637 };
638 
639 static const struct xfrm_algo_list xfrm_aalg_list = {
640 	.find = crypto_has_ahash,
641 	.algs = aalg_list,
642 	.entries = ARRAY_SIZE(aalg_list),
643 };
644 
645 static const struct xfrm_algo_list xfrm_ealg_list = {
646 	.find = crypto_has_skcipher,
647 	.algs = ealg_list,
648 	.entries = ARRAY_SIZE(ealg_list),
649 };
650 
651 static const struct xfrm_algo_list xfrm_calg_list = {
652 	.find = crypto_has_acomp,
653 	.algs = calg_list,
654 	.entries = ARRAY_SIZE(calg_list),
655 };
656 
657 static struct xfrm_algo_desc *xfrm_find_algo(
658 	const struct xfrm_algo_list *algo_list,
659 	int match(const struct xfrm_algo_desc *entry, const void *data),
660 	const void *data, int probe)
661 {
662 	struct xfrm_algo_desc *list = algo_list->algs;
663 	int i, status;
664 
665 	for (i = 0; i < algo_list->entries; i++) {
666 		if (!match(list + i, data))
667 			continue;
668 
669 		if (list[i].available)
670 			return &list[i];
671 
672 		if (!probe)
673 			break;
674 
675 		status = algo_list->find(list[i].name, 0, 0);
676 		if (!status)
677 			break;
678 
679 		list[i].available = status;
680 		return &list[i];
681 	}
682 	return NULL;
683 }
684 
685 static int xfrm_alg_id_match(const struct xfrm_algo_desc *entry,
686 			     const void *data)
687 {
688 	return entry->desc.sadb_alg_id == (unsigned long)data;
689 }
690 
691 struct xfrm_algo_desc *xfrm_aalg_get_byid(int alg_id)
692 {
693 	return xfrm_find_algo(&xfrm_aalg_list, xfrm_alg_id_match,
694 			      (void *)(unsigned long)alg_id, 1);
695 }
696 EXPORT_SYMBOL_GPL(xfrm_aalg_get_byid);
697 
698 struct xfrm_algo_desc *xfrm_ealg_get_byid(int alg_id)
699 {
700 	return xfrm_find_algo(&xfrm_ealg_list, xfrm_alg_id_match,
701 			      (void *)(unsigned long)alg_id, 1);
702 }
703 EXPORT_SYMBOL_GPL(xfrm_ealg_get_byid);
704 
705 struct xfrm_algo_desc *xfrm_calg_get_byid(int alg_id)
706 {
707 	return xfrm_find_algo(&xfrm_calg_list, xfrm_alg_id_match,
708 			      (void *)(unsigned long)alg_id, 1);
709 }
710 EXPORT_SYMBOL_GPL(xfrm_calg_get_byid);
711 
712 static int xfrm_alg_name_match(const struct xfrm_algo_desc *entry,
713 			       const void *data)
714 {
715 	const char *name = data;
716 
717 	return name && (!strcmp(name, entry->name) ||
718 			(entry->compat && !strcmp(name, entry->compat)));
719 }
720 
721 struct xfrm_algo_desc *xfrm_aalg_get_byname(const char *name, int probe)
722 {
723 	return xfrm_find_algo(&xfrm_aalg_list, xfrm_alg_name_match, name,
724 			      probe);
725 }
726 EXPORT_SYMBOL_GPL(xfrm_aalg_get_byname);
727 
728 struct xfrm_algo_desc *xfrm_ealg_get_byname(const char *name, int probe)
729 {
730 	return xfrm_find_algo(&xfrm_ealg_list, xfrm_alg_name_match, name,
731 			      probe);
732 }
733 EXPORT_SYMBOL_GPL(xfrm_ealg_get_byname);
734 
735 struct xfrm_algo_desc *xfrm_calg_get_byname(const char *name, int probe)
736 {
737 	return xfrm_find_algo(&xfrm_calg_list, xfrm_alg_name_match, name,
738 			      probe);
739 }
740 EXPORT_SYMBOL_GPL(xfrm_calg_get_byname);
741 
742 struct xfrm_aead_name {
743 	const char *name;
744 	int icvbits;
745 };
746 
747 static int xfrm_aead_name_match(const struct xfrm_algo_desc *entry,
748 				const void *data)
749 {
750 	const struct xfrm_aead_name *aead = data;
751 	const char *name = aead->name;
752 
753 	return aead->icvbits == entry->uinfo.aead.icv_truncbits && name &&
754 	       !strcmp(name, entry->name);
755 }
756 
757 struct xfrm_algo_desc *xfrm_aead_get_byname(const char *name, int icv_len, int probe)
758 {
759 	struct xfrm_aead_name data = {
760 		.name = name,
761 		.icvbits = icv_len,
762 	};
763 
764 	return xfrm_find_algo(&xfrm_aead_list, xfrm_aead_name_match, &data,
765 			      probe);
766 }
767 EXPORT_SYMBOL_GPL(xfrm_aead_get_byname);
768 
769 struct xfrm_algo_desc *xfrm_aalg_get_byidx(unsigned int idx)
770 {
771 	if (idx >= aalg_entries())
772 		return NULL;
773 
774 	return &aalg_list[idx];
775 }
776 EXPORT_SYMBOL_GPL(xfrm_aalg_get_byidx);
777 
778 struct xfrm_algo_desc *xfrm_ealg_get_byidx(unsigned int idx)
779 {
780 	if (idx >= ealg_entries())
781 		return NULL;
782 
783 	return &ealg_list[idx];
784 }
785 EXPORT_SYMBOL_GPL(xfrm_ealg_get_byidx);
786 
787 /*
788  * Probe for the availability of crypto algorithms, and set the available
789  * flag for any algorithms found on the system.  This is typically called by
790  * pfkey during userspace SA add, update or register.
791  */
792 void xfrm_probe_algs(void)
793 {
794 	int i, status;
795 
796 	BUG_ON(in_softirq());
797 
798 	for (i = 0; i < aalg_entries(); i++) {
799 		status = crypto_has_ahash(aalg_list[i].name, 0, 0);
800 		if (aalg_list[i].available != status)
801 			aalg_list[i].available = status;
802 	}
803 
804 	for (i = 0; i < ealg_entries(); i++) {
805 		status = crypto_has_skcipher(ealg_list[i].name, 0, 0);
806 		if (ealg_list[i].available != status)
807 			ealg_list[i].available = status;
808 	}
809 
810 	for (i = 0; i < calg_entries(); i++) {
811 		status = crypto_has_acomp(calg_list[i].name, 0, 0);
812 		if (calg_list[i].available != status)
813 			calg_list[i].available = status;
814 	}
815 }
816 EXPORT_SYMBOL_GPL(xfrm_probe_algs);
817 
818 int xfrm_count_pfkey_auth_supported(void)
819 {
820 	int i, n;
821 
822 	for (i = 0, n = 0; i < aalg_entries(); i++)
823 		if (aalg_list[i].available && aalg_list[i].pfkey_supported)
824 			n++;
825 	return n;
826 }
827 EXPORT_SYMBOL_GPL(xfrm_count_pfkey_auth_supported);
828 
829 int xfrm_count_pfkey_enc_supported(void)
830 {
831 	int i, n;
832 
833 	for (i = 0, n = 0; i < ealg_entries(); i++)
834 		if (ealg_list[i].available && ealg_list[i].pfkey_supported)
835 			n++;
836 	return n;
837 }
838 EXPORT_SYMBOL_GPL(xfrm_count_pfkey_enc_supported);
839 
840 MODULE_DESCRIPTION("XFRM Algorithm interface");
841 MODULE_LICENSE("GPL");
842