linux/net/xfrm/xfrm_algo.c
<<
>>
Prefs
   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 */
  28static struct xfrm_algo_desc aead_list[] = {
  29{
  30        .name = "rfc4106(gcm(aes))",
  31
  32        .uinfo = {
  33                .aead = {
  34                        .geniv = "seqiv",
  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 = "seqiv",
  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 = "seqiv",
  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 = "seqiv",
  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 = "seqiv",
 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 = "seqiv",
 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 = "seqiv",
 168                        .icv_truncbits = 128,
 169                }
 170        },
 171
 172        .pfkey_supported = 0,
 173},
 174};
 175
 176static 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
 348static 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
 559static 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
 592static inline int aalg_entries(void)
 593{
 594        return ARRAY_SIZE(aalg_list);
 595}
 596
 597static inline int ealg_entries(void)
 598{
 599        return ARRAY_SIZE(ealg_list);
 600}
 601
 602static inline int calg_entries(void)
 603{
 604        return ARRAY_SIZE(calg_list);
 605}
 606
 607struct xfrm_algo_list {
 608        struct xfrm_algo_desc *algs;
 609        int entries;
 610        u32 type;
 611        u32 mask;
 612};
 613
 614static 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
 621static 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
 628static 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
 635static 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
 642static 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
 671static 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
 677struct 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}
 682EXPORT_SYMBOL_GPL(xfrm_aalg_get_byid);
 683
 684struct 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}
 689EXPORT_SYMBOL_GPL(xfrm_ealg_get_byid);
 690
 691struct 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}
 696EXPORT_SYMBOL_GPL(xfrm_calg_get_byid);
 697
 698static 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
 707struct 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}
 712EXPORT_SYMBOL_GPL(xfrm_aalg_get_byname);
 713
 714struct 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}
 719EXPORT_SYMBOL_GPL(xfrm_ealg_get_byname);
 720
 721struct 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}
 726EXPORT_SYMBOL_GPL(xfrm_calg_get_byname);
 727
 728struct xfrm_aead_name {
 729        const char *name;
 730        int icvbits;
 731};
 732
 733static 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
 743struct 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}
 753EXPORT_SYMBOL_GPL(xfrm_aead_get_byname);
 754
 755struct 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}
 762EXPORT_SYMBOL_GPL(xfrm_aalg_get_byidx);
 763
 764struct 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}
 771EXPORT_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 */
 778void 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}
 804EXPORT_SYMBOL_GPL(xfrm_probe_algs);
 805
 806int 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}
 815EXPORT_SYMBOL_GPL(xfrm_count_pfkey_auth_supported);
 816
 817int 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}
 826EXPORT_SYMBOL_GPL(xfrm_count_pfkey_enc_supported);
 827
 828MODULE_LICENSE("GPL");
 829