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

sctp: Convert cookie authentication to use HMAC-SHA256

Convert SCTP cookies to use HMAC-SHA256, instead of the previous choice
of the legacy algorithms HMAC-MD5 and HMAC-SHA1. Simplify and optimize
the code by using the HMAC-SHA256 library instead of crypto_shash, and
by preparing the HMAC key when it is generated instead of per-operation.

This doesn't break compatibility, since the cookie format is an
implementation detail, not part of the SCTP protocol itself.

Note that the cookie size doesn't change either. The HMAC field was
already 32 bytes, even though previously at most 20 bytes were actually
compared. 32 bytes exactly fits an untruncated HMAC-SHA256 value. So,
although we could safely truncate the MAC to something slightly shorter,
for now just keep the cookie size the same.

I also considered SipHash, but that would generate only 8-byte MACs. An
8-byte MAC *might* suffice here. However, there's quite a lot of
information in the SCTP cookies: more than in TCP SYN cookies. So
absent an analysis that occasional forgeries of all that information is
okay in SCTP, I errored on the side of caution.

Remove HMAC-MD5 and HMAC-SHA1 as options, since the new HMAC-SHA256
option is just better. It's faster as well as more secure. For
example, benchmarking on x86_64, cookie authentication is now nearly 3x
as fast as the previous default choice and implementation of HMAC-MD5.

Also just make the kernel always support cookie authentication if SCTP
is supported at all, rather than making it optional in the build. (It
was sort of optional before, but it didn't really work properly. E.g.,
a kernel with CONFIG_SCTP_COOKIE_HMAC_MD5=n still supported HMAC-MD5
cookie authentication if CONFIG_CRYPTO_HMAC and CONFIG_CRYPTO_MD5
happened to be enabled in the kconfig for other reasons.)

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

authored by

Eric Biggers and committed by
Jakub Kicinski
2f3dd6ec bf40785f

+80 -188
+4 -7
Documentation/networking/ip-sysctl.rst
··· 3508 3508 a listening sctp socket to a connecting client in the INIT-ACK chunk. 3509 3509 Valid values are: 3510 3510 3511 - * md5 3512 - * sha1 3511 + * sha256 3513 3512 * none 3514 3513 3515 - Ability to assign md5 or sha1 as the selected alg is predicated on the 3516 - configuration of those algorithms at build time (CONFIG_CRYPTO_MD5 and 3517 - CONFIG_CRYPTO_SHA1). 3514 + md5 and sha1 are also accepted for backwards compatibility, but cause 3515 + sha256 to be selected. 3518 3516 3519 - Default: Dependent on configuration. MD5 if available, else SHA1 if 3520 - available, else none. 3517 + Default: sha256 3521 3518 3522 3519 rcvbuf_policy - INTEGER 3523 3520 Determines if the receive buffer is attributed to the socket or to
+2 -2
include/net/netns/sctp.h
··· 75 75 /* Whether Cookie Preservative is enabled(1) or not(0) */ 76 76 int cookie_preserve_enable; 77 77 78 - /* The namespace default hmac alg */ 79 - char *sctp_hmac_alg; 78 + /* Whether cookie authentication is enabled(1) or not(0) */ 79 + int cookie_auth_enable; 80 80 81 81 /* Valid.Cookie.Life - 60 seconds */ 82 82 unsigned int valid_cookie_life;
+2 -3
include/net/sctp/constants.h
··· 296 296 */ 297 297 #define SCTP_DEFAULT_MINSEGMENT 512 /* MTU size ... if no mtu disc */ 298 298 299 - #define SCTP_SECRET_SIZE 32 /* Number of octets in a 256 bits. */ 300 - 301 - #define SCTP_SIGNATURE_SIZE 20 /* size of a SLA-1 signature */ 299 + #define SCTP_COOKIE_KEY_SIZE 32 /* size of cookie HMAC key */ 300 + #define SCTP_COOKIE_MAC_SIZE 32 /* size of HMAC field in cookies */ 302 301 303 302 #define SCTP_COOKIE_MULTIPLE 32 /* Pad out our cookie to make our hash 304 303 * functions simpler to write.
+6 -22
include/net/sctp/structs.h
··· 32 32 #ifndef __sctp_structs_h__ 33 33 #define __sctp_structs_h__ 34 34 35 + #include <crypto/sha2.h> 35 36 #include <linux/ktime.h> 36 37 #include <linux/generic-radix-tree.h> 37 38 #include <linux/rhashtable-types.h> ··· 69 68 struct sctp_bind_addr; 70 69 struct sctp_ulpq; 71 70 struct sctp_ep_common; 72 - struct crypto_shash; 73 71 struct sctp_stream; 74 72 75 73 ··· 155 155 /* PF_ family specific functions. */ 156 156 struct sctp_pf *pf; 157 157 158 - /* Access to HMAC transform. */ 159 - struct crypto_shash *hmac; 160 - char *sctp_hmac_alg; 161 - 162 158 /* What is our base endpointer? */ 163 159 struct sctp_endpoint *ep; 164 160 ··· 223 227 frag_interleave:1, 224 228 recvrcvinfo:1, 225 229 recvnxtinfo:1, 226 - data_ready_signalled:1; 230 + data_ready_signalled:1, 231 + cookie_auth_enable:1; 227 232 228 233 atomic_t pd_mode; 229 234 ··· 332 335 333 336 /* The format of our cookie that we send to our peer. */ 334 337 struct sctp_signed_cookie { 335 - __u8 signature[SCTP_SECRET_SIZE]; 338 + __u8 mac[SCTP_COOKIE_MAC_SIZE]; 336 339 __u32 __pad; /* force sctp_cookie alignment to 64 bits */ 337 340 struct sctp_cookie c; 338 341 } __packed; ··· 1304 1307 /* This is really a list of struct sctp_association entries. */ 1305 1308 struct list_head asocs; 1306 1309 1307 - /* Secret Key: A secret key used by this endpoint to compute 1308 - * the MAC. This SHOULD be a cryptographic quality 1309 - * random number with a sufficient length. 1310 - * Discussion in [RFC1750] can be helpful in 1311 - * selection of the key. 1312 - */ 1313 - __u8 secret_key[SCTP_SECRET_SIZE]; 1310 + /* Cookie authentication key used by this endpoint */ 1311 + struct hmac_sha256_key cookie_auth_key; 1314 1312 1315 - /* digest: This is a digest of the sctp cookie. This field is 1316 - * only used on the receive path when we try to validate 1317 - * that the cookie has not been tampered with. We put 1318 - * this here so we pre-allocate this once and can re-use 1319 - * on every receive. 1320 - */ 1321 - __u8 *digest; 1322 - 1323 1313 /* sendbuf acct. policy. */ 1324 1314 __u32 sndbuf_policy; 1325 1315
+10 -33
net/sctp/Kconfig
··· 49 49 'cat /proc/net/sctp/sctp_dbg_objcnt' 50 50 51 51 If unsure, say N 52 + 52 53 choice 53 - prompt "Default SCTP cookie HMAC encoding" 54 - default SCTP_DEFAULT_COOKIE_HMAC_MD5 54 + prompt "Default SCTP cookie authentication method" 55 + default SCTP_DEFAULT_COOKIE_HMAC_SHA256 55 56 help 56 - This option sets the default sctp cookie hmac algorithm 57 - when in doubt select 'md5' 57 + This option sets the default SCTP cookie authentication method, for 58 + when a method hasn't been explicitly selected via the 59 + net.sctp.cookie_hmac_alg sysctl. 58 60 59 - config SCTP_DEFAULT_COOKIE_HMAC_MD5 60 - bool "Enable optional MD5 hmac cookie generation" 61 - help 62 - Enable optional MD5 hmac based SCTP cookie generation 63 - select SCTP_COOKIE_HMAC_MD5 61 + If unsure, choose the default (HMAC-SHA256). 64 62 65 - config SCTP_DEFAULT_COOKIE_HMAC_SHA1 66 - bool "Enable optional SHA1 hmac cookie generation" 67 - help 68 - Enable optional SHA1 hmac based SCTP cookie generation 69 - select SCTP_COOKIE_HMAC_SHA1 63 + config SCTP_DEFAULT_COOKIE_HMAC_SHA256 64 + bool "HMAC-SHA256" 70 65 71 66 config SCTP_DEFAULT_COOKIE_HMAC_NONE 72 - bool "Use no hmac alg in SCTP cookie generation" 73 - help 74 - Use no hmac algorithm in SCTP cookie generation 67 + bool "None" 75 68 76 69 endchoice 77 - 78 - config SCTP_COOKIE_HMAC_MD5 79 - bool "Enable optional MD5 hmac cookie generation" 80 - help 81 - Enable optional MD5 hmac based SCTP cookie generation 82 - select CRYPTO 83 - select CRYPTO_HMAC 84 - select CRYPTO_MD5 85 - 86 - config SCTP_COOKIE_HMAC_SHA1 87 - bool "Enable optional SHA1 hmac cookie generation" 88 - help 89 - Enable optional SHA1 hmac based SCTP cookie generation 90 - select CRYPTO 91 - select CRYPTO_HMAC 92 - select CRYPTO_SHA1 93 70 94 71 config INET_SCTP_DIAG 95 72 depends on INET_DIAG
+12 -11
net/sctp/endpointola.c
··· 35 35 /* Forward declarations for internal helpers. */ 36 36 static void sctp_endpoint_bh_rcv(struct work_struct *work); 37 37 38 + static void gen_cookie_auth_key(struct hmac_sha256_key *key) 39 + { 40 + u8 raw_key[SCTP_COOKIE_KEY_SIZE]; 41 + 42 + get_random_bytes(raw_key, sizeof(raw_key)); 43 + hmac_sha256_preparekey(key, raw_key, sizeof(raw_key)); 44 + memzero_explicit(raw_key, sizeof(raw_key)); 45 + } 46 + 38 47 /* 39 48 * Initialize the base fields of the endpoint structure. 40 49 */ ··· 53 44 { 54 45 struct net *net = sock_net(sk); 55 46 struct sctp_shared_key *null_key; 56 - 57 - ep->digest = kzalloc(SCTP_SIGNATURE_SIZE, gfp); 58 - if (!ep->digest) 59 - return NULL; 60 47 61 48 ep->asconf_enable = net->sctp.addip_enable; 62 49 ep->auth_enable = net->sctp.auth_enable; ··· 95 90 /* Get the receive buffer policy for this endpoint */ 96 91 ep->rcvbuf_policy = net->sctp.rcvbuf_policy; 97 92 98 - /* Initialize the secret key used with cookie. */ 99 - get_random_bytes(ep->secret_key, sizeof(ep->secret_key)); 93 + /* Generate the cookie authentication key. */ 94 + gen_cookie_auth_key(&ep->cookie_auth_key); 100 95 101 96 /* SCTP-AUTH extensions*/ 102 97 INIT_LIST_HEAD(&ep->endpoint_shared_keys); ··· 123 118 nomem_shkey: 124 119 sctp_auth_free(ep); 125 120 nomem: 126 - kfree(ep->digest); 127 121 return NULL; 128 122 129 123 } ··· 209 205 return; 210 206 } 211 207 212 - /* Free the digest buffer */ 213 - kfree(ep->digest); 214 - 215 208 /* SCTP-AUTH: Free up AUTH releated data such as shared keys 216 209 * chunks and hmacs arrays that were allocated 217 210 */ ··· 219 218 sctp_inq_free(&ep->base.inqueue); 220 219 sctp_bind_addr_free(&ep->base.bind_addr); 221 220 222 - memset(ep->secret_key, 0, sizeof(ep->secret_key)); 221 + memzero_explicit(&ep->cookie_auth_key, sizeof(ep->cookie_auth_key)); 223 222 224 223 sk = ep->base.sk; 225 224 /* Remove and free the port */
+3 -8
net/sctp/protocol.c
··· 1334 1334 /* Whether Cookie Preservative is enabled(1) or not(0) */ 1335 1335 net->sctp.cookie_preserve_enable = 1; 1336 1336 1337 - /* Default sctp sockets to use md5 as their hmac alg */ 1338 - #if defined (CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5) 1339 - net->sctp.sctp_hmac_alg = "md5"; 1340 - #elif defined (CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1) 1341 - net->sctp.sctp_hmac_alg = "sha1"; 1342 - #else 1343 - net->sctp.sctp_hmac_alg = NULL; 1344 - #endif 1337 + /* Whether cookie authentication is enabled(1) or not(0) */ 1338 + net->sctp.cookie_auth_enable = 1339 + !IS_ENABLED(CONFIG_SCTP_DEFAULT_COOKIE_HMAC_NONE); 1345 1340 1346 1341 /* Max.Burst - 4 */ 1347 1342 net->sctp.max_burst = SCTP_DEFAULT_MAX_BURST;
+17 -40
net/sctp/sm_make_chunk.c
··· 30 30 31 31 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 32 32 33 - #include <crypto/hash.h> 34 33 #include <crypto/utils.h> 35 34 #include <linux/types.h> 36 35 #include <linux/kernel.h> ··· 1674 1675 * out on the network. 1675 1676 */ 1676 1677 retval = kzalloc(*cookie_len, GFP_ATOMIC); 1677 - if (!retval) 1678 - goto nodata; 1678 + if (!retval) { 1679 + *cookie_len = 0; 1680 + return NULL; 1681 + } 1679 1682 1680 1683 cookie = (struct sctp_signed_cookie *) retval->body; 1681 1684 ··· 1708 1707 memcpy((__u8 *)(cookie + 1) + 1709 1708 ntohs(init_chunk->chunk_hdr->length), raw_addrs, addrs_len); 1710 1709 1711 - if (sctp_sk(ep->base.sk)->hmac) { 1712 - struct crypto_shash *tfm = sctp_sk(ep->base.sk)->hmac; 1713 - int err; 1714 - 1715 - /* Sign the message. */ 1716 - err = crypto_shash_setkey(tfm, ep->secret_key, 1717 - sizeof(ep->secret_key)) ?: 1718 - crypto_shash_tfm_digest(tfm, (u8 *)&cookie->c, bodysize, 1719 - cookie->signature); 1720 - if (err) 1721 - goto free_cookie; 1710 + /* Sign the cookie, if cookie authentication is enabled. */ 1711 + if (sctp_sk(ep->base.sk)->cookie_auth_enable) { 1712 + static_assert(sizeof(cookie->mac) == SHA256_DIGEST_SIZE); 1713 + hmac_sha256(&ep->cookie_auth_key, (const u8 *)&cookie->c, 1714 + bodysize, cookie->mac); 1722 1715 } 1723 1716 1724 1717 return retval; 1725 - 1726 - free_cookie: 1727 - kfree(retval); 1728 - nodata: 1729 - *cookie_len = 0; 1730 - return NULL; 1731 1718 } 1732 1719 1733 1720 /* Unpack the cookie from COOKIE ECHO chunk, recreating the association. */ ··· 1730 1741 struct sctp_signed_cookie *cookie; 1731 1742 struct sk_buff *skb = chunk->skb; 1732 1743 struct sctp_cookie *bear_cookie; 1733 - __u8 *digest = ep->digest; 1734 1744 enum sctp_scope scope; 1735 1745 unsigned int len; 1736 1746 ktime_t kt; ··· 1759 1771 cookie = chunk->subh.cookie_hdr; 1760 1772 bear_cookie = &cookie->c; 1761 1773 1762 - if (!sctp_sk(ep->base.sk)->hmac) 1763 - goto no_hmac; 1774 + /* Verify the cookie's MAC, if cookie authentication is enabled. */ 1775 + if (sctp_sk(ep->base.sk)->cookie_auth_enable) { 1776 + u8 mac[SHA256_DIGEST_SIZE]; 1764 1777 1765 - /* Check the signature. */ 1766 - { 1767 - struct crypto_shash *tfm = sctp_sk(ep->base.sk)->hmac; 1768 - int err; 1769 - 1770 - err = crypto_shash_setkey(tfm, ep->secret_key, 1771 - sizeof(ep->secret_key)) ?: 1772 - crypto_shash_tfm_digest(tfm, (u8 *)bear_cookie, bodysize, 1773 - digest); 1774 - if (err) { 1775 - *error = -SCTP_IERROR_NOMEM; 1778 + hmac_sha256(&ep->cookie_auth_key, (const u8 *)bear_cookie, 1779 + bodysize, mac); 1780 + static_assert(sizeof(cookie->mac) == sizeof(mac)); 1781 + if (crypto_memneq(mac, cookie->mac, sizeof(mac))) { 1782 + *error = -SCTP_IERROR_BAD_SIG; 1776 1783 goto fail; 1777 1784 } 1778 1785 } 1779 1786 1780 - if (crypto_memneq(digest, cookie->signature, SCTP_SIGNATURE_SIZE)) { 1781 - *error = -SCTP_IERROR_BAD_SIG; 1782 - goto fail; 1783 - } 1784 - 1785 - no_hmac: 1786 1787 /* IG Section 2.35.2: 1787 1788 * 3) Compare the port numbers and the verification tag contained 1788 1789 * within the COOKIE ECHO chunk to the actual port numbers and the
+1 -30
net/sctp/socket.c
··· 37 37 38 38 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 39 39 40 - #include <crypto/hash.h> 41 40 #include <linux/types.h> 42 41 #include <linux/kernel.h> 43 42 #include <linux/wait.h> ··· 4986 4987 sp->default_rcv_context = 0; 4987 4988 sp->max_burst = net->sctp.max_burst; 4988 4989 4989 - sp->sctp_hmac_alg = net->sctp.sctp_hmac_alg; 4990 + sp->cookie_auth_enable = net->sctp.cookie_auth_enable; 4990 4991 4991 4992 /* Initialize default setup parameters. These parameters 4992 4993 * can be modified with the SCTP_INITMSG socket option or ··· 5078 5079 if (!sp->ep) 5079 5080 return -ENOMEM; 5080 5081 5081 - sp->hmac = NULL; 5082 - 5083 5082 sk->sk_destruct = sctp_destruct_sock; 5084 5083 5085 5084 SCTP_DBG_OBJCNT_INC(sock); ··· 5114 5117 sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); 5115 5118 } 5116 5119 5117 - /* Triggered when there are no references on the socket anymore */ 5118 - static void sctp_destruct_common(struct sock *sk) 5119 - { 5120 - struct sctp_sock *sp = sctp_sk(sk); 5121 - 5122 - /* Free up the HMAC transform. */ 5123 - crypto_free_shash(sp->hmac); 5124 - } 5125 - 5126 5120 static void sctp_destruct_sock(struct sock *sk) 5127 5121 { 5128 - sctp_destruct_common(sk); 5129 5122 inet_sock_destruct(sk); 5130 5123 } 5131 5124 ··· 8517 8530 { 8518 8531 struct sctp_sock *sp = sctp_sk(sk); 8519 8532 struct sctp_endpoint *ep = sp->ep; 8520 - struct crypto_shash *tfm = NULL; 8521 - char alg[32]; 8522 8533 int err; 8523 - 8524 - /* Allocate HMAC for generating cookie. */ 8525 - if (!sp->hmac && sp->sctp_hmac_alg) { 8526 - sprintf(alg, "hmac(%s)", sp->sctp_hmac_alg); 8527 - tfm = crypto_alloc_shash(alg, 0, 0); 8528 - if (IS_ERR(tfm)) { 8529 - net_info_ratelimited("failed to load transform for %s: %ld\n", 8530 - sp->sctp_hmac_alg, PTR_ERR(tfm)); 8531 - return -ENOSYS; 8532 - } 8533 - sctp_sk(sk)->hmac = tfm; 8534 - } 8535 8534 8536 8535 /* 8537 8536 * If a bind() or sctp_bindx() is not called prior to a listen() ··· 9534 9561 * copy. 9535 9562 */ 9536 9563 newsp->ep = newep; 9537 - newsp->hmac = NULL; 9538 9564 9539 9565 /* Hook this new socket in to the bind_hash list. */ 9540 9566 head = &sctp_port_hashtable[sctp_phashfn(sock_net(oldsk), ··· 9685 9713 9686 9714 static void sctp_v6_destruct_sock(struct sock *sk) 9687 9715 { 9688 - sctp_destruct_common(sk); 9689 9716 inet6_sock_destruct(sk); 9690 9717 } 9691 9718
+23 -32
net/sctp/sysctl.c
··· 174 174 }, 175 175 { 176 176 .procname = "cookie_hmac_alg", 177 - .data = &init_net.sctp.sctp_hmac_alg, 177 + .data = &init_net.sctp.cookie_auth_enable, 178 178 .maxlen = 8, 179 179 .mode = 0644, 180 180 .proc_handler = proc_sctp_do_hmac_alg, ··· 388 388 void *buffer, size_t *lenp, loff_t *ppos) 389 389 { 390 390 struct net *net = container_of(ctl->data, struct net, 391 - sctp.sctp_hmac_alg); 391 + sctp.cookie_auth_enable); 392 392 struct ctl_table tbl; 393 - bool changed = false; 394 - char *none = "none"; 395 393 char tmp[8] = {0}; 396 394 int ret; 397 395 ··· 397 399 398 400 if (write) { 399 401 tbl.data = tmp; 400 - tbl.maxlen = sizeof(tmp); 401 - } else { 402 - tbl.data = net->sctp.sctp_hmac_alg ? : none; 403 - tbl.maxlen = strlen(tbl.data); 402 + tbl.maxlen = sizeof(tmp) - 1; 403 + ret = proc_dostring(&tbl, 1, buffer, lenp, ppos); 404 + if (ret) 405 + return ret; 406 + if (!strcmp(tmp, "sha256") || 407 + /* for backwards compatibility */ 408 + !strcmp(tmp, "md5") || !strcmp(tmp, "sha1")) { 409 + net->sctp.cookie_auth_enable = 1; 410 + return 0; 411 + } 412 + if (!strcmp(tmp, "none")) { 413 + net->sctp.cookie_auth_enable = 0; 414 + return 0; 415 + } 416 + return -EINVAL; 404 417 } 405 - 406 - ret = proc_dostring(&tbl, write, buffer, lenp, ppos); 407 - if (write && ret == 0) { 408 - #ifdef CONFIG_CRYPTO_MD5 409 - if (!strncmp(tmp, "md5", 3)) { 410 - net->sctp.sctp_hmac_alg = "md5"; 411 - changed = true; 412 - } 413 - #endif 414 - #ifdef CONFIG_CRYPTO_SHA1 415 - if (!strncmp(tmp, "sha1", 4)) { 416 - net->sctp.sctp_hmac_alg = "sha1"; 417 - changed = true; 418 - } 419 - #endif 420 - if (!strncmp(tmp, "none", 4)) { 421 - net->sctp.sctp_hmac_alg = NULL; 422 - changed = true; 423 - } 424 - if (!changed) 425 - ret = -EINVAL; 426 - } 427 - 428 - return ret; 418 + if (net->sctp.cookie_auth_enable) 419 + tbl.data = (char *)"sha256"; 420 + else 421 + tbl.data = (char *)"none"; 422 + tbl.maxlen = strlen(tbl.data); 423 + return proc_dostring(&tbl, 0, buffer, lenp, ppos); 429 424 } 430 425 431 426 static int proc_sctp_do_rto_min(const struct ctl_table *ctl, int write,