aboutsummaryrefslogtreecommitdiff
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/Kconfig1
-rw-r--r--net/ipv6/ah6.c35
-rw-r--r--net/ipv6/datagram.c2
-rw-r--r--net/ipv6/esp6.c90
-rw-r--r--net/ipv6/icmp.c4
-rw-r--r--net/ipv6/ipcomp6.c25
-rw-r--r--net/ipv6/ipv6_sockglue.c4
-rw-r--r--net/ipv6/raw.c2
8 files changed, 96 insertions, 67 deletions
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index e923d4dea41..0ba06c0c5d3 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -77,6 +77,7 @@ config INET6_ESP
select CRYPTO
select CRYPTO_HMAC
select CRYPTO_MD5
+ select CRYPTO_CBC
select CRYPTO_SHA1
select CRYPTO_DES
---help---
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index 9d4831bd433..00ffa7bc6c9 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -213,7 +213,10 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
ah->spi = x->id.spi;
ah->seq_no = htonl(++x->replay.oseq);
xfrm_aevent_doreplay(x);
- ahp->icv(ahp, skb, ah->auth_data);
+ err = ah_mac_digest(ahp, skb, ah->auth_data);
+ if (err)
+ goto error_free_iph;
+ memcpy(ah->auth_data, ahp->work_icv, ahp->icv_trunc_len);
err = 0;
@@ -251,6 +254,7 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
u16 hdr_len;
u16 ah_hlen;
int nexthdr;
+ int err = -EINVAL;
if (!pskb_may_pull(skb, sizeof(struct ip_auth_hdr)))
goto out;
@@ -292,8 +296,11 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
memset(ah->auth_data, 0, ahp->icv_trunc_len);
skb_push(skb, hdr_len);
- ahp->icv(ahp, skb, ah->auth_data);
- if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) {
+ err = ah_mac_digest(ahp, skb, ah->auth_data);
+ if (err)
+ goto free_out;
+ err = -EINVAL;
+ if (memcmp(ahp->work_icv, auth_data, ahp->icv_trunc_len)) {
LIMIT_NETDEBUG(KERN_WARNING "ipsec ah authentication error\n");
x->stats.integrity_failed++;
goto free_out;
@@ -310,7 +317,7 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
free_out:
kfree(tmp_hdr);
out:
- return -EINVAL;
+ return err;
}
static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
@@ -338,6 +345,7 @@ static int ah6_init_state(struct xfrm_state *x)
{
struct ah_data *ahp = NULL;
struct xfrm_algo_desc *aalg_desc;
+ struct crypto_hash *tfm;
if (!x->aalg)
goto error;
@@ -355,24 +363,27 @@ static int ah6_init_state(struct xfrm_state *x)
ahp->key = x->aalg->alg_key;
ahp->key_len = (x->aalg->alg_key_len+7)/8;
- ahp->tfm = crypto_alloc_tfm(x->aalg->alg_name, 0);
- if (!ahp->tfm)
+ tfm = crypto_alloc_hash(x->aalg->alg_name, 0, CRYPTO_ALG_ASYNC);
+ if (IS_ERR(tfm))
+ goto error;
+
+ ahp->tfm = tfm;
+ if (crypto_hash_setkey(tfm, ahp->key, ahp->key_len))
goto error;
- ahp->icv = ah_hmac_digest;
/*
* Lookup the algorithm description maintained by xfrm_algo,
* verify crypto transform properties, and store information
* we need for AH processing. This lookup cannot fail here
- * after a successful crypto_alloc_tfm().
+ * after a successful crypto_alloc_hash().
*/
aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0);
BUG_ON(!aalg_desc);
if (aalg_desc->uinfo.auth.icv_fullbits/8 !=
- crypto_tfm_alg_digestsize(ahp->tfm)) {
+ crypto_hash_digestsize(tfm)) {
printk(KERN_INFO "AH: %s digestsize %u != %hu\n",
- x->aalg->alg_name, crypto_tfm_alg_digestsize(ahp->tfm),
+ x->aalg->alg_name, crypto_hash_digestsize(tfm),
aalg_desc->uinfo.auth.icv_fullbits/8);
goto error;
}
@@ -396,7 +407,7 @@ static int ah6_init_state(struct xfrm_state *x)
error:
if (ahp) {
kfree(ahp->work_icv);
- crypto_free_tfm(ahp->tfm);
+ crypto_free_hash(ahp->tfm);
kfree(ahp);
}
return -EINVAL;
@@ -411,7 +422,7 @@ static void ah6_destroy(struct xfrm_state *x)
kfree(ahp->work_icv);
ahp->work_icv = NULL;
- crypto_free_tfm(ahp->tfm);
+ crypto_free_hash(ahp->tfm);
ahp->tfm = NULL;
kfree(ahp);
}
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 99a6eb23378..3b55b4c8e2d 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -696,7 +696,7 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
}
tc = *(int *)CMSG_DATA(cmsg);
- if (tc < 0 || tc > 0xff)
+ if (tc < -1 || tc > 0xff)
goto exit_f;
err = 0;
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index a278d5e862f..2ebfd281e72 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -24,6 +24,7 @@
* This file is derived from net/ipv4/esp.c
*/
+#include <linux/err.h>
#include <linux/module.h>
#include <net/ip.h>
#include <net/xfrm.h>
@@ -44,7 +45,8 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
int hdr_len;
struct ipv6hdr *top_iph;
struct ipv6_esp_hdr *esph;
- struct crypto_tfm *tfm;
+ struct crypto_blkcipher *tfm;
+ struct blkcipher_desc desc;
struct esp_data *esp;
struct sk_buff *trailer;
int blksize;
@@ -67,7 +69,9 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
alen = esp->auth.icv_trunc_len;
tfm = esp->conf.tfm;
- blksize = ALIGN(crypto_tfm_alg_blocksize(tfm), 4);
+ desc.tfm = tfm;
+ desc.flags = 0;
+ blksize = ALIGN(crypto_blkcipher_blocksize(tfm), 4);
clen = ALIGN(clen + 2, blksize);
if (esp->conf.padlen)
clen = ALIGN(clen, esp->conf.padlen);
@@ -96,7 +100,7 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
xfrm_aevent_doreplay(x);
if (esp->conf.ivlen)
- crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm));
+ crypto_blkcipher_set_iv(tfm, esp->conf.ivec, esp->conf.ivlen);
do {
struct scatterlist *sg = &esp->sgbuf[0];
@@ -107,24 +111,25 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
goto error;
}
skb_to_sgvec(skb, sg, esph->enc_data+esp->conf.ivlen-skb->data, clen);
- crypto_cipher_encrypt(tfm, sg, sg, clen);
+ err = crypto_blkcipher_encrypt(&desc, sg, sg, clen);
if (unlikely(sg != &esp->sgbuf[0]))
kfree(sg);
} while (0);
+ if (unlikely(err))
+ goto error;
+
if (esp->conf.ivlen) {
- memcpy(esph->enc_data, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm));
- crypto_cipher_get_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm));
+ memcpy(esph->enc_data, esp->conf.ivec, esp->conf.ivlen);
+ crypto_blkcipher_get_iv(tfm, esp->conf.ivec, esp->conf.ivlen);
}
if (esp->auth.icv_full_len) {
- esp->auth.icv(esp, skb, (u8*)esph-skb->data,
- sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen+clen, trailer->tail);
- pskb_put(skb, trailer, alen);
+ err = esp_mac_digest(esp, skb, (u8 *)esph - skb->data,
+ sizeof(*esph) + esp->conf.ivlen + clen);
+ memcpy(pskb_put(skb, trailer, alen), esp->auth.work_icv, alen);
}
- err = 0;
-
error:
return err;
}
@@ -134,8 +139,10 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
struct ipv6hdr *iph;
struct ipv6_esp_hdr *esph;
struct esp_data *esp = x->data;
+ struct crypto_blkcipher *tfm = esp->conf.tfm;
+ struct blkcipher_desc desc = { .tfm = tfm };
struct sk_buff *trailer;
- int blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4);
+ int blksize = ALIGN(crypto_blkcipher_blocksize(tfm), 4);
int alen = esp->auth.icv_trunc_len;
int elen = skb->len - sizeof(struct ipv6_esp_hdr) - esp->conf.ivlen - alen;
@@ -155,15 +162,16 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
/* If integrity check is required, do this. */
if (esp->auth.icv_full_len) {
- u8 sum[esp->auth.icv_full_len];
- u8 sum1[alen];
+ u8 sum[alen];
- esp->auth.icv(esp, skb, 0, skb->len-alen, sum);
+ ret = esp_mac_digest(esp, skb, 0, skb->len - alen);
+ if (ret)
+ goto out;
- if (skb_copy_bits(skb, skb->len-alen, sum1, alen))
+ if (skb_copy_bits(skb, skb->len - alen, sum, alen))
BUG();
- if (unlikely(memcmp(sum, sum1, alen))) {
+ if (unlikely(memcmp(esp->auth.work_icv, sum, alen))) {
x->stats.integrity_failed++;
ret = -EINVAL;
goto out;
@@ -182,7 +190,7 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
/* Get ivec. This can be wrong, check against another impls. */
if (esp->conf.ivlen)
- crypto_cipher_set_iv(esp->conf.tfm, esph->enc_data, crypto_tfm_alg_ivsize(esp->conf.tfm));
+ crypto_blkcipher_set_iv(tfm, esph->enc_data, esp->conf.ivlen);
{
u8 nexthdr[2];
@@ -197,9 +205,11 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
}
}
skb_to_sgvec(skb, sg, sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen, elen);
- crypto_cipher_decrypt(esp->conf.tfm, sg, sg, elen);
+ ret = crypto_blkcipher_decrypt(&desc, sg, sg, elen);
if (unlikely(sg != &esp->sgbuf[0]))
kfree(sg);
+ if (unlikely(ret))
+ goto out;
if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2))
BUG();
@@ -225,7 +235,7 @@ out:
static u32 esp6_get_max_size(struct xfrm_state *x, int mtu)
{
struct esp_data *esp = x->data;
- u32 blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4);
+ u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4);
if (x->props.mode) {
mtu = ALIGN(mtu + 2, blksize);
@@ -266,11 +276,11 @@ static void esp6_destroy(struct xfrm_state *x)
if (!esp)
return;
- crypto_free_tfm(esp->conf.tfm);
+ crypto_free_blkcipher(esp->conf.tfm);
esp->conf.tfm = NULL;
kfree(esp->conf.ivec);
esp->conf.ivec = NULL;
- crypto_free_tfm(esp->auth.tfm);
+ crypto_free_hash(esp->auth.tfm);
esp->auth.tfm = NULL;
kfree(esp->auth.work_icv);
esp->auth.work_icv = NULL;
@@ -280,6 +290,7 @@ static void esp6_destroy(struct xfrm_state *x)
static int esp6_init_state(struct xfrm_state *x)
{
struct esp_data *esp = NULL;
+ struct crypto_blkcipher *tfm;
/* null auth and encryption can have zero length keys */
if (x->aalg) {
@@ -298,24 +309,29 @@ static int esp6_init_state(struct xfrm_state *x)
if (x->aalg) {
struct xfrm_algo_desc *aalg_desc;
+ struct crypto_hash *hash;
esp->auth.key = x->aalg->alg_key;
esp->auth.key_len = (x->aalg->alg_key_len+7)/8;
- esp->auth.tfm = crypto_alloc_tfm(x->aalg->alg_name, 0);
- if (esp->auth.tfm == NULL)
+ hash = crypto_alloc_hash(x->aalg->alg_name, 0,
+ CRYPTO_ALG_ASYNC);
+ if (IS_ERR(hash))
+ goto error;
+
+ esp->auth.tfm = hash;
+ if (crypto_hash_setkey(hash, esp->auth.key, esp->auth.key_len))
goto error;
- esp->auth.icv = esp_hmac_digest;
aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0);
BUG_ON(!aalg_desc);
if (aalg_desc->uinfo.auth.icv_fullbits/8 !=
- crypto_tfm_alg_digestsize(esp->auth.tfm)) {
- printk(KERN_INFO "ESP: %s digestsize %u != %hu\n",
- x->aalg->alg_name,
- crypto_tfm_alg_digestsize(esp->auth.tfm),
- aalg_desc->uinfo.auth.icv_fullbits/8);
- goto error;
+ crypto_hash_digestsize(hash)) {
+ NETDEBUG(KERN_INFO "ESP: %s digestsize %u != %hu\n",
+ x->aalg->alg_name,
+ crypto_hash_digestsize(hash),
+ aalg_desc->uinfo.auth.icv_fullbits/8);
+ goto error;
}
esp->auth.icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8;
@@ -327,13 +343,11 @@ static int esp6_init_state(struct xfrm_state *x)
}
esp->conf.key = x->ealg->alg_key;
esp->conf.key_len = (x->ealg->alg_key_len+7)/8;
- if (x->props.ealgo == SADB_EALG_NULL)
- esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_ECB);
- else
- esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_CBC);
- if (esp->conf.tfm == NULL)
+ tfm = crypto_alloc_blkcipher(x->ealg->alg_name, 0, CRYPTO_ALG_ASYNC);
+ if (IS_ERR(tfm))
goto error;
- esp->conf.ivlen = crypto_tfm_alg_ivsize(esp->conf.tfm);
+ esp->conf.tfm = tfm;
+ esp->conf.ivlen = crypto_blkcipher_ivsize(tfm);
esp->conf.padlen = 0;
if (esp->conf.ivlen) {
esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL);
@@ -341,7 +355,7 @@ static int esp6_init_state(struct xfrm_state *x)
goto error;
get_random_bytes(esp->conf.ivec, esp->conf.ivlen);
}
- if (crypto_cipher_setkey(esp->conf.tfm, esp->conf.key, esp->conf.key_len))
+ if (crypto_blkcipher_setkey(tfm, esp->conf.key, esp->conf.key_len))
goto error;
x->props.header_len = sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen;
if (x->props.mode)
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 3d6e9a35115..356a8a7ef22 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -401,7 +401,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
if (hlimit < 0)
hlimit = ipv6_get_hoplimit(dst->dev);
- tclass = np->cork.tclass;
+ tclass = np->tclass;
if (tclass < 0)
tclass = 0;
@@ -497,7 +497,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
if (hlimit < 0)
hlimit = ipv6_get_hoplimit(dst->dev);
- tclass = np->cork.tclass;
+ tclass = np->tclass;
if (tclass < 0)
tclass = 0;
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index 7e4d1c17bfb..a81e9e9d93b 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -53,7 +53,7 @@
struct ipcomp6_tfms {
struct list_head list;
- struct crypto_tfm **tfms;
+ struct crypto_comp **tfms;
int users;
};
@@ -70,7 +70,7 @@ static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb)
int plen, dlen;
struct ipcomp_data *ipcd = x->data;
u8 *start, *scratch;
- struct crypto_tfm *tfm;
+ struct crypto_comp *tfm;
int cpu;
if (skb_linearize_cow(skb))
@@ -129,7 +129,7 @@ static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb)
struct ipcomp_data *ipcd = x->data;
int plen, dlen;
u8 *start, *scratch;
- struct crypto_tfm *tfm;
+ struct crypto_comp *tfm;
int cpu;
hdr_len = skb->h.raw - skb->data;
@@ -301,7 +301,7 @@ static void **ipcomp6_alloc_scratches(void)
return scratches;
}
-static void ipcomp6_free_tfms(struct crypto_tfm **tfms)
+static void ipcomp6_free_tfms(struct crypto_comp **tfms)
{
struct ipcomp6_tfms *pos;
int cpu;
@@ -323,28 +323,28 @@ static void ipcomp6_free_tfms(struct crypto_tfm **tfms)
return;
for_each_possible_cpu(cpu) {
- struct crypto_tfm *tfm = *per_cpu_ptr(tfms, cpu);
- crypto_free_tfm(tfm);
+ struct crypto_comp *tfm = *per_cpu_ptr(tfms, cpu);
+ crypto_free_comp(tfm);
}
free_percpu(tfms);
}
-static struct crypto_tfm **ipcomp6_alloc_tfms(const char *alg_name)
+static struct crypto_comp **ipcomp6_alloc_tfms(const char *alg_name)
{
struct ipcomp6_tfms *pos;
- struct crypto_tfm **tfms;
+ struct crypto_comp **tfms;
int cpu;
/* This can be any valid CPU ID so we don't need locking. */
cpu = raw_smp_processor_id();
list_for_each_entry(pos, &ipcomp6_tfms_list, list) {
- struct crypto_tfm *tfm;
+ struct crypto_comp *tfm;
tfms = pos->tfms;
tfm = *per_cpu_ptr(tfms, cpu);
- if (!strcmp(crypto_tfm_alg_name(tfm), alg_name)) {
+ if (!strcmp(crypto_comp_name(tfm), alg_name)) {
pos->users++;
return tfms;
}
@@ -358,12 +358,13 @@ static struct crypto_tfm **ipcomp6_alloc_tfms(const char *alg_name)
INIT_LIST_HEAD(&pos->list);
list_add(&pos->list, &ipcomp6_tfms_list);
- pos->tfms = tfms = alloc_percpu(struct crypto_tfm *);
+ pos->tfms = tfms = alloc_percpu(struct crypto_comp *);
if (!tfms)
goto error;
for_each_possible_cpu(cpu) {
- struct crypto_tfm *tfm = crypto_alloc_tfm(alg_name, 0);
+ struct crypto_comp *tfm = crypto_alloc_comp(alg_name, 0,
+ CRYPTO_ALG_ASYNC);
if (!tfm)
goto error;
*per_cpu_ptr(tfms, cpu) = tfm;
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 43327264e69..a5eaaf693ab 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -362,7 +362,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
break;
case IPV6_TCLASS:
- if (val < 0 || val > 0xff)
+ if (val < -1 || val > 0xff)
goto e_inval;
np->tclass = val;
retv = 0;
@@ -947,6 +947,8 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
case IPV6_TCLASS:
val = np->tclass;
+ if (val < 0)
+ val = 0;
break;
case IPV6_RECVTCLASS:
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index d57e61ce4a7..15b862d8aca 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -781,7 +781,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
}
if (tclass < 0) {
- tclass = np->cork.tclass;
+ tclass = np->tclass;
if (tclass < 0)
tclass = 0;
}