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  
aalg_entries(void)632  static inline int aalg_entries(void)
633  {
634  	return ARRAY_SIZE(aalg_list);
635  }
636  
ealg_entries(void)637  static inline int ealg_entries(void)
638  {
639  	return ARRAY_SIZE(ealg_list);
640  }
641  
calg_entries(void)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  
xfrm_find_algo(const struct xfrm_algo_list * algo_list,int match (const struct xfrm_algo_desc * entry,const void * data),const void * data,int probe)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  
xfrm_alg_id_match(const struct xfrm_algo_desc * entry,const void * data)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  
xfrm_aalg_get_byid(int alg_id)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  
xfrm_ealg_get_byid(int alg_id)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  
xfrm_calg_get_byid(int alg_id)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  
xfrm_alg_name_match(const struct xfrm_algo_desc * entry,const void * data)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  
xfrm_aalg_get_byname(const char * name,int probe)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  
xfrm_ealg_get_byname(const char * name,int probe)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  
xfrm_calg_get_byname(const char * name,int probe)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  
xfrm_aead_name_match(const struct xfrm_algo_desc * entry,const void * data)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  
xfrm_aead_get_byname(const char * name,int icv_len,int probe)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  
xfrm_aalg_get_byidx(unsigned int idx)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  
xfrm_ealg_get_byidx(unsigned int idx)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   */
xfrm_probe_algs(void)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  
xfrm_count_pfkey_auth_supported(void)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  
xfrm_count_pfkey_enc_supported(void)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_DESCRIPTION("XFRM Algorithm interface");
862  MODULE_LICENSE("GPL");
863