Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sctp: Use HMAC-SHA1 and HMAC-SHA256 library for chunk authentication

For SCTP chunk authentication, use the HMAC-SHA1 and HMAC-SHA256 library
functions instead of crypto_shash. This is simpler and faster. There's
no longer any need to pre-allocate 'crypto_shash' objects; the SCTP code
now simply calls into the HMAC code directly.

As part of this, make SCTP always support both HMAC-SHA1 and
HMAC-SHA256. Previously, it only guaranteed support for HMAC-SHA1.
However, HMAC-SHA256 tended to be supported too anyway, as it was
supported if CONFIG_CRYPTO_SHA256 was enabled elsewhere in the kconfig.

Acked-by: Xin Long <lucien.xin@gmail.com>
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
Link: https://patch.msgid.link/20250818205426.30222-4-ebiggers@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Eric Biggers and committed by
Jakub Kicinski
bf40785f dd91c79e

+48 -177
+6 -11
include/net/sctp/auth.h
··· 22 22 struct sctp_association; 23 23 struct sctp_authkey; 24 24 struct sctp_hmacalgo; 25 - struct crypto_shash; 26 25 27 - /* 28 - * Define a generic struct that will hold all the info 29 - * necessary for an HMAC transform 30 - */ 26 + /* Defines an HMAC algorithm supported by SCTP chunk authentication */ 31 27 struct sctp_hmac { 32 - __u16 hmac_id; /* one of the above ids */ 33 - char *hmac_name; /* name for loading */ 34 - __u16 hmac_len; /* length of the signature */ 28 + __u16 hmac_id; /* one of SCTP_AUTH_HMAC_ID_* */ 29 + __u16 hmac_len; /* length of the HMAC value in bytes */ 35 30 }; 36 31 37 32 /* This is generic structure that containst authentication bytes used ··· 73 78 struct sctp_association *asoc, 74 79 gfp_t gfp); 75 80 int sctp_auth_init_hmacs(struct sctp_endpoint *ep, gfp_t gfp); 76 - void sctp_auth_destroy_hmacs(struct crypto_shash *auth_hmacs[]); 77 - struct sctp_hmac *sctp_auth_get_hmac(__u16 hmac_id); 78 - struct sctp_hmac *sctp_auth_asoc_get_hmac(const struct sctp_association *asoc); 81 + const struct sctp_hmac *sctp_auth_get_hmac(__u16 hmac_id); 82 + const struct sctp_hmac * 83 + sctp_auth_asoc_get_hmac(const struct sctp_association *asoc); 79 84 void sctp_auth_asoc_set_default_hmac(struct sctp_association *asoc, 80 85 struct sctp_hmac_algo_param *hmacs); 81 86 int sctp_auth_asoc_verify_hmac_id(const struct sctp_association *asoc,
-4
include/net/sctp/constants.h
··· 417 417 SCTP_AUTH_HMAC_ID_RESERVED_0, 418 418 SCTP_AUTH_HMAC_ID_SHA1, 419 419 SCTP_AUTH_HMAC_ID_RESERVED_2, 420 - #if defined (CONFIG_CRYPTO_SHA256) || defined (CONFIG_CRYPTO_SHA256_MODULE) 421 420 SCTP_AUTH_HMAC_ID_SHA256, 422 - #endif 423 421 __SCTP_AUTH_HMAC_MAX 424 422 }; 425 423 426 424 #define SCTP_AUTH_HMAC_ID_MAX __SCTP_AUTH_HMAC_MAX - 1 427 425 #define SCTP_AUTH_NUM_HMACS __SCTP_AUTH_HMAC_MAX 428 - #define SCTP_SHA1_SIG_SIZE 20 429 - #define SCTP_SHA256_SIG_SIZE 32 430 426 431 427 /* SCTP-AUTH, Section 3.2 432 428 * The chunk types for INIT, INIT-ACK, SHUTDOWN-COMPLETE and AUTH chunks
-5
include/net/sctp/structs.h
··· 1329 1329 /* rcvbuf acct. policy. */ 1330 1330 __u32 rcvbuf_policy; 1331 1331 1332 - /* SCTP AUTH: array of the HMACs that will be allocated 1333 - * we need this per association so that we don't serialize 1334 - */ 1335 - struct crypto_shash **auth_hmacs; 1336 - 1337 1332 /* SCTP-AUTH: hmacs for the endpoint encoded into parameter */ 1338 1333 struct sctp_hmac_algo_param *auth_hmacs_list; 1339 1334
+9 -7
net/sctp/Kconfig
··· 7 7 tristate "The SCTP Protocol" 8 8 depends on INET 9 9 depends on IPV6 || IPV6=n 10 - select CRYPTO 11 - select CRYPTO_HMAC 12 - select CRYPTO_SHA1 10 + select CRYPTO_LIB_SHA1 11 + select CRYPTO_LIB_SHA256 12 + select CRYPTO_LIB_UTILS 13 13 select NET_CRC32C 14 14 select NET_UDP_TUNNEL 15 15 help ··· 79 79 bool "Enable optional MD5 hmac cookie generation" 80 80 help 81 81 Enable optional MD5 hmac based SCTP cookie generation 82 - select CRYPTO_HMAC if SCTP_COOKIE_HMAC_MD5 83 - select CRYPTO_MD5 if SCTP_COOKIE_HMAC_MD5 82 + select CRYPTO 83 + select CRYPTO_HMAC 84 + select CRYPTO_MD5 84 85 85 86 config SCTP_COOKIE_HMAC_SHA1 86 87 bool "Enable optional SHA1 hmac cookie generation" 87 88 help 88 89 Enable optional SHA1 hmac based SCTP cookie generation 89 - select CRYPTO_HMAC if SCTP_COOKIE_HMAC_SHA1 90 - select CRYPTO_SHA1 if SCTP_COOKIE_HMAC_SHA1 90 + select CRYPTO 91 + select CRYPTO_HMAC 92 + select CRYPTO_SHA1 91 93 92 94 config INET_SCTP_DIAG 93 95 depends on INET_DIAG
+29 -137
net/sctp/auth.c
··· 12 12 * Vlad Yasevich <vladislav.yasevich@hp.com> 13 13 */ 14 14 15 - #include <crypto/hash.h> 15 + #include <crypto/sha1.h> 16 + #include <crypto/sha2.h> 16 17 #include <linux/slab.h> 17 18 #include <linux/types.h> 18 - #include <linux/scatterlist.h> 19 19 #include <net/sctp/sctp.h> 20 20 #include <net/sctp/auth.h> 21 21 22 - static struct sctp_hmac sctp_hmac_list[SCTP_AUTH_NUM_HMACS] = { 22 + static const struct sctp_hmac sctp_hmac_list[SCTP_AUTH_NUM_HMACS] = { 23 23 { 24 24 /* id 0 is reserved. as all 0 */ 25 25 .hmac_id = SCTP_AUTH_HMAC_ID_RESERVED_0, 26 26 }, 27 27 { 28 28 .hmac_id = SCTP_AUTH_HMAC_ID_SHA1, 29 - .hmac_name = "hmac(sha1)", 30 - .hmac_len = SCTP_SHA1_SIG_SIZE, 29 + .hmac_len = SHA1_DIGEST_SIZE, 31 30 }, 32 31 { 33 32 /* id 2 is reserved as well */ 34 33 .hmac_id = SCTP_AUTH_HMAC_ID_RESERVED_2, 35 34 }, 36 - #if IS_ENABLED(CONFIG_CRYPTO_SHA256) 37 35 { 38 36 .hmac_id = SCTP_AUTH_HMAC_ID_SHA256, 39 - .hmac_name = "hmac(sha256)", 40 - .hmac_len = SCTP_SHA256_SIG_SIZE, 37 + .hmac_len = SHA256_DIGEST_SIZE, 41 38 } 42 - #endif 43 39 }; 44 40 41 + static bool sctp_hmac_supported(__u16 hmac_id) 42 + { 43 + return hmac_id < ARRAY_SIZE(sctp_hmac_list) && 44 + sctp_hmac_list[hmac_id].hmac_len != 0; 45 + } 45 46 46 47 void sctp_auth_key_put(struct sctp_auth_bytes *key) 47 48 { ··· 445 444 return NULL; 446 445 } 447 446 448 - /* 449 - * Initialize all the possible digest transforms that we can use. Right 450 - * now, the supported digests are SHA1 and SHA256. We do this here once 451 - * because of the restrictiong that transforms may only be allocated in 452 - * user context. This forces us to pre-allocated all possible transforms 453 - * at the endpoint init time. 454 - */ 455 - int sctp_auth_init_hmacs(struct sctp_endpoint *ep, gfp_t gfp) 456 - { 457 - struct crypto_shash *tfm = NULL; 458 - __u16 id; 459 - 460 - /* If the transforms are already allocated, we are done */ 461 - if (ep->auth_hmacs) 462 - return 0; 463 - 464 - /* Allocated the array of pointers to transorms */ 465 - ep->auth_hmacs = kcalloc(SCTP_AUTH_NUM_HMACS, 466 - sizeof(struct crypto_shash *), 467 - gfp); 468 - if (!ep->auth_hmacs) 469 - return -ENOMEM; 470 - 471 - for (id = 0; id < SCTP_AUTH_NUM_HMACS; id++) { 472 - 473 - /* See is we support the id. Supported IDs have name and 474 - * length fields set, so that we can allocated and use 475 - * them. We can safely just check for name, for without the 476 - * name, we can't allocate the TFM. 477 - */ 478 - if (!sctp_hmac_list[id].hmac_name) 479 - continue; 480 - 481 - /* If this TFM has been allocated, we are all set */ 482 - if (ep->auth_hmacs[id]) 483 - continue; 484 - 485 - /* Allocate the ID */ 486 - tfm = crypto_alloc_shash(sctp_hmac_list[id].hmac_name, 0, 0); 487 - if (IS_ERR(tfm)) 488 - goto out_err; 489 - 490 - ep->auth_hmacs[id] = tfm; 491 - } 492 - 493 - return 0; 494 - 495 - out_err: 496 - /* Clean up any successful allocations */ 497 - sctp_auth_destroy_hmacs(ep->auth_hmacs); 498 - ep->auth_hmacs = NULL; 499 - return -ENOMEM; 500 - } 501 - 502 - /* Destroy the hmac tfm array */ 503 - void sctp_auth_destroy_hmacs(struct crypto_shash *auth_hmacs[]) 504 - { 505 - int i; 506 - 507 - if (!auth_hmacs) 508 - return; 509 - 510 - for (i = 0; i < SCTP_AUTH_NUM_HMACS; i++) { 511 - crypto_free_shash(auth_hmacs[i]); 512 - } 513 - kfree(auth_hmacs); 514 - } 515 - 516 - 517 - struct sctp_hmac *sctp_auth_get_hmac(__u16 hmac_id) 447 + const struct sctp_hmac *sctp_auth_get_hmac(__u16 hmac_id) 518 448 { 519 449 return &sctp_hmac_list[hmac_id]; 520 450 } ··· 453 521 /* Get an hmac description information that we can use to build 454 522 * the AUTH chunk 455 523 */ 456 - struct sctp_hmac *sctp_auth_asoc_get_hmac(const struct sctp_association *asoc) 524 + const struct sctp_hmac * 525 + sctp_auth_asoc_get_hmac(const struct sctp_association *asoc) 457 526 { 458 527 struct sctp_hmac_algo_param *hmacs; 459 528 __u16 n_elt; ··· 476 543 sizeof(struct sctp_paramhdr)) >> 1; 477 544 for (i = 0; i < n_elt; i++) { 478 545 id = ntohs(hmacs->hmac_ids[i]); 479 - 480 - /* Check the id is in the supported range. And 481 - * see if we support the id. Supported IDs have name and 482 - * length fields set, so that we can allocate and use 483 - * them. We can safely just check for name, for without the 484 - * name, we can't allocate the TFM. 485 - */ 486 - if (id > SCTP_AUTH_HMAC_ID_MAX || 487 - !sctp_hmac_list[id].hmac_name) { 488 - id = 0; 489 - continue; 490 - } 491 - 492 - break; 546 + if (sctp_hmac_supported(id)) 547 + return &sctp_hmac_list[id]; 493 548 } 494 - 495 - if (id == 0) 496 - return NULL; 497 - 498 - return &sctp_hmac_list[id]; 549 + return NULL; 499 550 } 500 551 501 552 static int __sctp_auth_find_hmacid(__be16 *hmacs, int n_elts, __be16 hmac_id) ··· 523 606 void sctp_auth_asoc_set_default_hmac(struct sctp_association *asoc, 524 607 struct sctp_hmac_algo_param *hmacs) 525 608 { 526 - struct sctp_endpoint *ep; 527 609 __u16 id; 528 610 int i; 529 611 int n_params; ··· 533 617 534 618 n_params = (ntohs(hmacs->param_hdr.length) - 535 619 sizeof(struct sctp_paramhdr)) >> 1; 536 - ep = asoc->ep; 537 620 for (i = 0; i < n_params; i++) { 538 621 id = ntohs(hmacs->hmac_ids[i]); 539 - 540 - /* Check the id is in the supported range */ 541 - if (id > SCTP_AUTH_HMAC_ID_MAX) 542 - continue; 543 - 544 - /* If this TFM has been allocated, use this id */ 545 - if (ep->auth_hmacs[id]) { 622 + if (sctp_hmac_supported(id)) { 546 623 asoc->default_hmac_id = id; 547 624 break; 548 625 } ··· 618 709 struct sctp_shared_key *ep_key, gfp_t gfp) 619 710 { 620 711 struct sctp_auth_bytes *asoc_key; 621 - struct crypto_shash *tfm; 622 712 __u16 key_id, hmac_id; 623 - unsigned char *end; 624 713 int free_key = 0; 714 + size_t data_len; 625 715 __u8 *digest; 626 716 627 717 /* Extract the info we need: ··· 641 733 free_key = 1; 642 734 } 643 735 644 - /* set up scatter list */ 645 - end = skb_tail_pointer(skb); 646 - 647 - tfm = asoc->ep->auth_hmacs[hmac_id]; 648 - 736 + data_len = skb_tail_pointer(skb) - (unsigned char *)auth; 649 737 digest = (u8 *)(&auth->auth_hdr + 1); 650 - if (crypto_shash_setkey(tfm, &asoc_key->data[0], asoc_key->len)) 651 - goto free; 738 + if (hmac_id == SCTP_AUTH_HMAC_ID_SHA1) { 739 + hmac_sha1_usingrawkey(asoc_key->data, asoc_key->len, 740 + (const u8 *)auth, data_len, digest); 741 + } else { 742 + WARN_ON_ONCE(hmac_id != SCTP_AUTH_HMAC_ID_SHA256); 743 + hmac_sha256_usingrawkey(asoc_key->data, asoc_key->len, 744 + (const u8 *)auth, data_len, digest); 745 + } 652 746 653 - crypto_shash_tfm_digest(tfm, (u8 *)auth, end - (unsigned char *)auth, 654 - digest); 655 - 656 - free: 657 747 if (free_key) 658 748 sctp_auth_key_put(asoc_key); 659 749 } ··· 694 788 for (i = 0; i < hmacs->shmac_num_idents; i++) { 695 789 id = hmacs->shmac_idents[i]; 696 790 697 - if (id > SCTP_AUTH_HMAC_ID_MAX) 791 + if (!sctp_hmac_supported(id)) 698 792 return -EOPNOTSUPP; 699 793 700 794 if (SCTP_AUTH_HMAC_ID_SHA1 == id) 701 795 has_sha1 = 1; 702 - 703 - if (!sctp_hmac_list[id].hmac_name) 704 - return -EOPNOTSUPP; 705 796 } 706 797 707 798 if (!has_sha1) ··· 924 1021 925 1022 int sctp_auth_init(struct sctp_endpoint *ep, gfp_t gfp) 926 1023 { 927 - int err = -ENOMEM; 928 - 929 1024 /* Allocate space for HMACS and CHUNKS authentication 930 1025 * variables. There are arrays that we encode directly 931 1026 * into parameters to make the rest of the operations easier. ··· 961 1060 ep->auth_chunk_list = auth_chunks; 962 1061 } 963 1062 964 - /* Allocate and initialize transorms arrays for supported 965 - * HMACs. 966 - */ 967 - err = sctp_auth_init_hmacs(ep, gfp); 968 - if (err) 969 - goto nomem; 970 - 971 1063 return 0; 972 1064 973 1065 nomem: ··· 969 1075 kfree(ep->auth_chunk_list); 970 1076 ep->auth_hmacs_list = NULL; 971 1077 ep->auth_chunk_list = NULL; 972 - return err; 1078 + return -ENOMEM; 973 1079 } 974 1080 975 1081 void sctp_auth_free(struct sctp_endpoint *ep) ··· 978 1084 kfree(ep->auth_chunk_list); 979 1085 ep->auth_hmacs_list = NULL; 980 1086 ep->auth_chunk_list = NULL; 981 - sctp_auth_destroy_hmacs(ep->auth_hmacs); 982 - ep->auth_hmacs = NULL; 983 1087 }
+2 -1
net/sctp/chunk.c
··· 184 184 * DATA. 185 185 */ 186 186 if (sctp_auth_send_cid(SCTP_CID_DATA, asoc)) { 187 - struct sctp_hmac *hmac_desc = sctp_auth_asoc_get_hmac(asoc); 187 + const struct sctp_hmac *hmac_desc = 188 + sctp_auth_asoc_get_hmac(asoc); 188 189 189 190 if (hmac_desc) 190 191 max_data -= SCTP_PAD4(sizeof(struct sctp_auth_chunk) +
+1 -1
net/sctp/sm_make_chunk.c
··· 1320 1320 __u16 key_id) 1321 1321 { 1322 1322 struct sctp_authhdr auth_hdr; 1323 - struct sctp_hmac *hmac_desc; 1323 + const struct sctp_hmac *hmac_desc; 1324 1324 struct sctp_chunk *retval; 1325 1325 1326 1326 /* Get the first hmac that the peer told us to use */
+1 -1
net/sctp/sm_statefuns.c
··· 4362 4362 struct sctp_shared_key *sh_key = NULL; 4363 4363 struct sctp_authhdr *auth_hdr; 4364 4364 __u8 *save_digest, *digest; 4365 - struct sctp_hmac *hmac; 4365 + const struct sctp_hmac *hmac; 4366 4366 unsigned int sig_len; 4367 4367 __u16 key_id; 4368 4368
-10
net/sctp/socket.c
··· 9581 9581 if (err) 9582 9582 return err; 9583 9583 9584 - /* New ep's auth_hmacs should be set if old ep's is set, in case 9585 - * that net->sctp.auth_enable has been changed to 0 by users and 9586 - * new ep's auth_hmacs couldn't be set in sctp_endpoint_init(). 9587 - */ 9588 - if (oldsp->ep->auth_hmacs) { 9589 - err = sctp_auth_init_hmacs(newsp->ep, GFP_KERNEL); 9590 - if (err) 9591 - return err; 9592 - } 9593 - 9594 9584 sctp_auto_asconf_init(newsp); 9595 9585 9596 9586 /* Move any messages in the old socket's receive queue that are for the