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 305821c769SHerbert Xu #include <crypto/hash.h> 315a0e3ad6STejun Heo #include <linux/slab.h> 321f485649SVlad Yasevich #include <linux/types.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 }, 51aebf5de0SJavier Martinez Canillas #if IS_ENABLED(CONFIG_CRYPTO_SHA256) 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 666871584aSReshetova, Elena if (refcount_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; 876871584aSReshetova, Elena refcount_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( 188b02db702SXin Long struct sctp_random_param *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( 229b02db702SXin Long (struct sctp_random_param *)asoc->c.auth_random, 2301f485649SVlad Yasevich (sctp_chunks_param_t *)asoc->c.auth_chunks, 231b02db702SXin Long (sctp_hmac_algo_param_t *)asoc->c.auth_hmacs, gfp); 2321f485649SVlad Yasevich } 2331f485649SVlad Yasevich 2341f485649SVlad Yasevich /* Make a key vector based on peer's parameters */ 2358ad7c62bSAdrian Bunk static struct sctp_auth_bytes *sctp_auth_make_peer_vector( 2361f485649SVlad Yasevich const struct sctp_association *asoc, 2371f485649SVlad Yasevich gfp_t gfp) 2381f485649SVlad Yasevich { 2391f485649SVlad Yasevich return sctp_auth_make_key_vector(asoc->peer.peer_random, 2401f485649SVlad Yasevich asoc->peer.peer_chunks, 2411f485649SVlad Yasevich asoc->peer.peer_hmacs, 2421f485649SVlad Yasevich gfp); 2431f485649SVlad Yasevich } 2441f485649SVlad Yasevich 2451f485649SVlad Yasevich 2461f485649SVlad Yasevich /* Set the value of the association shared key base on the parameters 2471f485649SVlad Yasevich * given. The algorithm is: 2481f485649SVlad Yasevich * From the endpoint pair shared keys and the key vectors the 2491f485649SVlad Yasevich * association shared keys are computed. This is performed by selecting 2501f485649SVlad Yasevich * the numerically smaller key vector and concatenating it to the 2511f485649SVlad Yasevich * endpoint pair shared key, and then concatenating the numerically 2521f485649SVlad Yasevich * larger key vector to that. The result of the concatenation is the 2531f485649SVlad Yasevich * association shared key. 2541f485649SVlad Yasevich */ 2551f485649SVlad Yasevich static struct sctp_auth_bytes *sctp_auth_asoc_set_secret( 2561f485649SVlad Yasevich struct sctp_shared_key *ep_key, 2571f485649SVlad Yasevich struct sctp_auth_bytes *first_vector, 2581f485649SVlad Yasevich struct sctp_auth_bytes *last_vector, 2591f485649SVlad Yasevich gfp_t gfp) 2601f485649SVlad Yasevich { 2611f485649SVlad Yasevich struct sctp_auth_bytes *secret; 2621f485649SVlad Yasevich __u32 offset = 0; 2631f485649SVlad Yasevich __u32 auth_len; 2641f485649SVlad Yasevich 2651f485649SVlad Yasevich auth_len = first_vector->len + last_vector->len; 2661f485649SVlad Yasevich if (ep_key->key) 2671f485649SVlad Yasevich auth_len += ep_key->key->len; 2681f485649SVlad Yasevich 2691f485649SVlad Yasevich secret = sctp_auth_create_key(auth_len, gfp); 2701f485649SVlad Yasevich if (!secret) 2711f485649SVlad Yasevich return NULL; 2721f485649SVlad Yasevich 2731f485649SVlad Yasevich if (ep_key->key) { 2741f485649SVlad Yasevich memcpy(secret->data, ep_key->key->data, ep_key->key->len); 2751f485649SVlad Yasevich offset += ep_key->key->len; 2761f485649SVlad Yasevich } 2771f485649SVlad Yasevich 2781f485649SVlad Yasevich memcpy(secret->data + offset, first_vector->data, first_vector->len); 2791f485649SVlad Yasevich offset += first_vector->len; 2801f485649SVlad Yasevich 2811f485649SVlad Yasevich memcpy(secret->data + offset, last_vector->data, last_vector->len); 2821f485649SVlad Yasevich 2831f485649SVlad Yasevich return secret; 2841f485649SVlad Yasevich } 2851f485649SVlad Yasevich 2861f485649SVlad Yasevich /* Create an association shared key. Follow the algorithm 2871f485649SVlad Yasevich * described in SCTP-AUTH, Section 6.1 2881f485649SVlad Yasevich */ 2891f485649SVlad Yasevich static struct sctp_auth_bytes *sctp_auth_asoc_create_secret( 2901f485649SVlad Yasevich const struct sctp_association *asoc, 2911f485649SVlad Yasevich struct sctp_shared_key *ep_key, 2921f485649SVlad Yasevich gfp_t gfp) 2931f485649SVlad Yasevich { 2941f485649SVlad Yasevich struct sctp_auth_bytes *local_key_vector; 2951f485649SVlad Yasevich struct sctp_auth_bytes *peer_key_vector; 2961f485649SVlad Yasevich struct sctp_auth_bytes *first_vector, 2971f485649SVlad Yasevich *last_vector; 2981f485649SVlad Yasevich struct sctp_auth_bytes *secret = NULL; 2991f485649SVlad Yasevich int cmp; 3001f485649SVlad Yasevich 3011f485649SVlad Yasevich 3021f485649SVlad Yasevich /* Now we need to build the key vectors 3031f485649SVlad Yasevich * SCTP-AUTH , Section 6.1 3041f485649SVlad Yasevich * The RANDOM parameter, the CHUNKS parameter and the HMAC-ALGO 3051f485649SVlad Yasevich * parameter sent by each endpoint are concatenated as byte vectors. 3061f485649SVlad Yasevich * These parameters include the parameter type, parameter length, and 3071f485649SVlad Yasevich * the parameter value, but padding is omitted; all padding MUST be 3081f485649SVlad Yasevich * removed from this concatenation before proceeding with further 3091f485649SVlad Yasevich * computation of keys. Parameters which were not sent are simply 3101f485649SVlad Yasevich * omitted from the concatenation process. The resulting two vectors 3111f485649SVlad Yasevich * are called the two key vectors. 3121f485649SVlad Yasevich */ 3131f485649SVlad Yasevich 3141f485649SVlad Yasevich local_key_vector = sctp_auth_make_local_vector(asoc, gfp); 3151f485649SVlad Yasevich peer_key_vector = sctp_auth_make_peer_vector(asoc, gfp); 3161f485649SVlad Yasevich 3171f485649SVlad Yasevich if (!peer_key_vector || !local_key_vector) 3181f485649SVlad Yasevich goto out; 3191f485649SVlad Yasevich 32025985edcSLucas De Marchi /* Figure out the order in which the key_vectors will be 3211f485649SVlad Yasevich * added to the endpoint shared key. 3221f485649SVlad Yasevich * SCTP-AUTH, Section 6.1: 3231f485649SVlad Yasevich * This is performed by selecting the numerically smaller key 3241f485649SVlad Yasevich * vector and concatenating it to the endpoint pair shared 3251f485649SVlad Yasevich * key, and then concatenating the numerically larger key 3261f485649SVlad Yasevich * vector to that. If the key vectors are equal as numbers 3271f485649SVlad Yasevich * but differ in length, then the concatenation order is the 3281f485649SVlad Yasevich * endpoint shared key, followed by the shorter key vector, 3291f485649SVlad Yasevich * followed by the longer key vector. Otherwise, the key 3301f485649SVlad Yasevich * vectors are identical, and may be concatenated to the 3311f485649SVlad Yasevich * endpoint pair key in any order. 3321f485649SVlad Yasevich */ 3331f485649SVlad Yasevich cmp = sctp_auth_compare_vectors(local_key_vector, 3341f485649SVlad Yasevich peer_key_vector); 3351f485649SVlad Yasevich if (cmp < 0) { 3361f485649SVlad Yasevich first_vector = local_key_vector; 3371f485649SVlad Yasevich last_vector = peer_key_vector; 3381f485649SVlad Yasevich } else { 3391f485649SVlad Yasevich first_vector = peer_key_vector; 3401f485649SVlad Yasevich last_vector = local_key_vector; 3411f485649SVlad Yasevich } 3421f485649SVlad Yasevich 3431f485649SVlad Yasevich secret = sctp_auth_asoc_set_secret(ep_key, first_vector, last_vector, 3441f485649SVlad Yasevich gfp); 3451f485649SVlad Yasevich out: 34603536e23SDaniel Borkmann sctp_auth_key_put(local_key_vector); 34703536e23SDaniel Borkmann sctp_auth_key_put(peer_key_vector); 3481f485649SVlad Yasevich 3491f485649SVlad Yasevich return secret; 3501f485649SVlad Yasevich } 3511f485649SVlad Yasevich 3521f485649SVlad Yasevich /* 3531f485649SVlad Yasevich * Populate the association overlay list with the list 3541f485649SVlad Yasevich * from the endpoint. 3551f485649SVlad Yasevich */ 3561f485649SVlad Yasevich int sctp_auth_asoc_copy_shkeys(const struct sctp_endpoint *ep, 3571f485649SVlad Yasevich struct sctp_association *asoc, 3581f485649SVlad Yasevich gfp_t gfp) 3591f485649SVlad Yasevich { 3601f485649SVlad Yasevich struct sctp_shared_key *sh_key; 3611f485649SVlad Yasevich struct sctp_shared_key *new; 3621f485649SVlad Yasevich 3631f485649SVlad Yasevich BUG_ON(!list_empty(&asoc->endpoint_shared_keys)); 3641f485649SVlad Yasevich 3651f485649SVlad Yasevich key_for_each(sh_key, &ep->endpoint_shared_keys) { 3661f485649SVlad Yasevich new = sctp_auth_shkey_create(sh_key->key_id, gfp); 3671f485649SVlad Yasevich if (!new) 3681f485649SVlad Yasevich goto nomem; 3691f485649SVlad Yasevich 3701f485649SVlad Yasevich new->key = sh_key->key; 3711f485649SVlad Yasevich sctp_auth_key_hold(new->key); 3721f485649SVlad Yasevich list_add(&new->key_list, &asoc->endpoint_shared_keys); 3731f485649SVlad Yasevich } 3741f485649SVlad Yasevich 3751f485649SVlad Yasevich return 0; 3761f485649SVlad Yasevich 3771f485649SVlad Yasevich nomem: 3781f485649SVlad Yasevich sctp_auth_destroy_keys(&asoc->endpoint_shared_keys); 3791f485649SVlad Yasevich return -ENOMEM; 3801f485649SVlad Yasevich } 3811f485649SVlad Yasevich 3821f485649SVlad Yasevich 383ae36806aSMarcelo Ricardo Leitner /* Public interface to create the association shared key. 3841f485649SVlad Yasevich * See code above for the algorithm. 3851f485649SVlad Yasevich */ 3861f485649SVlad Yasevich int sctp_auth_asoc_init_active_key(struct sctp_association *asoc, gfp_t gfp) 3871f485649SVlad Yasevich { 3881f485649SVlad Yasevich struct sctp_auth_bytes *secret; 3891f485649SVlad Yasevich struct sctp_shared_key *ep_key; 390ae36806aSMarcelo Ricardo Leitner struct sctp_chunk *chunk; 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 413ae36806aSMarcelo Ricardo Leitner /* Update send queue in case any chunk already in there now 414ae36806aSMarcelo Ricardo Leitner * needs authenticating 415ae36806aSMarcelo Ricardo Leitner */ 416ae36806aSMarcelo Ricardo Leitner list_for_each_entry(chunk, &asoc->outqueue.out_chunk_list, list) { 417ae36806aSMarcelo Ricardo Leitner if (sctp_auth_send_cid(chunk->chunk_hdr->type, asoc)) 418ae36806aSMarcelo Ricardo Leitner chunk->auth = 1; 419ae36806aSMarcelo Ricardo Leitner } 420ae36806aSMarcelo Ricardo Leitner 4211f485649SVlad Yasevich return 0; 4221f485649SVlad Yasevich } 4231f485649SVlad Yasevich 4241f485649SVlad Yasevich 4251f485649SVlad Yasevich /* Find the endpoint pair shared key based on the key_id */ 4261f485649SVlad Yasevich struct sctp_shared_key *sctp_auth_get_shkey( 4271f485649SVlad Yasevich const struct sctp_association *asoc, 4281f485649SVlad Yasevich __u16 key_id) 4291f485649SVlad Yasevich { 4307cc08b55SWei Yongjun struct sctp_shared_key *key; 4311f485649SVlad Yasevich 4321f485649SVlad Yasevich /* First search associations set of endpoint pair shared keys */ 4331f485649SVlad Yasevich key_for_each(key, &asoc->endpoint_shared_keys) { 4341f485649SVlad Yasevich if (key->key_id == key_id) 4357cc08b55SWei Yongjun return key; 4361f485649SVlad Yasevich } 4371f485649SVlad Yasevich 4387cc08b55SWei Yongjun return NULL; 4391f485649SVlad Yasevich } 4401f485649SVlad Yasevich 4411f485649SVlad Yasevich /* 4421f485649SVlad Yasevich * Initialize all the possible digest transforms that we can use. Right now 4431f485649SVlad Yasevich * now, the supported digests are SHA1 and SHA256. We do this here once 4441f485649SVlad Yasevich * because of the restrictiong that transforms may only be allocated in 4451f485649SVlad Yasevich * user context. This forces us to pre-allocated all possible transforms 4461f485649SVlad Yasevich * at the endpoint init time. 4471f485649SVlad Yasevich */ 4481f485649SVlad Yasevich int sctp_auth_init_hmacs(struct sctp_endpoint *ep, gfp_t gfp) 4491f485649SVlad Yasevich { 4505821c769SHerbert Xu struct crypto_shash *tfm = NULL; 4511f485649SVlad Yasevich __u16 id; 4521f485649SVlad Yasevich 453b14878ccSVlad Yasevich /* If AUTH extension is disabled, we are done */ 454b14878ccSVlad Yasevich if (!ep->auth_enable) { 4551f485649SVlad Yasevich ep->auth_hmacs = NULL; 4561f485649SVlad Yasevich return 0; 4571f485649SVlad Yasevich } 4581f485649SVlad Yasevich 459b14878ccSVlad Yasevich /* If the transforms are already allocated, we are done */ 4601f485649SVlad Yasevich if (ep->auth_hmacs) 4611f485649SVlad Yasevich return 0; 4621f485649SVlad Yasevich 4631f485649SVlad Yasevich /* Allocated the array of pointers to transorms */ 4645821c769SHerbert Xu ep->auth_hmacs = kzalloc(sizeof(struct crypto_shash *) * 4655821c769SHerbert Xu SCTP_AUTH_NUM_HMACS, gfp); 4661f485649SVlad Yasevich if (!ep->auth_hmacs) 4671f485649SVlad Yasevich return -ENOMEM; 4681f485649SVlad Yasevich 4691f485649SVlad Yasevich for (id = 0; id < SCTP_AUTH_NUM_HMACS; id++) { 4701f485649SVlad Yasevich 4711f485649SVlad Yasevich /* See is we support the id. Supported IDs have name and 4721f485649SVlad Yasevich * length fields set, so that we can allocated and use 4731f485649SVlad Yasevich * them. We can safely just check for name, for without the 4741f485649SVlad Yasevich * name, we can't allocate the TFM. 4751f485649SVlad Yasevich */ 4761f485649SVlad Yasevich if (!sctp_hmac_list[id].hmac_name) 4771f485649SVlad Yasevich continue; 4781f485649SVlad Yasevich 4791f485649SVlad Yasevich /* If this TFM has been allocated, we are all set */ 4801f485649SVlad Yasevich if (ep->auth_hmacs[id]) 4811f485649SVlad Yasevich continue; 4821f485649SVlad Yasevich 4831f485649SVlad Yasevich /* Allocate the ID */ 4845821c769SHerbert Xu tfm = crypto_alloc_shash(sctp_hmac_list[id].hmac_name, 0, 0); 4851f485649SVlad Yasevich if (IS_ERR(tfm)) 4861f485649SVlad Yasevich goto out_err; 4871f485649SVlad Yasevich 4881f485649SVlad Yasevich ep->auth_hmacs[id] = tfm; 4891f485649SVlad Yasevich } 4901f485649SVlad Yasevich 4911f485649SVlad Yasevich return 0; 4921f485649SVlad Yasevich 4931f485649SVlad Yasevich out_err: 49473ac36eaSColy Li /* Clean up any successful allocations */ 4951f485649SVlad Yasevich sctp_auth_destroy_hmacs(ep->auth_hmacs); 4961f485649SVlad Yasevich return -ENOMEM; 4971f485649SVlad Yasevich } 4981f485649SVlad Yasevich 4991f485649SVlad Yasevich /* Destroy the hmac tfm array */ 5005821c769SHerbert Xu void sctp_auth_destroy_hmacs(struct crypto_shash *auth_hmacs[]) 5011f485649SVlad Yasevich { 5021f485649SVlad Yasevich int i; 5031f485649SVlad Yasevich 5041f485649SVlad Yasevich if (!auth_hmacs) 5051f485649SVlad Yasevich return; 5061f485649SVlad Yasevich 5078d72651dSwangweidong for (i = 0; i < SCTP_AUTH_NUM_HMACS; i++) { 5085821c769SHerbert Xu crypto_free_shash(auth_hmacs[i]); 5091f485649SVlad Yasevich } 5101f485649SVlad Yasevich kfree(auth_hmacs); 5111f485649SVlad Yasevich } 5121f485649SVlad Yasevich 5131f485649SVlad Yasevich 5141f485649SVlad Yasevich struct sctp_hmac *sctp_auth_get_hmac(__u16 hmac_id) 5151f485649SVlad Yasevich { 5161f485649SVlad Yasevich return &sctp_hmac_list[hmac_id]; 5171f485649SVlad Yasevich } 5181f485649SVlad Yasevich 5191f485649SVlad Yasevich /* Get an hmac description information that we can use to build 5201f485649SVlad Yasevich * the AUTH chunk 5211f485649SVlad Yasevich */ 5221f485649SVlad Yasevich struct sctp_hmac *sctp_auth_asoc_get_hmac(const struct sctp_association *asoc) 5231f485649SVlad Yasevich { 5241f485649SVlad Yasevich struct sctp_hmac_algo_param *hmacs; 5251f485649SVlad Yasevich __u16 n_elt; 5261f485649SVlad Yasevich __u16 id = 0; 5271f485649SVlad Yasevich int i; 5281f485649SVlad Yasevich 5291f485649SVlad Yasevich /* If we have a default entry, use it */ 5301f485649SVlad Yasevich if (asoc->default_hmac_id) 5311f485649SVlad Yasevich return &sctp_hmac_list[asoc->default_hmac_id]; 5321f485649SVlad Yasevich 5331f485649SVlad Yasevich /* Since we do not have a default entry, find the first entry 5341f485649SVlad Yasevich * we support and return that. Do not cache that id. 5351f485649SVlad Yasevich */ 5361f485649SVlad Yasevich hmacs = asoc->peer.peer_hmacs; 5371f485649SVlad Yasevich if (!hmacs) 5381f485649SVlad Yasevich return NULL; 5391f485649SVlad Yasevich 5403c918704SXin Long n_elt = (ntohs(hmacs->param_hdr.length) - 5413c918704SXin Long sizeof(struct sctp_paramhdr)) >> 1; 5421f485649SVlad Yasevich for (i = 0; i < n_elt; i++) { 5431f485649SVlad Yasevich id = ntohs(hmacs->hmac_ids[i]); 5441f485649SVlad Yasevich 545747edc0fSwangweidong /* Check the id is in the supported range. And 546747edc0fSwangweidong * see if we support the id. Supported IDs have name and 547747edc0fSwangweidong * length fields set, so that we can allocate and use 5481f485649SVlad Yasevich * them. We can safely just check for name, for without the 5491f485649SVlad Yasevich * name, we can't allocate the TFM. 5501f485649SVlad Yasevich */ 551747edc0fSwangweidong if (id > SCTP_AUTH_HMAC_ID_MAX || 552747edc0fSwangweidong !sctp_hmac_list[id].hmac_name) { 55351e97a12SDan Rosenberg id = 0; 5541f485649SVlad Yasevich continue; 55551e97a12SDan Rosenberg } 5561f485649SVlad Yasevich 5571f485649SVlad Yasevich break; 5581f485649SVlad Yasevich } 5591f485649SVlad Yasevich 5601f485649SVlad Yasevich if (id == 0) 5611f485649SVlad Yasevich return NULL; 5621f485649SVlad Yasevich 5631f485649SVlad Yasevich return &sctp_hmac_list[id]; 5641f485649SVlad Yasevich } 5651f485649SVlad Yasevich 566d06f6082SAl Viro static int __sctp_auth_find_hmacid(__be16 *hmacs, int n_elts, __be16 hmac_id) 5671f485649SVlad Yasevich { 5681f485649SVlad Yasevich int found = 0; 5691f485649SVlad Yasevich int i; 5701f485649SVlad Yasevich 5711f485649SVlad Yasevich for (i = 0; i < n_elts; i++) { 5721f485649SVlad Yasevich if (hmac_id == hmacs[i]) { 5731f485649SVlad Yasevich found = 1; 5741f485649SVlad Yasevich break; 5751f485649SVlad Yasevich } 5761f485649SVlad Yasevich } 5771f485649SVlad Yasevich 5781f485649SVlad Yasevich return found; 5791f485649SVlad Yasevich } 5801f485649SVlad Yasevich 5811f485649SVlad Yasevich /* See if the HMAC_ID is one that we claim as supported */ 5821f485649SVlad Yasevich int sctp_auth_asoc_verify_hmac_id(const struct sctp_association *asoc, 583d06f6082SAl Viro __be16 hmac_id) 5841f485649SVlad Yasevich { 5851f485649SVlad Yasevich struct sctp_hmac_algo_param *hmacs; 5861f485649SVlad Yasevich __u16 n_elt; 5871f485649SVlad Yasevich 5881f485649SVlad Yasevich if (!asoc) 5891f485649SVlad Yasevich return 0; 5901f485649SVlad Yasevich 5911f485649SVlad Yasevich hmacs = (struct sctp_hmac_algo_param *)asoc->c.auth_hmacs; 5923c918704SXin Long n_elt = (ntohs(hmacs->param_hdr.length) - 5933c918704SXin Long sizeof(struct sctp_paramhdr)) >> 1; 5941f485649SVlad Yasevich 5951f485649SVlad Yasevich return __sctp_auth_find_hmacid(hmacs->hmac_ids, n_elt, hmac_id); 5961f485649SVlad Yasevich } 5971f485649SVlad Yasevich 5981f485649SVlad Yasevich 5991f485649SVlad Yasevich /* Cache the default HMAC id. This to follow this text from SCTP-AUTH: 6001f485649SVlad Yasevich * Section 6.1: 6011f485649SVlad Yasevich * The receiver of a HMAC-ALGO parameter SHOULD use the first listed 6021f485649SVlad Yasevich * algorithm it supports. 6031f485649SVlad Yasevich */ 6041f485649SVlad Yasevich void sctp_auth_asoc_set_default_hmac(struct sctp_association *asoc, 6051f485649SVlad Yasevich struct sctp_hmac_algo_param *hmacs) 6061f485649SVlad Yasevich { 6071f485649SVlad Yasevich struct sctp_endpoint *ep; 6081f485649SVlad Yasevich __u16 id; 6091f485649SVlad Yasevich int i; 6101f485649SVlad Yasevich int n_params; 6111f485649SVlad Yasevich 6121f485649SVlad Yasevich /* if the default id is already set, use it */ 6131f485649SVlad Yasevich if (asoc->default_hmac_id) 6141f485649SVlad Yasevich return; 6151f485649SVlad Yasevich 6163c918704SXin Long n_params = (ntohs(hmacs->param_hdr.length) - 6173c918704SXin Long sizeof(struct sctp_paramhdr)) >> 1; 6181f485649SVlad Yasevich ep = asoc->ep; 6191f485649SVlad Yasevich for (i = 0; i < n_params; i++) { 6201f485649SVlad Yasevich id = ntohs(hmacs->hmac_ids[i]); 6211f485649SVlad Yasevich 6221f485649SVlad Yasevich /* Check the id is in the supported range */ 6231f485649SVlad Yasevich if (id > SCTP_AUTH_HMAC_ID_MAX) 6241f485649SVlad Yasevich continue; 6251f485649SVlad Yasevich 6261f485649SVlad Yasevich /* If this TFM has been allocated, use this id */ 6271f485649SVlad Yasevich if (ep->auth_hmacs[id]) { 6281f485649SVlad Yasevich asoc->default_hmac_id = id; 6291f485649SVlad Yasevich break; 6301f485649SVlad Yasevich } 6311f485649SVlad Yasevich } 6321f485649SVlad Yasevich } 6331f485649SVlad Yasevich 6341f485649SVlad Yasevich 6351f485649SVlad Yasevich /* Check to see if the given chunk is supposed to be authenticated */ 6366d85e68fSXin Long static int __sctp_auth_cid(enum sctp_cid chunk, struct sctp_chunks_param *param) 6371f485649SVlad Yasevich { 6381f485649SVlad Yasevich unsigned short len; 6391f485649SVlad Yasevich int found = 0; 6401f485649SVlad Yasevich int i; 6411f485649SVlad Yasevich 642555d3d5dSVlad Yasevich if (!param || param->param_hdr.length == 0) 6431f485649SVlad Yasevich return 0; 6441f485649SVlad Yasevich 6453c918704SXin Long len = ntohs(param->param_hdr.length) - sizeof(struct sctp_paramhdr); 6461f485649SVlad Yasevich 6471f485649SVlad Yasevich /* SCTP-AUTH, Section 3.2 6481f485649SVlad Yasevich * The chunk types for INIT, INIT-ACK, SHUTDOWN-COMPLETE and AUTH 6491f485649SVlad Yasevich * chunks MUST NOT be listed in the CHUNKS parameter. However, if 6501f485649SVlad Yasevich * a CHUNKS parameter is received then the types for INIT, INIT-ACK, 6511f485649SVlad Yasevich * SHUTDOWN-COMPLETE and AUTH chunks MUST be ignored. 6521f485649SVlad Yasevich */ 6531f485649SVlad Yasevich for (i = 0; !found && i < len; i++) { 6541f485649SVlad Yasevich switch (param->chunks[i]) { 6551f485649SVlad Yasevich case SCTP_CID_INIT: 6561f485649SVlad Yasevich case SCTP_CID_INIT_ACK: 6571f485649SVlad Yasevich case SCTP_CID_SHUTDOWN_COMPLETE: 6581f485649SVlad Yasevich case SCTP_CID_AUTH: 6591f485649SVlad Yasevich break; 6601f485649SVlad Yasevich 6611f485649SVlad Yasevich default: 6621f485649SVlad Yasevich if (param->chunks[i] == chunk) 6631f485649SVlad Yasevich found = 1; 6641f485649SVlad Yasevich break; 6651f485649SVlad Yasevich } 6661f485649SVlad Yasevich } 6671f485649SVlad Yasevich 6681f485649SVlad Yasevich return found; 6691f485649SVlad Yasevich } 6701f485649SVlad Yasevich 6711f485649SVlad Yasevich /* Check if peer requested that this chunk is authenticated */ 6726d85e68fSXin Long int sctp_auth_send_cid(enum sctp_cid chunk, const struct sctp_association *asoc) 6731f485649SVlad Yasevich { 674e1fc3b14SEric W. Biederman if (!asoc) 675e1fc3b14SEric W. Biederman return 0; 676e1fc3b14SEric W. Biederman 677b14878ccSVlad Yasevich if (!asoc->ep->auth_enable || !asoc->peer.auth_capable) 6781f485649SVlad Yasevich return 0; 6791f485649SVlad Yasevich 6801f485649SVlad Yasevich return __sctp_auth_cid(chunk, asoc->peer.peer_chunks); 6811f485649SVlad Yasevich } 6821f485649SVlad Yasevich 6831f485649SVlad Yasevich /* Check if we requested that peer authenticate this chunk. */ 6846d85e68fSXin Long int sctp_auth_recv_cid(enum sctp_cid chunk, const struct sctp_association *asoc) 6851f485649SVlad Yasevich { 686e1fc3b14SEric W. Biederman if (!asoc) 687e1fc3b14SEric W. Biederman return 0; 688e1fc3b14SEric W. Biederman 689b14878ccSVlad Yasevich if (!asoc->ep->auth_enable) 6901f485649SVlad Yasevich return 0; 6911f485649SVlad Yasevich 6921f485649SVlad Yasevich return __sctp_auth_cid(chunk, 6931f485649SVlad Yasevich (struct sctp_chunks_param *)asoc->c.auth_chunks); 6941f485649SVlad Yasevich } 6951f485649SVlad Yasevich 6961f485649SVlad Yasevich /* SCTP-AUTH: Section 6.2: 6971f485649SVlad Yasevich * The sender MUST calculate the MAC as described in RFC2104 [2] using 6981f485649SVlad Yasevich * the hash function H as described by the MAC Identifier and the shared 6991f485649SVlad Yasevich * association key K based on the endpoint pair shared key described by 7001f485649SVlad Yasevich * the shared key identifier. The 'data' used for the computation of 7011f485649SVlad Yasevich * the AUTH-chunk is given by the AUTH chunk with its HMAC field set to 7021f485649SVlad Yasevich * zero (as shown in Figure 6) followed by all chunks that are placed 7031f485649SVlad Yasevich * after the AUTH chunk in the SCTP packet. 7041f485649SVlad Yasevich */ 7051f485649SVlad Yasevich void sctp_auth_calculate_hmac(const struct sctp_association *asoc, 7061f485649SVlad Yasevich struct sk_buff *skb, 7071f485649SVlad Yasevich struct sctp_auth_chunk *auth, 7081f485649SVlad Yasevich gfp_t gfp) 7091f485649SVlad Yasevich { 7105821c769SHerbert Xu struct crypto_shash *tfm; 7111f485649SVlad Yasevich struct sctp_auth_bytes *asoc_key; 7121f485649SVlad Yasevich __u16 key_id, hmac_id; 7131f485649SVlad Yasevich __u8 *digest; 7141f485649SVlad Yasevich unsigned char *end; 7151f485649SVlad Yasevich int free_key = 0; 7161f485649SVlad Yasevich 7171f485649SVlad Yasevich /* Extract the info we need: 7181f485649SVlad Yasevich * - hmac id 7191f485649SVlad Yasevich * - key id 7201f485649SVlad Yasevich */ 7211f485649SVlad Yasevich key_id = ntohs(auth->auth_hdr.shkey_id); 7221f485649SVlad Yasevich hmac_id = ntohs(auth->auth_hdr.hmac_id); 7231f485649SVlad Yasevich 7241f485649SVlad Yasevich if (key_id == asoc->active_key_id) 7251f485649SVlad Yasevich asoc_key = asoc->asoc_shared_key; 7261f485649SVlad Yasevich else { 7271f485649SVlad Yasevich struct sctp_shared_key *ep_key; 7281f485649SVlad Yasevich 7291f485649SVlad Yasevich ep_key = sctp_auth_get_shkey(asoc, key_id); 7301f485649SVlad Yasevich if (!ep_key) 7311f485649SVlad Yasevich return; 7321f485649SVlad Yasevich 7331f485649SVlad Yasevich asoc_key = sctp_auth_asoc_create_secret(asoc, ep_key, gfp); 7341f485649SVlad Yasevich if (!asoc_key) 7351f485649SVlad Yasevich return; 7361f485649SVlad Yasevich 7371f485649SVlad Yasevich free_key = 1; 7381f485649SVlad Yasevich } 7391f485649SVlad Yasevich 7401f485649SVlad Yasevich /* set up scatter list */ 7411f485649SVlad Yasevich end = skb_tail_pointer(skb); 7421f485649SVlad Yasevich 7435821c769SHerbert Xu tfm = asoc->ep->auth_hmacs[hmac_id]; 7441f485649SVlad Yasevich 7451f485649SVlad Yasevich digest = auth->auth_hdr.hmac; 7465821c769SHerbert Xu if (crypto_shash_setkey(tfm, &asoc_key->data[0], asoc_key->len)) 7471f485649SVlad Yasevich goto free; 7481f485649SVlad Yasevich 7495821c769SHerbert Xu { 7505821c769SHerbert Xu SHASH_DESC_ON_STACK(desc, tfm); 7515821c769SHerbert Xu 7525821c769SHerbert Xu desc->tfm = tfm; 7535821c769SHerbert Xu desc->flags = 0; 7545821c769SHerbert Xu crypto_shash_digest(desc, (u8 *)auth, 7555821c769SHerbert Xu end - (unsigned char *)auth, digest); 7565821c769SHerbert Xu shash_desc_zero(desc); 7575821c769SHerbert Xu } 7581f485649SVlad Yasevich 7591f485649SVlad Yasevich free: 7601f485649SVlad Yasevich if (free_key) 7611f485649SVlad Yasevich sctp_auth_key_put(asoc_key); 7621f485649SVlad Yasevich } 76365b07e5dSVlad Yasevich 76465b07e5dSVlad Yasevich /* API Helpers */ 76565b07e5dSVlad Yasevich 76665b07e5dSVlad Yasevich /* Add a chunk to the endpoint authenticated chunk list */ 76765b07e5dSVlad Yasevich int sctp_auth_ep_add_chunkid(struct sctp_endpoint *ep, __u8 chunk_id) 76865b07e5dSVlad Yasevich { 76965b07e5dSVlad Yasevich struct sctp_chunks_param *p = ep->auth_chunk_list; 77065b07e5dSVlad Yasevich __u16 nchunks; 77165b07e5dSVlad Yasevich __u16 param_len; 77265b07e5dSVlad Yasevich 77365b07e5dSVlad Yasevich /* If this chunk is already specified, we are done */ 77465b07e5dSVlad Yasevich if (__sctp_auth_cid(chunk_id, p)) 77565b07e5dSVlad Yasevich return 0; 77665b07e5dSVlad Yasevich 77765b07e5dSVlad Yasevich /* Check if we can add this chunk to the array */ 77865b07e5dSVlad Yasevich param_len = ntohs(p->param_hdr.length); 7793c918704SXin Long nchunks = param_len - sizeof(struct sctp_paramhdr); 78065b07e5dSVlad Yasevich if (nchunks == SCTP_NUM_CHUNK_TYPES) 78165b07e5dSVlad Yasevich return -EINVAL; 78265b07e5dSVlad Yasevich 78365b07e5dSVlad Yasevich p->chunks[nchunks] = chunk_id; 78465b07e5dSVlad Yasevich p->param_hdr.length = htons(param_len + 1); 78565b07e5dSVlad Yasevich return 0; 78665b07e5dSVlad Yasevich } 78765b07e5dSVlad Yasevich 78865b07e5dSVlad Yasevich /* Add hmac identifires to the endpoint list of supported hmac ids */ 78965b07e5dSVlad Yasevich int sctp_auth_ep_set_hmacs(struct sctp_endpoint *ep, 79065b07e5dSVlad Yasevich struct sctp_hmacalgo *hmacs) 79165b07e5dSVlad Yasevich { 79265b07e5dSVlad Yasevich int has_sha1 = 0; 79365b07e5dSVlad Yasevich __u16 id; 79465b07e5dSVlad Yasevich int i; 79565b07e5dSVlad Yasevich 79665b07e5dSVlad Yasevich /* Scan the list looking for unsupported id. Also make sure that 79765b07e5dSVlad Yasevich * SHA1 is specified. 79865b07e5dSVlad Yasevich */ 79965b07e5dSVlad Yasevich for (i = 0; i < hmacs->shmac_num_idents; i++) { 80065b07e5dSVlad Yasevich id = hmacs->shmac_idents[i]; 80165b07e5dSVlad Yasevich 802d9724055SVlad Yasevich if (id > SCTP_AUTH_HMAC_ID_MAX) 803d9724055SVlad Yasevich return -EOPNOTSUPP; 804d9724055SVlad Yasevich 80565b07e5dSVlad Yasevich if (SCTP_AUTH_HMAC_ID_SHA1 == id) 80665b07e5dSVlad Yasevich has_sha1 = 1; 80765b07e5dSVlad Yasevich 80865b07e5dSVlad Yasevich if (!sctp_hmac_list[id].hmac_name) 80965b07e5dSVlad Yasevich return -EOPNOTSUPP; 81065b07e5dSVlad Yasevich } 81165b07e5dSVlad Yasevich 81265b07e5dSVlad Yasevich if (!has_sha1) 81365b07e5dSVlad Yasevich return -EINVAL; 81465b07e5dSVlad Yasevich 815ed5a377dSlucien for (i = 0; i < hmacs->shmac_num_idents; i++) 8163c918704SXin Long ep->auth_hmacs_list->hmac_ids[i] = 8173c918704SXin Long htons(hmacs->shmac_idents[i]); 8183c918704SXin Long ep->auth_hmacs_list->param_hdr.length = 8193c918704SXin Long htons(sizeof(struct sctp_paramhdr) + 82065b07e5dSVlad Yasevich hmacs->shmac_num_idents * sizeof(__u16)); 82165b07e5dSVlad Yasevich return 0; 82265b07e5dSVlad Yasevich } 82365b07e5dSVlad Yasevich 82465b07e5dSVlad Yasevich /* Set a new shared key on either endpoint or association. If the 82565b07e5dSVlad Yasevich * the key with a same ID already exists, replace the key (remove the 82665b07e5dSVlad Yasevich * old key and add a new one). 82765b07e5dSVlad Yasevich */ 82865b07e5dSVlad Yasevich int sctp_auth_set_key(struct sctp_endpoint *ep, 82965b07e5dSVlad Yasevich struct sctp_association *asoc, 83065b07e5dSVlad Yasevich struct sctp_authkey *auth_key) 83165b07e5dSVlad Yasevich { 83265b07e5dSVlad Yasevich struct sctp_shared_key *cur_key = NULL; 83365b07e5dSVlad Yasevich struct sctp_auth_bytes *key; 83465b07e5dSVlad Yasevich struct list_head *sh_keys; 83565b07e5dSVlad Yasevich int replace = 0; 83665b07e5dSVlad Yasevich 83765b07e5dSVlad Yasevich /* Try to find the given key id to see if 83865b07e5dSVlad Yasevich * we are doing a replace, or adding a new key 83965b07e5dSVlad Yasevich */ 84065b07e5dSVlad Yasevich if (asoc) 84165b07e5dSVlad Yasevich sh_keys = &asoc->endpoint_shared_keys; 84265b07e5dSVlad Yasevich else 84365b07e5dSVlad Yasevich sh_keys = &ep->endpoint_shared_keys; 84465b07e5dSVlad Yasevich 84565b07e5dSVlad Yasevich key_for_each(cur_key, sh_keys) { 84665b07e5dSVlad Yasevich if (cur_key->key_id == auth_key->sca_keynumber) { 84765b07e5dSVlad Yasevich replace = 1; 84865b07e5dSVlad Yasevich break; 84965b07e5dSVlad Yasevich } 85065b07e5dSVlad Yasevich } 85165b07e5dSVlad Yasevich 85265b07e5dSVlad Yasevich /* If we are not replacing a key id, we need to allocate 85365b07e5dSVlad Yasevich * a shared key. 85465b07e5dSVlad Yasevich */ 85565b07e5dSVlad Yasevich if (!replace) { 85665b07e5dSVlad Yasevich cur_key = sctp_auth_shkey_create(auth_key->sca_keynumber, 85765b07e5dSVlad Yasevich GFP_KERNEL); 85865b07e5dSVlad Yasevich if (!cur_key) 85965b07e5dSVlad Yasevich return -ENOMEM; 86065b07e5dSVlad Yasevich } 86165b07e5dSVlad Yasevich 86265b07e5dSVlad Yasevich /* Create a new key data based on the info passed in */ 8637e8616d8SVlad Yasevich key = sctp_auth_create_key(auth_key->sca_keylength, GFP_KERNEL); 86465b07e5dSVlad Yasevich if (!key) 86565b07e5dSVlad Yasevich goto nomem; 86665b07e5dSVlad Yasevich 8677e8616d8SVlad Yasevich memcpy(key->data, &auth_key->sca_key[0], auth_key->sca_keylength); 86865b07e5dSVlad Yasevich 86965b07e5dSVlad Yasevich /* If we are replacing, remove the old keys data from the 87065b07e5dSVlad Yasevich * key id. If we are adding new key id, add it to the 87165b07e5dSVlad Yasevich * list. 87265b07e5dSVlad Yasevich */ 87365b07e5dSVlad Yasevich if (replace) 87465b07e5dSVlad Yasevich sctp_auth_key_put(cur_key->key); 87565b07e5dSVlad Yasevich else 87665b07e5dSVlad Yasevich list_add(&cur_key->key_list, sh_keys); 87765b07e5dSVlad Yasevich 87865b07e5dSVlad Yasevich cur_key->key = key; 87965b07e5dSVlad Yasevich return 0; 88065b07e5dSVlad Yasevich nomem: 88165b07e5dSVlad Yasevich if (!replace) 88265b07e5dSVlad Yasevich sctp_auth_shkey_free(cur_key); 88365b07e5dSVlad Yasevich 88465b07e5dSVlad Yasevich return -ENOMEM; 88565b07e5dSVlad Yasevich } 88665b07e5dSVlad Yasevich 88765b07e5dSVlad Yasevich int sctp_auth_set_active_key(struct sctp_endpoint *ep, 88865b07e5dSVlad Yasevich struct sctp_association *asoc, 88965b07e5dSVlad Yasevich __u16 key_id) 89065b07e5dSVlad Yasevich { 89165b07e5dSVlad Yasevich struct sctp_shared_key *key; 89265b07e5dSVlad Yasevich struct list_head *sh_keys; 89365b07e5dSVlad Yasevich int found = 0; 89465b07e5dSVlad Yasevich 89565b07e5dSVlad Yasevich /* The key identifier MUST correst to an existing key */ 89665b07e5dSVlad Yasevich if (asoc) 89765b07e5dSVlad Yasevich sh_keys = &asoc->endpoint_shared_keys; 89865b07e5dSVlad Yasevich else 89965b07e5dSVlad Yasevich sh_keys = &ep->endpoint_shared_keys; 90065b07e5dSVlad Yasevich 90165b07e5dSVlad Yasevich key_for_each(key, sh_keys) { 90265b07e5dSVlad Yasevich if (key->key_id == key_id) { 90365b07e5dSVlad Yasevich found = 1; 90465b07e5dSVlad Yasevich break; 90565b07e5dSVlad Yasevich } 90665b07e5dSVlad Yasevich } 90765b07e5dSVlad Yasevich 90865b07e5dSVlad Yasevich if (!found) 90965b07e5dSVlad Yasevich return -EINVAL; 91065b07e5dSVlad Yasevich 91165b07e5dSVlad Yasevich if (asoc) { 91265b07e5dSVlad Yasevich asoc->active_key_id = key_id; 91365b07e5dSVlad Yasevich sctp_auth_asoc_init_active_key(asoc, GFP_KERNEL); 91465b07e5dSVlad Yasevich } else 91565b07e5dSVlad Yasevich ep->active_key_id = key_id; 91665b07e5dSVlad Yasevich 91765b07e5dSVlad Yasevich return 0; 91865b07e5dSVlad Yasevich } 91965b07e5dSVlad Yasevich 92065b07e5dSVlad Yasevich int sctp_auth_del_key_id(struct sctp_endpoint *ep, 92165b07e5dSVlad Yasevich struct sctp_association *asoc, 92265b07e5dSVlad Yasevich __u16 key_id) 92365b07e5dSVlad Yasevich { 92465b07e5dSVlad Yasevich struct sctp_shared_key *key; 92565b07e5dSVlad Yasevich struct list_head *sh_keys; 92665b07e5dSVlad Yasevich int found = 0; 92765b07e5dSVlad Yasevich 92865b07e5dSVlad Yasevich /* The key identifier MUST NOT be the current active key 92965b07e5dSVlad Yasevich * The key identifier MUST correst to an existing key 93065b07e5dSVlad Yasevich */ 93165b07e5dSVlad Yasevich if (asoc) { 93265b07e5dSVlad Yasevich if (asoc->active_key_id == key_id) 93365b07e5dSVlad Yasevich return -EINVAL; 93465b07e5dSVlad Yasevich 93565b07e5dSVlad Yasevich sh_keys = &asoc->endpoint_shared_keys; 93665b07e5dSVlad Yasevich } else { 93765b07e5dSVlad Yasevich if (ep->active_key_id == key_id) 93865b07e5dSVlad Yasevich return -EINVAL; 93965b07e5dSVlad Yasevich 94065b07e5dSVlad Yasevich sh_keys = &ep->endpoint_shared_keys; 94165b07e5dSVlad Yasevich } 94265b07e5dSVlad Yasevich 94365b07e5dSVlad Yasevich key_for_each(key, sh_keys) { 94465b07e5dSVlad Yasevich if (key->key_id == key_id) { 94565b07e5dSVlad Yasevich found = 1; 94665b07e5dSVlad Yasevich break; 94765b07e5dSVlad Yasevich } 94865b07e5dSVlad Yasevich } 94965b07e5dSVlad Yasevich 95065b07e5dSVlad Yasevich if (!found) 95165b07e5dSVlad Yasevich return -EINVAL; 95265b07e5dSVlad Yasevich 95365b07e5dSVlad Yasevich /* Delete the shared key */ 95465b07e5dSVlad Yasevich list_del_init(&key->key_list); 95565b07e5dSVlad Yasevich sctp_auth_shkey_free(key); 95665b07e5dSVlad Yasevich 95765b07e5dSVlad Yasevich return 0; 95865b07e5dSVlad Yasevich } 959