11f485649SVlad Yasevich /* SCTP kernel reference Implementation 21f485649SVlad Yasevich * (C) Copyright 2007 Hewlett-Packard Development Company, L.P. 31f485649SVlad Yasevich * 41f485649SVlad Yasevich * This file is part of the SCTP kernel reference Implementation 51f485649SVlad Yasevich * 61f485649SVlad Yasevich * The SCTP reference 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 * 121f485649SVlad Yasevich * The SCTP reference 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 371f485649SVlad Yasevich #include <linux/types.h> 381f485649SVlad Yasevich #include <linux/crypto.h> 391f485649SVlad Yasevich #include <linux/scatterlist.h> 401f485649SVlad Yasevich #include <net/sctp/sctp.h> 411f485649SVlad Yasevich #include <net/sctp/auth.h> 421f485649SVlad Yasevich 431f485649SVlad Yasevich static struct sctp_hmac sctp_hmac_list[SCTP_AUTH_NUM_HMACS] = { 441f485649SVlad Yasevich { 451f485649SVlad Yasevich /* id 0 is reserved. as all 0 */ 461f485649SVlad Yasevich .hmac_id = SCTP_AUTH_HMAC_ID_RESERVED_0, 471f485649SVlad Yasevich }, 481f485649SVlad Yasevich { 491f485649SVlad Yasevich .hmac_id = SCTP_AUTH_HMAC_ID_SHA1, 501f485649SVlad Yasevich .hmac_name="hmac(sha1)", 511f485649SVlad Yasevich .hmac_len = SCTP_SHA1_SIG_SIZE, 521f485649SVlad Yasevich }, 531f485649SVlad Yasevich { 541f485649SVlad Yasevich /* id 2 is reserved as well */ 551f485649SVlad Yasevich .hmac_id = SCTP_AUTH_HMAC_ID_RESERVED_2, 561f485649SVlad Yasevich }, 571f485649SVlad Yasevich { 581f485649SVlad Yasevich .hmac_id = SCTP_AUTH_HMAC_ID_SHA256, 591f485649SVlad Yasevich .hmac_name="hmac(sha256)", 601f485649SVlad Yasevich .hmac_len = SCTP_SHA256_SIG_SIZE, 611f485649SVlad Yasevich } 621f485649SVlad Yasevich }; 631f485649SVlad Yasevich 641f485649SVlad Yasevich 651f485649SVlad Yasevich void sctp_auth_key_put(struct sctp_auth_bytes *key) 661f485649SVlad Yasevich { 671f485649SVlad Yasevich if (!key) 681f485649SVlad Yasevich return; 691f485649SVlad Yasevich 701f485649SVlad Yasevich if (atomic_dec_and_test(&key->refcnt)) { 711f485649SVlad Yasevich kfree(key); 721f485649SVlad Yasevich SCTP_DBG_OBJCNT_DEC(keys); 731f485649SVlad Yasevich } 741f485649SVlad Yasevich } 751f485649SVlad Yasevich 761f485649SVlad Yasevich /* Create a new key structure of a given length */ 771f485649SVlad Yasevich static struct sctp_auth_bytes *sctp_auth_create_key(__u32 key_len, gfp_t gfp) 781f485649SVlad Yasevich { 791f485649SVlad Yasevich struct sctp_auth_bytes *key; 801f485649SVlad Yasevich 811f485649SVlad Yasevich /* Allocate the shared key */ 821f485649SVlad Yasevich key = kmalloc(sizeof(struct sctp_auth_bytes) + key_len, gfp); 831f485649SVlad Yasevich if (!key) 841f485649SVlad Yasevich return NULL; 851f485649SVlad Yasevich 861f485649SVlad Yasevich key->len = key_len; 871f485649SVlad Yasevich atomic_set(&key->refcnt, 1); 881f485649SVlad Yasevich SCTP_DBG_OBJCNT_INC(keys); 891f485649SVlad Yasevich 901f485649SVlad Yasevich return key; 911f485649SVlad Yasevich } 921f485649SVlad Yasevich 931f485649SVlad Yasevich /* Create a new shared key container with a give key id */ 941f485649SVlad Yasevich struct sctp_shared_key *sctp_auth_shkey_create(__u16 key_id, gfp_t gfp) 951f485649SVlad Yasevich { 961f485649SVlad Yasevich struct sctp_shared_key *new; 971f485649SVlad Yasevich 981f485649SVlad Yasevich /* Allocate the shared key container */ 991f485649SVlad Yasevich new = kzalloc(sizeof(struct sctp_shared_key), gfp); 1001f485649SVlad Yasevich if (!new) 1011f485649SVlad Yasevich return NULL; 1021f485649SVlad Yasevich 1031f485649SVlad Yasevich INIT_LIST_HEAD(&new->key_list); 1041f485649SVlad Yasevich new->key_id = key_id; 1051f485649SVlad Yasevich 1061f485649SVlad Yasevich return new; 1071f485649SVlad Yasevich } 1081f485649SVlad Yasevich 1091f485649SVlad Yasevich /* Free the shared key stucture */ 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 1181f485649SVlad Yasevich /* Destory 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 1381f485649SVlad Yasevich * < 0 - vector 1 is smaller then vector2 1391f485649SVlad Yasevich * > 0 - vector 1 is greater then vector2 1401f485649SVlad Yasevich * 1411f485649SVlad Yasevich * Algorithm is: 1421f485649SVlad Yasevich * This is performed by selecting the numerically smaller key vector... 1431f485649SVlad Yasevich * If the key vectors are equal as numbers but differ in length ... 1441f485649SVlad Yasevich * the shorter vector is considered smaller 1451f485649SVlad Yasevich * 1461f485649SVlad Yasevich * Examples (with small values): 1471f485649SVlad Yasevich * 000123456789 > 123456789 (first number is longer) 1481f485649SVlad Yasevich * 000123456789 < 234567891 (second number is larger numerically) 1491f485649SVlad Yasevich * 123456789 > 2345678 (first number is both larger & longer) 1501f485649SVlad Yasevich */ 1511f485649SVlad Yasevich static int sctp_auth_compare_vectors(struct sctp_auth_bytes *vector1, 1521f485649SVlad Yasevich struct sctp_auth_bytes *vector2) 1531f485649SVlad Yasevich { 1541f485649SVlad Yasevich int diff; 1551f485649SVlad Yasevich int i; 1561f485649SVlad Yasevich const __u8 *longer; 1571f485649SVlad Yasevich 1581f485649SVlad Yasevich diff = vector1->len - vector2->len; 1591f485649SVlad Yasevich if (diff) { 1601f485649SVlad Yasevich longer = (diff > 0) ? vector1->data : vector2->data; 1611f485649SVlad Yasevich 1621f485649SVlad Yasevich /* Check to see if the longer number is 1631f485649SVlad Yasevich * lead-zero padded. If it is not, it 1641f485649SVlad Yasevich * is automatically larger numerically. 1651f485649SVlad Yasevich */ 1661f485649SVlad Yasevich for (i = 0; i < abs(diff); i++ ) { 1671f485649SVlad Yasevich if (longer[i] != 0) 1681f485649SVlad Yasevich return diff; 1691f485649SVlad Yasevich } 1701f485649SVlad Yasevich } 1711f485649SVlad Yasevich 1721f485649SVlad Yasevich /* lengths are the same, compare numbers */ 1731f485649SVlad Yasevich return memcmp(vector1->data, vector2->data, vector1->len); 1741f485649SVlad Yasevich } 1751f485649SVlad Yasevich 1761f485649SVlad Yasevich /* 1771f485649SVlad Yasevich * Create a key vector as described in SCTP-AUTH, Section 6.1 1781f485649SVlad Yasevich * The RANDOM parameter, the CHUNKS parameter and the HMAC-ALGO 1791f485649SVlad Yasevich * parameter sent by each endpoint are concatenated as byte vectors. 1801f485649SVlad Yasevich * These parameters include the parameter type, parameter length, and 1811f485649SVlad Yasevich * the parameter value, but padding is omitted; all padding MUST be 1821f485649SVlad Yasevich * removed from this concatenation before proceeding with further 1831f485649SVlad Yasevich * computation of keys. Parameters which were not sent are simply 1841f485649SVlad Yasevich * omitted from the concatenation process. The resulting two vectors 1851f485649SVlad Yasevich * are called the two key vectors. 1861f485649SVlad Yasevich */ 1871f485649SVlad Yasevich static struct sctp_auth_bytes *sctp_auth_make_key_vector( 1881f485649SVlad Yasevich sctp_random_param_t *random, 1891f485649SVlad Yasevich sctp_chunks_param_t *chunks, 1901f485649SVlad Yasevich sctp_hmac_algo_param_t *hmacs, 1911f485649SVlad Yasevich gfp_t gfp) 1921f485649SVlad Yasevich { 1931f485649SVlad Yasevich struct sctp_auth_bytes *new; 1941f485649SVlad Yasevich __u32 len; 1951f485649SVlad Yasevich __u32 offset = 0; 1961f485649SVlad Yasevich 1971f485649SVlad Yasevich len = ntohs(random->param_hdr.length) + ntohs(hmacs->param_hdr.length); 1981f485649SVlad Yasevich if (chunks) 1991f485649SVlad Yasevich len += ntohs(chunks->param_hdr.length); 2001f485649SVlad Yasevich 2011f485649SVlad Yasevich new = kmalloc(sizeof(struct sctp_auth_bytes) + len, gfp); 2021f485649SVlad Yasevich if (!new) 2031f485649SVlad Yasevich return NULL; 2041f485649SVlad Yasevich 2051f485649SVlad Yasevich new->len = len; 2061f485649SVlad Yasevich 2071f485649SVlad Yasevich memcpy(new->data, random, ntohs(random->param_hdr.length)); 2081f485649SVlad Yasevich offset += ntohs(random->param_hdr.length); 2091f485649SVlad Yasevich 2101f485649SVlad Yasevich if (chunks) { 2111f485649SVlad Yasevich memcpy(new->data + offset, chunks, 2121f485649SVlad Yasevich ntohs(chunks->param_hdr.length)); 2131f485649SVlad Yasevich offset += ntohs(chunks->param_hdr.length); 2141f485649SVlad Yasevich } 2151f485649SVlad Yasevich 2161f485649SVlad Yasevich memcpy(new->data + offset, hmacs, ntohs(hmacs->param_hdr.length)); 2171f485649SVlad Yasevich 2181f485649SVlad Yasevich return new; 2191f485649SVlad Yasevich } 2201f485649SVlad Yasevich 2211f485649SVlad Yasevich 2221f485649SVlad Yasevich /* Make a key vector based on our local parameters */ 2238ad7c62bSAdrian Bunk static struct sctp_auth_bytes *sctp_auth_make_local_vector( 2241f485649SVlad Yasevich const struct sctp_association *asoc, 2251f485649SVlad Yasevich gfp_t gfp) 2261f485649SVlad Yasevich { 2271f485649SVlad Yasevich return sctp_auth_make_key_vector( 2281f485649SVlad Yasevich (sctp_random_param_t*)asoc->c.auth_random, 2291f485649SVlad Yasevich (sctp_chunks_param_t*)asoc->c.auth_chunks, 2301f485649SVlad Yasevich (sctp_hmac_algo_param_t*)asoc->c.auth_hmacs, 2311f485649SVlad Yasevich 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 3201f485649SVlad Yasevich /* Figure out the order in wich 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: 3461f485649SVlad Yasevich kfree(local_key_vector); 3471f485649SVlad Yasevich kfree(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 3831f485649SVlad Yasevich /* Public interface to creat 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; 3901f485649SVlad Yasevich 3911f485649SVlad Yasevich /* If we don't support AUTH, or peer is not capable 3921f485649SVlad Yasevich * we don't need to do anything. 3931f485649SVlad Yasevich */ 3941f485649SVlad Yasevich if (!sctp_auth_enable || !asoc->peer.auth_capable) 3951f485649SVlad Yasevich return 0; 3961f485649SVlad Yasevich 3971f485649SVlad Yasevich /* If the key_id is non-zero and we couldn't find an 3981f485649SVlad Yasevich * endpoint pair shared key, we can't compute the 3991f485649SVlad Yasevich * secret. 4001f485649SVlad Yasevich * For key_id 0, endpoint pair shared key is a NULL key. 4011f485649SVlad Yasevich */ 4021f485649SVlad Yasevich ep_key = sctp_auth_get_shkey(asoc, asoc->active_key_id); 4031f485649SVlad Yasevich BUG_ON(!ep_key); 4041f485649SVlad Yasevich 4051f485649SVlad Yasevich secret = sctp_auth_asoc_create_secret(asoc, ep_key, gfp); 4061f485649SVlad Yasevich if (!secret) 4071f485649SVlad Yasevich return -ENOMEM; 4081f485649SVlad Yasevich 4091f485649SVlad Yasevich sctp_auth_key_put(asoc->asoc_shared_key); 4101f485649SVlad Yasevich asoc->asoc_shared_key = secret; 4111f485649SVlad Yasevich 4121f485649SVlad Yasevich return 0; 4131f485649SVlad Yasevich } 4141f485649SVlad Yasevich 4151f485649SVlad Yasevich 4161f485649SVlad Yasevich /* Find the endpoint pair shared key based on the key_id */ 4171f485649SVlad Yasevich struct sctp_shared_key *sctp_auth_get_shkey( 4181f485649SVlad Yasevich const struct sctp_association *asoc, 4191f485649SVlad Yasevich __u16 key_id) 4201f485649SVlad Yasevich { 4211f485649SVlad Yasevich struct sctp_shared_key *key = NULL; 4221f485649SVlad Yasevich 4231f485649SVlad Yasevich /* First search associations set of endpoint pair shared keys */ 4241f485649SVlad Yasevich key_for_each(key, &asoc->endpoint_shared_keys) { 4251f485649SVlad Yasevich if (key->key_id == key_id) 4261f485649SVlad Yasevich break; 4271f485649SVlad Yasevich } 4281f485649SVlad Yasevich 4291f485649SVlad Yasevich return key; 4301f485649SVlad Yasevich } 4311f485649SVlad Yasevich 4321f485649SVlad Yasevich /* 4331f485649SVlad Yasevich * Initialize all the possible digest transforms that we can use. Right now 4341f485649SVlad Yasevich * now, the supported digests are SHA1 and SHA256. We do this here once 4351f485649SVlad Yasevich * because of the restrictiong that transforms may only be allocated in 4361f485649SVlad Yasevich * user context. This forces us to pre-allocated all possible transforms 4371f485649SVlad Yasevich * at the endpoint init time. 4381f485649SVlad Yasevich */ 4391f485649SVlad Yasevich int sctp_auth_init_hmacs(struct sctp_endpoint *ep, gfp_t gfp) 4401f485649SVlad Yasevich { 4411f485649SVlad Yasevich struct crypto_hash *tfm = NULL; 4421f485649SVlad Yasevich __u16 id; 4431f485649SVlad Yasevich 4441f485649SVlad Yasevich /* if the transforms are already allocted, we are done */ 4451f485649SVlad Yasevich if (!sctp_auth_enable) { 4461f485649SVlad Yasevich ep->auth_hmacs = NULL; 4471f485649SVlad Yasevich return 0; 4481f485649SVlad Yasevich } 4491f485649SVlad Yasevich 4501f485649SVlad Yasevich if (ep->auth_hmacs) 4511f485649SVlad Yasevich return 0; 4521f485649SVlad Yasevich 4531f485649SVlad Yasevich /* Allocated the array of pointers to transorms */ 4541f485649SVlad Yasevich ep->auth_hmacs = kzalloc( 4551f485649SVlad Yasevich sizeof(struct crypto_hash *) * SCTP_AUTH_NUM_HMACS, 4561f485649SVlad Yasevich gfp); 4571f485649SVlad Yasevich if (!ep->auth_hmacs) 4581f485649SVlad Yasevich return -ENOMEM; 4591f485649SVlad Yasevich 4601f485649SVlad Yasevich for (id = 0; id < SCTP_AUTH_NUM_HMACS; id++) { 4611f485649SVlad Yasevich 4621f485649SVlad Yasevich /* See is we support the id. Supported IDs have name and 4631f485649SVlad Yasevich * length fields set, so that we can allocated and use 4641f485649SVlad Yasevich * them. We can safely just check for name, for without the 4651f485649SVlad Yasevich * name, we can't allocate the TFM. 4661f485649SVlad Yasevich */ 4671f485649SVlad Yasevich if (!sctp_hmac_list[id].hmac_name) 4681f485649SVlad Yasevich continue; 4691f485649SVlad Yasevich 4701f485649SVlad Yasevich /* If this TFM has been allocated, we are all set */ 4711f485649SVlad Yasevich if (ep->auth_hmacs[id]) 4721f485649SVlad Yasevich continue; 4731f485649SVlad Yasevich 4741f485649SVlad Yasevich /* Allocate the ID */ 4751f485649SVlad Yasevich tfm = crypto_alloc_hash(sctp_hmac_list[id].hmac_name, 0, 4761f485649SVlad Yasevich CRYPTO_ALG_ASYNC); 4771f485649SVlad Yasevich if (IS_ERR(tfm)) 4781f485649SVlad Yasevich goto out_err; 4791f485649SVlad Yasevich 4801f485649SVlad Yasevich ep->auth_hmacs[id] = tfm; 4811f485649SVlad Yasevich } 4821f485649SVlad Yasevich 4831f485649SVlad Yasevich return 0; 4841f485649SVlad Yasevich 4851f485649SVlad Yasevich out_err: 4861f485649SVlad Yasevich /* Clean up any successfull allocations */ 4871f485649SVlad Yasevich sctp_auth_destroy_hmacs(ep->auth_hmacs); 4881f485649SVlad Yasevich return -ENOMEM; 4891f485649SVlad Yasevich } 4901f485649SVlad Yasevich 4911f485649SVlad Yasevich /* Destroy the hmac tfm array */ 4921f485649SVlad Yasevich void sctp_auth_destroy_hmacs(struct crypto_hash *auth_hmacs[]) 4931f485649SVlad Yasevich { 4941f485649SVlad Yasevich int i; 4951f485649SVlad Yasevich 4961f485649SVlad Yasevich if (!auth_hmacs) 4971f485649SVlad Yasevich return; 4981f485649SVlad Yasevich 4991f485649SVlad Yasevich for (i = 0; i < SCTP_AUTH_NUM_HMACS; i++) 5001f485649SVlad Yasevich { 5011f485649SVlad Yasevich if (auth_hmacs[i]) 5021f485649SVlad Yasevich crypto_free_hash(auth_hmacs[i]); 5031f485649SVlad Yasevich } 5041f485649SVlad Yasevich kfree(auth_hmacs); 5051f485649SVlad Yasevich } 5061f485649SVlad Yasevich 5071f485649SVlad Yasevich 5081f485649SVlad Yasevich struct sctp_hmac *sctp_auth_get_hmac(__u16 hmac_id) 5091f485649SVlad Yasevich { 5101f485649SVlad Yasevich return &sctp_hmac_list[hmac_id]; 5111f485649SVlad Yasevich } 5121f485649SVlad Yasevich 5131f485649SVlad Yasevich /* Get an hmac description information that we can use to build 5141f485649SVlad Yasevich * the AUTH chunk 5151f485649SVlad Yasevich */ 5161f485649SVlad Yasevich struct sctp_hmac *sctp_auth_asoc_get_hmac(const struct sctp_association *asoc) 5171f485649SVlad Yasevich { 5181f485649SVlad Yasevich struct sctp_hmac_algo_param *hmacs; 5191f485649SVlad Yasevich __u16 n_elt; 5201f485649SVlad Yasevich __u16 id = 0; 5211f485649SVlad Yasevich int i; 5221f485649SVlad Yasevich 5231f485649SVlad Yasevich /* If we have a default entry, use it */ 5241f485649SVlad Yasevich if (asoc->default_hmac_id) 5251f485649SVlad Yasevich return &sctp_hmac_list[asoc->default_hmac_id]; 5261f485649SVlad Yasevich 5271f485649SVlad Yasevich /* Since we do not have a default entry, find the first entry 5281f485649SVlad Yasevich * we support and return that. Do not cache that id. 5291f485649SVlad Yasevich */ 5301f485649SVlad Yasevich hmacs = asoc->peer.peer_hmacs; 5311f485649SVlad Yasevich if (!hmacs) 5321f485649SVlad Yasevich return NULL; 5331f485649SVlad Yasevich 5341f485649SVlad Yasevich n_elt = (ntohs(hmacs->param_hdr.length) - sizeof(sctp_paramhdr_t)) >> 1; 5351f485649SVlad Yasevich for (i = 0; i < n_elt; i++) { 5361f485649SVlad Yasevich id = ntohs(hmacs->hmac_ids[i]); 5371f485649SVlad Yasevich 5381f485649SVlad Yasevich /* Check the id is in the supported range */ 5391f485649SVlad Yasevich if (id > SCTP_AUTH_HMAC_ID_MAX) 5401f485649SVlad Yasevich continue; 5411f485649SVlad Yasevich 5421f485649SVlad Yasevich /* See is we support the id. Supported IDs have name and 5431f485649SVlad Yasevich * length fields set, so that we can allocated and use 5441f485649SVlad Yasevich * them. We can safely just check for name, for without the 5451f485649SVlad Yasevich * name, we can't allocate the TFM. 5461f485649SVlad Yasevich */ 5471f485649SVlad Yasevich if (!sctp_hmac_list[id].hmac_name) 5481f485649SVlad Yasevich continue; 5491f485649SVlad Yasevich 5501f485649SVlad Yasevich break; 5511f485649SVlad Yasevich } 5521f485649SVlad Yasevich 5531f485649SVlad Yasevich if (id == 0) 5541f485649SVlad Yasevich return NULL; 5551f485649SVlad Yasevich 5561f485649SVlad Yasevich return &sctp_hmac_list[id]; 5571f485649SVlad Yasevich } 5581f485649SVlad Yasevich 5591f485649SVlad Yasevich static int __sctp_auth_find_hmacid(__u16 *hmacs, int n_elts, __u16 hmac_id) 5601f485649SVlad Yasevich { 5611f485649SVlad Yasevich int found = 0; 5621f485649SVlad Yasevich int i; 5631f485649SVlad Yasevich 5641f485649SVlad Yasevich for (i = 0; i < n_elts; i++) { 5651f485649SVlad Yasevich if (hmac_id == hmacs[i]) { 5661f485649SVlad Yasevich found = 1; 5671f485649SVlad Yasevich break; 5681f485649SVlad Yasevich } 5691f485649SVlad Yasevich } 5701f485649SVlad Yasevich 5711f485649SVlad Yasevich return found; 5721f485649SVlad Yasevich } 5731f485649SVlad Yasevich 5741f485649SVlad Yasevich /* See if the HMAC_ID is one that we claim as supported */ 5751f485649SVlad Yasevich int sctp_auth_asoc_verify_hmac_id(const struct sctp_association *asoc, 5761f485649SVlad Yasevich __u16 hmac_id) 5771f485649SVlad Yasevich { 5781f485649SVlad Yasevich struct sctp_hmac_algo_param *hmacs; 5791f485649SVlad Yasevich __u16 n_elt; 5801f485649SVlad Yasevich 5811f485649SVlad Yasevich if (!asoc) 5821f485649SVlad Yasevich return 0; 5831f485649SVlad Yasevich 5841f485649SVlad Yasevich hmacs = (struct sctp_hmac_algo_param *)asoc->c.auth_hmacs; 5851f485649SVlad Yasevich n_elt = (ntohs(hmacs->param_hdr.length) - sizeof(sctp_paramhdr_t)) >> 1; 5861f485649SVlad Yasevich 5871f485649SVlad Yasevich return __sctp_auth_find_hmacid(hmacs->hmac_ids, n_elt, hmac_id); 5881f485649SVlad Yasevich } 5891f485649SVlad Yasevich 5901f485649SVlad Yasevich 5911f485649SVlad Yasevich /* Cache the default HMAC id. This to follow this text from SCTP-AUTH: 5921f485649SVlad Yasevich * Section 6.1: 5931f485649SVlad Yasevich * The receiver of a HMAC-ALGO parameter SHOULD use the first listed 5941f485649SVlad Yasevich * algorithm it supports. 5951f485649SVlad Yasevich */ 5961f485649SVlad Yasevich void sctp_auth_asoc_set_default_hmac(struct sctp_association *asoc, 5971f485649SVlad Yasevich struct sctp_hmac_algo_param *hmacs) 5981f485649SVlad Yasevich { 5991f485649SVlad Yasevich struct sctp_endpoint *ep; 6001f485649SVlad Yasevich __u16 id; 6011f485649SVlad Yasevich int i; 6021f485649SVlad Yasevich int n_params; 6031f485649SVlad Yasevich 6041f485649SVlad Yasevich /* if the default id is already set, use it */ 6051f485649SVlad Yasevich if (asoc->default_hmac_id) 6061f485649SVlad Yasevich return; 6071f485649SVlad Yasevich 6081f485649SVlad Yasevich n_params = (ntohs(hmacs->param_hdr.length) 6091f485649SVlad Yasevich - sizeof(sctp_paramhdr_t)) >> 1; 6101f485649SVlad Yasevich ep = asoc->ep; 6111f485649SVlad Yasevich for (i = 0; i < n_params; i++) { 6121f485649SVlad Yasevich id = ntohs(hmacs->hmac_ids[i]); 6131f485649SVlad Yasevich 6141f485649SVlad Yasevich /* Check the id is in the supported range */ 6151f485649SVlad Yasevich if (id > SCTP_AUTH_HMAC_ID_MAX) 6161f485649SVlad Yasevich continue; 6171f485649SVlad Yasevich 6181f485649SVlad Yasevich /* If this TFM has been allocated, use this id */ 6191f485649SVlad Yasevich if (ep->auth_hmacs[id]) { 6201f485649SVlad Yasevich asoc->default_hmac_id = id; 6211f485649SVlad Yasevich break; 6221f485649SVlad Yasevich } 6231f485649SVlad Yasevich } 6241f485649SVlad Yasevich } 6251f485649SVlad Yasevich 6261f485649SVlad Yasevich 6271f485649SVlad Yasevich /* Check to see if the given chunk is supposed to be authenticated */ 6281f485649SVlad Yasevich static int __sctp_auth_cid(sctp_cid_t chunk, struct sctp_chunks_param *param) 6291f485649SVlad Yasevich { 6301f485649SVlad Yasevich unsigned short len; 6311f485649SVlad Yasevich int found = 0; 6321f485649SVlad Yasevich int i; 6331f485649SVlad Yasevich 6341f485649SVlad Yasevich if (!param) 6351f485649SVlad Yasevich return 0; 6361f485649SVlad Yasevich 6371f485649SVlad Yasevich len = ntohs(param->param_hdr.length) - sizeof(sctp_paramhdr_t); 6381f485649SVlad Yasevich 6391f485649SVlad Yasevich /* SCTP-AUTH, Section 3.2 6401f485649SVlad Yasevich * The chunk types for INIT, INIT-ACK, SHUTDOWN-COMPLETE and AUTH 6411f485649SVlad Yasevich * chunks MUST NOT be listed in the CHUNKS parameter. However, if 6421f485649SVlad Yasevich * a CHUNKS parameter is received then the types for INIT, INIT-ACK, 6431f485649SVlad Yasevich * SHUTDOWN-COMPLETE and AUTH chunks MUST be ignored. 6441f485649SVlad Yasevich */ 6451f485649SVlad Yasevich for (i = 0; !found && i < len; i++) { 6461f485649SVlad Yasevich switch (param->chunks[i]) { 6471f485649SVlad Yasevich case SCTP_CID_INIT: 6481f485649SVlad Yasevich case SCTP_CID_INIT_ACK: 6491f485649SVlad Yasevich case SCTP_CID_SHUTDOWN_COMPLETE: 6501f485649SVlad Yasevich case SCTP_CID_AUTH: 6511f485649SVlad Yasevich break; 6521f485649SVlad Yasevich 6531f485649SVlad Yasevich default: 6541f485649SVlad Yasevich if (param->chunks[i] == chunk) 6551f485649SVlad Yasevich found = 1; 6561f485649SVlad Yasevich break; 6571f485649SVlad Yasevich } 6581f485649SVlad Yasevich } 6591f485649SVlad Yasevich 6601f485649SVlad Yasevich return found; 6611f485649SVlad Yasevich } 6621f485649SVlad Yasevich 6631f485649SVlad Yasevich /* Check if peer requested that this chunk is authenticated */ 6641f485649SVlad Yasevich int sctp_auth_send_cid(sctp_cid_t chunk, const struct sctp_association *asoc) 6651f485649SVlad Yasevich { 6661f485649SVlad Yasevich if (!sctp_auth_enable || !asoc || !asoc->peer.auth_capable) 6671f485649SVlad Yasevich return 0; 6681f485649SVlad Yasevich 6691f485649SVlad Yasevich return __sctp_auth_cid(chunk, asoc->peer.peer_chunks); 6701f485649SVlad Yasevich } 6711f485649SVlad Yasevich 6721f485649SVlad Yasevich /* Check if we requested that peer authenticate this chunk. */ 6731f485649SVlad Yasevich int sctp_auth_recv_cid(sctp_cid_t chunk, const struct sctp_association *asoc) 6741f485649SVlad Yasevich { 6751f485649SVlad Yasevich if (!sctp_auth_enable || !asoc) 6761f485649SVlad Yasevich return 0; 6771f485649SVlad Yasevich 6781f485649SVlad Yasevich return __sctp_auth_cid(chunk, 6791f485649SVlad Yasevich (struct sctp_chunks_param *)asoc->c.auth_chunks); 6801f485649SVlad Yasevich } 6811f485649SVlad Yasevich 6821f485649SVlad Yasevich /* SCTP-AUTH: Section 6.2: 6831f485649SVlad Yasevich * The sender MUST calculate the MAC as described in RFC2104 [2] using 6841f485649SVlad Yasevich * the hash function H as described by the MAC Identifier and the shared 6851f485649SVlad Yasevich * association key K based on the endpoint pair shared key described by 6861f485649SVlad Yasevich * the shared key identifier. The 'data' used for the computation of 6871f485649SVlad Yasevich * the AUTH-chunk is given by the AUTH chunk with its HMAC field set to 6881f485649SVlad Yasevich * zero (as shown in Figure 6) followed by all chunks that are placed 6891f485649SVlad Yasevich * after the AUTH chunk in the SCTP packet. 6901f485649SVlad Yasevich */ 6911f485649SVlad Yasevich void sctp_auth_calculate_hmac(const struct sctp_association *asoc, 6921f485649SVlad Yasevich struct sk_buff *skb, 6931f485649SVlad Yasevich struct sctp_auth_chunk *auth, 6941f485649SVlad Yasevich gfp_t gfp) 6951f485649SVlad Yasevich { 6961f485649SVlad Yasevich struct scatterlist sg; 6971f485649SVlad Yasevich struct hash_desc desc; 6981f485649SVlad Yasevich struct sctp_auth_bytes *asoc_key; 6991f485649SVlad Yasevich __u16 key_id, hmac_id; 7001f485649SVlad Yasevich __u8 *digest; 7011f485649SVlad Yasevich unsigned char *end; 7021f485649SVlad Yasevich int free_key = 0; 7031f485649SVlad Yasevich 7041f485649SVlad Yasevich /* Extract the info we need: 7051f485649SVlad Yasevich * - hmac id 7061f485649SVlad Yasevich * - key id 7071f485649SVlad Yasevich */ 7081f485649SVlad Yasevich key_id = ntohs(auth->auth_hdr.shkey_id); 7091f485649SVlad Yasevich hmac_id = ntohs(auth->auth_hdr.hmac_id); 7101f485649SVlad Yasevich 7111f485649SVlad Yasevich if (key_id == asoc->active_key_id) 7121f485649SVlad Yasevich asoc_key = asoc->asoc_shared_key; 7131f485649SVlad Yasevich else { 7141f485649SVlad Yasevich struct sctp_shared_key *ep_key; 7151f485649SVlad Yasevich 7161f485649SVlad Yasevich ep_key = sctp_auth_get_shkey(asoc, key_id); 7171f485649SVlad Yasevich if (!ep_key) 7181f485649SVlad Yasevich return; 7191f485649SVlad Yasevich 7201f485649SVlad Yasevich asoc_key = sctp_auth_asoc_create_secret(asoc, ep_key, gfp); 7211f485649SVlad Yasevich if (!asoc_key) 7221f485649SVlad Yasevich return; 7231f485649SVlad Yasevich 7241f485649SVlad Yasevich free_key = 1; 7251f485649SVlad Yasevich } 7261f485649SVlad Yasevich 7271f485649SVlad Yasevich /* set up scatter list */ 7281f485649SVlad Yasevich end = skb_tail_pointer(skb); 72968e3f5ddSHerbert Xu sg_init_one(&sg, auth, end - (unsigned char *)auth); 7301f485649SVlad Yasevich 7311f485649SVlad Yasevich desc.tfm = asoc->ep->auth_hmacs[hmac_id]; 7321f485649SVlad Yasevich desc.flags = 0; 7331f485649SVlad Yasevich 7341f485649SVlad Yasevich digest = auth->auth_hdr.hmac; 7351f485649SVlad Yasevich if (crypto_hash_setkey(desc.tfm, &asoc_key->data[0], asoc_key->len)) 7361f485649SVlad Yasevich goto free; 7371f485649SVlad Yasevich 7381f485649SVlad Yasevich crypto_hash_digest(&desc, &sg, sg.length, digest); 7391f485649SVlad Yasevich 7401f485649SVlad Yasevich free: 7411f485649SVlad Yasevich if (free_key) 7421f485649SVlad Yasevich sctp_auth_key_put(asoc_key); 7431f485649SVlad Yasevich } 74465b07e5dSVlad Yasevich 74565b07e5dSVlad Yasevich /* API Helpers */ 74665b07e5dSVlad Yasevich 74765b07e5dSVlad Yasevich /* Add a chunk to the endpoint authenticated chunk list */ 74865b07e5dSVlad Yasevich int sctp_auth_ep_add_chunkid(struct sctp_endpoint *ep, __u8 chunk_id) 74965b07e5dSVlad Yasevich { 75065b07e5dSVlad Yasevich struct sctp_chunks_param *p = ep->auth_chunk_list; 75165b07e5dSVlad Yasevich __u16 nchunks; 75265b07e5dSVlad Yasevich __u16 param_len; 75365b07e5dSVlad Yasevich 75465b07e5dSVlad Yasevich /* If this chunk is already specified, we are done */ 75565b07e5dSVlad Yasevich if (__sctp_auth_cid(chunk_id, p)) 75665b07e5dSVlad Yasevich return 0; 75765b07e5dSVlad Yasevich 75865b07e5dSVlad Yasevich /* Check if we can add this chunk to the array */ 75965b07e5dSVlad Yasevich param_len = ntohs(p->param_hdr.length); 76065b07e5dSVlad Yasevich nchunks = param_len - sizeof(sctp_paramhdr_t); 76165b07e5dSVlad Yasevich if (nchunks == SCTP_NUM_CHUNK_TYPES) 76265b07e5dSVlad Yasevich return -EINVAL; 76365b07e5dSVlad Yasevich 76465b07e5dSVlad Yasevich p->chunks[nchunks] = chunk_id; 76565b07e5dSVlad Yasevich p->param_hdr.length = htons(param_len + 1); 76665b07e5dSVlad Yasevich return 0; 76765b07e5dSVlad Yasevich } 76865b07e5dSVlad Yasevich 76965b07e5dSVlad Yasevich /* Add hmac identifires to the endpoint list of supported hmac ids */ 77065b07e5dSVlad Yasevich int sctp_auth_ep_set_hmacs(struct sctp_endpoint *ep, 77165b07e5dSVlad Yasevich struct sctp_hmacalgo *hmacs) 77265b07e5dSVlad Yasevich { 77365b07e5dSVlad Yasevich int has_sha1 = 0; 77465b07e5dSVlad Yasevich __u16 id; 77565b07e5dSVlad Yasevich int i; 77665b07e5dSVlad Yasevich 77765b07e5dSVlad Yasevich /* Scan the list looking for unsupported id. Also make sure that 77865b07e5dSVlad Yasevich * SHA1 is specified. 77965b07e5dSVlad Yasevich */ 78065b07e5dSVlad Yasevich for (i = 0; i < hmacs->shmac_num_idents; i++) { 78165b07e5dSVlad Yasevich id = hmacs->shmac_idents[i]; 78265b07e5dSVlad Yasevich 78365b07e5dSVlad Yasevich if (SCTP_AUTH_HMAC_ID_SHA1 == id) 78465b07e5dSVlad Yasevich has_sha1 = 1; 78565b07e5dSVlad Yasevich 78665b07e5dSVlad Yasevich if (!sctp_hmac_list[id].hmac_name) 78765b07e5dSVlad Yasevich return -EOPNOTSUPP; 78865b07e5dSVlad Yasevich } 78965b07e5dSVlad Yasevich 79065b07e5dSVlad Yasevich if (!has_sha1) 79165b07e5dSVlad Yasevich return -EINVAL; 79265b07e5dSVlad Yasevich 79365b07e5dSVlad Yasevich memcpy(ep->auth_hmacs_list->hmac_ids, &hmacs->shmac_idents[0], 79465b07e5dSVlad Yasevich hmacs->shmac_num_idents * sizeof(__u16)); 79565b07e5dSVlad Yasevich ep->auth_hmacs_list->param_hdr.length = htons(sizeof(sctp_paramhdr_t) + 79665b07e5dSVlad Yasevich hmacs->shmac_num_idents * sizeof(__u16)); 79765b07e5dSVlad Yasevich return 0; 79865b07e5dSVlad Yasevich } 79965b07e5dSVlad Yasevich 80065b07e5dSVlad Yasevich /* Set a new shared key on either endpoint or association. If the 80165b07e5dSVlad Yasevich * the key with a same ID already exists, replace the key (remove the 80265b07e5dSVlad Yasevich * old key and add a new one). 80365b07e5dSVlad Yasevich */ 80465b07e5dSVlad Yasevich int sctp_auth_set_key(struct sctp_endpoint *ep, 80565b07e5dSVlad Yasevich struct sctp_association *asoc, 80665b07e5dSVlad Yasevich struct sctp_authkey *auth_key) 80765b07e5dSVlad Yasevich { 80865b07e5dSVlad Yasevich struct sctp_shared_key *cur_key = NULL; 80965b07e5dSVlad Yasevich struct sctp_auth_bytes *key; 81065b07e5dSVlad Yasevich struct list_head *sh_keys; 81165b07e5dSVlad Yasevich int replace = 0; 81265b07e5dSVlad Yasevich 81365b07e5dSVlad Yasevich /* Try to find the given key id to see if 81465b07e5dSVlad Yasevich * we are doing a replace, or adding a new key 81565b07e5dSVlad Yasevich */ 81665b07e5dSVlad Yasevich if (asoc) 81765b07e5dSVlad Yasevich sh_keys = &asoc->endpoint_shared_keys; 81865b07e5dSVlad Yasevich else 81965b07e5dSVlad Yasevich sh_keys = &ep->endpoint_shared_keys; 82065b07e5dSVlad Yasevich 82165b07e5dSVlad Yasevich key_for_each(cur_key, sh_keys) { 82265b07e5dSVlad Yasevich if (cur_key->key_id == auth_key->sca_keynumber) { 82365b07e5dSVlad Yasevich replace = 1; 82465b07e5dSVlad Yasevich break; 82565b07e5dSVlad Yasevich } 82665b07e5dSVlad Yasevich } 82765b07e5dSVlad Yasevich 82865b07e5dSVlad Yasevich /* If we are not replacing a key id, we need to allocate 82965b07e5dSVlad Yasevich * a shared key. 83065b07e5dSVlad Yasevich */ 83165b07e5dSVlad Yasevich if (!replace) { 83265b07e5dSVlad Yasevich cur_key = sctp_auth_shkey_create(auth_key->sca_keynumber, 83365b07e5dSVlad Yasevich GFP_KERNEL); 83465b07e5dSVlad Yasevich if (!cur_key) 83565b07e5dSVlad Yasevich return -ENOMEM; 83665b07e5dSVlad Yasevich } 83765b07e5dSVlad Yasevich 83865b07e5dSVlad Yasevich /* Create a new key data based on the info passed in */ 83965b07e5dSVlad Yasevich key = sctp_auth_create_key(auth_key->sca_keylen, GFP_KERNEL); 84065b07e5dSVlad Yasevich if (!key) 84165b07e5dSVlad Yasevich goto nomem; 84265b07e5dSVlad Yasevich 84365b07e5dSVlad Yasevich memcpy(key->data, &auth_key->sca_key[0], auth_key->sca_keylen); 84465b07e5dSVlad Yasevich 84565b07e5dSVlad Yasevich /* If we are replacing, remove the old keys data from the 84665b07e5dSVlad Yasevich * key id. If we are adding new key id, add it to the 84765b07e5dSVlad Yasevich * list. 84865b07e5dSVlad Yasevich */ 84965b07e5dSVlad Yasevich if (replace) 85065b07e5dSVlad Yasevich sctp_auth_key_put(cur_key->key); 85165b07e5dSVlad Yasevich else 85265b07e5dSVlad Yasevich list_add(&cur_key->key_list, sh_keys); 85365b07e5dSVlad Yasevich 85465b07e5dSVlad Yasevich cur_key->key = key; 85565b07e5dSVlad Yasevich sctp_auth_key_hold(key); 85665b07e5dSVlad Yasevich 85765b07e5dSVlad Yasevich return 0; 85865b07e5dSVlad Yasevich nomem: 85965b07e5dSVlad Yasevich if (!replace) 86065b07e5dSVlad Yasevich sctp_auth_shkey_free(cur_key); 86165b07e5dSVlad Yasevich 86265b07e5dSVlad Yasevich return -ENOMEM; 86365b07e5dSVlad Yasevich } 86465b07e5dSVlad Yasevich 86565b07e5dSVlad Yasevich int sctp_auth_set_active_key(struct sctp_endpoint *ep, 86665b07e5dSVlad Yasevich struct sctp_association *asoc, 86765b07e5dSVlad Yasevich __u16 key_id) 86865b07e5dSVlad Yasevich { 86965b07e5dSVlad Yasevich struct sctp_shared_key *key; 87065b07e5dSVlad Yasevich struct list_head *sh_keys; 87165b07e5dSVlad Yasevich int found = 0; 87265b07e5dSVlad Yasevich 87365b07e5dSVlad Yasevich /* The key identifier MUST correst to an existing key */ 87465b07e5dSVlad Yasevich if (asoc) 87565b07e5dSVlad Yasevich sh_keys = &asoc->endpoint_shared_keys; 87665b07e5dSVlad Yasevich else 87765b07e5dSVlad Yasevich sh_keys = &ep->endpoint_shared_keys; 87865b07e5dSVlad Yasevich 87965b07e5dSVlad Yasevich key_for_each(key, sh_keys) { 88065b07e5dSVlad Yasevich if (key->key_id == key_id) { 88165b07e5dSVlad Yasevich found = 1; 88265b07e5dSVlad Yasevich break; 88365b07e5dSVlad Yasevich } 88465b07e5dSVlad Yasevich } 88565b07e5dSVlad Yasevich 88665b07e5dSVlad Yasevich if (!found) 88765b07e5dSVlad Yasevich return -EINVAL; 88865b07e5dSVlad Yasevich 88965b07e5dSVlad Yasevich if (asoc) { 89065b07e5dSVlad Yasevich asoc->active_key_id = key_id; 89165b07e5dSVlad Yasevich sctp_auth_asoc_init_active_key(asoc, GFP_KERNEL); 89265b07e5dSVlad Yasevich } else 89365b07e5dSVlad Yasevich ep->active_key_id = key_id; 89465b07e5dSVlad Yasevich 89565b07e5dSVlad Yasevich return 0; 89665b07e5dSVlad Yasevich } 89765b07e5dSVlad Yasevich 89865b07e5dSVlad Yasevich int sctp_auth_del_key_id(struct sctp_endpoint *ep, 89965b07e5dSVlad Yasevich struct sctp_association *asoc, 90065b07e5dSVlad Yasevich __u16 key_id) 90165b07e5dSVlad Yasevich { 90265b07e5dSVlad Yasevich struct sctp_shared_key *key; 90365b07e5dSVlad Yasevich struct list_head *sh_keys; 90465b07e5dSVlad Yasevich int found = 0; 90565b07e5dSVlad Yasevich 90665b07e5dSVlad Yasevich /* The key identifier MUST NOT be the current active key 90765b07e5dSVlad Yasevich * The key identifier MUST correst to an existing key 90865b07e5dSVlad Yasevich */ 90965b07e5dSVlad Yasevich if (asoc) { 91065b07e5dSVlad Yasevich if (asoc->active_key_id == key_id) 91165b07e5dSVlad Yasevich return -EINVAL; 91265b07e5dSVlad Yasevich 91365b07e5dSVlad Yasevich sh_keys = &asoc->endpoint_shared_keys; 91465b07e5dSVlad Yasevich } else { 91565b07e5dSVlad Yasevich if (ep->active_key_id == key_id) 91665b07e5dSVlad Yasevich return -EINVAL; 91765b07e5dSVlad Yasevich 91865b07e5dSVlad Yasevich sh_keys = &ep->endpoint_shared_keys; 91965b07e5dSVlad Yasevich } 92065b07e5dSVlad Yasevich 92165b07e5dSVlad Yasevich key_for_each(key, sh_keys) { 92265b07e5dSVlad Yasevich if (key->key_id == key_id) { 92365b07e5dSVlad Yasevich found = 1; 92465b07e5dSVlad Yasevich break; 92565b07e5dSVlad Yasevich } 92665b07e5dSVlad Yasevich } 92765b07e5dSVlad Yasevich 92865b07e5dSVlad Yasevich if (!found) 92965b07e5dSVlad Yasevich return -EINVAL; 93065b07e5dSVlad Yasevich 93165b07e5dSVlad Yasevich /* Delete the shared key */ 93265b07e5dSVlad Yasevich list_del_init(&key->key_list); 93365b07e5dSVlad Yasevich sctp_auth_shkey_free(key); 93465b07e5dSVlad Yasevich 93565b07e5dSVlad Yasevich return 0; 93665b07e5dSVlad Yasevich } 937