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