Hi,

This patch is a glue for using AES-XCBC-MAC from IPsec.
This depends on the previous patch.

I have already checked the patch with TAHI test.

I should have put sequence number on my patches, sorry.


Signed-off-by: Kazunori MIYAZAWA <[EMAIL PROTECTED]>

--
Kazunori Miyazawa


diff --git a/include/linux/pfkeyv2.h b/include/linux/pfkeyv2.h
index 6351c40..707e22a 100644
--- a/include/linux/pfkeyv2.h
+++ b/include/linux/pfkeyv2.h
@@ -285,6 +285,7 @@ struct sadb_x_sec_ctx {
 #define SADB_X_AALG_SHA2_384HMAC       6
 #define SADB_X_AALG_SHA2_512HMAC       7
 #define SADB_X_AALG_RIPEMD160HMAC      8
+#define SADB_X_AALG_AES_XCBC_MAC       9
 #define SADB_X_AALG_NULL               251     /* kame */
 #define SADB_AALG_MAX                  251
 
diff --git a/include/net/ah.h b/include/net/ah.h
index ceff00a..32c5496 100644
--- a/include/net/ah.h
+++ b/include/net/ah.h
@@ -14,13 +14,13 @@ struct ah_data
        int                     icv_full_len;
        int                     icv_trunc_len;
 
-       void                    (*icv)(struct ah_data*,
+       int                     (*icv)(struct ah_data*,
                                       struct sk_buff *skb, u8 *icv);
 
        struct crypto_tfm       *tfm;
 };
 
-static inline void
+static inline int
 ah_hmac_digest(struct ah_data *ahp, struct sk_buff *skb, u8 *auth_data)
 {
        struct crypto_tfm *tfm = ahp->tfm;
@@ -30,6 +30,29 @@ ah_hmac_digest(struct ah_data *ahp, stru
        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);
+
+       return 0;
 }
 
+#ifdef CONFIG_CRYPTO_XCBC
+static inline int
+ah_xcbc_digest(struct ah_data *ahp, struct sk_buff *skb, u8 *auth_data)
+{
+       struct crypto_tfm *tfm = ahp->tfm;
+       int err;
+
+       memset(auth_data, 0, ahp->icv_trunc_len);
+       err = crypto_xcbc_init(tfm, ahp->key, ahp->key_len);
+       if (err != 0)
+               return err;
+       
+       skb_icv_walk(skb, tfm, 0, skb->len, crypto_xcbc_update);
+       err = crypto_xcbc_final(tfm, ahp->key, ahp->key_len, ahp->work_icv);
+       if (err != 0)
+               return err;
+       memcpy(auth_data, ahp->work_icv, ahp->icv_trunc_len);
+
+       return 0;
+}
+#endif
 #endif
diff --git a/include/net/esp.h b/include/net/esp.h
index 90cd94f..eb53b58 100644
--- a/include/net/esp.h
+++ b/include/net/esp.h
@@ -31,7 +31,7 @@ struct esp_data
                u8                      *work_icv;
                int                     icv_full_len;
                int                     icv_trunc_len;
-               void                    (*icv)(struct esp_data*,
+               int                     (*icv)(struct esp_data*,
                                               struct sk_buff *skb,
                                               int offset, int len, u8 *icv);
                struct crypto_tfm       *tfm;
@@ -42,7 +42,7 @@ extern int skb_to_sgvec(struct sk_buff *
 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
+static inline int
 esp_hmac_digest(struct esp_data *esp, struct sk_buff *skb, int offset,
                 int len, u8 *auth_data)
 {
@@ -54,6 +54,30 @@ esp_hmac_digest(struct esp_data *esp, st
        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);
+
+       return 0;
 }
 
+#ifdef CONFIG_CRYPTO_XCBC
+static inline int
+esp_xcbc_digest(struct esp_data *esp, struct sk_buff *skb, int offset,
+                int len, u8 *auth_data)
+{
+       struct crypto_tfm *tfm = esp->auth.tfm;
+       char *icv = esp->auth.work_icv;
+       int err = 0;
+
+       memset(auth_data, 0, esp->auth.icv_trunc_len);
+       err = crypto_xcbc_init(tfm, esp->auth.key, esp->auth.key_len);
+       if (err != 0)
+               return err;
+       skb_icv_walk(skb, tfm, offset, len, crypto_xcbc_update);
+       err = crypto_xcbc_final(tfm, esp->auth.key, esp->auth.key_len, icv);
+       if (err != 0)
+               return err;
+       memcpy(auth_data, icv, esp->auth.icv_trunc_len);
+
+       return 0;
+}
+#endif
 #endif
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index aed537f..853079a 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -97,7 +97,9 @@ static int ah_output(struct xfrm_state *
        ah->reserved = 0;
        ah->spi = x->id.spi;
        ah->seq_no = htonl(++x->replay.oseq);
-       ahp->icv(ahp, skb, ah->auth_data);
+       err = ahp->icv(ahp, skb, ah->auth_data);
+       if (err != 0)
+               goto error;
 
        top_iph->tos = iph->tos;
        top_iph->ttl = iph->ttl;
@@ -122,6 +124,7 @@ static int ah_input(struct xfrm_state *x
        struct ip_auth_hdr *ah;
        struct ah_data *ahp;
        char work_buf[60];
+       int err = -EINVAL;
 
        if (!pskb_may_pull(skb, sizeof(struct ip_auth_hdr)))
                goto out;
@@ -164,7 +167,9 @@ static int ah_input(struct xfrm_state *x
                
                memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
                skb_push(skb, skb->data - skb->nh.raw);
-               ahp->icv(ahp, skb, ah->auth_data);
+               err = ahp->icv(ahp, skb, ah->auth_data);
+               if (err != 0)
+                       goto out;
                if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) {
                        x->stats.integrity_failed++;
                        goto out;
@@ -205,6 +210,8 @@ static int ah_init_state(struct xfrm_sta
 {
        struct ah_data *ahp = NULL;
        struct xfrm_algo_desc *aalg_desc;
+       unsigned int digestsize;
+       u32 mode = 0;
 
        if (!x->aalg)
                goto error;
@@ -222,26 +229,37 @@ static int ah_init_state(struct xfrm_sta
 
        memset(ahp, 0, sizeof(*ahp));
 
+       aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0);
+       BUG_ON(!aalg_desc);
+
+#ifdef CONFIG_CRYPTO_XCBC
+       mode = aalg_desc->desc.sadb_alg_id == SADB_X_AALG_AES_XCBC_MAC ?
+               CRYPTO_TFM_MODE_CBC : 0;
+#endif
+
        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);
+       ahp->tfm = crypto_alloc_tfm(x->aalg->alg_name, mode);
        if (!ahp->tfm)
                goto error;
+#ifdef CONFIG_CRYPTO_XCBC
+       ahp->icv = !mode ? ah_hmac_digest : ah_xcbc_digest;
+#else
        ahp->icv = ah_hmac_digest;
-       
+#endif
+       digestsize = !mode ? crypto_tfm_alg_digestsize(ahp->tfm) :
+               crypto_tfm_alg_blocksize(ahp->tfm);
+
        /*
         * 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().
         */
-       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)) {
+       if (aalg_desc->uinfo.auth.icv_fullbits/8 != digestsize) {
                printk(KERN_INFO "AH: %s digestsize %u != %hu\n",
-                      x->aalg->alg_name, crypto_tfm_alg_digestsize(ahp->tfm),
+                      x->aalg->alg_name, digestsize,
                       aalg_desc->uinfo.auth.icv_fullbits/8);
                goto error;
        }
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 73bfcae..78a709a 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -121,8 +121,10 @@ static int esp_output(struct xfrm_state 
        }
 
        if (esp->auth.icv_full_len) {
-               esp->auth.icv(esp, skb, (u8*)esph-skb->data,
+               err = esp->auth.icv(esp, skb, (u8*)esph-skb->data,
                              sizeof(struct ip_esp_hdr) + esp->conf.ivlen+clen, 
trailer->tail);
+               if (err != 0)
+                       goto error;
                pskb_put(skb, trailer, alen);
        }
 
@@ -161,8 +163,9 @@ static int esp_input(struct xfrm_state *
        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);
+
+               if ((esp->auth.icv(esp, skb, 0, skb->len-alen, sum)) != 0)
+                       goto out;
 
                if (skb_copy_bits(skb, skb->len-alen, sum1, alen))
                        BUG();
@@ -376,22 +379,34 @@ static int esp_init_state(struct xfrm_st
 
        if (x->aalg) {
                struct xfrm_algo_desc *aalg_desc;
+               unsigned int digestsize;
+               u32 mode = 0;
 
+               aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0);
+               BUG_ON(!aalg_desc);
+
+#ifdef CONFIG_CRYPTO_XCBC
+               mode = aalg_desc->desc.sadb_alg_id == SADB_X_AALG_AES_XCBC_MAC ?
+                       CRYPTO_TFM_MODE_CBC : 0;
+#endif
                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);
+               esp->auth.tfm = crypto_alloc_tfm(x->aalg->alg_name, mode);
                if (esp->auth.tfm == NULL)
                        goto error;
+#ifdef CONFIG_CRYPTO_XCBC
+               esp->auth.icv = !mode ? esp_hmac_digest : esp_xcbc_digest;
+#else
                esp->auth.icv = esp_hmac_digest;
+#endif
 
-               aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0);
-               BUG_ON(!aalg_desc);
+               digestsize = !mode ? crypto_tfm_alg_digestsize(esp->auth.tfm) :
+                       crypto_tfm_alg_blocksize(esp->auth.tfm);
 
-               if (aalg_desc->uinfo.auth.icv_fullbits/8 !=
-                   crypto_tfm_alg_digestsize(esp->auth.tfm)) {
+               if (aalg_desc->uinfo.auth.icv_fullbits/8 != digestsize) {
                        NETDEBUG(KERN_INFO "ESP: %s digestsize %u != %hu\n",
                                 x->aalg->alg_name,
-                                crypto_tfm_alg_digestsize(esp->auth.tfm),
+                                digestsize,
                                 aalg_desc->uinfo.auth.icv_fullbits/8);
                        goto error;
                }
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index 13cc7f8..700f25e 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -343,6 +343,8 @@ static int ah6_init_state(struct xfrm_st
 {
        struct ah_data *ahp = NULL;
        struct xfrm_algo_desc *aalg_desc;
+       unsigned int digestsize;
+       u32 mode = 0;
 
        if (!x->aalg)
                goto error;
@@ -360,12 +362,28 @@ static int ah6_init_state(struct xfrm_st
 
        memset(ahp, 0, sizeof(*ahp));
 
+       aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0);
+       BUG_ON(!aalg_desc);
+
+#ifdef CONFIG_CRYPTO_XCBC
+       mode = aalg_desc->desc.sadb_alg_id == SADB_X_AALG_AES_XCBC_MAC ?
+               CRYPTO_TFM_MODE_CBC : 0;
+#endif
+       printk(KERN_DEBUG "%s(x=%p) mode=%u\n", __FUNCTION__, x, mode);
        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);
+       ahp->tfm = crypto_alloc_tfm(x->aalg->alg_name, mode);
        if (!ahp->tfm)
                goto error;
+#ifdef CONFIG_CRYPTO_XCBC
+       ahp->icv = !mode ? ah_hmac_digest : ah_xcbc_digest;
+#else
        ahp->icv = ah_hmac_digest;
+#endif
+       
+
+       digestsize = !mode ? crypto_tfm_alg_digestsize(ahp->tfm) :
+               crypto_tfm_alg_blocksize(ahp->tfm);
        
        /*
         * Lookup the algorithm description maintained by xfrm_algo,
@@ -373,13 +391,9 @@ static int ah6_init_state(struct xfrm_st
         * we need for AH processing.  This lookup cannot fail here
         * after a successful crypto_alloc_tfm().
         */
-       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)) {
+       if (aalg_desc->uinfo.auth.icv_fullbits/8 != digestsize) {
                printk(KERN_INFO "AH: %s digestsize %u != %hu\n",
-                      x->aalg->alg_name, crypto_tfm_alg_digestsize(ahp->tfm),
+                      x->aalg->alg_name, digestsize,
                       aalg_desc->uinfo.auth.icv_fullbits/8);
                goto error;
        }
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 6de8ee1..4c21a0b 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -313,22 +313,34 @@ static int esp6_init_state(struct xfrm_s
 
        if (x->aalg) {
                struct xfrm_algo_desc *aalg_desc;
+               unsigned int digestsize;
+               u32 mode = 0;
+
+               aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0);
+               BUG_ON(!aalg_desc);
+
+#ifdef CONFIG_CRYPTO_XCBC
+               mode = aalg_desc->desc.sadb_alg_id == SADB_X_AALG_AES_XCBC_MAC ?
+                       CRYPTO_TFM_MODE_CBC : 0;
+#endif
 
                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);
+               esp->auth.tfm = crypto_alloc_tfm(x->aalg->alg_name, mode);
                if (esp->auth.tfm == NULL)
                        goto error;
+#ifdef CONFIG_CRYPTO_XCBC
+               esp->auth.icv = !mode ? esp_hmac_digest : esp_xcbc_digest;
+#else
                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)) {
+#endif
+
+               digestsize = !mode ? crypto_tfm_alg_digestsize(esp->auth.tfm) :
+                       crypto_tfm_alg_blocksize(esp->auth.tfm);
+
+               if (aalg_desc->uinfo.auth.icv_fullbits/8 != digestsize) {
                                printk(KERN_INFO "ESP: %s digestsize %u != 
%hu\n",
-                                       x->aalg->alg_name,
-                                       
crypto_tfm_alg_digestsize(esp->auth.tfm),
+                                       x->aalg->alg_name, digestsize,
                                        aalg_desc->uinfo.auth.icv_fullbits/8);
                                goto error;
                }
diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c
index 6ed3302..0d19222 100644
--- a/net/xfrm/xfrm_algo.c
+++ b/net/xfrm/xfrm_algo.c
@@ -115,6 +115,25 @@ static struct xfrm_algo_desc aalg_list[]
                .sadb_alg_maxbits = 160
        }
 },
+#ifdef CONFIG_CRYPTO_XCBC
+{
+       .name = "aes",
+
+       .uinfo = {
+               .auth = {
+                       .icv_truncbits = 96,
+                       .icv_fullbits = 128,
+               }
+       },
+
+       .desc = {
+               .sadb_alg_id = SADB_X_AALG_AES_XCBC_MAC,
+               .sadb_alg_ivlen = 0,
+               .sadb_alg_minbits = 128,
+               .sadb_alg_maxbits = 128 
+       }
+},
+#endif
 };
 
 static struct xfrm_algo_desc ealg_list[] = {

Reply via email to