Exemple #1
0
int sadb_msg_send_acquire(struct ipsec_sa *sa)
{
	int i=0, error = 0;
	uint  comb_num = 0;
	struct sadb_comb combs[4];
	struct digest_implementation *di = NULL;
	struct cipher_implementation *ci = NULL;
	struct sadb_msg *msg = NULL;
	struct sadb_ext *ext_msgs[SADB_EXT_MAX+1];
	struct socket_list *pfkey_socketsp = NULL;

	memset(ext_msgs, 0, sizeof(ext_msgs));
	memset(combs, 0, sizeof(combs));

	if (sa->ipsec_proto == SADB_SATYPE_AH || sa->ipsec_proto == SADB_SATYPE_ESP) {
		di = find_digest_by_name("md5", 0 /* atomic */);
		if (di) {
			combs[comb_num].sadb_comb_auth = SADB_AALG_MD5HMAC;
			combs[comb_num].sadb_comb_auth_minbits = AUTH_MD5HMAC_KEY_BITS;
			combs[comb_num].sadb_comb_auth_maxbits = AUTH_MD5HMAC_KEY_BITS;
			combs[comb_num].sadb_comb_reserved = 0;
			combs[comb_num].sadb_comb_soft_allocations = 0;
			combs[comb_num].sadb_comb_hard_allocations = 0;
			combs[comb_num].sadb_comb_soft_bytes = 0;
			combs[comb_num].sadb_comb_hard_bytes = 0;
			combs[comb_num].sadb_comb_soft_addtime = 57600;
			combs[comb_num].sadb_comb_hard_addtime = 86400;
			combs[comb_num].sadb_comb_soft_usetime = 57600;
			combs[comb_num].sadb_comb_hard_usetime = 86400;
			comb_num++;
			di = NULL;	
		}
	
		di = find_digest_by_name("sha1", 0 /* atomic */);
		if (di) {
			combs[comb_num].sadb_comb_auth = SADB_AALG_SHA1HMAC;
			combs[comb_num].sadb_comb_auth_minbits = AUTH_SHA1HMAC_KEY_BITS;
			combs[comb_num].sadb_comb_auth_maxbits = AUTH_SHA1HMAC_KEY_BITS;
			combs[comb_num].sadb_comb_reserved = 0;
			combs[comb_num].sadb_comb_soft_allocations = 0;
			combs[comb_num].sadb_comb_hard_allocations = 0;
			combs[comb_num].sadb_comb_soft_bytes = 0;
			combs[comb_num].sadb_comb_hard_bytes = 0;
			combs[comb_num].sadb_comb_soft_addtime = 57600;
			combs[comb_num].sadb_comb_hard_addtime = 86400;
			combs[comb_num].sadb_comb_soft_usetime = 57600;
			combs[comb_num].sadb_comb_hard_usetime = 86400;
			comb_num++;
			di = NULL;
		}
	}

	if (sa->ipsec_proto == SADB_SATYPE_ESP) {
		ci = find_cipher_by_name("des-cbc", 1 /* atomic */);
		if (ci) {
			combs[comb_num].sadb_comb_encrypt = SADB_EALG_DESCBC;
			combs[comb_num].sadb_comb_encrypt_minbits = ESP_DES_KEY_BITS;
			combs[comb_num].sadb_comb_encrypt_maxbits = ESP_DES_KEY_BITS;
			combs[comb_num].sadb_comb_reserved = 0;
			combs[comb_num].sadb_comb_soft_allocations = 0;
			combs[comb_num].sadb_comb_hard_allocations = 0;
			combs[comb_num].sadb_comb_soft_bytes = 0;
			combs[comb_num].sadb_comb_hard_bytes = 0;
			combs[comb_num].sadb_comb_soft_addtime = 57600;
			combs[comb_num].sadb_comb_hard_addtime = 86400;
			combs[comb_num].sadb_comb_soft_usetime = 57600;
			combs[comb_num].sadb_comb_hard_usetime = 86400;
			comb_num++;
			ci = NULL;
		}

		ci = find_cipher_by_name("des_ede3-cbc", 1 /* atomic */);
		if (ci) {
			combs[comb_num].sadb_comb_encrypt = SADB_EALG_3DESCBC;
			combs[comb_num].sadb_comb_encrypt_minbits = ESP_3DES_KEY_BITS;
			combs[comb_num].sadb_comb_encrypt_maxbits = ESP_3DES_KEY_BITS;
			combs[comb_num].sadb_comb_reserved = 0;
			combs[comb_num].sadb_comb_soft_allocations = 0;
			combs[comb_num].sadb_comb_hard_allocations = 0;
			combs[comb_num].sadb_comb_soft_bytes = 0;
			combs[comb_num].sadb_comb_hard_bytes = 0;
			combs[comb_num].sadb_comb_soft_addtime = 57600;
			combs[comb_num].sadb_comb_hard_addtime = 86400;
			combs[comb_num].sadb_comb_soft_usetime = 57600;
			combs[comb_num].sadb_comb_hard_usetime = 86400;
			comb_num++;
			ci = NULL;
		}

		ci = find_cipher_by_name("aes-cbc", 1 /* atomic */);
		if (ci) {
			combs[comb_num].sadb_comb_encrypt = SADB_EALG_AES;
			combs[comb_num].sadb_comb_encrypt_minbits = ESP_AES_KEY_BITS;
			combs[comb_num].sadb_comb_encrypt_maxbits = ESP_AES_KEY_BITS;
			combs[comb_num].sadb_comb_reserved = 0;
			combs[comb_num].sadb_comb_soft_allocations = 0;
			combs[comb_num].sadb_comb_hard_allocations = 0;
			combs[comb_num].sadb_comb_soft_bytes = 0;
			combs[comb_num].sadb_comb_hard_bytes = 0;
			combs[comb_num].sadb_comb_soft_addtime = 57600;
			combs[comb_num].sadb_comb_hard_addtime = 86400;
			combs[comb_num].sadb_comb_soft_usetime = 57600;
			combs[comb_num].sadb_comb_hard_usetime = 86400;
			comb_num++;
			ci = NULL;
		}
	}

	error = pfkey_msg_hdr_build(&ext_msgs[0],
				    SADB_ACQUIRE,
				    sa->ipsec_proto,
				    0,
				    0,
				    0);
	if (error) {
		PFKEY_DEBUG("pfkey_msg_hdr_build is failed\n");
		goto free_ext_finish;
	}

	error = pfkey_address_build(&ext_msgs[SADB_EXT_ADDRESS_SRC],
					SADB_EXT_ADDRESS_SRC,
					sa->proto,
					sa->prefixlen_s,
					(struct sockaddr*)&sa->src);
	if (error) goto free_ext_finish;

	error = pfkey_address_build(&ext_msgs[SADB_EXT_ADDRESS_DST],
					SADB_EXT_ADDRESS_DST,
					sa->proto,
					sa->prefixlen_d,
					(struct sockaddr*)&sa->dst);
	if (error) goto free_ext_finish;

	error = pfkey_prop_build(&ext_msgs[SADB_EXT_PROPOSAL],
					64,
					comb_num,
					combs);
	if (error) goto free_ext_finish;


	error = pfkey_msg_build(&msg, ext_msgs, EXT_BITS_OUT);

	write_lock(&pfkey_sk_lock);
	for (pfkey_socketsp = pfkey_registered_sockets[sa->ipsec_proto];
		pfkey_socketsp;
			pfkey_socketsp = pfkey_socketsp->next)
	{
		pfkey_upmsg(pfkey_socketsp->socketp, msg);
	}
	write_unlock(&pfkey_sk_lock);

	kfree(msg);
free_ext_finish:

	for(i=0; i<SADB_MAX+1; i++) {
		if (ext_msgs[i]) {
			kfree(ext_msgs[i]);
		}
	}

	return 0;
}
Exemple #2
0
int sadb_key_to_esp(const __u8 esp_algo, const struct sadb_key* ext_msg, struct ipsec_sa* sa_entry)
{
	int error = 0;
	char *algoname = NULL;
	struct cipher_implementation *ci=NULL;

	if (!sa_entry) {
		PFKEY_DEBUG("sa_entry is null\n");
		error = -EINVAL;
		goto err;
	}

	if (esp_algo != SADB_EALG_NULL && !ext_msg) {
		PFKEY_DEBUG("ext_msg is null\n");
		error = -EINVAL;
		goto err;
	}

	switch (esp_algo) {
	case SADB_EALG_DESCBC:
		algoname = "des-cbc";
		PFKEY_DEBUG("esp algorithm is DES-CBC\n");
		if(ext_msg->sadb_key_bits != ESP_DES_KEY_BITS){
			PFKEY_DEBUG("the key length is not match\n");
			error = -EINVAL;
			goto err;
		} 
		break;
	case SADB_EALG_3DESCBC:
		algoname = "des_ede3-cbc";
		PFKEY_DEBUG("esp algorithm is 3DES-CBC\n");
		if(ext_msg->sadb_key_bits != ESP_3DES_KEY_BITS){
			PFKEY_DEBUG("the key length is not match\n");
			error = -EINVAL;
			goto err;
		}
		break;
	case SADB_EALG_NULL:
		algoname = "null-algo";
		PFKEY_DEBUG("esp algorithm is NULL\n");
		break; 
	case SADB_EALG_AES:
		algoname = "aes-cbc";
		PFKEY_DEBUG("esp algorithm is AES(128-bit)\n");
		if (ext_msg->sadb_key_bits != ESP_AES_KEY_BITS) {
			PFKEY_DEBUG("the key length is no match\n");
			error = -EINVAL;
			goto err;
		}
		break;
	case SADB_EALG_NONE: /* currently not enter */
	default:
		PFKEY_DEBUG("esp_algo is NONE or not supported one\n");
		error = -EINVAL;
		goto err;
	}	

	ci = find_cipher_by_name(algoname, 1);
	if(!ci){
		PFKEY_DEBUG("algorithm %u:%s is not supported\n", esp_algo, algoname);
		error = -EINVAL;
		goto err;
	}
	ci->lock();

	sa_entry->esp_algo.algo = esp_algo;

	if (esp_algo != SADB_EALG_NULL) {
		sa_entry->esp_algo.key_len = (ext_msg->sadb_key_bits)/OCTETBITS;
	} else {
		sa_entry->esp_algo.key_len = 0;
	}

	sa_entry->esp_algo.cx = ci->realloc_context (NULL, ci, sa_entry->esp_algo.key_len);
	if (!sa_entry->esp_algo.cx) {
		ci->unlock();
		error = -EINVAL;
		goto err;
	}
	sa_entry->esp_algo.cx->ci = ci;

	if (esp_algo != SADB_EALG_NULL) {
		sa_entry->esp_algo.key = kmalloc(sa_entry->esp_algo.key_len, GFP_KERNEL);
		if (!sa_entry->esp_algo.key) {
			PFKEY_DEBUG("could not allocate memory for key\n");
			ci->wipe_context(sa_entry->esp_algo.cx);
			ci->free_context(sa_entry->esp_algo.cx);
			ci->unlock();
			error = -ENOMEM;
			goto err;
		}
		memset(sa_entry->esp_algo.key, 0, sa_entry->esp_algo.key_len);
		memcpy(sa_entry->esp_algo.key, ((char*)ext_msg)+sizeof(struct sadb_key), sa_entry->esp_algo.key_len);

		sa_entry->esp_algo.cx->keyinfo = (u32*)kmalloc(ci->key_schedule_size, GFP_KERNEL);
		if (!sa_entry->esp_algo.cx->keyinfo) {
			PFKEY_DEBUG("could not allocate memory for keyinfo\n");
			ci->unlock();
			error = -ENOMEM;
			goto err;
		}

		memset(sa_entry->esp_algo.cx->keyinfo, 0, ci->key_schedule_size);

		error = ci->set_key(sa_entry->esp_algo.cx, ((char*)ext_msg)+sizeof(struct sadb_key), sa_entry->esp_algo.key_len);
		if (error < 0) {
			PFKEY_DEBUG("set_key failed, key is wondered weak \n");
			ci->wipe_context(sa_entry->esp_algo.cx);
			ci->free_context(sa_entry->esp_algo.cx);
			ci->unlock();
			goto err;
		}
	}
err:
	return error;

}
Exemple #3
0
int sadb_msg_register_parse(struct sock *sk, struct sadb_msg *msg, struct sadb_msg **reply)
{
	int error = 0;
	uint  alg_num = 0;
	struct sadb_alg algs[5];
	struct digest_implementation *di = NULL;
	struct cipher_implementation *ci = NULL;
	struct sadb_ext *reply_ext_msgs[SADB_EXT_MAX+1];

	if (!(sk&&msg)) {
		PFKEY_DEBUG("msg or sk is null\n");
		error = -EINVAL;
		PFKEY_DEBUG("msg or *reply is null\n");
		goto err; 	
	}

	error = sadb_msg_sanity_check(msg);
	if (error) {
		goto err;
	}

	memset(reply_ext_msgs, 0, sizeof(reply_ext_msgs));
	memset(algs, 0, sizeof(algs));

	switch (msg->sadb_msg_satype) {

	case SADB_SATYPE_AH:
	case SADB_SATYPE_ESP:
		break;
	case SADB_SATYPE_RSVP:
	case SADB_SATYPE_OSPFV2:
	case SADB_SATYPE_RIPV2:
	case SADB_SATYPE_MIP:
	case SADB_X_SATYPE_IPIP:
	case SADB_X_SATYPE_COMP:
	case SADB_X_SATYPE_INT:

	default:
		error = -EINVAL;
		goto err;
	}

	write_lock(&pfkey_sk_lock);
	/*
	 register a socket with the proper SA type's socket list
	 it will be release in pfkey_release process (file:pfkey_v2.c).
	*/
	error = pfkey_list_insert_socket(sk->socket, &pfkey_registered_sockets[msg->sadb_msg_satype]);
	if (error) {
		goto err;
	}
	write_unlock(&pfkey_sk_lock);

	PFKEY_DEBUG("socket=%p registered, SA type is %d\n", sk->socket, msg->sadb_msg_satype);

	reply_ext_msgs[0] = (struct sadb_ext*)msg;

	if (msg->sadb_msg_satype == SADB_SATYPE_AH || msg->sadb_msg_satype == SADB_SATYPE_ESP) {
		di = find_digest_by_name("md5", 0 /* atomic */);
		if (di) {
			algs[alg_num].sadb_alg_id = SADB_AALG_MD5HMAC;
			algs[alg_num].sadb_alg_ivlen = 0;
			algs[alg_num].sadb_alg_minbits = AUTH_MD5HMAC_KEY_BITS;
			algs[alg_num].sadb_alg_maxbits = AUTH_MD5HMAC_KEY_BITS;
			algs[alg_num].sadb_alg_reserved = 0;
			alg_num++;
			di = NULL;	
		}
	
		di = find_digest_by_name("sha1", 0 /* atomic */);
		if (di) {
			algs[alg_num].sadb_alg_id = SADB_AALG_SHA1HMAC;
			algs[alg_num].sadb_alg_ivlen = 0;
			algs[alg_num].sadb_alg_minbits = AUTH_SHA1HMAC_KEY_BITS;
			algs[alg_num].sadb_alg_maxbits = AUTH_SHA1HMAC_KEY_BITS;
			algs[alg_num].sadb_alg_reserved = 0;
			alg_num++;
			di = NULL;
		}

		if (msg->sadb_msg_satype == SADB_SATYPE_AH) {
			error = pfkey_supported_build(&reply_ext_msgs[SADB_EXT_SUPPORTED_AUTH],
						SADB_EXT_SUPPORTED_AUTH,
						alg_num,
						algs);
			if (error) goto free_ext_finish;
		}

	}

	if (msg->sadb_msg_satype == SADB_SATYPE_ESP) {
		ci = find_cipher_by_name("des-cbc", 1 /* atomic */);
		if (ci) {
			ci->lock();
			algs[alg_num].sadb_alg_id = SADB_EALG_DESCBC;
			algs[alg_num].sadb_alg_ivlen = ci->ivsize;
			algs[alg_num].sadb_alg_minbits = ESP_DES_KEY_BITS;
			algs[alg_num].sadb_alg_maxbits = ESP_DES_KEY_BITS;
			algs[alg_num].sadb_alg_reserved = 0;
			alg_num++;
			ci->unlock();
			ci = NULL;
		}

		ci = find_cipher_by_name("des_ede3-cbc", 1 /* atomic */);
		if (ci) {
			ci->lock();
			algs[alg_num].sadb_alg_id = SADB_EALG_3DESCBC;
			algs[alg_num].sadb_alg_ivlen = ci->ivsize;
			algs[alg_num].sadb_alg_minbits = ESP_3DES_KEY_BITS;
			algs[alg_num].sadb_alg_maxbits = ESP_3DES_KEY_BITS;
			algs[alg_num].sadb_alg_reserved = 0;
			alg_num++;
			ci->unlock();
			ci = NULL;
		}
		ci = find_cipher_by_name("aes-cbc", 1 /* atomic */);
		if (ci) {
			ci->lock();
			algs[alg_num].sadb_alg_id = SADB_EALG_AES;
			algs[alg_num].sadb_alg_ivlen = ci->ivsize;
			algs[alg_num].sadb_alg_minbits = ESP_AES_KEY_BITS;
			algs[alg_num].sadb_alg_maxbits = ESP_AES_KEY_BITS;
			algs[alg_num].sadb_alg_reserved = 0;
			alg_num++;
			ci->unlock();
			ci = NULL;
		}

		error = pfkey_supported_build(&reply_ext_msgs[SADB_EXT_SUPPORTED_ENCRYPT],
						SADB_EXT_SUPPORTED_ENCRYPT,
						alg_num,
						algs);
		if (error) goto free_ext_finish;

	}

	pfkey_msg_build(reply, reply_ext_msgs, EXT_BITS_OUT);

free_ext_finish:

	if (reply_ext_msgs[SADB_EXT_SUPPORTED_AUTH])
		kfree(reply_ext_msgs[SADB_EXT_SUPPORTED_AUTH]);

	if (reply_ext_msgs[SADB_EXT_SUPPORTED_ENCRYPT])
		kfree(reply_ext_msgs[SADB_EXT_SUPPORTED_ENCRYPT]);


err:

	return error;
}
static int
cryptoloop_init (struct loop_device *lo, struct loop_info *info)
{
	struct cryptoloop_context *lx =
	    (struct cryptoloop_context *) lo->key_reserved;
	int err = -EINVAL;
	char cipher[LO_NAME_SIZE];
	struct cipher_implementation *ci;
	struct cipher_context *cx;

	/* encryption breaks for non sector aligned offsets */
	if (info->lo_offset % LOOP_IV_SECTOR_SIZE)
		goto out;

	lx->blocksize = LOOP_IV_SECTOR_SIZE;
	lx->debug = 0;

	strncpy (cipher, info->lo_name, LO_NAME_SIZE);
	cipher[LO_NAME_SIZE - 1] = 0;

	ci = find_cipher_by_name (cipher, 1);
	if (!ci)
		goto out;

	ci->lock ();
	err = -ENOMEM;
	cx = ci->realloc_context (NULL, ci, info->lo_encrypt_key_size);
	if (!cx)
		goto out_ci;
	cx->ci = ci;
	ci->wipe_context (cx);

#if defined(CONFIG_CRYPTOLOOP_ATOMIC)
	if (ci->set_key_atomic (cx, info->lo_encrypt_key,
				info->lo_encrypt_key_size)) {
#else
	if (ci->set_key (cx, info->lo_encrypt_key, info->lo_encrypt_key_size)) {
#endif
		err = -EINVAL;
		goto out_key;
	}
	lo->key_data = cx;
	err = 0;
	goto out;

      out_key:
	ci->wipe_context (cx);
	ci->free_context (cx);
      out_ci:
	ci->unlock ();
      out:
	if (!err) {
		MOD_INC_USE_COUNT;
	}

	return err;
}

static int
cryptoloop_transfer (struct loop_device *lo, int cmd, char *raw_buf,
		     char *loop_buf, int size, loop_iv_t IV)
{
	const struct cryptoloop_context *lx =
	    (struct cryptoloop_context *) lo->key_reserved;
	struct cipher_context *cx = (struct cipher_context *) lo->key_data;
	struct cipher_implementation *ci = cx->ci;
	cipher_trans_proc_iv encdecfunc;
	const int blocksize = lx->blocksize ? lx->blocksize : size;
	char const *in;
	char *out;

	if (cmd == READ) {
#if defined(CONFIG_CRYPTOLOOP_ATOMIC)
		encdecfunc = ci->decrypt_atomic_iv;
#else
		encdecfunc = ci->decrypt_iv;
#endif
		in = raw_buf;
		out = loop_buf;
	} else {
#if defined(CONFIG_CRYPTOLOOP_ATOMIC)
		encdecfunc = ci->encrypt_atomic_iv;
#else
		encdecfunc = ci->encrypt_iv;
#endif
		in = loop_buf;
		out = raw_buf;
	}

#if defined(CONFIG_CRYPTOLOOP_IV_HACK)
	/* contributed by Clemens Fruhwirth
	 *
	 * Expand IV to 512 byte metric 
	 */

	IV *= loop_get_bs(lo) >> LOOP_IV_SECTOR_BITS;

	/* 
	 * Too bad offset information is lost, but we use a dirty
	 * trick to recover it from the raw_buf address (ab)using the
	 * page alignments and the blocksize alignments
	 */

	IV += ((unsigned long) raw_buf & (loop_get_bs (lo)-1)) >> LOOP_IV_SECTOR_BITS;

#endif /* CONFIG_CRYPTOLOOP_IV_HACK */

	/*
	 * scale IV back to custom (iv_)blocksize units
	 */
	
	IV /= blocksize / LOOP_IV_SECTOR_SIZE;

#if defined(CONFIG_CRYPTOLOOP_DEBUG)
	if (lx->debug)
		printk (KERN_DEBUG
			"cryptoloop_transfer: cmd=%d size=%d iv=%ld blksize=%d iv_blksize=%d\n",
			cmd, size, (unsigned long) IV, loop_get_bs (lo),
			blocksize);
#endif /* CONFIG_CRYPTOLOOP_DEBUG */

	/* split up transfer request into blocksize (default = 512) byte data blocks */
	while (size > 0) {
		const int _size = (size > blocksize) ? blocksize : size;
		u32 iv[4] = { 0, };

		if (size < blocksize)
			printk (KERN_WARNING
				"cryptoloop_transfer: block (IV = %ld) smaller than blocksize! (%d < %d)\n",
				(unsigned long) IV, size, blocksize);

		iv[0] = cpu_to_le32 (IV & 0xffffffff);
		encdecfunc (cx, in, out, _size, (u8 *) iv);

		IV++;
		size -= _size;
		in += _size;
		out += _size;
	}

	return 0;
}

static int
cryptoloop_ioctl (struct loop_device *lo, int cmd, unsigned long arg)
{
	struct cryptoloop_context *lx =
	    (struct cryptoloop_context *) lo->key_reserved;
	int err = -EINVAL;
	int arg_int = 0;

	if (get_user (arg_int, (int *) arg))
		return -EFAULT;

	switch (cmd) {
	case CRYPTOLOOP_SET_BLKSIZE:
		printk (KERN_DEBUG
			"cryptoloop: switch to blocksize %d requested\n",
			arg_int);
		if (arg_int >= 0 && (arg_int % LOOP_IV_SECTOR_SIZE == 0)) {
			lx->blocksize = arg_int;
			err = 0;
		}
		break;

	case CRYPTOLOOP_SET_DEBUG:
		printk (KERN_DEBUG "cryptoloop: set debug = %d requested\n",
			arg_int);
		lx->debug = arg_int;
		err = 0;
		break;

	default:
		err = -EINVAL;
		break;
	}

	return err;
}

static int
cryptoloop_release (struct loop_device *lo)
{
	struct cipher_context *cx = (struct cipher_context *) lo->key_data;

	if (cx != NULL) {
		cx->ci->wipe_context (cx);
		cx->ci->unlock ();
		cx->ci->free_context (cx);
		lo->key_data = NULL;
		MOD_DEC_USE_COUNT;
		return 0;
	}

	printk (KERN_ERR "cryptoloop_release(): cx == NULL ????\n");
	return -EINVAL;
}

struct loop_func_table cryptoloop_funcs = {
	number:LO_CRYPT_CRYPTOAPI,
	init:cryptoloop_init,
	ioctl:cryptoloop_ioctl,
	transfer:cryptoloop_transfer,
	release:cryptoloop_release
};