160c778b2SVlad Yasevich /* SCTP kernel implementation 21f485649SVlad Yasevich * (C) Copyright 2007 Hewlett-Packard Development Company, L.P. 31f485649SVlad Yasevich * 460c778b2SVlad Yasevich * This file is part of the SCTP kernel implementation 51f485649SVlad Yasevich * 660c778b2SVlad Yasevich * This SCTP implementation is free software; 71f485649SVlad Yasevich * you can redistribute it and/or modify it under the terms of 81f485649SVlad Yasevich * the GNU General Public License as published by 91f485649SVlad Yasevich * the Free Software Foundation; either version 2, or (at your option) 101f485649SVlad Yasevich * any later version. 111f485649SVlad Yasevich * 1260c778b2SVlad Yasevich * This SCTP implementation is distributed in the hope that it 131f485649SVlad Yasevich * will be useful, but WITHOUT ANY WARRANTY; without even the implied 141f485649SVlad Yasevich * ************************ 151f485649SVlad Yasevich * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 161f485649SVlad Yasevich * See the GNU General Public License for more details. 171f485649SVlad Yasevich * 181f485649SVlad Yasevich * You should have received a copy of the GNU General Public License 194b2f13a2SJeff Kirsher * along with GNU CC; see the file COPYING. If not, see 204b2f13a2SJeff Kirsher * <http://www.gnu.org/licenses/>. 211f485649SVlad Yasevich * 221f485649SVlad Yasevich * Please send any bug reports or fixes you make to the 231f485649SVlad Yasevich * email address(es): 2491705c61SDaniel Borkmann * lksctp developers <linux-sctp@vger.kernel.org> 251f485649SVlad Yasevich * 261f485649SVlad Yasevich * Written or modified by: 271f485649SVlad Yasevich * Vlad Yasevich <vladislav.yasevich@hp.com> 281f485649SVlad Yasevich */ 291f485649SVlad Yasevich 305a0e3ad6STejun Heo #include <linux/slab.h> 311f485649SVlad Yasevich #include <linux/types.h> 321f485649SVlad Yasevich #include <linux/crypto.h> 331f485649SVlad Yasevich #include <linux/scatterlist.h> 341f485649SVlad Yasevich #include <net/sctp/sctp.h> 351f485649SVlad Yasevich #include <net/sctp/auth.h> 361f485649SVlad Yasevich 371f485649SVlad Yasevich static struct sctp_hmac sctp_hmac_list[SCTP_AUTH_NUM_HMACS] = { 381f485649SVlad Yasevich { 391f485649SVlad Yasevich /* id 0 is reserved. as all 0 */ 401f485649SVlad Yasevich .hmac_id = SCTP_AUTH_HMAC_ID_RESERVED_0, 411f485649SVlad Yasevich }, 421f485649SVlad Yasevich { 431f485649SVlad Yasevich .hmac_id = SCTP_AUTH_HMAC_ID_SHA1, 441f485649SVlad Yasevich .hmac_name = "hmac(sha1)", 451f485649SVlad Yasevich .hmac_len = SCTP_SHA1_SIG_SIZE, 461f485649SVlad Yasevich }, 471f485649SVlad Yasevich { 481f485649SVlad Yasevich /* id 2 is reserved as well */ 491f485649SVlad Yasevich .hmac_id = SCTP_AUTH_HMAC_ID_RESERVED_2, 501f485649SVlad Yasevich }, 51b7e0fe9fSVlad Yasevich #if defined (CONFIG_CRYPTO_SHA256) || defined (CONFIG_CRYPTO_SHA256_MODULE) 521f485649SVlad Yasevich { 531f485649SVlad Yasevich .hmac_id = SCTP_AUTH_HMAC_ID_SHA256, 541f485649SVlad Yasevich .hmac_name = "hmac(sha256)", 551f485649SVlad Yasevich .hmac_len = SCTP_SHA256_SIG_SIZE, 561f485649SVlad Yasevich } 57b7e0fe9fSVlad Yasevich #endif 581f485649SVlad Yasevich }; 591f485649SVlad Yasevich 601f485649SVlad Yasevich 611f485649SVlad Yasevich void sctp_auth_key_put(struct sctp_auth_bytes *key) 621f485649SVlad Yasevich { 631f485649SVlad Yasevich if (!key) 641f485649SVlad Yasevich return; 651f485649SVlad Yasevich 661f485649SVlad Yasevich if (atomic_dec_and_test(&key->refcnt)) { 67586c31f3SDaniel Borkmann kzfree(key); 681f485649SVlad Yasevich SCTP_DBG_OBJCNT_DEC(keys); 691f485649SVlad Yasevich } 701f485649SVlad Yasevich } 711f485649SVlad Yasevich 721f485649SVlad Yasevich /* Create a new key structure of a given length */ 731f485649SVlad Yasevich static struct sctp_auth_bytes *sctp_auth_create_key(__u32 key_len, gfp_t gfp) 741f485649SVlad Yasevich { 751f485649SVlad Yasevich struct sctp_auth_bytes *key; 761f485649SVlad Yasevich 7730c2235cSVlad Yasevich /* Verify that we are not going to overflow INT_MAX */ 78c89304b8SXi Wang if (key_len > (INT_MAX - sizeof(struct sctp_auth_bytes))) 7930c2235cSVlad Yasevich return NULL; 8030c2235cSVlad Yasevich 811f485649SVlad Yasevich /* Allocate the shared key */ 821f485649SVlad Yasevich key = kmalloc(sizeof(struct sctp_auth_bytes) + key_len, gfp); 831f485649SVlad Yasevich if (!key) 841f485649SVlad Yasevich return NULL; 851f485649SVlad Yasevich 861f485649SVlad Yasevich key->len = key_len; 871f485649SVlad Yasevich atomic_set(&key->refcnt, 1); 881f485649SVlad Yasevich SCTP_DBG_OBJCNT_INC(keys); 891f485649SVlad Yasevich 901f485649SVlad Yasevich return key; 911f485649SVlad Yasevich } 921f485649SVlad Yasevich 931f485649SVlad Yasevich /* Create a new shared key container with a give key id */ 941f485649SVlad Yasevich struct sctp_shared_key *sctp_auth_shkey_create(__u16 key_id, gfp_t gfp) 951f485649SVlad Yasevich { 961f485649SVlad Yasevich struct sctp_shared_key *new; 971f485649SVlad Yasevich 981f485649SVlad Yasevich /* Allocate the shared key container */ 991f485649SVlad Yasevich new = kzalloc(sizeof(struct sctp_shared_key), gfp); 1001f485649SVlad Yasevich if (!new) 1011f485649SVlad Yasevich return NULL; 1021f485649SVlad Yasevich 1031f485649SVlad Yasevich INIT_LIST_HEAD(&new->key_list); 1041f485649SVlad Yasevich new->key_id = key_id; 1051f485649SVlad Yasevich 1061f485649SVlad Yasevich return new; 1071f485649SVlad Yasevich } 1081f485649SVlad Yasevich 10925985edcSLucas De Marchi /* Free the shared key structure */ 1108ad7c62bSAdrian Bunk static void sctp_auth_shkey_free(struct sctp_shared_key *sh_key) 1111f485649SVlad Yasevich { 1121f485649SVlad Yasevich BUG_ON(!list_empty(&sh_key->key_list)); 1131f485649SVlad Yasevich sctp_auth_key_put(sh_key->key); 1141f485649SVlad Yasevich sh_key->key = NULL; 1151f485649SVlad Yasevich kfree(sh_key); 1161f485649SVlad Yasevich } 1171f485649SVlad Yasevich 11825985edcSLucas De Marchi /* Destroy the entire key list. This is done during the 1191f485649SVlad Yasevich * associon and endpoint free process. 1201f485649SVlad Yasevich */ 1211f485649SVlad Yasevich void sctp_auth_destroy_keys(struct list_head *keys) 1221f485649SVlad Yasevich { 1231f485649SVlad Yasevich struct sctp_shared_key *ep_key; 1241f485649SVlad Yasevich struct sctp_shared_key *tmp; 1251f485649SVlad Yasevich 1261f485649SVlad Yasevich if (list_empty(keys)) 1271f485649SVlad Yasevich return; 1281f485649SVlad Yasevich 1291f485649SVlad Yasevich key_for_each_safe(ep_key, tmp, keys) { 1301f485649SVlad Yasevich list_del_init(&ep_key->key_list); 1311f485649SVlad Yasevich sctp_auth_shkey_free(ep_key); 1321f485649SVlad Yasevich } 1331f485649SVlad Yasevich } 1341f485649SVlad Yasevich 1351f485649SVlad Yasevich /* Compare two byte vectors as numbers. Return values 1361f485649SVlad Yasevich * are: 1371f485649SVlad Yasevich * 0 - vectors are equal 138025dfdafSFrederik Schwarzer * < 0 - vector 1 is smaller than vector2 139025dfdafSFrederik Schwarzer * > 0 - vector 1 is greater than vector2 1401f485649SVlad Yasevich * 1411f485649SVlad Yasevich * Algorithm is: 1421f485649SVlad Yasevich * This is performed by selecting the numerically smaller key vector... 1431f485649SVlad Yasevich * If the key vectors are equal as numbers but differ in length ... 1441f485649SVlad Yasevich * the shorter vector is considered smaller 1451f485649SVlad Yasevich * 1461f485649SVlad Yasevich * Examples (with small values): 1471f485649SVlad Yasevich * 000123456789 > 123456789 (first number is longer) 1481f485649SVlad Yasevich * 000123456789 < 234567891 (second number is larger numerically) 1491f485649SVlad Yasevich * 123456789 > 2345678 (first number is both larger & longer) 1501f485649SVlad Yasevich */ 1511f485649SVlad Yasevich static int sctp_auth_compare_vectors(struct sctp_auth_bytes *vector1, 1521f485649SVlad Yasevich struct sctp_auth_bytes *vector2) 1531f485649SVlad Yasevich { 1541f485649SVlad Yasevich int diff; 1551f485649SVlad Yasevich int i; 1561f485649SVlad Yasevich const __u8 *longer; 1571f485649SVlad Yasevich 1581f485649SVlad Yasevich diff = vector1->len - vector2->len; 1591f485649SVlad Yasevich if (diff) { 1601f485649SVlad Yasevich longer = (diff > 0) ? vector1->data : vector2->data; 1611f485649SVlad Yasevich 1621f485649SVlad Yasevich /* Check to see if the longer number is 1631f485649SVlad Yasevich * lead-zero padded. If it is not, it 1641f485649SVlad Yasevich * is automatically larger numerically. 1651f485649SVlad Yasevich */ 1661f485649SVlad Yasevich for (i = 0; i < abs(diff); i++) { 1671f485649SVlad Yasevich if (longer[i] != 0) 1681f485649SVlad Yasevich return diff; 1691f485649SVlad Yasevich } 1701f485649SVlad Yasevich } 1711f485649SVlad Yasevich 1721f485649SVlad Yasevich /* lengths are the same, compare numbers */ 1731f485649SVlad Yasevich return memcmp(vector1->data, vector2->data, vector1->len); 1741f485649SVlad Yasevich } 1751f485649SVlad Yasevich 1761f485649SVlad Yasevich /* 1771f485649SVlad Yasevich * Create a key vector as described in SCTP-AUTH, Section 6.1 1781f485649SVlad Yasevich * The RANDOM parameter, the CHUNKS parameter and the HMAC-ALGO 1791f485649SVlad Yasevich * parameter sent by each endpoint are concatenated as byte vectors. 1801f485649SVlad Yasevich * These parameters include the parameter type, parameter length, and 1811f485649SVlad Yasevich * the parameter value, but padding is omitted; all padding MUST be 1821f485649SVlad Yasevich * removed from this concatenation before proceeding with further 1831f485649SVlad Yasevich * computation of keys. Parameters which were not sent are simply 1841f485649SVlad Yasevich * omitted from the concatenation process. The resulting two vectors 1851f485649SVlad Yasevich * are called the two key vectors. 1861f485649SVlad Yasevich */ 1871f485649SVlad Yasevich static struct sctp_auth_bytes *sctp_auth_make_key_vector( 1881f485649SVlad Yasevich sctp_random_param_t *random, 1891f485649SVlad Yasevich sctp_chunks_param_t *chunks, 1901f485649SVlad Yasevich sctp_hmac_algo_param_t *hmacs, 1911f485649SVlad Yasevich gfp_t gfp) 1921f485649SVlad Yasevich { 1931f485649SVlad Yasevich struct sctp_auth_bytes *new; 1941f485649SVlad Yasevich __u32 len; 1951f485649SVlad Yasevich __u32 offset = 0; 196241448c2SDaniel Borkmann __u16 random_len, hmacs_len, chunks_len = 0; 1971f485649SVlad Yasevich 198241448c2SDaniel Borkmann random_len = ntohs(random->param_hdr.length); 199241448c2SDaniel Borkmann hmacs_len = ntohs(hmacs->param_hdr.length); 2001f485649SVlad Yasevich if (chunks) 201241448c2SDaniel Borkmann chunks_len = ntohs(chunks->param_hdr.length); 202241448c2SDaniel Borkmann 203241448c2SDaniel Borkmann len = random_len + hmacs_len + chunks_len; 2041f485649SVlad Yasevich 20503536e23SDaniel Borkmann new = sctp_auth_create_key(len, gfp); 2061f485649SVlad Yasevich if (!new) 2071f485649SVlad Yasevich return NULL; 2081f485649SVlad Yasevich 209241448c2SDaniel Borkmann memcpy(new->data, random, random_len); 210241448c2SDaniel Borkmann offset += random_len; 2111f485649SVlad Yasevich 2121f485649SVlad Yasevich if (chunks) { 213241448c2SDaniel Borkmann memcpy(new->data + offset, chunks, chunks_len); 214241448c2SDaniel Borkmann offset += chunks_len; 2151f485649SVlad Yasevich } 2161f485649SVlad Yasevich 217241448c2SDaniel Borkmann memcpy(new->data + offset, hmacs, hmacs_len); 2181f485649SVlad Yasevich 2191f485649SVlad Yasevich return new; 2201f485649SVlad Yasevich } 2211f485649SVlad Yasevich 2221f485649SVlad Yasevich 2231f485649SVlad Yasevich /* Make a key vector based on our local parameters */ 2248ad7c62bSAdrian Bunk static struct sctp_auth_bytes *sctp_auth_make_local_vector( 2251f485649SVlad Yasevich const struct sctp_association *asoc, 2261f485649SVlad Yasevich gfp_t gfp) 2271f485649SVlad Yasevich { 2281f485649SVlad Yasevich return sctp_auth_make_key_vector( 2291f485649SVlad Yasevich (sctp_random_param_t *)asoc->c.auth_random, 2301f485649SVlad Yasevich (sctp_chunks_param_t *)asoc->c.auth_chunks, 2311f485649SVlad Yasevich (sctp_hmac_algo_param_t *)asoc->c.auth_hmacs, 2321f485649SVlad Yasevich gfp); 2331f485649SVlad Yasevich } 2341f485649SVlad Yasevich 2351f485649SVlad Yasevich /* Make a key vector based on peer's parameters */ 2368ad7c62bSAdrian Bunk static struct sctp_auth_bytes *sctp_auth_make_peer_vector( 2371f485649SVlad Yasevich const struct sctp_association *asoc, 2381f485649SVlad Yasevich gfp_t gfp) 2391f485649SVlad Yasevich { 2401f485649SVlad Yasevich return sctp_auth_make_key_vector(asoc->peer.peer_random, 2411f485649SVlad Yasevich asoc->peer.peer_chunks, 2421f485649SVlad Yasevich asoc->peer.peer_hmacs, 2431f485649SVlad Yasevich gfp); 2441f485649SVlad Yasevich } 2451f485649SVlad Yasevich 2461f485649SVlad Yasevich 2471f485649SVlad Yasevich /* Set the value of the association shared key base on the parameters 2481f485649SVlad Yasevich * given. The algorithm is: 2491f485649SVlad Yasevich * From the endpoint pair shared keys and the key vectors the 2501f485649SVlad Yasevich * association shared keys are computed. This is performed by selecting 2511f485649SVlad Yasevich * the numerically smaller key vector and concatenating it to the 2521f485649SVlad Yasevich * endpoint pair shared key, and then concatenating the numerically 2531f485649SVlad Yasevich * larger key vector to that. The result of the concatenation is the 2541f485649SVlad Yasevich * association shared key. 2551f485649SVlad Yasevich */ 2561f485649SVlad Yasevich static struct sctp_auth_bytes *sctp_auth_asoc_set_secret( 2571f485649SVlad Yasevich struct sctp_shared_key *ep_key, 2581f485649SVlad Yasevich struct sctp_auth_bytes *first_vector, 2591f485649SVlad Yasevich struct sctp_auth_bytes *last_vector, 2601f485649SVlad Yasevich gfp_t gfp) 2611f485649SVlad Yasevich { 2621f485649SVlad Yasevich struct sctp_auth_bytes *secret; 2631f485649SVlad Yasevich __u32 offset = 0; 2641f485649SVlad Yasevich __u32 auth_len; 2651f485649SVlad Yasevich 2661f485649SVlad Yasevich auth_len = first_vector->len + last_vector->len; 2671f485649SVlad Yasevich if (ep_key->key) 2681f485649SVlad Yasevich auth_len += ep_key->key->len; 2691f485649SVlad Yasevich 2701f485649SVlad Yasevich secret = sctp_auth_create_key(auth_len, gfp); 2711f485649SVlad Yasevich if (!secret) 2721f485649SVlad Yasevich return NULL; 2731f485649SVlad Yasevich 2741f485649SVlad Yasevich if (ep_key->key) { 2751f485649SVlad Yasevich memcpy(secret->data, ep_key->key->data, ep_key->key->len); 2761f485649SVlad Yasevich offset += ep_key->key->len; 2771f485649SVlad Yasevich } 2781f485649SVlad Yasevich 2791f485649SVlad Yasevich memcpy(secret->data + offset, first_vector->data, first_vector->len); 2801f485649SVlad Yasevich offset += first_vector->len; 2811f485649SVlad Yasevich 2821f485649SVlad Yasevich memcpy(secret->data + offset, last_vector->data, last_vector->len); 2831f485649SVlad Yasevich 2841f485649SVlad Yasevich return secret; 2851f485649SVlad Yasevich } 2861f485649SVlad Yasevich 2871f485649SVlad Yasevich /* Create an association shared key. Follow the algorithm 2881f485649SVlad Yasevich * described in SCTP-AUTH, Section 6.1 2891f485649SVlad Yasevich */ 2901f485649SVlad Yasevich static struct sctp_auth_bytes *sctp_auth_asoc_create_secret( 2911f485649SVlad Yasevich const struct sctp_association *asoc, 2921f485649SVlad Yasevich struct sctp_shared_key *ep_key, 2931f485649SVlad Yasevich gfp_t gfp) 2941f485649SVlad Yasevich { 2951f485649SVlad Yasevich struct sctp_auth_bytes *local_key_vector; 2961f485649SVlad Yasevich struct sctp_auth_bytes *peer_key_vector; 2971f485649SVlad Yasevich struct sctp_auth_bytes *first_vector, 2981f485649SVlad Yasevich *last_vector; 2991f485649SVlad Yasevich struct sctp_auth_bytes *secret = NULL; 3001f485649SVlad Yasevich int cmp; 3011f485649SVlad Yasevich 3021f485649SVlad Yasevich 3031f485649SVlad Yasevich /* Now we need to build the key vectors 3041f485649SVlad Yasevich * SCTP-AUTH , Section 6.1 3051f485649SVlad Yasevich * The RANDOM parameter, the CHUNKS parameter and the HMAC-ALGO 3061f485649SVlad Yasevich * parameter sent by each endpoint are concatenated as byte vectors. 3071f485649SVlad Yasevich * These parameters include the parameter type, parameter length, and 3081f485649SVlad Yasevich * the parameter value, but padding is omitted; all padding MUST be 3091f485649SVlad Yasevich * removed from this concatenation before proceeding with further 3101f485649SVlad Yasevich * computation of keys. Parameters which were not sent are simply 3111f485649SVlad Yasevich * omitted from the concatenation process. The resulting two vectors 3121f485649SVlad Yasevich * are called the two key vectors. 3131f485649SVlad Yasevich */ 3141f485649SVlad Yasevich 3151f485649SVlad Yasevich local_key_vector = sctp_auth_make_local_vector(asoc, gfp); 3161f485649SVlad Yasevich peer_key_vector = sctp_auth_make_peer_vector(asoc, gfp); 3171f485649SVlad Yasevich 3181f485649SVlad Yasevich if (!peer_key_vector || !local_key_vector) 3191f485649SVlad Yasevich goto out; 3201f485649SVlad Yasevich 32125985edcSLucas De Marchi /* Figure out the order in which the key_vectors will be 3221f485649SVlad Yasevich * added to the endpoint shared key. 3231f485649SVlad Yasevich * SCTP-AUTH, Section 6.1: 3241f485649SVlad Yasevich * This is performed by selecting the numerically smaller key 3251f485649SVlad Yasevich * vector and concatenating it to the endpoint pair shared 3261f485649SVlad Yasevich * key, and then concatenating the numerically larger key 3271f485649SVlad Yasevich * vector to that. If the key vectors are equal as numbers 3281f485649SVlad Yasevich * but differ in length, then the concatenation order is the 3291f485649SVlad Yasevich * endpoint shared key, followed by the shorter key vector, 3301f485649SVlad Yasevich * followed by the longer key vector. Otherwise, the key 3311f485649SVlad Yasevich * vectors are identical, and may be concatenated to the 3321f485649SVlad Yasevich * endpoint pair key in any order. 3331f485649SVlad Yasevich */ 3341f485649SVlad Yasevich cmp = sctp_auth_compare_vectors(local_key_vector, 3351f485649SVlad Yasevich peer_key_vector); 3361f485649SVlad Yasevich if (cmp < 0) { 3371f485649SVlad Yasevich first_vector = local_key_vector; 3381f485649SVlad Yasevich last_vector = peer_key_vector; 3391f485649SVlad Yasevich } else { 3401f485649SVlad Yasevich first_vector = peer_key_vector; 3411f485649SVlad Yasevich last_vector = local_key_vector; 3421f485649SVlad Yasevich } 3431f485649SVlad Yasevich 3441f485649SVlad Yasevich secret = sctp_auth_asoc_set_secret(ep_key, first_vector, last_vector, 3451f485649SVlad Yasevich gfp); 3461f485649SVlad Yasevich out: 34703536e23SDaniel Borkmann sctp_auth_key_put(local_key_vector); 34803536e23SDaniel Borkmann sctp_auth_key_put(peer_key_vector); 3491f485649SVlad Yasevich 3501f485649SVlad Yasevich return secret; 3511f485649SVlad Yasevich } 3521f485649SVlad Yasevich 3531f485649SVlad Yasevich /* 3541f485649SVlad Yasevich * Populate the association overlay list with the list 3551f485649SVlad Yasevich * from the endpoint. 3561f485649SVlad Yasevich */ 3571f485649SVlad Yasevich int sctp_auth_asoc_copy_shkeys(const struct sctp_endpoint *ep, 3581f485649SVlad Yasevich struct sctp_association *asoc, 3591f485649SVlad Yasevich gfp_t gfp) 3601f485649SVlad Yasevich { 3611f485649SVlad Yasevich struct sctp_shared_key *sh_key; 3621f485649SVlad Yasevich struct sctp_shared_key *new; 3631f485649SVlad Yasevich 3641f485649SVlad Yasevich BUG_ON(!list_empty(&asoc->endpoint_shared_keys)); 3651f485649SVlad Yasevich 3661f485649SVlad Yasevich key_for_each(sh_key, &ep->endpoint_shared_keys) { 3671f485649SVlad Yasevich new = sctp_auth_shkey_create(sh_key->key_id, gfp); 3681f485649SVlad Yasevich if (!new) 3691f485649SVlad Yasevich goto nomem; 3701f485649SVlad Yasevich 3711f485649SVlad Yasevich new->key = sh_key->key; 3721f485649SVlad Yasevich sctp_auth_key_hold(new->key); 3731f485649SVlad Yasevich list_add(&new->key_list, &asoc->endpoint_shared_keys); 3741f485649SVlad Yasevich } 3751f485649SVlad Yasevich 3761f485649SVlad Yasevich return 0; 3771f485649SVlad Yasevich 3781f485649SVlad Yasevich nomem: 3791f485649SVlad Yasevich sctp_auth_destroy_keys(&asoc->endpoint_shared_keys); 3801f485649SVlad Yasevich return -ENOMEM; 3811f485649SVlad Yasevich } 3821f485649SVlad Yasevich 3831f485649SVlad Yasevich 3841f485649SVlad Yasevich /* Public interface to creat the association shared key. 3851f485649SVlad Yasevich * See code above for the algorithm. 3861f485649SVlad Yasevich */ 3871f485649SVlad Yasevich int sctp_auth_asoc_init_active_key(struct sctp_association *asoc, gfp_t gfp) 3881f485649SVlad Yasevich { 3891f485649SVlad Yasevich struct sctp_auth_bytes *secret; 3901f485649SVlad Yasevich struct sctp_shared_key *ep_key; 3911f485649SVlad Yasevich 3921f485649SVlad Yasevich /* If we don't support AUTH, or peer is not capable 3931f485649SVlad Yasevich * we don't need to do anything. 3941f485649SVlad Yasevich */ 395b14878ccSVlad Yasevich if (!asoc->ep->auth_enable || !asoc->peer.auth_capable) 3961f485649SVlad Yasevich return 0; 3971f485649SVlad Yasevich 3981f485649SVlad Yasevich /* If the key_id is non-zero and we couldn't find an 3991f485649SVlad Yasevich * endpoint pair shared key, we can't compute the 4001f485649SVlad Yasevich * secret. 4011f485649SVlad Yasevich * For key_id 0, endpoint pair shared key is a NULL key. 4021f485649SVlad Yasevich */ 4031f485649SVlad Yasevich ep_key = sctp_auth_get_shkey(asoc, asoc->active_key_id); 4041f485649SVlad Yasevich BUG_ON(!ep_key); 4051f485649SVlad Yasevich 4061f485649SVlad Yasevich secret = sctp_auth_asoc_create_secret(asoc, ep_key, gfp); 4071f485649SVlad Yasevich if (!secret) 4081f485649SVlad Yasevich return -ENOMEM; 4091f485649SVlad Yasevich 4101f485649SVlad Yasevich sctp_auth_key_put(asoc->asoc_shared_key); 4111f485649SVlad Yasevich asoc->asoc_shared_key = secret; 4121f485649SVlad Yasevich 4131f485649SVlad Yasevich return 0; 4141f485649SVlad Yasevich } 4151f485649SVlad Yasevich 4161f485649SVlad Yasevich 4171f485649SVlad Yasevich /* Find the endpoint pair shared key based on the key_id */ 4181f485649SVlad Yasevich struct sctp_shared_key *sctp_auth_get_shkey( 4191f485649SVlad Yasevich const struct sctp_association *asoc, 4201f485649SVlad Yasevich __u16 key_id) 4211f485649SVlad Yasevich { 4227cc08b55SWei Yongjun struct sctp_shared_key *key; 4231f485649SVlad Yasevich 4241f485649SVlad Yasevich /* First search associations set of endpoint pair shared keys */ 4251f485649SVlad Yasevich key_for_each(key, &asoc->endpoint_shared_keys) { 4261f485649SVlad Yasevich if (key->key_id == key_id) 4277cc08b55SWei Yongjun return key; 4281f485649SVlad Yasevich } 4291f485649SVlad Yasevich 4307cc08b55SWei Yongjun return NULL; 4311f485649SVlad Yasevich } 4321f485649SVlad Yasevich 4331f485649SVlad Yasevich /* 4341f485649SVlad Yasevich * Initialize all the possible digest transforms that we can use. Right now 4351f485649SVlad Yasevich * now, the supported digests are SHA1 and SHA256. We do this here once 4361f485649SVlad Yasevich * because of the restrictiong that transforms may only be allocated in 4371f485649SVlad Yasevich * user context. This forces us to pre-allocated all possible transforms 4381f485649SVlad Yasevich * at the endpoint init time. 4391f485649SVlad Yasevich */ 4401f485649SVlad Yasevich int sctp_auth_init_hmacs(struct sctp_endpoint *ep, gfp_t gfp) 4411f485649SVlad Yasevich { 4421f485649SVlad Yasevich struct crypto_hash *tfm = NULL; 4431f485649SVlad Yasevich __u16 id; 4441f485649SVlad Yasevich 445b14878ccSVlad Yasevich /* If AUTH extension is disabled, we are done */ 446b14878ccSVlad Yasevich if (!ep->auth_enable) { 4471f485649SVlad Yasevich ep->auth_hmacs = NULL; 4481f485649SVlad Yasevich return 0; 4491f485649SVlad Yasevich } 4501f485649SVlad Yasevich 451b14878ccSVlad Yasevich /* If the transforms are already allocated, we are done */ 4521f485649SVlad Yasevich if (ep->auth_hmacs) 4531f485649SVlad Yasevich return 0; 4541f485649SVlad Yasevich 4551f485649SVlad Yasevich /* Allocated the array of pointers to transorms */ 4561f485649SVlad Yasevich ep->auth_hmacs = kzalloc( 4571f485649SVlad Yasevich sizeof(struct crypto_hash *) * SCTP_AUTH_NUM_HMACS, 4581f485649SVlad Yasevich gfp); 4591f485649SVlad Yasevich if (!ep->auth_hmacs) 4601f485649SVlad Yasevich return -ENOMEM; 4611f485649SVlad Yasevich 4621f485649SVlad Yasevich for (id = 0; id < SCTP_AUTH_NUM_HMACS; id++) { 4631f485649SVlad Yasevich 4641f485649SVlad Yasevich /* See is we support the id. Supported IDs have name and 4651f485649SVlad Yasevich * length fields set, so that we can allocated and use 4661f485649SVlad Yasevich * them. We can safely just check for name, for without the 4671f485649SVlad Yasevich * name, we can't allocate the TFM. 4681f485649SVlad Yasevich */ 4691f485649SVlad Yasevich if (!sctp_hmac_list[id].hmac_name) 4701f485649SVlad Yasevich continue; 4711f485649SVlad Yasevich 4721f485649SVlad Yasevich /* If this TFM has been allocated, we are all set */ 4731f485649SVlad Yasevich if (ep->auth_hmacs[id]) 4741f485649SVlad Yasevich continue; 4751f485649SVlad Yasevich 4761f485649SVlad Yasevich /* Allocate the ID */ 4771f485649SVlad Yasevich tfm = crypto_alloc_hash(sctp_hmac_list[id].hmac_name, 0, 4781f485649SVlad Yasevich CRYPTO_ALG_ASYNC); 4791f485649SVlad Yasevich if (IS_ERR(tfm)) 4801f485649SVlad Yasevich goto out_err; 4811f485649SVlad Yasevich 4821f485649SVlad Yasevich ep->auth_hmacs[id] = tfm; 4831f485649SVlad Yasevich } 4841f485649SVlad Yasevich 4851f485649SVlad Yasevich return 0; 4861f485649SVlad Yasevich 4871f485649SVlad Yasevich out_err: 48873ac36eaSColy Li /* Clean up any successful allocations */ 4891f485649SVlad Yasevich sctp_auth_destroy_hmacs(ep->auth_hmacs); 4901f485649SVlad Yasevich return -ENOMEM; 4911f485649SVlad Yasevich } 4921f485649SVlad Yasevich 4931f485649SVlad Yasevich /* Destroy the hmac tfm array */ 4941f485649SVlad Yasevich void sctp_auth_destroy_hmacs(struct crypto_hash *auth_hmacs[]) 4951f485649SVlad Yasevich { 4961f485649SVlad Yasevich int i; 4971f485649SVlad Yasevich 4981f485649SVlad Yasevich if (!auth_hmacs) 4991f485649SVlad Yasevich return; 5001f485649SVlad Yasevich 5018d72651dSwangweidong for (i = 0; i < SCTP_AUTH_NUM_HMACS; i++) { 5021f485649SVlad Yasevich if (auth_hmacs[i]) 5031f485649SVlad Yasevich crypto_free_hash(auth_hmacs[i]); 5041f485649SVlad Yasevich } 5051f485649SVlad Yasevich kfree(auth_hmacs); 5061f485649SVlad Yasevich } 5071f485649SVlad Yasevich 5081f485649SVlad Yasevich 5091f485649SVlad Yasevich struct sctp_hmac *sctp_auth_get_hmac(__u16 hmac_id) 5101f485649SVlad Yasevich { 5111f485649SVlad Yasevich return &sctp_hmac_list[hmac_id]; 5121f485649SVlad Yasevich } 5131f485649SVlad Yasevich 5141f485649SVlad Yasevich /* Get an hmac description information that we can use to build 5151f485649SVlad Yasevich * the AUTH chunk 5161f485649SVlad Yasevich */ 5171f485649SVlad Yasevich struct sctp_hmac *sctp_auth_asoc_get_hmac(const struct sctp_association *asoc) 5181f485649SVlad Yasevich { 5191f485649SVlad Yasevich struct sctp_hmac_algo_param *hmacs; 5201f485649SVlad Yasevich __u16 n_elt; 5211f485649SVlad Yasevich __u16 id = 0; 5221f485649SVlad Yasevich int i; 5231f485649SVlad Yasevich 5241f485649SVlad Yasevich /* If we have a default entry, use it */ 5251f485649SVlad Yasevich if (asoc->default_hmac_id) 5261f485649SVlad Yasevich return &sctp_hmac_list[asoc->default_hmac_id]; 5271f485649SVlad Yasevich 5281f485649SVlad Yasevich /* Since we do not have a default entry, find the first entry 5291f485649SVlad Yasevich * we support and return that. Do not cache that id. 5301f485649SVlad Yasevich */ 5311f485649SVlad Yasevich hmacs = asoc->peer.peer_hmacs; 5321f485649SVlad Yasevich if (!hmacs) 5331f485649SVlad Yasevich return NULL; 5341f485649SVlad Yasevich 5351f485649SVlad Yasevich n_elt = (ntohs(hmacs->param_hdr.length) - sizeof(sctp_paramhdr_t)) >> 1; 5361f485649SVlad Yasevich for (i = 0; i < n_elt; i++) { 5371f485649SVlad Yasevich id = ntohs(hmacs->hmac_ids[i]); 5381f485649SVlad Yasevich 539747edc0fSwangweidong /* Check the id is in the supported range. And 540747edc0fSwangweidong * see if we support the id. Supported IDs have name and 541747edc0fSwangweidong * length fields set, so that we can allocate and use 5421f485649SVlad Yasevich * them. We can safely just check for name, for without the 5431f485649SVlad Yasevich * name, we can't allocate the TFM. 5441f485649SVlad Yasevich */ 545747edc0fSwangweidong if (id > SCTP_AUTH_HMAC_ID_MAX || 546747edc0fSwangweidong !sctp_hmac_list[id].hmac_name) { 54751e97a12SDan Rosenberg id = 0; 5481f485649SVlad Yasevich continue; 54951e97a12SDan Rosenberg } 5501f485649SVlad Yasevich 5511f485649SVlad Yasevich break; 5521f485649SVlad Yasevich } 5531f485649SVlad Yasevich 5541f485649SVlad Yasevich if (id == 0) 5551f485649SVlad Yasevich return NULL; 5561f485649SVlad Yasevich 5571f485649SVlad Yasevich return &sctp_hmac_list[id]; 5581f485649SVlad Yasevich } 5591f485649SVlad Yasevich 560d06f6082SAl Viro static int __sctp_auth_find_hmacid(__be16 *hmacs, int n_elts, __be16 hmac_id) 5611f485649SVlad Yasevich { 5621f485649SVlad Yasevich int found = 0; 5631f485649SVlad Yasevich int i; 5641f485649SVlad Yasevich 5651f485649SVlad Yasevich for (i = 0; i < n_elts; i++) { 5661f485649SVlad Yasevich if (hmac_id == hmacs[i]) { 5671f485649SVlad Yasevich found = 1; 5681f485649SVlad Yasevich break; 5691f485649SVlad Yasevich } 5701f485649SVlad Yasevich } 5711f485649SVlad Yasevich 5721f485649SVlad Yasevich return found; 5731f485649SVlad Yasevich } 5741f485649SVlad Yasevich 5751f485649SVlad Yasevich /* See if the HMAC_ID is one that we claim as supported */ 5761f485649SVlad Yasevich int sctp_auth_asoc_verify_hmac_id(const struct sctp_association *asoc, 577d06f6082SAl Viro __be16 hmac_id) 5781f485649SVlad Yasevich { 5791f485649SVlad Yasevich struct sctp_hmac_algo_param *hmacs; 5801f485649SVlad Yasevich __u16 n_elt; 5811f485649SVlad Yasevich 5821f485649SVlad Yasevich if (!asoc) 5831f485649SVlad Yasevich return 0; 5841f485649SVlad Yasevich 5851f485649SVlad Yasevich hmacs = (struct sctp_hmac_algo_param *)asoc->c.auth_hmacs; 5861f485649SVlad Yasevich n_elt = (ntohs(hmacs->param_hdr.length) - sizeof(sctp_paramhdr_t)) >> 1; 5871f485649SVlad Yasevich 5881f485649SVlad Yasevich return __sctp_auth_find_hmacid(hmacs->hmac_ids, n_elt, hmac_id); 5891f485649SVlad Yasevich } 5901f485649SVlad Yasevich 5911f485649SVlad Yasevich 5921f485649SVlad Yasevich /* Cache the default HMAC id. This to follow this text from SCTP-AUTH: 5931f485649SVlad Yasevich * Section 6.1: 5941f485649SVlad Yasevich * The receiver of a HMAC-ALGO parameter SHOULD use the first listed 5951f485649SVlad Yasevich * algorithm it supports. 5961f485649SVlad Yasevich */ 5971f485649SVlad Yasevich void sctp_auth_asoc_set_default_hmac(struct sctp_association *asoc, 5981f485649SVlad Yasevich struct sctp_hmac_algo_param *hmacs) 5991f485649SVlad Yasevich { 6001f485649SVlad Yasevich struct sctp_endpoint *ep; 6011f485649SVlad Yasevich __u16 id; 6021f485649SVlad Yasevich int i; 6031f485649SVlad Yasevich int n_params; 6041f485649SVlad Yasevich 6051f485649SVlad Yasevich /* if the default id is already set, use it */ 6061f485649SVlad Yasevich if (asoc->default_hmac_id) 6071f485649SVlad Yasevich return; 6081f485649SVlad Yasevich 6091f485649SVlad Yasevich n_params = (ntohs(hmacs->param_hdr.length) 6101f485649SVlad Yasevich - sizeof(sctp_paramhdr_t)) >> 1; 6111f485649SVlad Yasevich ep = asoc->ep; 6121f485649SVlad Yasevich for (i = 0; i < n_params; i++) { 6131f485649SVlad Yasevich id = ntohs(hmacs->hmac_ids[i]); 6141f485649SVlad Yasevich 6151f485649SVlad Yasevich /* Check the id is in the supported range */ 6161f485649SVlad Yasevich if (id > SCTP_AUTH_HMAC_ID_MAX) 6171f485649SVlad Yasevich continue; 6181f485649SVlad Yasevich 6191f485649SVlad Yasevich /* If this TFM has been allocated, use this id */ 6201f485649SVlad Yasevich if (ep->auth_hmacs[id]) { 6211f485649SVlad Yasevich asoc->default_hmac_id = id; 6221f485649SVlad Yasevich break; 6231f485649SVlad Yasevich } 6241f485649SVlad Yasevich } 6251f485649SVlad Yasevich } 6261f485649SVlad Yasevich 6271f485649SVlad Yasevich 6281f485649SVlad Yasevich /* Check to see if the given chunk is supposed to be authenticated */ 6291f485649SVlad Yasevich static int __sctp_auth_cid(sctp_cid_t chunk, struct sctp_chunks_param *param) 6301f485649SVlad Yasevich { 6311f485649SVlad Yasevich unsigned short len; 6321f485649SVlad Yasevich int found = 0; 6331f485649SVlad Yasevich int i; 6341f485649SVlad Yasevich 635555d3d5dSVlad Yasevich if (!param || param->param_hdr.length == 0) 6361f485649SVlad Yasevich return 0; 6371f485649SVlad Yasevich 6381f485649SVlad Yasevich len = ntohs(param->param_hdr.length) - sizeof(sctp_paramhdr_t); 6391f485649SVlad Yasevich 6401f485649SVlad Yasevich /* SCTP-AUTH, Section 3.2 6411f485649SVlad Yasevich * The chunk types for INIT, INIT-ACK, SHUTDOWN-COMPLETE and AUTH 6421f485649SVlad Yasevich * chunks MUST NOT be listed in the CHUNKS parameter. However, if 6431f485649SVlad Yasevich * a CHUNKS parameter is received then the types for INIT, INIT-ACK, 6441f485649SVlad Yasevich * SHUTDOWN-COMPLETE and AUTH chunks MUST be ignored. 6451f485649SVlad Yasevich */ 6461f485649SVlad Yasevich for (i = 0; !found && i < len; i++) { 6471f485649SVlad Yasevich switch (param->chunks[i]) { 6481f485649SVlad Yasevich case SCTP_CID_INIT: 6491f485649SVlad Yasevich case SCTP_CID_INIT_ACK: 6501f485649SVlad Yasevich case SCTP_CID_SHUTDOWN_COMPLETE: 6511f485649SVlad Yasevich case SCTP_CID_AUTH: 6521f485649SVlad Yasevich break; 6531f485649SVlad Yasevich 6541f485649SVlad Yasevich default: 6551f485649SVlad Yasevich if (param->chunks[i] == chunk) 6561f485649SVlad Yasevich found = 1; 6571f485649SVlad Yasevich break; 6581f485649SVlad Yasevich } 6591f485649SVlad Yasevich } 6601f485649SVlad Yasevich 6611f485649SVlad Yasevich return found; 6621f485649SVlad Yasevich } 6631f485649SVlad Yasevich 6641f485649SVlad Yasevich /* Check if peer requested that this chunk is authenticated */ 6651f485649SVlad Yasevich int sctp_auth_send_cid(sctp_cid_t chunk, const struct sctp_association *asoc) 6661f485649SVlad Yasevich { 667e1fc3b14SEric W. Biederman if (!asoc) 668e1fc3b14SEric W. Biederman return 0; 669e1fc3b14SEric W. Biederman 670b14878ccSVlad Yasevich if (!asoc->ep->auth_enable || !asoc->peer.auth_capable) 6711f485649SVlad Yasevich return 0; 6721f485649SVlad Yasevich 6731f485649SVlad Yasevich return __sctp_auth_cid(chunk, asoc->peer.peer_chunks); 6741f485649SVlad Yasevich } 6751f485649SVlad Yasevich 6761f485649SVlad Yasevich /* Check if we requested that peer authenticate this chunk. */ 6771f485649SVlad Yasevich int sctp_auth_recv_cid(sctp_cid_t chunk, const struct sctp_association *asoc) 6781f485649SVlad Yasevich { 679e1fc3b14SEric W. Biederman if (!asoc) 680e1fc3b14SEric W. Biederman return 0; 681e1fc3b14SEric W. Biederman 682b14878ccSVlad Yasevich if (!asoc->ep->auth_enable) 6831f485649SVlad Yasevich return 0; 6841f485649SVlad Yasevich 6851f485649SVlad Yasevich return __sctp_auth_cid(chunk, 6861f485649SVlad Yasevich (struct sctp_chunks_param *)asoc->c.auth_chunks); 6871f485649SVlad Yasevich } 6881f485649SVlad Yasevich 6891f485649SVlad Yasevich /* SCTP-AUTH: Section 6.2: 6901f485649SVlad Yasevich * The sender MUST calculate the MAC as described in RFC2104 [2] using 6911f485649SVlad Yasevich * the hash function H as described by the MAC Identifier and the shared 6921f485649SVlad Yasevich * association key K based on the endpoint pair shared key described by 6931f485649SVlad Yasevich * the shared key identifier. The 'data' used for the computation of 6941f485649SVlad Yasevich * the AUTH-chunk is given by the AUTH chunk with its HMAC field set to 6951f485649SVlad Yasevich * zero (as shown in Figure 6) followed by all chunks that are placed 6961f485649SVlad Yasevich * after the AUTH chunk in the SCTP packet. 6971f485649SVlad Yasevich */ 6981f485649SVlad Yasevich void sctp_auth_calculate_hmac(const struct sctp_association *asoc, 6991f485649SVlad Yasevich struct sk_buff *skb, 7001f485649SVlad Yasevich struct sctp_auth_chunk *auth, 7011f485649SVlad Yasevich gfp_t gfp) 7021f485649SVlad Yasevich { 7031f485649SVlad Yasevich struct scatterlist sg; 7041f485649SVlad Yasevich struct hash_desc desc; 7051f485649SVlad Yasevich struct sctp_auth_bytes *asoc_key; 7061f485649SVlad Yasevich __u16 key_id, hmac_id; 7071f485649SVlad Yasevich __u8 *digest; 7081f485649SVlad Yasevich unsigned char *end; 7091f485649SVlad Yasevich int free_key = 0; 7101f485649SVlad Yasevich 7111f485649SVlad Yasevich /* Extract the info we need: 7121f485649SVlad Yasevich * - hmac id 7131f485649SVlad Yasevich * - key id 7141f485649SVlad Yasevich */ 7151f485649SVlad Yasevich key_id = ntohs(auth->auth_hdr.shkey_id); 7161f485649SVlad Yasevich hmac_id = ntohs(auth->auth_hdr.hmac_id); 7171f485649SVlad Yasevich 7181f485649SVlad Yasevich if (key_id == asoc->active_key_id) 7191f485649SVlad Yasevich asoc_key = asoc->asoc_shared_key; 7201f485649SVlad Yasevich else { 7211f485649SVlad Yasevich struct sctp_shared_key *ep_key; 7221f485649SVlad Yasevich 7231f485649SVlad Yasevich ep_key = sctp_auth_get_shkey(asoc, key_id); 7241f485649SVlad Yasevich if (!ep_key) 7251f485649SVlad Yasevich return; 7261f485649SVlad Yasevich 7271f485649SVlad Yasevich asoc_key = sctp_auth_asoc_create_secret(asoc, ep_key, gfp); 7281f485649SVlad Yasevich if (!asoc_key) 7291f485649SVlad Yasevich return; 7301f485649SVlad Yasevich 7311f485649SVlad Yasevich free_key = 1; 7321f485649SVlad Yasevich } 7331f485649SVlad Yasevich 7341f485649SVlad Yasevich /* set up scatter list */ 7351f485649SVlad Yasevich end = skb_tail_pointer(skb); 73668e3f5ddSHerbert Xu sg_init_one(&sg, auth, end - (unsigned char *)auth); 7371f485649SVlad Yasevich 7381f485649SVlad Yasevich desc.tfm = asoc->ep->auth_hmacs[hmac_id]; 7391f485649SVlad Yasevich desc.flags = 0; 7401f485649SVlad Yasevich 7411f485649SVlad Yasevich digest = auth->auth_hdr.hmac; 7421f485649SVlad Yasevich if (crypto_hash_setkey(desc.tfm, &asoc_key->data[0], asoc_key->len)) 7431f485649SVlad Yasevich goto free; 7441f485649SVlad Yasevich 7451f485649SVlad Yasevich crypto_hash_digest(&desc, &sg, sg.length, digest); 7461f485649SVlad Yasevich 7471f485649SVlad Yasevich free: 7481f485649SVlad Yasevich if (free_key) 7491f485649SVlad Yasevich sctp_auth_key_put(asoc_key); 7501f485649SVlad Yasevich } 75165b07e5dSVlad Yasevich 75265b07e5dSVlad Yasevich /* API Helpers */ 75365b07e5dSVlad Yasevich 75465b07e5dSVlad Yasevich /* Add a chunk to the endpoint authenticated chunk list */ 75565b07e5dSVlad Yasevich int sctp_auth_ep_add_chunkid(struct sctp_endpoint *ep, __u8 chunk_id) 75665b07e5dSVlad Yasevich { 75765b07e5dSVlad Yasevich struct sctp_chunks_param *p = ep->auth_chunk_list; 75865b07e5dSVlad Yasevich __u16 nchunks; 75965b07e5dSVlad Yasevich __u16 param_len; 76065b07e5dSVlad Yasevich 76165b07e5dSVlad Yasevich /* If this chunk is already specified, we are done */ 76265b07e5dSVlad Yasevich if (__sctp_auth_cid(chunk_id, p)) 76365b07e5dSVlad Yasevich return 0; 76465b07e5dSVlad Yasevich 76565b07e5dSVlad Yasevich /* Check if we can add this chunk to the array */ 76665b07e5dSVlad Yasevich param_len = ntohs(p->param_hdr.length); 76765b07e5dSVlad Yasevich nchunks = param_len - sizeof(sctp_paramhdr_t); 76865b07e5dSVlad Yasevich if (nchunks == SCTP_NUM_CHUNK_TYPES) 76965b07e5dSVlad Yasevich return -EINVAL; 77065b07e5dSVlad Yasevich 77165b07e5dSVlad Yasevich p->chunks[nchunks] = chunk_id; 77265b07e5dSVlad Yasevich p->param_hdr.length = htons(param_len + 1); 77365b07e5dSVlad Yasevich return 0; 77465b07e5dSVlad Yasevich } 77565b07e5dSVlad Yasevich 77665b07e5dSVlad Yasevich /* Add hmac identifires to the endpoint list of supported hmac ids */ 77765b07e5dSVlad Yasevich int sctp_auth_ep_set_hmacs(struct sctp_endpoint *ep, 77865b07e5dSVlad Yasevich struct sctp_hmacalgo *hmacs) 77965b07e5dSVlad Yasevich { 78065b07e5dSVlad Yasevich int has_sha1 = 0; 78165b07e5dSVlad Yasevich __u16 id; 78265b07e5dSVlad Yasevich int i; 78365b07e5dSVlad Yasevich 78465b07e5dSVlad Yasevich /* Scan the list looking for unsupported id. Also make sure that 78565b07e5dSVlad Yasevich * SHA1 is specified. 78665b07e5dSVlad Yasevich */ 78765b07e5dSVlad Yasevich for (i = 0; i < hmacs->shmac_num_idents; i++) { 78865b07e5dSVlad Yasevich id = hmacs->shmac_idents[i]; 78965b07e5dSVlad Yasevich 790d9724055SVlad Yasevich if (id > SCTP_AUTH_HMAC_ID_MAX) 791d9724055SVlad Yasevich return -EOPNOTSUPP; 792d9724055SVlad Yasevich 79365b07e5dSVlad Yasevich if (SCTP_AUTH_HMAC_ID_SHA1 == id) 79465b07e5dSVlad Yasevich has_sha1 = 1; 79565b07e5dSVlad Yasevich 79665b07e5dSVlad Yasevich if (!sctp_hmac_list[id].hmac_name) 79765b07e5dSVlad Yasevich return -EOPNOTSUPP; 79865b07e5dSVlad Yasevich } 79965b07e5dSVlad Yasevich 80065b07e5dSVlad Yasevich if (!has_sha1) 80165b07e5dSVlad Yasevich return -EINVAL; 80265b07e5dSVlad Yasevich 80365b07e5dSVlad Yasevich memcpy(ep->auth_hmacs_list->hmac_ids, &hmacs->shmac_idents[0], 80465b07e5dSVlad Yasevich hmacs->shmac_num_idents * sizeof(__u16)); 80565b07e5dSVlad Yasevich ep->auth_hmacs_list->param_hdr.length = htons(sizeof(sctp_paramhdr_t) + 80665b07e5dSVlad Yasevich hmacs->shmac_num_idents * sizeof(__u16)); 80765b07e5dSVlad Yasevich return 0; 80865b07e5dSVlad Yasevich } 80965b07e5dSVlad Yasevich 81065b07e5dSVlad Yasevich /* Set a new shared key on either endpoint or association. If the 81165b07e5dSVlad Yasevich * the key with a same ID already exists, replace the key (remove the 81265b07e5dSVlad Yasevich * old key and add a new one). 81365b07e5dSVlad Yasevich */ 81465b07e5dSVlad Yasevich int sctp_auth_set_key(struct sctp_endpoint *ep, 81565b07e5dSVlad Yasevich struct sctp_association *asoc, 81665b07e5dSVlad Yasevich struct sctp_authkey *auth_key) 81765b07e5dSVlad Yasevich { 81865b07e5dSVlad Yasevich struct sctp_shared_key *cur_key = NULL; 81965b07e5dSVlad Yasevich struct sctp_auth_bytes *key; 82065b07e5dSVlad Yasevich struct list_head *sh_keys; 82165b07e5dSVlad Yasevich int replace = 0; 82265b07e5dSVlad Yasevich 82365b07e5dSVlad Yasevich /* Try to find the given key id to see if 82465b07e5dSVlad Yasevich * we are doing a replace, or adding a new key 82565b07e5dSVlad Yasevich */ 82665b07e5dSVlad Yasevich if (asoc) 82765b07e5dSVlad Yasevich sh_keys = &asoc->endpoint_shared_keys; 82865b07e5dSVlad Yasevich else 82965b07e5dSVlad Yasevich sh_keys = &ep->endpoint_shared_keys; 83065b07e5dSVlad Yasevich 83165b07e5dSVlad Yasevich key_for_each(cur_key, sh_keys) { 83265b07e5dSVlad Yasevich if (cur_key->key_id == auth_key->sca_keynumber) { 83365b07e5dSVlad Yasevich replace = 1; 83465b07e5dSVlad Yasevich break; 83565b07e5dSVlad Yasevich } 83665b07e5dSVlad Yasevich } 83765b07e5dSVlad Yasevich 83865b07e5dSVlad Yasevich /* If we are not replacing a key id, we need to allocate 83965b07e5dSVlad Yasevich * a shared key. 84065b07e5dSVlad Yasevich */ 84165b07e5dSVlad Yasevich if (!replace) { 84265b07e5dSVlad Yasevich cur_key = sctp_auth_shkey_create(auth_key->sca_keynumber, 84365b07e5dSVlad Yasevich GFP_KERNEL); 84465b07e5dSVlad Yasevich if (!cur_key) 84565b07e5dSVlad Yasevich return -ENOMEM; 84665b07e5dSVlad Yasevich } 84765b07e5dSVlad Yasevich 84865b07e5dSVlad Yasevich /* Create a new key data based on the info passed in */ 8497e8616d8SVlad Yasevich key = sctp_auth_create_key(auth_key->sca_keylength, GFP_KERNEL); 85065b07e5dSVlad Yasevich if (!key) 85165b07e5dSVlad Yasevich goto nomem; 85265b07e5dSVlad Yasevich 8537e8616d8SVlad Yasevich memcpy(key->data, &auth_key->sca_key[0], auth_key->sca_keylength); 85465b07e5dSVlad Yasevich 85565b07e5dSVlad Yasevich /* If we are replacing, remove the old keys data from the 85665b07e5dSVlad Yasevich * key id. If we are adding new key id, add it to the 85765b07e5dSVlad Yasevich * list. 85865b07e5dSVlad Yasevich */ 85965b07e5dSVlad Yasevich if (replace) 86065b07e5dSVlad Yasevich sctp_auth_key_put(cur_key->key); 86165b07e5dSVlad Yasevich else 86265b07e5dSVlad Yasevich list_add(&cur_key->key_list, sh_keys); 86365b07e5dSVlad Yasevich 86465b07e5dSVlad Yasevich cur_key->key = key; 86565b07e5dSVlad Yasevich sctp_auth_key_hold(key); 86665b07e5dSVlad Yasevich 86765b07e5dSVlad Yasevich return 0; 86865b07e5dSVlad Yasevich nomem: 86965b07e5dSVlad Yasevich if (!replace) 87065b07e5dSVlad Yasevich sctp_auth_shkey_free(cur_key); 87165b07e5dSVlad Yasevich 87265b07e5dSVlad Yasevich return -ENOMEM; 87365b07e5dSVlad Yasevich } 87465b07e5dSVlad Yasevich 87565b07e5dSVlad Yasevich int sctp_auth_set_active_key(struct sctp_endpoint *ep, 87665b07e5dSVlad Yasevich struct sctp_association *asoc, 87765b07e5dSVlad Yasevich __u16 key_id) 87865b07e5dSVlad Yasevich { 87965b07e5dSVlad Yasevich struct sctp_shared_key *key; 88065b07e5dSVlad Yasevich struct list_head *sh_keys; 88165b07e5dSVlad Yasevich int found = 0; 88265b07e5dSVlad Yasevich 88365b07e5dSVlad Yasevich /* The key identifier MUST correst to an existing key */ 88465b07e5dSVlad Yasevich if (asoc) 88565b07e5dSVlad Yasevich sh_keys = &asoc->endpoint_shared_keys; 88665b07e5dSVlad Yasevich else 88765b07e5dSVlad Yasevich sh_keys = &ep->endpoint_shared_keys; 88865b07e5dSVlad Yasevich 88965b07e5dSVlad Yasevich key_for_each(key, sh_keys) { 89065b07e5dSVlad Yasevich if (key->key_id == key_id) { 89165b07e5dSVlad Yasevich found = 1; 89265b07e5dSVlad Yasevich break; 89365b07e5dSVlad Yasevich } 89465b07e5dSVlad Yasevich } 89565b07e5dSVlad Yasevich 89665b07e5dSVlad Yasevich if (!found) 89765b07e5dSVlad Yasevich return -EINVAL; 89865b07e5dSVlad Yasevich 89965b07e5dSVlad Yasevich if (asoc) { 90065b07e5dSVlad Yasevich asoc->active_key_id = key_id; 90165b07e5dSVlad Yasevich sctp_auth_asoc_init_active_key(asoc, GFP_KERNEL); 90265b07e5dSVlad Yasevich } else 90365b07e5dSVlad Yasevich ep->active_key_id = key_id; 90465b07e5dSVlad Yasevich 90565b07e5dSVlad Yasevich return 0; 90665b07e5dSVlad Yasevich } 90765b07e5dSVlad Yasevich 90865b07e5dSVlad Yasevich int sctp_auth_del_key_id(struct sctp_endpoint *ep, 90965b07e5dSVlad Yasevich struct sctp_association *asoc, 91065b07e5dSVlad Yasevich __u16 key_id) 91165b07e5dSVlad Yasevich { 91265b07e5dSVlad Yasevich struct sctp_shared_key *key; 91365b07e5dSVlad Yasevich struct list_head *sh_keys; 91465b07e5dSVlad Yasevich int found = 0; 91565b07e5dSVlad Yasevich 91665b07e5dSVlad Yasevich /* The key identifier MUST NOT be the current active key 91765b07e5dSVlad Yasevich * The key identifier MUST correst to an existing key 91865b07e5dSVlad Yasevich */ 91965b07e5dSVlad Yasevich if (asoc) { 92065b07e5dSVlad Yasevich if (asoc->active_key_id == key_id) 92165b07e5dSVlad Yasevich return -EINVAL; 92265b07e5dSVlad Yasevich 92365b07e5dSVlad Yasevich sh_keys = &asoc->endpoint_shared_keys; 92465b07e5dSVlad Yasevich } else { 92565b07e5dSVlad Yasevich if (ep->active_key_id == key_id) 92665b07e5dSVlad Yasevich return -EINVAL; 92765b07e5dSVlad Yasevich 92865b07e5dSVlad Yasevich sh_keys = &ep->endpoint_shared_keys; 92965b07e5dSVlad Yasevich } 93065b07e5dSVlad Yasevich 93165b07e5dSVlad Yasevich key_for_each(key, sh_keys) { 93265b07e5dSVlad Yasevich if (key->key_id == key_id) { 93365b07e5dSVlad Yasevich found = 1; 93465b07e5dSVlad Yasevich break; 93565b07e5dSVlad Yasevich } 93665b07e5dSVlad Yasevich } 93765b07e5dSVlad Yasevich 93865b07e5dSVlad Yasevich if (!found) 93965b07e5dSVlad Yasevich return -EINVAL; 94065b07e5dSVlad Yasevich 94165b07e5dSVlad Yasevich /* Delete the shared key */ 94265b07e5dSVlad Yasevich list_del_init(&key->key_list); 94365b07e5dSVlad Yasevich sctp_auth_shkey_free(key); 94465b07e5dSVlad Yasevich 94565b07e5dSVlad Yasevich return 0; 94665b07e5dSVlad Yasevich } 947