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

sctp: Make hmac algorithm selection for cookie generation dynamic

Currently sctp allows for the optional use of md5 of sha1 hmac algorithms to
generate cookie values when establishing new connections via two build time
config options. Theres no real reason to make this a static selection. We can
add a sysctl that allows for the dynamic selection of these algorithms at run
time, with the default value determined by the corresponding crypto library
availability.
This comes in handy when, for example running a system in FIPS mode, where use
of md5 is disallowed, but SHA1 is permitted.

Note: This new sysctl has no corresponding socket option to select the cookie
hmac algorithm. I chose not to implement that intentionally, as RFC 6458
contains no option for this value, and I opted not to pollute the socket option
namespace.

Change notes:
v2)
* Updated subject to have the proper sctp prefix as per Dave M.
* Replaced deafult selection options with new options that allow
developers to explicitly select available hmac algs at build time
as per suggestion by Vlad Y.

Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
CC: Vlad Yasevich <vyasevich@gmail.com>
CC: "David S. Miller" <davem@davemloft.net>
CC: netdev@vger.kernel.org
Acked-by: Vlad Yasevich <vyasevich@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Neil Horman and committed by
David S. Miller
3c68198e 342567cc

+105 -37
+14
Documentation/networking/ip-sysctl.txt
··· 1514 1514 1515 1515 Default: 1 1516 1516 1517 + cookie_hmac_alg - STRING 1518 + Select the hmac algorithm used when generating the cookie value sent by 1519 + a listening sctp socket to a connecting client in the INIT-ACK chunk. 1520 + Valid values are: 1521 + * md5 1522 + * sha1 1523 + * none 1524 + Ability to assign md5 or sha1 as the selected alg is predicated on the 1525 + configuarion of those algorithms at build time (CONFIG_CRYPTO_MD5 and 1526 + CONFIG_CRYPTO_SHA1). 1527 + 1528 + Default: Dependent on configuration. MD5 if available, else SHA1 if 1529 + available, else none. 1530 + 1517 1531 rcvbuf_policy - INTEGER 1518 1532 Determines if the receive buffer is attributed to the socket or to 1519 1533 association. SCTP supports the capability to create multiple
+3
include/net/netns/sctp.h
··· 62 62 /* Whether Cookie Preservative is enabled(1) or not(0) */ 63 63 int cookie_preserve_enable; 64 64 65 + /* The namespace default hmac alg */ 66 + char *sctp_hmac_alg; 67 + 65 68 /* Valid.Cookie.Life - 60 seconds */ 66 69 unsigned int valid_cookie_life; 67 70
-8
include/net/sctp/constants.h
··· 312 312 * functions simpler to write. 313 313 */ 314 314 315 - #if defined (CONFIG_SCTP_HMAC_MD5) 316 - #define SCTP_COOKIE_HMAC_ALG "hmac(md5)" 317 - #elif defined (CONFIG_SCTP_HMAC_SHA1) 318 - #define SCTP_COOKIE_HMAC_ALG "hmac(sha1)" 319 - #else 320 - #define SCTP_COOKIE_HMAC_ALG NULL 321 - #endif 322 - 323 315 /* These return values describe the success or failure of a number of 324 316 * routines which form the lower interface to SCTP_outqueue. 325 317 */
+1
include/net/sctp/structs.h
··· 177 177 178 178 /* Access to HMAC transform. */ 179 179 struct crypto_hash *hmac; 180 + char *sctp_hmac_alg; 180 181 181 182 /* What is our base endpointer? */ 182 183 struct sctp_endpoint *ep;
+12 -25
net/sctp/Kconfig
··· 9 9 select CRYPTO 10 10 select CRYPTO_HMAC 11 11 select CRYPTO_SHA1 12 - select CRYPTO_MD5 if SCTP_HMAC_MD5 13 12 select LIBCRC32C 14 13 ---help--- 15 14 Stream Control Transmission Protocol ··· 67 68 68 69 If unsure, say N 69 70 70 - choice 71 - prompt "SCTP: Cookie HMAC Algorithm" 72 - default SCTP_HMAC_MD5 71 + config SCTP_COOKIE_HMAC_MD5 72 + bool "Enable optional MD5 hmac cookie generation" 73 73 help 74 - HMAC algorithm to be used during association initialization. It 75 - is strongly recommended to use HMAC-SHA1 or HMAC-MD5. See 76 - configuration for Cryptographic API and enable those algorithms 77 - to make usable by SCTP. 74 + Enable optional MD5 hmac based SCTP cookie generation 75 + default y 76 + select CRYPTO_HMAC if SCTP_COOKIE_HMAC_MD5 77 + select CRYPTO_MD5 if SCTP_COOKIE_HMAC_MD5 78 78 79 - config SCTP_HMAC_NONE 80 - bool "None" 81 - help 82 - Choosing this disables the use of an HMAC during association 83 - establishment. It is advised to use either HMAC-MD5 or HMAC-SHA1. 84 - 85 - config SCTP_HMAC_SHA1 86 - bool "HMAC-SHA1" 87 - help 88 - Enable the use of HMAC-SHA1 during association establishment. It 89 - is advised to use either HMAC-MD5 or HMAC-SHA1. 90 - 91 - config SCTP_HMAC_MD5 92 - bool "HMAC-MD5" 79 + config SCTP_COOKIE_HMAC_SHA1 80 + bool "Enable optional SHA1 hmac cookie generation" 93 81 help 94 - Enable the use of HMAC-MD5 during association establishment. It is 95 - advised to use either HMAC-MD5 or HMAC-SHA1. 82 + Enable optional SHA1 hmac based SCTP cookie generation 83 + default y 84 + select CRYPTO_HMAC if SCTP_COOKIE_HMAC_SHA1 85 + select CRYPTO_SHA1 if SCTP_COOKIE_HMAC_SHA1 96 86 97 - endchoice 98 87 99 88 endif # IP_SCTP
+9
net/sctp/protocol.c
··· 1190 1190 /* Whether Cookie Preservative is enabled(1) or not(0) */ 1191 1191 net->sctp.cookie_preserve_enable = 1; 1192 1192 1193 + /* Default sctp sockets to use md5 as their hmac alg */ 1194 + #if defined (CONFIG_CRYPTO_MD5) 1195 + net->sctp.sctp_hmac_alg = "md5"; 1196 + #elif defined (CONFIG_CRYPTO_SHA1) 1197 + net->sctp.sctp_hmac_alg = "sha1"; 1198 + #else 1199 + net->sctp.sctp_hmac_alg = NULL; 1200 + #endif 1201 + 1193 1202 /* Max.Burst - 4 */ 1194 1203 net->sctp.max_burst = SCTP_DEFAULT_MAX_BURST; 1195 1204
+7 -4
net/sctp/socket.c
··· 110 110 static int sctp_autobind(struct sock *sk); 111 111 static void sctp_sock_migrate(struct sock *, struct sock *, 112 112 struct sctp_association *, sctp_socket_type_t); 113 - static char *sctp_hmac_alg = SCTP_COOKIE_HMAC_ALG; 114 113 115 114 extern struct kmem_cache *sctp_bucket_cachep; 116 115 extern long sysctl_sctp_mem[3]; ··· 3889 3890 sp->default_rcv_context = 0; 3890 3891 sp->max_burst = net->sctp.max_burst; 3891 3892 3893 + sp->sctp_hmac_alg = net->sctp.sctp_hmac_alg; 3894 + 3892 3895 /* Initialize default setup parameters. These parameters 3893 3896 * can be modified with the SCTP_INITMSG socket option or 3894 3897 * overridden by the SCTP_INIT CMSG. ··· 5982 5981 struct sctp_sock *sp = sctp_sk(sk); 5983 5982 struct sctp_endpoint *ep = sp->ep; 5984 5983 struct crypto_hash *tfm = NULL; 5984 + char alg[32]; 5985 5985 5986 5986 /* Allocate HMAC for generating cookie. */ 5987 - if (!sctp_sk(sk)->hmac && sctp_hmac_alg) { 5988 - tfm = crypto_alloc_hash(sctp_hmac_alg, 0, CRYPTO_ALG_ASYNC); 5987 + if (!sp->hmac && sp->sctp_hmac_alg) { 5988 + sprintf(alg, "hmac(%s)", sp->sctp_hmac_alg); 5989 + tfm = crypto_alloc_hash(alg, 0, CRYPTO_ALG_ASYNC); 5989 5990 if (IS_ERR(tfm)) { 5990 5991 net_info_ratelimited("failed to load transform for %s: %ld\n", 5991 - sctp_hmac_alg, PTR_ERR(tfm)); 5992 + sp->sctp_hmac_alg, PTR_ERR(tfm)); 5992 5993 return -ENOSYS; 5993 5994 } 5994 5995 sctp_sk(sk)->hmac = tfm;
+59
net/sctp/sysctl.c
··· 62 62 extern int sysctl_sctp_rmem[3]; 63 63 extern int sysctl_sctp_wmem[3]; 64 64 65 + static int proc_sctp_do_hmac_alg(ctl_table *ctl, 66 + int write, 67 + void __user *buffer, size_t *lenp, 68 + 69 + loff_t *ppos); 65 70 static ctl_table sctp_table[] = { 66 71 { 67 72 .procname = "sctp_mem", ··· 150 145 .maxlen = sizeof(int), 151 146 .mode = 0644, 152 147 .proc_handler = proc_dointvec, 148 + }, 149 + { 150 + .procname = "cookie_hmac_alg", 151 + .maxlen = 8, 152 + .mode = 0644, 153 + .proc_handler = proc_sctp_do_hmac_alg, 153 154 }, 154 155 { 155 156 .procname = "valid_cookie_life", ··· 299 288 300 289 { /* sentinel */ } 301 290 }; 291 + 292 + static int proc_sctp_do_hmac_alg(ctl_table *ctl, 293 + int write, 294 + void __user *buffer, size_t *lenp, 295 + loff_t *ppos) 296 + { 297 + struct net *net = current->nsproxy->net_ns; 298 + char tmp[8]; 299 + ctl_table tbl; 300 + int ret; 301 + int changed = 0; 302 + char *none = "none"; 303 + 304 + memset(&tbl, 0, sizeof(struct ctl_table)); 305 + 306 + if (write) { 307 + tbl.data = tmp; 308 + tbl.maxlen = 8; 309 + } else { 310 + tbl.data = net->sctp.sctp_hmac_alg ? : none; 311 + tbl.maxlen = strlen(tbl.data); 312 + } 313 + ret = proc_dostring(&tbl, write, buffer, lenp, ppos); 314 + 315 + if (write) { 316 + #ifdef CONFIG_CRYPTO_MD5 317 + if (!strncmp(tmp, "md5", 3)) { 318 + net->sctp.sctp_hmac_alg = "md5"; 319 + changed = 1; 320 + } 321 + #endif 322 + #ifdef CONFIG_CRYPTO_SHA1 323 + if (!strncmp(tmp, "sha1", 4)) { 324 + net->sctp.sctp_hmac_alg = "sha1"; 325 + changed = 1; 326 + } 327 + #endif 328 + if (!strncmp(tmp, "none", 4)) { 329 + net->sctp.sctp_hmac_alg = NULL; 330 + changed = 1; 331 + } 332 + 333 + if (!changed) 334 + ret = -EINVAL; 335 + } 336 + 337 + return ret; 338 + } 302 339 303 340 int sctp_sysctl_net_register(struct net *net) 304 341 {