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 191f485649SVlad Yasevich * along with GNU CC; see the file COPYING. If not, write to 201f485649SVlad Yasevich * the Free Software Foundation, 59 Temple Place - Suite 330, 211f485649SVlad Yasevich * Boston, MA 02111-1307, USA. 221f485649SVlad Yasevich * 231f485649SVlad Yasevich * Please send any bug reports or fixes you make to the 241f485649SVlad Yasevich * email address(es): 251f485649SVlad Yasevich * lksctp developers <lksctp-developers@lists.sourceforge.net> 261f485649SVlad Yasevich * 271f485649SVlad Yasevich * Or submit a bug report through the following website: 281f485649SVlad Yasevich * http://www.sf.net/projects/lksctp 291f485649SVlad Yasevich * 301f485649SVlad Yasevich * Written or modified by: 311f485649SVlad Yasevich * Vlad Yasevich <vladislav.yasevich@hp.com> 321f485649SVlad Yasevich * 331f485649SVlad Yasevich * Any bugs reported given to us we will try to fix... any fixes shared will 341f485649SVlad Yasevich * be incorporated into the next SCTP release. 351f485649SVlad Yasevich */ 361f485649SVlad Yasevich 375a0e3ad6STejun Heo #include <linux/slab.h> 381f485649SVlad Yasevich #include <linux/types.h> 391f485649SVlad Yasevich #include <linux/crypto.h> 401f485649SVlad Yasevich #include <linux/scatterlist.h> 411f485649SVlad Yasevich #include <net/sctp/sctp.h> 421f485649SVlad Yasevich #include <net/sctp/auth.h> 431f485649SVlad Yasevich 441f485649SVlad Yasevich static struct sctp_hmac sctp_hmac_list[SCTP_AUTH_NUM_HMACS] = { 451f485649SVlad Yasevich { 461f485649SVlad Yasevich /* id 0 is reserved. as all 0 */ 471f485649SVlad Yasevich .hmac_id = SCTP_AUTH_HMAC_ID_RESERVED_0, 481f485649SVlad Yasevich }, 491f485649SVlad Yasevich { 501f485649SVlad Yasevich .hmac_id = SCTP_AUTH_HMAC_ID_SHA1, 511f485649SVlad Yasevich .hmac_name="hmac(sha1)", 521f485649SVlad Yasevich .hmac_len = SCTP_SHA1_SIG_SIZE, 531f485649SVlad Yasevich }, 541f485649SVlad Yasevich { 551f485649SVlad Yasevich /* id 2 is reserved as well */ 561f485649SVlad Yasevich .hmac_id = SCTP_AUTH_HMAC_ID_RESERVED_2, 571f485649SVlad Yasevich }, 58b7e0fe9fSVlad Yasevich #if defined (CONFIG_CRYPTO_SHA256) || defined (CONFIG_CRYPTO_SHA256_MODULE) 591f485649SVlad Yasevich { 601f485649SVlad Yasevich .hmac_id = SCTP_AUTH_HMAC_ID_SHA256, 611f485649SVlad Yasevich .hmac_name="hmac(sha256)", 621f485649SVlad Yasevich .hmac_len = SCTP_SHA256_SIG_SIZE, 631f485649SVlad Yasevich } 64b7e0fe9fSVlad Yasevich #endif 651f485649SVlad Yasevich }; 661f485649SVlad Yasevich 671f485649SVlad Yasevich 681f485649SVlad Yasevich void sctp_auth_key_put(struct sctp_auth_bytes *key) 691f485649SVlad Yasevich { 701f485649SVlad Yasevich if (!key) 711f485649SVlad Yasevich return; 721f485649SVlad Yasevich 731f485649SVlad Yasevich if (atomic_dec_and_test(&key->refcnt)) { 741f485649SVlad Yasevich kfree(key); 751f485649SVlad Yasevich SCTP_DBG_OBJCNT_DEC(keys); 761f485649SVlad Yasevich } 771f485649SVlad Yasevich } 781f485649SVlad Yasevich 791f485649SVlad Yasevich /* Create a new key structure of a given length */ 801f485649SVlad Yasevich static struct sctp_auth_bytes *sctp_auth_create_key(__u32 key_len, gfp_t gfp) 811f485649SVlad Yasevich { 821f485649SVlad Yasevich struct sctp_auth_bytes *key; 831f485649SVlad Yasevich 8430c2235cSVlad Yasevich /* Verify that we are not going to overflow INT_MAX */ 85c89304b8SXi Wang if (key_len > (INT_MAX - sizeof(struct sctp_auth_bytes))) 8630c2235cSVlad Yasevich return NULL; 8730c2235cSVlad Yasevich 881f485649SVlad Yasevich /* Allocate the shared key */ 891f485649SVlad Yasevich key = kmalloc(sizeof(struct sctp_auth_bytes) + key_len, gfp); 901f485649SVlad Yasevich if (!key) 911f485649SVlad Yasevich return NULL; 921f485649SVlad Yasevich 931f485649SVlad Yasevich key->len = key_len; 941f485649SVlad Yasevich atomic_set(&key->refcnt, 1); 951f485649SVlad Yasevich SCTP_DBG_OBJCNT_INC(keys); 961f485649SVlad Yasevich 971f485649SVlad Yasevich return key; 981f485649SVlad Yasevich } 991f485649SVlad Yasevich 1001f485649SVlad Yasevich /* Create a new shared key container with a give key id */ 1011f485649SVlad Yasevich struct sctp_shared_key *sctp_auth_shkey_create(__u16 key_id, gfp_t gfp) 1021f485649SVlad Yasevich { 1031f485649SVlad Yasevich struct sctp_shared_key *new; 1041f485649SVlad Yasevich 1051f485649SVlad Yasevich /* Allocate the shared key container */ 1061f485649SVlad Yasevich new = kzalloc(sizeof(struct sctp_shared_key), gfp); 1071f485649SVlad Yasevich if (!new) 1081f485649SVlad Yasevich return NULL; 1091f485649SVlad Yasevich 1101f485649SVlad Yasevich INIT_LIST_HEAD(&new->key_list); 1111f485649SVlad Yasevich new->key_id = key_id; 1121f485649SVlad Yasevich 1131f485649SVlad Yasevich return new; 1141f485649SVlad Yasevich } 1151f485649SVlad Yasevich 11625985edcSLucas De Marchi /* Free the shared key structure */ 1178ad7c62bSAdrian Bunk static void sctp_auth_shkey_free(struct sctp_shared_key *sh_key) 1181f485649SVlad Yasevich { 1191f485649SVlad Yasevich BUG_ON(!list_empty(&sh_key->key_list)); 1201f485649SVlad Yasevich sctp_auth_key_put(sh_key->key); 1211f485649SVlad Yasevich sh_key->key = NULL; 1221f485649SVlad Yasevich kfree(sh_key); 1231f485649SVlad Yasevich } 1241f485649SVlad Yasevich 12525985edcSLucas De Marchi /* Destroy the entire key list. This is done during the 1261f485649SVlad Yasevich * associon and endpoint free process. 1271f485649SVlad Yasevich */ 1281f485649SVlad Yasevich void sctp_auth_destroy_keys(struct list_head *keys) 1291f485649SVlad Yasevich { 1301f485649SVlad Yasevich struct sctp_shared_key *ep_key; 1311f485649SVlad Yasevich struct sctp_shared_key *tmp; 1321f485649SVlad Yasevich 1331f485649SVlad Yasevich if (list_empty(keys)) 1341f485649SVlad Yasevich return; 1351f485649SVlad Yasevich 1361f485649SVlad Yasevich key_for_each_safe(ep_key, tmp, keys) { 1371f485649SVlad Yasevich list_del_init(&ep_key->key_list); 1381f485649SVlad Yasevich sctp_auth_shkey_free(ep_key); 1391f485649SVlad Yasevich } 1401f485649SVlad Yasevich } 1411f485649SVlad Yasevich 1421f485649SVlad Yasevich /* Compare two byte vectors as numbers. Return values 1431f485649SVlad Yasevich * are: 1441f485649SVlad Yasevich * 0 - vectors are equal 145025dfdafSFrederik Schwarzer * < 0 - vector 1 is smaller than vector2 146025dfdafSFrederik Schwarzer * > 0 - vector 1 is greater than vector2 1471f485649SVlad Yasevich * 1481f485649SVlad Yasevich * Algorithm is: 1491f485649SVlad Yasevich * This is performed by selecting the numerically smaller key vector... 1501f485649SVlad Yasevich * If the key vectors are equal as numbers but differ in length ... 1511f485649SVlad Yasevich * the shorter vector is considered smaller 1521f485649SVlad Yasevich * 1531f485649SVlad Yasevich * Examples (with small values): 1541f485649SVlad Yasevich * 000123456789 > 123456789 (first number is longer) 1551f485649SVlad Yasevich * 000123456789 < 234567891 (second number is larger numerically) 1561f485649SVlad Yasevich * 123456789 > 2345678 (first number is both larger & longer) 1571f485649SVlad Yasevich */ 1581f485649SVlad Yasevich static int sctp_auth_compare_vectors(struct sctp_auth_bytes *vector1, 1591f485649SVlad Yasevich struct sctp_auth_bytes *vector2) 1601f485649SVlad Yasevich { 1611f485649SVlad Yasevich int diff; 1621f485649SVlad Yasevich int i; 1631f485649SVlad Yasevich const __u8 *longer; 1641f485649SVlad Yasevich 1651f485649SVlad Yasevich diff = vector1->len - vector2->len; 1661f485649SVlad Yasevich if (diff) { 1671f485649SVlad Yasevich longer = (diff > 0) ? vector1->data : vector2->data; 1681f485649SVlad Yasevich 1691f485649SVlad Yasevich /* Check to see if the longer number is 1701f485649SVlad Yasevich * lead-zero padded. If it is not, it 1711f485649SVlad Yasevich * is automatically larger numerically. 1721f485649SVlad Yasevich */ 1731f485649SVlad Yasevich for (i = 0; i < abs(diff); i++ ) { 1741f485649SVlad Yasevich if (longer[i] != 0) 1751f485649SVlad Yasevich return diff; 1761f485649SVlad Yasevich } 1771f485649SVlad Yasevich } 1781f485649SVlad Yasevich 1791f485649SVlad Yasevich /* lengths are the same, compare numbers */ 1801f485649SVlad Yasevich return memcmp(vector1->data, vector2->data, vector1->len); 1811f485649SVlad Yasevich } 1821f485649SVlad Yasevich 1831f485649SVlad Yasevich /* 1841f485649SVlad Yasevich * Create a key vector as described in SCTP-AUTH, Section 6.1 1851f485649SVlad Yasevich * The RANDOM parameter, the CHUNKS parameter and the HMAC-ALGO 1861f485649SVlad Yasevich * parameter sent by each endpoint are concatenated as byte vectors. 1871f485649SVlad Yasevich * These parameters include the parameter type, parameter length, and 1881f485649SVlad Yasevich * the parameter value, but padding is omitted; all padding MUST be 1891f485649SVlad Yasevich * removed from this concatenation before proceeding with further 1901f485649SVlad Yasevich * computation of keys. Parameters which were not sent are simply 1911f485649SVlad Yasevich * omitted from the concatenation process. The resulting two vectors 1921f485649SVlad Yasevich * are called the two key vectors. 1931f485649SVlad Yasevich */ 1941f485649SVlad Yasevich static struct sctp_auth_bytes *sctp_auth_make_key_vector( 1951f485649SVlad Yasevich sctp_random_param_t *random, 1961f485649SVlad Yasevich sctp_chunks_param_t *chunks, 1971f485649SVlad Yasevich sctp_hmac_algo_param_t *hmacs, 1981f485649SVlad Yasevich gfp_t gfp) 1991f485649SVlad Yasevich { 2001f485649SVlad Yasevich struct sctp_auth_bytes *new; 2011f485649SVlad Yasevich __u32 len; 2021f485649SVlad Yasevich __u32 offset = 0; 2031f485649SVlad Yasevich 2041f485649SVlad Yasevich len = ntohs(random->param_hdr.length) + ntohs(hmacs->param_hdr.length); 2051f485649SVlad Yasevich if (chunks) 2061f485649SVlad Yasevich len += ntohs(chunks->param_hdr.length); 2071f485649SVlad Yasevich 2081f485649SVlad Yasevich new = kmalloc(sizeof(struct sctp_auth_bytes) + len, gfp); 2091f485649SVlad Yasevich if (!new) 2101f485649SVlad Yasevich return NULL; 2111f485649SVlad Yasevich 2121f485649SVlad Yasevich new->len = len; 2131f485649SVlad Yasevich 2141f485649SVlad Yasevich memcpy(new->data, random, ntohs(random->param_hdr.length)); 2151f485649SVlad Yasevich offset += ntohs(random->param_hdr.length); 2161f485649SVlad Yasevich 2171f485649SVlad Yasevich if (chunks) { 2181f485649SVlad Yasevich memcpy(new->data + offset, chunks, 2191f485649SVlad Yasevich ntohs(chunks->param_hdr.length)); 2201f485649SVlad Yasevich offset += ntohs(chunks->param_hdr.length); 2211f485649SVlad Yasevich } 2221f485649SVlad Yasevich 2231f485649SVlad Yasevich memcpy(new->data + offset, hmacs, ntohs(hmacs->param_hdr.length)); 2241f485649SVlad Yasevich 2251f485649SVlad Yasevich return new; 2261f485649SVlad Yasevich } 2271f485649SVlad Yasevich 2281f485649SVlad Yasevich 2291f485649SVlad Yasevich /* Make a key vector based on our local parameters */ 2308ad7c62bSAdrian Bunk static struct sctp_auth_bytes *sctp_auth_make_local_vector( 2311f485649SVlad Yasevich const struct sctp_association *asoc, 2321f485649SVlad Yasevich gfp_t gfp) 2331f485649SVlad Yasevich { 2341f485649SVlad Yasevich return sctp_auth_make_key_vector( 2351f485649SVlad Yasevich (sctp_random_param_t*)asoc->c.auth_random, 2361f485649SVlad Yasevich (sctp_chunks_param_t*)asoc->c.auth_chunks, 2371f485649SVlad Yasevich (sctp_hmac_algo_param_t*)asoc->c.auth_hmacs, 2381f485649SVlad Yasevich gfp); 2391f485649SVlad Yasevich } 2401f485649SVlad Yasevich 2411f485649SVlad Yasevich /* Make a key vector based on peer's parameters */ 2428ad7c62bSAdrian Bunk static struct sctp_auth_bytes *sctp_auth_make_peer_vector( 2431f485649SVlad Yasevich const struct sctp_association *asoc, 2441f485649SVlad Yasevich gfp_t gfp) 2451f485649SVlad Yasevich { 2461f485649SVlad Yasevich return sctp_auth_make_key_vector(asoc->peer.peer_random, 2471f485649SVlad Yasevich asoc->peer.peer_chunks, 2481f485649SVlad Yasevich asoc->peer.peer_hmacs, 2491f485649SVlad Yasevich gfp); 2501f485649SVlad Yasevich } 2511f485649SVlad Yasevich 2521f485649SVlad Yasevich 2531f485649SVlad Yasevich /* Set the value of the association shared key base on the parameters 2541f485649SVlad Yasevich * given. The algorithm is: 2551f485649SVlad Yasevich * From the endpoint pair shared keys and the key vectors the 2561f485649SVlad Yasevich * association shared keys are computed. This is performed by selecting 2571f485649SVlad Yasevich * the numerically smaller key vector and concatenating it to the 2581f485649SVlad Yasevich * endpoint pair shared key, and then concatenating the numerically 2591f485649SVlad Yasevich * larger key vector to that. The result of the concatenation is the 2601f485649SVlad Yasevich * association shared key. 2611f485649SVlad Yasevich */ 2621f485649SVlad Yasevich static struct sctp_auth_bytes *sctp_auth_asoc_set_secret( 2631f485649SVlad Yasevich struct sctp_shared_key *ep_key, 2641f485649SVlad Yasevich struct sctp_auth_bytes *first_vector, 2651f485649SVlad Yasevich struct sctp_auth_bytes *last_vector, 2661f485649SVlad Yasevich gfp_t gfp) 2671f485649SVlad Yasevich { 2681f485649SVlad Yasevich struct sctp_auth_bytes *secret; 2691f485649SVlad Yasevich __u32 offset = 0; 2701f485649SVlad Yasevich __u32 auth_len; 2711f485649SVlad Yasevich 2721f485649SVlad Yasevich auth_len = first_vector->len + last_vector->len; 2731f485649SVlad Yasevich if (ep_key->key) 2741f485649SVlad Yasevich auth_len += ep_key->key->len; 2751f485649SVlad Yasevich 2761f485649SVlad Yasevich secret = sctp_auth_create_key(auth_len, gfp); 2771f485649SVlad Yasevich if (!secret) 2781f485649SVlad Yasevich return NULL; 2791f485649SVlad Yasevich 2801f485649SVlad Yasevich if (ep_key->key) { 2811f485649SVlad Yasevich memcpy(secret->data, ep_key->key->data, ep_key->key->len); 2821f485649SVlad Yasevich offset += ep_key->key->len; 2831f485649SVlad Yasevich } 2841f485649SVlad Yasevich 2851f485649SVlad Yasevich memcpy(secret->data + offset, first_vector->data, first_vector->len); 2861f485649SVlad Yasevich offset += first_vector->len; 2871f485649SVlad Yasevich 2881f485649SVlad Yasevich memcpy(secret->data + offset, last_vector->data, last_vector->len); 2891f485649SVlad Yasevich 2901f485649SVlad Yasevich return secret; 2911f485649SVlad Yasevich } 2921f485649SVlad Yasevich 2931f485649SVlad Yasevich /* Create an association shared key. Follow the algorithm 2941f485649SVlad Yasevich * described in SCTP-AUTH, Section 6.1 2951f485649SVlad Yasevich */ 2961f485649SVlad Yasevich static struct sctp_auth_bytes *sctp_auth_asoc_create_secret( 2971f485649SVlad Yasevich const struct sctp_association *asoc, 2981f485649SVlad Yasevich struct sctp_shared_key *ep_key, 2991f485649SVlad Yasevich gfp_t gfp) 3001f485649SVlad Yasevich { 3011f485649SVlad Yasevich struct sctp_auth_bytes *local_key_vector; 3021f485649SVlad Yasevich struct sctp_auth_bytes *peer_key_vector; 3031f485649SVlad Yasevich struct sctp_auth_bytes *first_vector, 3041f485649SVlad Yasevich *last_vector; 3051f485649SVlad Yasevich struct sctp_auth_bytes *secret = NULL; 3061f485649SVlad Yasevich int cmp; 3071f485649SVlad Yasevich 3081f485649SVlad Yasevich 3091f485649SVlad Yasevich /* Now we need to build the key vectors 3101f485649SVlad Yasevich * SCTP-AUTH , Section 6.1 3111f485649SVlad Yasevich * The RANDOM parameter, the CHUNKS parameter and the HMAC-ALGO 3121f485649SVlad Yasevich * parameter sent by each endpoint are concatenated as byte vectors. 3131f485649SVlad Yasevich * These parameters include the parameter type, parameter length, and 3141f485649SVlad Yasevich * the parameter value, but padding is omitted; all padding MUST be 3151f485649SVlad Yasevich * removed from this concatenation before proceeding with further 3161f485649SVlad Yasevich * computation of keys. Parameters which were not sent are simply 3171f485649SVlad Yasevich * omitted from the concatenation process. The resulting two vectors 3181f485649SVlad Yasevich * are called the two key vectors. 3191f485649SVlad Yasevich */ 3201f485649SVlad Yasevich 3211f485649SVlad Yasevich local_key_vector = sctp_auth_make_local_vector(asoc, gfp); 3221f485649SVlad Yasevich peer_key_vector = sctp_auth_make_peer_vector(asoc, gfp); 3231f485649SVlad Yasevich 3241f485649SVlad Yasevich if (!peer_key_vector || !local_key_vector) 3251f485649SVlad Yasevich goto out; 3261f485649SVlad Yasevich 32725985edcSLucas De Marchi /* Figure out the order in which the key_vectors will be 3281f485649SVlad Yasevich * added to the endpoint shared key. 3291f485649SVlad Yasevich * SCTP-AUTH, Section 6.1: 3301f485649SVlad Yasevich * This is performed by selecting the numerically smaller key 3311f485649SVlad Yasevich * vector and concatenating it to the endpoint pair shared 3321f485649SVlad Yasevich * key, and then concatenating the numerically larger key 3331f485649SVlad Yasevich * vector to that. If the key vectors are equal as numbers 3341f485649SVlad Yasevich * but differ in length, then the concatenation order is the 3351f485649SVlad Yasevich * endpoint shared key, followed by the shorter key vector, 3361f485649SVlad Yasevich * followed by the longer key vector. Otherwise, the key 3371f485649SVlad Yasevich * vectors are identical, and may be concatenated to the 3381f485649SVlad Yasevich * endpoint pair key in any order. 3391f485649SVlad Yasevich */ 3401f485649SVlad Yasevich cmp = sctp_auth_compare_vectors(local_key_vector, 3411f485649SVlad Yasevich peer_key_vector); 3421f485649SVlad Yasevich if (cmp < 0) { 3431f485649SVlad Yasevich first_vector = local_key_vector; 3441f485649SVlad Yasevich last_vector = peer_key_vector; 3451f485649SVlad Yasevich } else { 3461f485649SVlad Yasevich first_vector = peer_key_vector; 3471f485649SVlad Yasevich last_vector = local_key_vector; 3481f485649SVlad Yasevich } 3491f485649SVlad Yasevich 3501f485649SVlad Yasevich secret = sctp_auth_asoc_set_secret(ep_key, first_vector, last_vector, 3511f485649SVlad Yasevich gfp); 3521f485649SVlad Yasevich out: 3531f485649SVlad Yasevich kfree(local_key_vector); 3541f485649SVlad Yasevich kfree(peer_key_vector); 3551f485649SVlad Yasevich 3561f485649SVlad Yasevich return secret; 3571f485649SVlad Yasevich } 3581f485649SVlad Yasevich 3591f485649SVlad Yasevich /* 3601f485649SVlad Yasevich * Populate the association overlay list with the list 3611f485649SVlad Yasevich * from the endpoint. 3621f485649SVlad Yasevich */ 3631f485649SVlad Yasevich int sctp_auth_asoc_copy_shkeys(const struct sctp_endpoint *ep, 3641f485649SVlad Yasevich struct sctp_association *asoc, 3651f485649SVlad Yasevich gfp_t gfp) 3661f485649SVlad Yasevich { 3671f485649SVlad Yasevich struct sctp_shared_key *sh_key; 3681f485649SVlad Yasevich struct sctp_shared_key *new; 3691f485649SVlad Yasevich 3701f485649SVlad Yasevich BUG_ON(!list_empty(&asoc->endpoint_shared_keys)); 3711f485649SVlad Yasevich 3721f485649SVlad Yasevich key_for_each(sh_key, &ep->endpoint_shared_keys) { 3731f485649SVlad Yasevich new = sctp_auth_shkey_create(sh_key->key_id, gfp); 3741f485649SVlad Yasevich if (!new) 3751f485649SVlad Yasevich goto nomem; 3761f485649SVlad Yasevich 3771f485649SVlad Yasevich new->key = sh_key->key; 3781f485649SVlad Yasevich sctp_auth_key_hold(new->key); 3791f485649SVlad Yasevich list_add(&new->key_list, &asoc->endpoint_shared_keys); 3801f485649SVlad Yasevich } 3811f485649SVlad Yasevich 3821f485649SVlad Yasevich return 0; 3831f485649SVlad Yasevich 3841f485649SVlad Yasevich nomem: 3851f485649SVlad Yasevich sctp_auth_destroy_keys(&asoc->endpoint_shared_keys); 3861f485649SVlad Yasevich return -ENOMEM; 3871f485649SVlad Yasevich } 3881f485649SVlad Yasevich 3891f485649SVlad Yasevich 3901f485649SVlad Yasevich /* Public interface to creat the association shared key. 3911f485649SVlad Yasevich * See code above for the algorithm. 3921f485649SVlad Yasevich */ 3931f485649SVlad Yasevich int sctp_auth_asoc_init_active_key(struct sctp_association *asoc, gfp_t gfp) 3941f485649SVlad Yasevich { 395e1fc3b14SEric W. Biederman struct net *net = sock_net(asoc->base.sk); 3961f485649SVlad Yasevich struct sctp_auth_bytes *secret; 3971f485649SVlad Yasevich struct sctp_shared_key *ep_key; 3981f485649SVlad Yasevich 3991f485649SVlad Yasevich /* If we don't support AUTH, or peer is not capable 4001f485649SVlad Yasevich * we don't need to do anything. 4011f485649SVlad Yasevich */ 402e1fc3b14SEric W. Biederman if (!net->sctp.auth_enable || !asoc->peer.auth_capable) 4031f485649SVlad Yasevich return 0; 4041f485649SVlad Yasevich 4051f485649SVlad Yasevich /* If the key_id is non-zero and we couldn't find an 4061f485649SVlad Yasevich * endpoint pair shared key, we can't compute the 4071f485649SVlad Yasevich * secret. 4081f485649SVlad Yasevich * For key_id 0, endpoint pair shared key is a NULL key. 4091f485649SVlad Yasevich */ 4101f485649SVlad Yasevich ep_key = sctp_auth_get_shkey(asoc, asoc->active_key_id); 4111f485649SVlad Yasevich BUG_ON(!ep_key); 4121f485649SVlad Yasevich 4131f485649SVlad Yasevich secret = sctp_auth_asoc_create_secret(asoc, ep_key, gfp); 4141f485649SVlad Yasevich if (!secret) 4151f485649SVlad Yasevich return -ENOMEM; 4161f485649SVlad Yasevich 4171f485649SVlad Yasevich sctp_auth_key_put(asoc->asoc_shared_key); 4181f485649SVlad Yasevich asoc->asoc_shared_key = secret; 4191f485649SVlad Yasevich 4201f485649SVlad Yasevich return 0; 4211f485649SVlad Yasevich } 4221f485649SVlad Yasevich 4231f485649SVlad Yasevich 4241f485649SVlad Yasevich /* Find the endpoint pair shared key based on the key_id */ 4251f485649SVlad Yasevich struct sctp_shared_key *sctp_auth_get_shkey( 4261f485649SVlad Yasevich const struct sctp_association *asoc, 4271f485649SVlad Yasevich __u16 key_id) 4281f485649SVlad Yasevich { 4297cc08b55SWei Yongjun struct sctp_shared_key *key; 4301f485649SVlad Yasevich 4311f485649SVlad Yasevich /* First search associations set of endpoint pair shared keys */ 4321f485649SVlad Yasevich key_for_each(key, &asoc->endpoint_shared_keys) { 4331f485649SVlad Yasevich if (key->key_id == key_id) 4347cc08b55SWei Yongjun return key; 4351f485649SVlad Yasevich } 4361f485649SVlad Yasevich 4377cc08b55SWei Yongjun return NULL; 4381f485649SVlad Yasevich } 4391f485649SVlad Yasevich 4401f485649SVlad Yasevich /* 4411f485649SVlad Yasevich * Initialize all the possible digest transforms that we can use. Right now 4421f485649SVlad Yasevich * now, the supported digests are SHA1 and SHA256. We do this here once 4431f485649SVlad Yasevich * because of the restrictiong that transforms may only be allocated in 4441f485649SVlad Yasevich * user context. This forces us to pre-allocated all possible transforms 4451f485649SVlad Yasevich * at the endpoint init time. 4461f485649SVlad Yasevich */ 4471f485649SVlad Yasevich int sctp_auth_init_hmacs(struct sctp_endpoint *ep, gfp_t gfp) 4481f485649SVlad Yasevich { 449e1fc3b14SEric W. Biederman struct net *net = sock_net(ep->base.sk); 4501f485649SVlad Yasevich struct crypto_hash *tfm = NULL; 4511f485649SVlad Yasevich __u16 id; 4521f485649SVlad Yasevich 4531f485649SVlad Yasevich /* if the transforms are already allocted, we are done */ 454e1fc3b14SEric W. Biederman if (!net->sctp.auth_enable) { 4551f485649SVlad Yasevich ep->auth_hmacs = NULL; 4561f485649SVlad Yasevich return 0; 4571f485649SVlad Yasevich } 4581f485649SVlad Yasevich 4591f485649SVlad Yasevich if (ep->auth_hmacs) 4601f485649SVlad Yasevich return 0; 4611f485649SVlad Yasevich 4621f485649SVlad Yasevich /* Allocated the array of pointers to transorms */ 4631f485649SVlad Yasevich ep->auth_hmacs = kzalloc( 4641f485649SVlad Yasevich sizeof(struct crypto_hash *) * SCTP_AUTH_NUM_HMACS, 4651f485649SVlad Yasevich 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 */ 4841f485649SVlad Yasevich tfm = crypto_alloc_hash(sctp_hmac_list[id].hmac_name, 0, 4851f485649SVlad Yasevich CRYPTO_ALG_ASYNC); 4861f485649SVlad Yasevich if (IS_ERR(tfm)) 4871f485649SVlad Yasevich goto out_err; 4881f485649SVlad Yasevich 4891f485649SVlad Yasevich ep->auth_hmacs[id] = tfm; 4901f485649SVlad Yasevich } 4911f485649SVlad Yasevich 4921f485649SVlad Yasevich return 0; 4931f485649SVlad Yasevich 4941f485649SVlad Yasevich out_err: 49573ac36eaSColy Li /* Clean up any successful allocations */ 4961f485649SVlad Yasevich sctp_auth_destroy_hmacs(ep->auth_hmacs); 4971f485649SVlad Yasevich return -ENOMEM; 4981f485649SVlad Yasevich } 4991f485649SVlad Yasevich 5001f485649SVlad Yasevich /* Destroy the hmac tfm array */ 5011f485649SVlad Yasevich void sctp_auth_destroy_hmacs(struct crypto_hash *auth_hmacs[]) 5021f485649SVlad Yasevich { 5031f485649SVlad Yasevich int i; 5041f485649SVlad Yasevich 5051f485649SVlad Yasevich if (!auth_hmacs) 5061f485649SVlad Yasevich return; 5071f485649SVlad Yasevich 5081f485649SVlad Yasevich for (i = 0; i < SCTP_AUTH_NUM_HMACS; i++) 5091f485649SVlad Yasevich { 5101f485649SVlad Yasevich if (auth_hmacs[i]) 5111f485649SVlad Yasevich crypto_free_hash(auth_hmacs[i]); 5121f485649SVlad Yasevich } 5131f485649SVlad Yasevich kfree(auth_hmacs); 5141f485649SVlad Yasevich } 5151f485649SVlad Yasevich 5161f485649SVlad Yasevich 5171f485649SVlad Yasevich struct sctp_hmac *sctp_auth_get_hmac(__u16 hmac_id) 5181f485649SVlad Yasevich { 5191f485649SVlad Yasevich return &sctp_hmac_list[hmac_id]; 5201f485649SVlad Yasevich } 5211f485649SVlad Yasevich 5221f485649SVlad Yasevich /* Get an hmac description information that we can use to build 5231f485649SVlad Yasevich * the AUTH chunk 5241f485649SVlad Yasevich */ 5251f485649SVlad Yasevich struct sctp_hmac *sctp_auth_asoc_get_hmac(const struct sctp_association *asoc) 5261f485649SVlad Yasevich { 5271f485649SVlad Yasevich struct sctp_hmac_algo_param *hmacs; 5281f485649SVlad Yasevich __u16 n_elt; 5291f485649SVlad Yasevich __u16 id = 0; 5301f485649SVlad Yasevich int i; 5311f485649SVlad Yasevich 5321f485649SVlad Yasevich /* If we have a default entry, use it */ 5331f485649SVlad Yasevich if (asoc->default_hmac_id) 5341f485649SVlad Yasevich return &sctp_hmac_list[asoc->default_hmac_id]; 5351f485649SVlad Yasevich 5361f485649SVlad Yasevich /* Since we do not have a default entry, find the first entry 5371f485649SVlad Yasevich * we support and return that. Do not cache that id. 5381f485649SVlad Yasevich */ 5391f485649SVlad Yasevich hmacs = asoc->peer.peer_hmacs; 5401f485649SVlad Yasevich if (!hmacs) 5411f485649SVlad Yasevich return NULL; 5421f485649SVlad Yasevich 5431f485649SVlad Yasevich n_elt = (ntohs(hmacs->param_hdr.length) - sizeof(sctp_paramhdr_t)) >> 1; 5441f485649SVlad Yasevich for (i = 0; i < n_elt; i++) { 5451f485649SVlad Yasevich id = ntohs(hmacs->hmac_ids[i]); 5461f485649SVlad Yasevich 5471f485649SVlad Yasevich /* Check the id is in the supported range */ 54851e97a12SDan Rosenberg if (id > SCTP_AUTH_HMAC_ID_MAX) { 54951e97a12SDan Rosenberg id = 0; 5501f485649SVlad Yasevich continue; 55151e97a12SDan Rosenberg } 5521f485649SVlad Yasevich 5531f485649SVlad Yasevich /* See is we support the id. Supported IDs have name and 5541f485649SVlad Yasevich * length fields set, so that we can allocated and use 5551f485649SVlad Yasevich * them. We can safely just check for name, for without the 5561f485649SVlad Yasevich * name, we can't allocate the TFM. 5571f485649SVlad Yasevich */ 55851e97a12SDan Rosenberg if (!sctp_hmac_list[id].hmac_name) { 55951e97a12SDan Rosenberg id = 0; 5601f485649SVlad Yasevich continue; 56151e97a12SDan Rosenberg } 5621f485649SVlad Yasevich 5631f485649SVlad Yasevich break; 5641f485649SVlad Yasevich } 5651f485649SVlad Yasevich 5661f485649SVlad Yasevich if (id == 0) 5671f485649SVlad Yasevich return NULL; 5681f485649SVlad Yasevich 5691f485649SVlad Yasevich return &sctp_hmac_list[id]; 5701f485649SVlad Yasevich } 5711f485649SVlad Yasevich 572d06f6082SAl Viro static int __sctp_auth_find_hmacid(__be16 *hmacs, int n_elts, __be16 hmac_id) 5731f485649SVlad Yasevich { 5741f485649SVlad Yasevich int found = 0; 5751f485649SVlad Yasevich int i; 5761f485649SVlad Yasevich 5771f485649SVlad Yasevich for (i = 0; i < n_elts; i++) { 5781f485649SVlad Yasevich if (hmac_id == hmacs[i]) { 5791f485649SVlad Yasevich found = 1; 5801f485649SVlad Yasevich break; 5811f485649SVlad Yasevich } 5821f485649SVlad Yasevich } 5831f485649SVlad Yasevich 5841f485649SVlad Yasevich return found; 5851f485649SVlad Yasevich } 5861f485649SVlad Yasevich 5871f485649SVlad Yasevich /* See if the HMAC_ID is one that we claim as supported */ 5881f485649SVlad Yasevich int sctp_auth_asoc_verify_hmac_id(const struct sctp_association *asoc, 589d06f6082SAl Viro __be16 hmac_id) 5901f485649SVlad Yasevich { 5911f485649SVlad Yasevich struct sctp_hmac_algo_param *hmacs; 5921f485649SVlad Yasevich __u16 n_elt; 5931f485649SVlad Yasevich 5941f485649SVlad Yasevich if (!asoc) 5951f485649SVlad Yasevich return 0; 5961f485649SVlad Yasevich 5971f485649SVlad Yasevich hmacs = (struct sctp_hmac_algo_param *)asoc->c.auth_hmacs; 5981f485649SVlad Yasevich n_elt = (ntohs(hmacs->param_hdr.length) - sizeof(sctp_paramhdr_t)) >> 1; 5991f485649SVlad Yasevich 6001f485649SVlad Yasevich return __sctp_auth_find_hmacid(hmacs->hmac_ids, n_elt, hmac_id); 6011f485649SVlad Yasevich } 6021f485649SVlad Yasevich 6031f485649SVlad Yasevich 6041f485649SVlad Yasevich /* Cache the default HMAC id. This to follow this text from SCTP-AUTH: 6051f485649SVlad Yasevich * Section 6.1: 6061f485649SVlad Yasevich * The receiver of a HMAC-ALGO parameter SHOULD use the first listed 6071f485649SVlad Yasevich * algorithm it supports. 6081f485649SVlad Yasevich */ 6091f485649SVlad Yasevich void sctp_auth_asoc_set_default_hmac(struct sctp_association *asoc, 6101f485649SVlad Yasevich struct sctp_hmac_algo_param *hmacs) 6111f485649SVlad Yasevich { 6121f485649SVlad Yasevich struct sctp_endpoint *ep; 6131f485649SVlad Yasevich __u16 id; 6141f485649SVlad Yasevich int i; 6151f485649SVlad Yasevich int n_params; 6161f485649SVlad Yasevich 6171f485649SVlad Yasevich /* if the default id is already set, use it */ 6181f485649SVlad Yasevich if (asoc->default_hmac_id) 6191f485649SVlad Yasevich return; 6201f485649SVlad Yasevich 6211f485649SVlad Yasevich n_params = (ntohs(hmacs->param_hdr.length) 6221f485649SVlad Yasevich - sizeof(sctp_paramhdr_t)) >> 1; 6231f485649SVlad Yasevich ep = asoc->ep; 6241f485649SVlad Yasevich for (i = 0; i < n_params; i++) { 6251f485649SVlad Yasevich id = ntohs(hmacs->hmac_ids[i]); 6261f485649SVlad Yasevich 6271f485649SVlad Yasevich /* Check the id is in the supported range */ 6281f485649SVlad Yasevich if (id > SCTP_AUTH_HMAC_ID_MAX) 6291f485649SVlad Yasevich continue; 6301f485649SVlad Yasevich 6311f485649SVlad Yasevich /* If this TFM has been allocated, use this id */ 6321f485649SVlad Yasevich if (ep->auth_hmacs[id]) { 6331f485649SVlad Yasevich asoc->default_hmac_id = id; 6341f485649SVlad Yasevich break; 6351f485649SVlad Yasevich } 6361f485649SVlad Yasevich } 6371f485649SVlad Yasevich } 6381f485649SVlad Yasevich 6391f485649SVlad Yasevich 6401f485649SVlad Yasevich /* Check to see if the given chunk is supposed to be authenticated */ 6411f485649SVlad Yasevich static int __sctp_auth_cid(sctp_cid_t chunk, struct sctp_chunks_param *param) 6421f485649SVlad Yasevich { 6431f485649SVlad Yasevich unsigned short len; 6441f485649SVlad Yasevich int found = 0; 6451f485649SVlad Yasevich int i; 6461f485649SVlad Yasevich 647555d3d5dSVlad Yasevich if (!param || param->param_hdr.length == 0) 6481f485649SVlad Yasevich return 0; 6491f485649SVlad Yasevich 6501f485649SVlad Yasevich len = ntohs(param->param_hdr.length) - sizeof(sctp_paramhdr_t); 6511f485649SVlad Yasevich 6521f485649SVlad Yasevich /* SCTP-AUTH, Section 3.2 6531f485649SVlad Yasevich * The chunk types for INIT, INIT-ACK, SHUTDOWN-COMPLETE and AUTH 6541f485649SVlad Yasevich * chunks MUST NOT be listed in the CHUNKS parameter. However, if 6551f485649SVlad Yasevich * a CHUNKS parameter is received then the types for INIT, INIT-ACK, 6561f485649SVlad Yasevich * SHUTDOWN-COMPLETE and AUTH chunks MUST be ignored. 6571f485649SVlad Yasevich */ 6581f485649SVlad Yasevich for (i = 0; !found && i < len; i++) { 6591f485649SVlad Yasevich switch (param->chunks[i]) { 6601f485649SVlad Yasevich case SCTP_CID_INIT: 6611f485649SVlad Yasevich case SCTP_CID_INIT_ACK: 6621f485649SVlad Yasevich case SCTP_CID_SHUTDOWN_COMPLETE: 6631f485649SVlad Yasevich case SCTP_CID_AUTH: 6641f485649SVlad Yasevich break; 6651f485649SVlad Yasevich 6661f485649SVlad Yasevich default: 6671f485649SVlad Yasevich if (param->chunks[i] == chunk) 6681f485649SVlad Yasevich found = 1; 6691f485649SVlad Yasevich break; 6701f485649SVlad Yasevich } 6711f485649SVlad Yasevich } 6721f485649SVlad Yasevich 6731f485649SVlad Yasevich return found; 6741f485649SVlad Yasevich } 6751f485649SVlad Yasevich 6761f485649SVlad Yasevich /* Check if peer requested that this chunk is authenticated */ 6771f485649SVlad Yasevich int sctp_auth_send_cid(sctp_cid_t chunk, const struct sctp_association *asoc) 6781f485649SVlad Yasevich { 679e1fc3b14SEric W. Biederman struct net *net; 680e1fc3b14SEric W. Biederman if (!asoc) 681e1fc3b14SEric W. Biederman return 0; 682e1fc3b14SEric W. Biederman 683e1fc3b14SEric W. Biederman net = sock_net(asoc->base.sk); 684e1fc3b14SEric W. Biederman if (!net->sctp.auth_enable || !asoc->peer.auth_capable) 6851f485649SVlad Yasevich return 0; 6861f485649SVlad Yasevich 6871f485649SVlad Yasevich return __sctp_auth_cid(chunk, asoc->peer.peer_chunks); 6881f485649SVlad Yasevich } 6891f485649SVlad Yasevich 6901f485649SVlad Yasevich /* Check if we requested that peer authenticate this chunk. */ 6911f485649SVlad Yasevich int sctp_auth_recv_cid(sctp_cid_t chunk, const struct sctp_association *asoc) 6921f485649SVlad Yasevich { 693e1fc3b14SEric W. Biederman struct net *net; 694e1fc3b14SEric W. Biederman if (!asoc) 695e1fc3b14SEric W. Biederman return 0; 696e1fc3b14SEric W. Biederman 697e1fc3b14SEric W. Biederman net = sock_net(asoc->base.sk); 69802644a17SDan Carpenter if (!net->sctp.auth_enable) 6991f485649SVlad Yasevich return 0; 7001f485649SVlad Yasevich 7011f485649SVlad Yasevich return __sctp_auth_cid(chunk, 7021f485649SVlad Yasevich (struct sctp_chunks_param *)asoc->c.auth_chunks); 7031f485649SVlad Yasevich } 7041f485649SVlad Yasevich 7051f485649SVlad Yasevich /* SCTP-AUTH: Section 6.2: 7061f485649SVlad Yasevich * The sender MUST calculate the MAC as described in RFC2104 [2] using 7071f485649SVlad Yasevich * the hash function H as described by the MAC Identifier and the shared 7081f485649SVlad Yasevich * association key K based on the endpoint pair shared key described by 7091f485649SVlad Yasevich * the shared key identifier. The 'data' used for the computation of 7101f485649SVlad Yasevich * the AUTH-chunk is given by the AUTH chunk with its HMAC field set to 7111f485649SVlad Yasevich * zero (as shown in Figure 6) followed by all chunks that are placed 7121f485649SVlad Yasevich * after the AUTH chunk in the SCTP packet. 7131f485649SVlad Yasevich */ 7141f485649SVlad Yasevich void sctp_auth_calculate_hmac(const struct sctp_association *asoc, 7151f485649SVlad Yasevich struct sk_buff *skb, 7161f485649SVlad Yasevich struct sctp_auth_chunk *auth, 7171f485649SVlad Yasevich gfp_t gfp) 7181f485649SVlad Yasevich { 7191f485649SVlad Yasevich struct scatterlist sg; 7201f485649SVlad Yasevich struct hash_desc desc; 7211f485649SVlad Yasevich struct sctp_auth_bytes *asoc_key; 7221f485649SVlad Yasevich __u16 key_id, hmac_id; 7231f485649SVlad Yasevich __u8 *digest; 7241f485649SVlad Yasevich unsigned char *end; 7251f485649SVlad Yasevich int free_key = 0; 7261f485649SVlad Yasevich 7271f485649SVlad Yasevich /* Extract the info we need: 7281f485649SVlad Yasevich * - hmac id 7291f485649SVlad Yasevich * - key id 7301f485649SVlad Yasevich */ 7311f485649SVlad Yasevich key_id = ntohs(auth->auth_hdr.shkey_id); 7321f485649SVlad Yasevich hmac_id = ntohs(auth->auth_hdr.hmac_id); 7331f485649SVlad Yasevich 7341f485649SVlad Yasevich if (key_id == asoc->active_key_id) 7351f485649SVlad Yasevich asoc_key = asoc->asoc_shared_key; 7361f485649SVlad Yasevich else { 7371f485649SVlad Yasevich struct sctp_shared_key *ep_key; 7381f485649SVlad Yasevich 7391f485649SVlad Yasevich ep_key = sctp_auth_get_shkey(asoc, key_id); 7401f485649SVlad Yasevich if (!ep_key) 7411f485649SVlad Yasevich return; 7421f485649SVlad Yasevich 7431f485649SVlad Yasevich asoc_key = sctp_auth_asoc_create_secret(asoc, ep_key, gfp); 7441f485649SVlad Yasevich if (!asoc_key) 7451f485649SVlad Yasevich return; 7461f485649SVlad Yasevich 7471f485649SVlad Yasevich free_key = 1; 7481f485649SVlad Yasevich } 7491f485649SVlad Yasevich 7501f485649SVlad Yasevich /* set up scatter list */ 7511f485649SVlad Yasevich end = skb_tail_pointer(skb); 75268e3f5ddSHerbert Xu sg_init_one(&sg, auth, end - (unsigned char *)auth); 7531f485649SVlad Yasevich 7541f485649SVlad Yasevich desc.tfm = asoc->ep->auth_hmacs[hmac_id]; 7551f485649SVlad Yasevich desc.flags = 0; 7561f485649SVlad Yasevich 7571f485649SVlad Yasevich digest = auth->auth_hdr.hmac; 7581f485649SVlad Yasevich if (crypto_hash_setkey(desc.tfm, &asoc_key->data[0], asoc_key->len)) 7591f485649SVlad Yasevich goto free; 7601f485649SVlad Yasevich 7611f485649SVlad Yasevich crypto_hash_digest(&desc, &sg, sg.length, digest); 7621f485649SVlad Yasevich 7631f485649SVlad Yasevich free: 7641f485649SVlad Yasevich if (free_key) 7651f485649SVlad Yasevich sctp_auth_key_put(asoc_key); 7661f485649SVlad Yasevich } 76765b07e5dSVlad Yasevich 76865b07e5dSVlad Yasevich /* API Helpers */ 76965b07e5dSVlad Yasevich 77065b07e5dSVlad Yasevich /* Add a chunk to the endpoint authenticated chunk list */ 77165b07e5dSVlad Yasevich int sctp_auth_ep_add_chunkid(struct sctp_endpoint *ep, __u8 chunk_id) 77265b07e5dSVlad Yasevich { 77365b07e5dSVlad Yasevich struct sctp_chunks_param *p = ep->auth_chunk_list; 77465b07e5dSVlad Yasevich __u16 nchunks; 77565b07e5dSVlad Yasevich __u16 param_len; 77665b07e5dSVlad Yasevich 77765b07e5dSVlad Yasevich /* If this chunk is already specified, we are done */ 77865b07e5dSVlad Yasevich if (__sctp_auth_cid(chunk_id, p)) 77965b07e5dSVlad Yasevich return 0; 78065b07e5dSVlad Yasevich 78165b07e5dSVlad Yasevich /* Check if we can add this chunk to the array */ 78265b07e5dSVlad Yasevich param_len = ntohs(p->param_hdr.length); 78365b07e5dSVlad Yasevich nchunks = param_len - sizeof(sctp_paramhdr_t); 78465b07e5dSVlad Yasevich if (nchunks == SCTP_NUM_CHUNK_TYPES) 78565b07e5dSVlad Yasevich return -EINVAL; 78665b07e5dSVlad Yasevich 78765b07e5dSVlad Yasevich p->chunks[nchunks] = chunk_id; 78865b07e5dSVlad Yasevich p->param_hdr.length = htons(param_len + 1); 78965b07e5dSVlad Yasevich return 0; 79065b07e5dSVlad Yasevich } 79165b07e5dSVlad Yasevich 79265b07e5dSVlad Yasevich /* Add hmac identifires to the endpoint list of supported hmac ids */ 79365b07e5dSVlad Yasevich int sctp_auth_ep_set_hmacs(struct sctp_endpoint *ep, 79465b07e5dSVlad Yasevich struct sctp_hmacalgo *hmacs) 79565b07e5dSVlad Yasevich { 79665b07e5dSVlad Yasevich int has_sha1 = 0; 79765b07e5dSVlad Yasevich __u16 id; 79865b07e5dSVlad Yasevich int i; 79965b07e5dSVlad Yasevich 80065b07e5dSVlad Yasevich /* Scan the list looking for unsupported id. Also make sure that 80165b07e5dSVlad Yasevich * SHA1 is specified. 80265b07e5dSVlad Yasevich */ 80365b07e5dSVlad Yasevich for (i = 0; i < hmacs->shmac_num_idents; i++) { 80465b07e5dSVlad Yasevich id = hmacs->shmac_idents[i]; 80565b07e5dSVlad Yasevich 806d9724055SVlad Yasevich if (id > SCTP_AUTH_HMAC_ID_MAX) 807d9724055SVlad Yasevich return -EOPNOTSUPP; 808d9724055SVlad Yasevich 80965b07e5dSVlad Yasevich if (SCTP_AUTH_HMAC_ID_SHA1 == id) 81065b07e5dSVlad Yasevich has_sha1 = 1; 81165b07e5dSVlad Yasevich 81265b07e5dSVlad Yasevich if (!sctp_hmac_list[id].hmac_name) 81365b07e5dSVlad Yasevich return -EOPNOTSUPP; 81465b07e5dSVlad Yasevich } 81565b07e5dSVlad Yasevich 81665b07e5dSVlad Yasevich if (!has_sha1) 81765b07e5dSVlad Yasevich return -EINVAL; 81865b07e5dSVlad Yasevich 81965b07e5dSVlad Yasevich memcpy(ep->auth_hmacs_list->hmac_ids, &hmacs->shmac_idents[0], 82065b07e5dSVlad Yasevich hmacs->shmac_num_idents * sizeof(__u16)); 82165b07e5dSVlad Yasevich ep->auth_hmacs_list->param_hdr.length = htons(sizeof(sctp_paramhdr_t) + 82265b07e5dSVlad Yasevich hmacs->shmac_num_idents * sizeof(__u16)); 82365b07e5dSVlad Yasevich return 0; 82465b07e5dSVlad Yasevich } 82565b07e5dSVlad Yasevich 82665b07e5dSVlad Yasevich /* Set a new shared key on either endpoint or association. If the 82765b07e5dSVlad Yasevich * the key with a same ID already exists, replace the key (remove the 82865b07e5dSVlad Yasevich * old key and add a new one). 82965b07e5dSVlad Yasevich */ 83065b07e5dSVlad Yasevich int sctp_auth_set_key(struct sctp_endpoint *ep, 83165b07e5dSVlad Yasevich struct sctp_association *asoc, 83265b07e5dSVlad Yasevich struct sctp_authkey *auth_key) 83365b07e5dSVlad Yasevich { 83465b07e5dSVlad Yasevich struct sctp_shared_key *cur_key = NULL; 83565b07e5dSVlad Yasevich struct sctp_auth_bytes *key; 83665b07e5dSVlad Yasevich struct list_head *sh_keys; 83765b07e5dSVlad Yasevich int replace = 0; 83865b07e5dSVlad Yasevich 83965b07e5dSVlad Yasevich /* Try to find the given key id to see if 84065b07e5dSVlad Yasevich * we are doing a replace, or adding a new key 84165b07e5dSVlad Yasevich */ 84265b07e5dSVlad Yasevich if (asoc) 84365b07e5dSVlad Yasevich sh_keys = &asoc->endpoint_shared_keys; 84465b07e5dSVlad Yasevich else 84565b07e5dSVlad Yasevich sh_keys = &ep->endpoint_shared_keys; 84665b07e5dSVlad Yasevich 84765b07e5dSVlad Yasevich key_for_each(cur_key, sh_keys) { 84865b07e5dSVlad Yasevich if (cur_key->key_id == auth_key->sca_keynumber) { 84965b07e5dSVlad Yasevich replace = 1; 85065b07e5dSVlad Yasevich break; 85165b07e5dSVlad Yasevich } 85265b07e5dSVlad Yasevich } 85365b07e5dSVlad Yasevich 85465b07e5dSVlad Yasevich /* If we are not replacing a key id, we need to allocate 85565b07e5dSVlad Yasevich * a shared key. 85665b07e5dSVlad Yasevich */ 85765b07e5dSVlad Yasevich if (!replace) { 85865b07e5dSVlad Yasevich cur_key = sctp_auth_shkey_create(auth_key->sca_keynumber, 85965b07e5dSVlad Yasevich GFP_KERNEL); 86065b07e5dSVlad Yasevich if (!cur_key) 86165b07e5dSVlad Yasevich return -ENOMEM; 86265b07e5dSVlad Yasevich } 86365b07e5dSVlad Yasevich 86465b07e5dSVlad Yasevich /* Create a new key data based on the info passed in */ 8657e8616d8SVlad Yasevich key = sctp_auth_create_key(auth_key->sca_keylength, GFP_KERNEL); 86665b07e5dSVlad Yasevich if (!key) 86765b07e5dSVlad Yasevich goto nomem; 86865b07e5dSVlad Yasevich 8697e8616d8SVlad Yasevich memcpy(key->data, &auth_key->sca_key[0], auth_key->sca_keylength); 87065b07e5dSVlad Yasevich 87165b07e5dSVlad Yasevich /* If we are replacing, remove the old keys data from the 87265b07e5dSVlad Yasevich * key id. If we are adding new key id, add it to the 87365b07e5dSVlad Yasevich * list. 87465b07e5dSVlad Yasevich */ 87565b07e5dSVlad Yasevich if (replace) 87665b07e5dSVlad Yasevich sctp_auth_key_put(cur_key->key); 87765b07e5dSVlad Yasevich else 87865b07e5dSVlad Yasevich list_add(&cur_key->key_list, sh_keys); 87965b07e5dSVlad Yasevich 88065b07e5dSVlad Yasevich cur_key->key = key; 88165b07e5dSVlad Yasevich sctp_auth_key_hold(key); 88265b07e5dSVlad Yasevich 88365b07e5dSVlad Yasevich return 0; 88465b07e5dSVlad Yasevich nomem: 88565b07e5dSVlad Yasevich if (!replace) 88665b07e5dSVlad Yasevich sctp_auth_shkey_free(cur_key); 88765b07e5dSVlad Yasevich 88865b07e5dSVlad Yasevich return -ENOMEM; 88965b07e5dSVlad Yasevich } 89065b07e5dSVlad Yasevich 89165b07e5dSVlad Yasevich int sctp_auth_set_active_key(struct sctp_endpoint *ep, 89265b07e5dSVlad Yasevich struct sctp_association *asoc, 89365b07e5dSVlad Yasevich __u16 key_id) 89465b07e5dSVlad Yasevich { 89565b07e5dSVlad Yasevich struct sctp_shared_key *key; 89665b07e5dSVlad Yasevich struct list_head *sh_keys; 89765b07e5dSVlad Yasevich int found = 0; 89865b07e5dSVlad Yasevich 89965b07e5dSVlad Yasevich /* The key identifier MUST correst to an existing key */ 90065b07e5dSVlad Yasevich if (asoc) 90165b07e5dSVlad Yasevich sh_keys = &asoc->endpoint_shared_keys; 90265b07e5dSVlad Yasevich else 90365b07e5dSVlad Yasevich sh_keys = &ep->endpoint_shared_keys; 90465b07e5dSVlad Yasevich 90565b07e5dSVlad Yasevich key_for_each(key, sh_keys) { 90665b07e5dSVlad Yasevich if (key->key_id == key_id) { 90765b07e5dSVlad Yasevich found = 1; 90865b07e5dSVlad Yasevich break; 90965b07e5dSVlad Yasevich } 91065b07e5dSVlad Yasevich } 91165b07e5dSVlad Yasevich 91265b07e5dSVlad Yasevich if (!found) 91365b07e5dSVlad Yasevich return -EINVAL; 91465b07e5dSVlad Yasevich 91565b07e5dSVlad Yasevich if (asoc) { 91665b07e5dSVlad Yasevich asoc->active_key_id = key_id; 91765b07e5dSVlad Yasevich sctp_auth_asoc_init_active_key(asoc, GFP_KERNEL); 91865b07e5dSVlad Yasevich } else 91965b07e5dSVlad Yasevich ep->active_key_id = key_id; 92065b07e5dSVlad Yasevich 92165b07e5dSVlad Yasevich return 0; 92265b07e5dSVlad Yasevich } 92365b07e5dSVlad Yasevich 92465b07e5dSVlad Yasevich int sctp_auth_del_key_id(struct sctp_endpoint *ep, 92565b07e5dSVlad Yasevich struct sctp_association *asoc, 92665b07e5dSVlad Yasevich __u16 key_id) 92765b07e5dSVlad Yasevich { 92865b07e5dSVlad Yasevich struct sctp_shared_key *key; 92965b07e5dSVlad Yasevich struct list_head *sh_keys; 93065b07e5dSVlad Yasevich int found = 0; 93165b07e5dSVlad Yasevich 93265b07e5dSVlad Yasevich /* The key identifier MUST NOT be the current active key 93365b07e5dSVlad Yasevich * The key identifier MUST correst to an existing key 93465b07e5dSVlad Yasevich */ 93565b07e5dSVlad Yasevich if (asoc) { 93665b07e5dSVlad Yasevich if (asoc->active_key_id == key_id) 93765b07e5dSVlad Yasevich return -EINVAL; 93865b07e5dSVlad Yasevich 93965b07e5dSVlad Yasevich sh_keys = &asoc->endpoint_shared_keys; 94065b07e5dSVlad Yasevich } else { 94165b07e5dSVlad Yasevich if (ep->active_key_id == key_id) 94265b07e5dSVlad Yasevich return -EINVAL; 94365b07e5dSVlad Yasevich 94465b07e5dSVlad Yasevich sh_keys = &ep->endpoint_shared_keys; 94565b07e5dSVlad Yasevich } 94665b07e5dSVlad Yasevich 94765b07e5dSVlad Yasevich key_for_each(key, sh_keys) { 94865b07e5dSVlad Yasevich if (key->key_id == key_id) { 94965b07e5dSVlad Yasevich found = 1; 95065b07e5dSVlad Yasevich break; 95165b07e5dSVlad Yasevich } 95265b07e5dSVlad Yasevich } 95365b07e5dSVlad Yasevich 95465b07e5dSVlad Yasevich if (!found) 95565b07e5dSVlad Yasevich return -EINVAL; 95665b07e5dSVlad Yasevich 95765b07e5dSVlad Yasevich /* Delete the shared key */ 95865b07e5dSVlad Yasevich list_del_init(&key->key_list); 95965b07e5dSVlad Yasevich sctp_auth_shkey_free(key); 96065b07e5dSVlad Yasevich 96165b07e5dSVlad Yasevich return 0; 96265b07e5dSVlad Yasevich } 963