Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 34251
b: refs/heads/master
c: 07d4ee5
h: refs/heads/master
i:
  34249: 8ae4a73
  34247: e6a34aa
v: v3
  • Loading branch information
Herbert Xu committed Sep 21, 2006
1 parent c46a04e commit 7be25cc
Show file tree
Hide file tree
Showing 9 changed files with 159 additions and 98 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: e9d41164e2fdd897fe4520c2079ea0000f6e0ec3
refs/heads/master: 07d4ee583e21830ec5604d31f65cdc60a6eca19e
29 changes: 18 additions & 11 deletions trunk/include/net/ah.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,29 @@ struct ah_data
int icv_full_len;
int icv_trunc_len;

void (*icv)(struct ah_data*,
struct sk_buff *skb, u8 *icv);

struct crypto_tfm *tfm;
struct crypto_hash *tfm;
};

static inline void
ah_hmac_digest(struct ah_data *ahp, struct sk_buff *skb, u8 *auth_data)
static inline int ah_mac_digest(struct ah_data *ahp, struct sk_buff *skb,
u8 *auth_data)
{
struct crypto_tfm *tfm = ahp->tfm;
struct hash_desc desc;
int err;

desc.tfm = ahp->tfm;
desc.flags = 0;

memset(auth_data, 0, ahp->icv_trunc_len);
crypto_hmac_init(tfm, ahp->key, &ahp->key_len);
skb_icv_walk(skb, tfm, 0, skb->len, crypto_hmac_update);
crypto_hmac_final(tfm, ahp->key, &ahp->key_len, ahp->work_icv);
memcpy(auth_data, ahp->work_icv, ahp->icv_trunc_len);
err = crypto_hash_init(&desc);
if (unlikely(err))
goto out;
err = skb_icv_walk(skb, &desc, 0, skb->len, crypto_hash_update);
if (unlikely(err))
goto out;
err = crypto_hash_final(&desc, ahp->work_icv);

out:
return err;
}

#endif
28 changes: 16 additions & 12 deletions trunk/include/net/esp.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,26 +35,30 @@ struct esp_data
void (*icv)(struct esp_data*,
struct sk_buff *skb,
int offset, int len, u8 *icv);
struct crypto_tfm *tfm;
struct crypto_hash *tfm;
} auth;
};

extern int skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len);
extern int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer);
extern void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len);

static inline void
esp_hmac_digest(struct esp_data *esp, struct sk_buff *skb, int offset,
int len, u8 *auth_data)
static inline int esp_mac_digest(struct esp_data *esp, struct sk_buff *skb,
int offset, int len)
{
struct crypto_tfm *tfm = esp->auth.tfm;
char *icv = esp->auth.work_icv;

memset(auth_data, 0, esp->auth.icv_trunc_len);
crypto_hmac_init(tfm, esp->auth.key, &esp->auth.key_len);
skb_icv_walk(skb, tfm, offset, len, crypto_hmac_update);
crypto_hmac_final(tfm, esp->auth.key, &esp->auth.key_len, icv);
memcpy(auth_data, icv, esp->auth.icv_trunc_len);
struct hash_desc desc;
int err;

desc.tfm = esp->auth.tfm;
desc.flags = 0;

err = crypto_hash_init(&desc);
if (unlikely(err))
return err;
err = skb_icv_walk(skb, &desc, offset, len, crypto_hash_update);
if (unlikely(err))
return err;
return crypto_hash_final(&desc, esp->auth.work_icv);
}

#endif
9 changes: 5 additions & 4 deletions trunk/include/net/xfrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -984,12 +984,13 @@ extern struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name, int probe);
extern struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name, int probe);
extern struct xfrm_algo_desc *xfrm_calg_get_byname(char *name, int probe);

struct crypto_tfm;
struct hash_desc;
struct scatterlist;
typedef void (icv_update_fn_t)(struct crypto_tfm *, struct scatterlist *, unsigned int);
typedef int (icv_update_fn_t)(struct hash_desc *, struct scatterlist *,
unsigned int);

extern void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm,
int offset, int len, icv_update_fn_t icv_update);
extern int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *tfm,
int offset, int len, icv_update_fn_t icv_update);

static inline int xfrm_addr_cmp(xfrm_address_t *a, xfrm_address_t *b,
int family)
Expand Down
36 changes: 24 additions & 12 deletions trunk/net/ipv4/ah4.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <linux/err.h>
#include <linux/module.h>
#include <net/ip.h>
#include <net/xfrm.h>
Expand Down Expand Up @@ -97,7 +98,10 @@ static int ah_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;
memcpy(ah->auth_data, ahp->work_icv, ahp->icv_trunc_len);

top_iph->tos = iph->tos;
top_iph->ttl = iph->ttl;
Expand All @@ -119,6 +123,7 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
{
int ah_hlen;
int ihl;
int err = -EINVAL;
struct iphdr *iph;
struct ip_auth_hdr *ah;
struct ah_data *ahp;
Expand Down Expand Up @@ -166,8 +171,11 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)

memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
skb_push(skb, ihl);
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 out;
err = -EINVAL;
if (memcmp(ahp->work_icv, auth_data, ahp->icv_trunc_len)) {
x->stats.integrity_failed++;
goto out;
}
Expand All @@ -179,7 +187,7 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
return 0;

out:
return -EINVAL;
return err;
}

static void ah4_err(struct sk_buff *skb, u32 info)
Expand All @@ -204,6 +212,7 @@ static int ah_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;
Expand All @@ -221,24 +230,27 @@ static int ah_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;
}
Expand All @@ -262,7 +274,7 @@ static int ah_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;
Expand All @@ -277,7 +289,7 @@ static void ah_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);
}
Expand Down
36 changes: 21 additions & 15 deletions trunk/net/ipv4/esp4.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,9 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
}

if (esp->auth.icv_full_len) {
esp->auth.icv(esp, skb, (u8*)esph-skb->data,
sizeof(struct ip_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);
}

ip_send_check(top_iph);
Expand Down Expand Up @@ -163,15 +163,16 @@ static int esp_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];

esp->auth.icv(esp, skb, 0, skb->len-alen, sum);
u8 sum[alen];

if (skb_copy_bits(skb, skb->len-alen, sum1, alen))
err = esp_mac_digest(esp, skb, 0, skb->len - alen);
if (err)
goto out;

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++;
goto out;
}
Expand Down Expand Up @@ -307,7 +308,7 @@ static void esp_destroy(struct xfrm_state *x)
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;
Expand All @@ -333,22 +334,27 @@ static int esp_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)) {
crypto_hash_digestsize(hash)) {
NETDEBUG(KERN_INFO "ESP: %s digestsize %u != %hu\n",
x->aalg->alg_name,
crypto_tfm_alg_digestsize(esp->auth.tfm),
crypto_hash_digestsize(hash),
aalg_desc->uinfo.auth.icv_fullbits/8);
goto error;
}
Expand Down
35 changes: 23 additions & 12 deletions trunk/net/ipv6/ah6.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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,
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}
Expand All @@ -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;
Expand All @@ -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);
}
Expand Down
Loading

0 comments on commit 7be25cc

Please sign in to comment.