]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/ipv6/esp6.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[linux-2.6-omap-h63xx.git] / net / ipv6 / esp6.c
index 46a7e687948eced50158700a8b0f677e4b0debca..e78680a9985b2cf86a1b6671c1a73a258973a57c 100644 (file)
@@ -99,8 +99,13 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
        esph->seq_no = htonl(++x->replay.oseq);
        xfrm_aevent_doreplay(x);
 
-       if (esp->conf.ivlen)
+       if (esp->conf.ivlen) {
+               if (unlikely(!esp->conf.ivinitted)) {
+                       get_random_bytes(esp->conf.ivec, esp->conf.ivlen);
+                       esp->conf.ivinitted = 1;
+               }
                crypto_blkcipher_set_iv(tfm, esp->conf.ivec, esp->conf.ivlen);
+       }
 
        do {
                struct scatterlist *sg = &esp->sgbuf[0];
@@ -125,9 +130,9 @@ static int esp6_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 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);
        }
 
 error:
@@ -162,15 +167,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;
@@ -236,7 +242,7 @@ static u32 esp6_get_max_size(struct xfrm_state *x, int mtu)
        struct esp_data *esp = x->data;
        u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4);
 
-       if (x->props.mode) {
+       if (x->props.mode == XFRM_MODE_TUNNEL) {
                mtu = ALIGN(mtu + 2, blksize);
        } else {
                /* The worst case. */
@@ -279,7 +285,7 @@ static void esp6_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;
@@ -308,24 +314,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;
@@ -347,12 +358,12 @@ static int esp6_init_state(struct xfrm_state *x)
                esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL);
                if (unlikely(esp->conf.ivec == NULL))
                        goto error;
-               get_random_bytes(esp->conf.ivec, esp->conf.ivlen);
+               esp->conf.ivinitted = 0;
        }
        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)
+       if (x->props.mode == XFRM_MODE_TUNNEL)
                x->props.header_len += sizeof(struct ipv6hdr);
        x->data = esp;
        return 0;
@@ -373,7 +384,8 @@ static struct xfrm_type esp6_type =
        .destructor     = esp6_destroy,
        .get_max_size   = esp6_get_max_size,
        .input          = esp6_input,
-       .output         = esp6_output
+       .output         = esp6_output,
+       .hdr_offset     = xfrm6_find_1stfragopt,
 };
 
 static struct inet6_protocol esp6_protocol = {