⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 auth.c

📁 在linux环境下的流控制传输协议(sctp)的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* SCTP kernel implementation * (C) Copyright 2007 Hewlett-Packard Development Company, L.P. * * This file is part of the SCTP kernel implementation * * This SCTP implementation is free software; * you can redistribute it and/or modify it under the terms of * the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This SCTP implementation is distributed in the hope that it * will be useful, but WITHOUT ANY WARRANTY; without even the implied *                 ************************ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU CC; see the file COPYING.  If not, write to * the Free Software Foundation, 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * Please send any bug reports or fixes you make to the * email address(es): *    lksctp developers <lksctp-developers@lists.sourceforge.net> * * Or submit a bug report through the following website: *    http://www.sf.net/projects/lksctp * * Written or modified by: *   Vlad Yasevich     <vladislav.yasevich@hp.com> * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. */#include <linux/types.h>#include <linux/crypto.h>#include <linux/scatterlist.h>#include <net/sctp/sctp.h>#include <net/sctp/auth.h>static struct sctp_hmac sctp_hmac_list[SCTP_AUTH_NUM_HMACS] = {	{		/* id 0 is reserved.  as all 0 */		.hmac_id = SCTP_AUTH_HMAC_ID_RESERVED_0,	},	{		.hmac_id = SCTP_AUTH_HMAC_ID_SHA1,		.hmac_name="hmac(sha1)",		.hmac_len = SCTP_SHA1_SIG_SIZE,	},	{		/* id 2 is reserved as well */		.hmac_id = SCTP_AUTH_HMAC_ID_RESERVED_2,	},#if defined (CONFIG_CRYPTO_SHA256) || defined (CONFIG_CRYPTO_SHA256_MODULE)	{		.hmac_id = SCTP_AUTH_HMAC_ID_SHA256,		.hmac_name="hmac(sha256)",		.hmac_len = SCTP_SHA256_SIG_SIZE,	}#endif};void sctp_auth_key_put(struct sctp_auth_bytes *key){	if (!key)		return;	if (atomic_dec_and_test(&key->refcnt)) {		kfree(key);		SCTP_DBG_OBJCNT_DEC(keys);	}}/* Create a new key structure of a given length */static struct sctp_auth_bytes *sctp_auth_create_key(__u32 key_len, gfp_t gfp){	struct sctp_auth_bytes *key;	/* Allocate the shared key */	key = kmalloc(sizeof(struct sctp_auth_bytes) + key_len, gfp);	if (!key)		return NULL;	key->len = key_len;	atomic_set(&key->refcnt, 1);	SCTP_DBG_OBJCNT_INC(keys);	return key;}/* Create a new shared key container with a give key id */struct sctp_shared_key *sctp_auth_shkey_create(__u16 key_id, gfp_t gfp){	struct sctp_shared_key *new;	/* Allocate the shared key container */	new = kzalloc(sizeof(struct sctp_shared_key), gfp);	if (!new)		return NULL;	INIT_LIST_HEAD(&new->key_list);	new->key_id = key_id;	return new;}/* Free the shared key stucture */static void sctp_auth_shkey_free(struct sctp_shared_key *sh_key){	BUG_ON(!list_empty(&sh_key->key_list));	sctp_auth_key_put(sh_key->key);	sh_key->key = NULL;	kfree(sh_key);}/* Destory the entire key list.  This is done during the * associon and endpoint free process. */void sctp_auth_destroy_keys(struct list_head *keys){	struct sctp_shared_key *ep_key;	struct sctp_shared_key *tmp;	if (list_empty(keys))		return;	key_for_each_safe(ep_key, tmp, keys) {		list_del_init(&ep_key->key_list);		sctp_auth_shkey_free(ep_key);	}}/* Compare two byte vectors as numbers.  Return values * are: * 	  0 - vectors are equal * 	< 0 - vector 1 is smaller then vector2 * 	> 0 - vector 1 is greater then vector2 * * Algorithm is: * 	This is performed by selecting the numerically smaller key vector... *	If the key vectors are equal as numbers but differ in length ... *	the shorter vector is considered smaller * * Examples (with small values): * 	000123456789 > 123456789 (first number is longer) * 	000123456789 < 234567891 (second number is larger numerically) * 	123456789 > 2345678 	 (first number is both larger & longer) */static int sctp_auth_compare_vectors(struct sctp_auth_bytes *vector1,			      struct sctp_auth_bytes *vector2){	int diff;	int i;	const __u8 *longer;	diff = vector1->len - vector2->len;	if (diff) {		longer = (diff > 0) ? vector1->data : vector2->data;		/* Check to see if the longer number is		 * lead-zero padded.  If it is not, it		 * is automatically larger numerically.		 */		for (i = 0; i < abs(diff); i++ ) {			if (longer[i] != 0)				return diff;		}	}	/* lengths are the same, compare numbers */	return memcmp(vector1->data, vector2->data, vector1->len);}/* * Create a key vector as described in SCTP-AUTH, Section 6.1 *    The RANDOM parameter, the CHUNKS parameter and the HMAC-ALGO *    parameter sent by each endpoint are concatenated as byte vectors. *    These parameters include the parameter type, parameter length, and *    the parameter value, but padding is omitted; all padding MUST be *    removed from this concatenation before proceeding with further *    computation of keys.  Parameters which were not sent are simply *    omitted from the concatenation process.  The resulting two vectors *    are called the two key vectors. */static struct sctp_auth_bytes *sctp_auth_make_key_vector(			sctp_random_param_t *random,			sctp_chunks_param_t *chunks,			sctp_hmac_algo_param_t *hmacs,			gfp_t gfp){	struct sctp_auth_bytes *new;	__u32	len;	__u32	offset = 0;	len = ntohs(random->param_hdr.length) + ntohs(hmacs->param_hdr.length);        if (chunks)		len += ntohs(chunks->param_hdr.length);	new = kmalloc(sizeof(struct sctp_auth_bytes) + len, gfp);	if (!new)		return NULL;	new->len = len;	memcpy(new->data, random, ntohs(random->param_hdr.length));	offset += ntohs(random->param_hdr.length);	if (chunks) {		memcpy(new->data + offset, chunks,			ntohs(chunks->param_hdr.length));		offset += ntohs(chunks->param_hdr.length);	}	memcpy(new->data + offset, hmacs, ntohs(hmacs->param_hdr.length));	return new;}/* Make a key vector based on our local parameters */static struct sctp_auth_bytes *sctp_auth_make_local_vector(				    const struct sctp_association *asoc,				    gfp_t gfp){	return sctp_auth_make_key_vector(				    (sctp_random_param_t*)asoc->c.auth_random,				    (sctp_chunks_param_t*)asoc->c.auth_chunks,				    (sctp_hmac_algo_param_t*)asoc->c.auth_hmacs,				    gfp);}/* Make a key vector based on peer's parameters */static struct sctp_auth_bytes *sctp_auth_make_peer_vector(				    const struct sctp_association *asoc,				    gfp_t gfp){	return sctp_auth_make_key_vector(asoc->peer.peer_random,					 asoc->peer.peer_chunks,					 asoc->peer.peer_hmacs,					 gfp);}/* Set the value of the association shared key base on the parameters * given.  The algorithm is: *    From the endpoint pair shared keys and the key vectors the *    association shared keys are computed.  This is performed by selecting *    the numerically smaller key vector and concatenating it to the *    endpoint pair shared key, and then concatenating the numerically *    larger key vector to that.  The result of the concatenation is the *    association shared key. */static struct sctp_auth_bytes *sctp_auth_asoc_set_secret(			struct sctp_shared_key *ep_key,			struct sctp_auth_bytes *first_vector,			struct sctp_auth_bytes *last_vector,			gfp_t gfp){	struct sctp_auth_bytes *secret;	__u32 offset = 0;	__u32 auth_len;	auth_len = first_vector->len + last_vector->len;	if (ep_key->key)		auth_len += ep_key->key->len;	secret = sctp_auth_create_key(auth_len, gfp);	if (!secret)		return NULL;	if (ep_key->key) {		memcpy(secret->data, ep_key->key->data, ep_key->key->len);		offset += ep_key->key->len;	}	memcpy(secret->data + offset, first_vector->data, first_vector->len);	offset += first_vector->len;	memcpy(secret->data + offset, last_vector->data, last_vector->len);	return secret;}/* Create an association shared key.  Follow the algorithm * described in SCTP-AUTH, Section 6.1 */static struct sctp_auth_bytes *sctp_auth_asoc_create_secret(				 const struct sctp_association *asoc,				 struct sctp_shared_key *ep_key,				 gfp_t gfp){	struct sctp_auth_bytes *local_key_vector;	struct sctp_auth_bytes *peer_key_vector;	struct sctp_auth_bytes	*first_vector,				*last_vector;	struct sctp_auth_bytes	*secret = NULL;	int	cmp;	/* Now we need to build the key vectors	 * SCTP-AUTH , Section 6.1	 *    The RANDOM parameter, the CHUNKS parameter and the HMAC-ALGO	 *    parameter sent by each endpoint are concatenated as byte vectors.	 *    These parameters include the parameter type, parameter length, and	 *    the parameter value, but padding is omitted; all padding MUST be	 *    removed from this concatenation before proceeding with further	 *    computation of keys.  Parameters which were not sent are simply	 *    omitted from the concatenation process.  The resulting two vectors	 *    are called the two key vectors.	 */	local_key_vector = sctp_auth_make_local_vector(asoc, gfp);	peer_key_vector = sctp_auth_make_peer_vector(asoc, gfp);	if (!peer_key_vector || !local_key_vector)		goto out;	/* Figure out the order in wich the key_vectors will be	 * added to the endpoint shared key.	 * SCTP-AUTH, Section 6.1:	 *   This is performed by selecting the numerically smaller key	 *   vector and concatenating it to the endpoint pair shared	 *   key, and then concatenating the numerically larger key	 *   vector to that.  If the key vectors are equal as numbers	 *   but differ in length, then the concatenation order is the	 *   endpoint shared key, followed by the shorter key vector,	 *   followed by the longer key vector.  Otherwise, the key	 *   vectors are identical, and may be concatenated to the	 *   endpoint pair key in any order.	 */	cmp = sctp_auth_compare_vectors(local_key_vector,					peer_key_vector);	if (cmp < 0) {		first_vector = local_key_vector;		last_vector = peer_key_vector;	} else {		first_vector = peer_key_vector;		last_vector = local_key_vector;	}	secret = sctp_auth_asoc_set_secret(ep_key, first_vector, last_vector,					    gfp);out:	kfree(local_key_vector);	kfree(peer_key_vector);	return secret;}/* * Populate the association overlay list with the list * from the endpoint. */int sctp_auth_asoc_copy_shkeys(const struct sctp_endpoint *ep,				struct sctp_association *asoc,				gfp_t gfp){	struct sctp_shared_key *sh_key;	struct sctp_shared_key *new;	BUG_ON(!list_empty(&asoc->endpoint_shared_keys));	key_for_each(sh_key, &ep->endpoint_shared_keys) {		new = sctp_auth_shkey_create(sh_key->key_id, gfp);		if (!new)			goto nomem;		new->key = sh_key->key;		sctp_auth_key_hold(new->key);		list_add(&new->key_list, &asoc->endpoint_shared_keys);	}	return 0;nomem:	sctp_auth_destroy_keys(&asoc->endpoint_shared_keys);	return -ENOMEM;}/* Public interface to creat the association shared key. * See code above for the algorithm. */int sctp_auth_asoc_init_active_key(struct sctp_association *asoc, gfp_t gfp){	struct sctp_auth_bytes	*secret;	struct sctp_shared_key *ep_key;	/* If we don't support AUTH, or peer is not capable	 * we don't need to do anything.	 */	if (!sctp_auth_enable || !asoc->peer.auth_capable)		return 0;	/* If the key_id is non-zero and we couldn't find an	 * endpoint pair shared key, we can't compute the	 * secret.	 * For key_id 0, endpoint pair shared key is a NULL key.	 */	ep_key = sctp_auth_get_shkey(asoc, asoc->active_key_id);	BUG_ON(!ep_key);	secret = sctp_auth_asoc_create_secret(asoc, ep_key, gfp);	if (!secret)		return -ENOMEM;	sctp_auth_key_put(asoc->asoc_shared_key);	asoc->asoc_shared_key = secret;	return 0;}/* Find the endpoint pair shared key based on the key_id */struct sctp_shared_key *sctp_auth_get_shkey(				const struct sctp_association *asoc,				__u16 key_id){	struct sctp_shared_key *key;	/* First search associations set of endpoint pair shared keys */	key_for_each(key, &asoc->endpoint_shared_keys) {		if (key->key_id == key_id)			return key;	}	return NULL;}/* * Initialize all the possible digest transforms that we can use.  Right now * now, the supported digests are SHA1 and SHA256.  We do this here once * because of the restrictiong that transforms may only be allocated in * user context.  This forces us to pre-allocated all possible transforms * at the endpoint init time. */int sctp_auth_init_hmacs(struct sctp_endpoint *ep, gfp_t gfp){	struct crypto_hash *tfm = NULL;	__u16   id;	/* if the transforms are already allocted, we are done */	if (!sctp_auth_enable) {		ep->auth_hmacs = NULL;		return 0;	}	if (ep->auth_hmacs)		return 0;	/* Allocated the array of pointers to transorms */	ep->auth_hmacs = kzalloc(			    sizeof(struct crypto_hash *) * SCTP_AUTH_NUM_HMACS,			    gfp);	if (!ep->auth_hmacs)		return -ENOMEM;	for (id = 0; id < SCTP_AUTH_NUM_HMACS; id++) {		/* See is we support the id.  Supported IDs have name and		 * length fields set, so that we can allocated and use		 * them.  We can safely just check for name, for without the		 * name, we can't allocate the TFM.		 */		if (!sctp_hmac_list[id].hmac_name)			continue;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -