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