fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / net / xfrm / xfrm_algo.c
index 0612ecb..f1cf340 100644 (file)
@@ -9,10 +9,10 @@
  * any later version.
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/pfkeyv2.h>
+#include <linux/crypto.h>
 #include <net/xfrm.h>
 #if defined(CONFIG_INET_AH) || defined(CONFIG_INET_AH_MODULE) || defined(CONFIG_INET6_AH) || defined(CONFIG_INET6_AH_MODULE)
 #include <net/ah.h>
@@ -30,7 +30,8 @@
  */
 static struct xfrm_algo_desc aalg_list[] = {
 {
-       .name = "digest_null",
+       .name = "hmac(digest_null)",
+       .compat = "digest_null",
        
        .uinfo = {
                .auth = {
@@ -47,7 +48,8 @@ static struct xfrm_algo_desc aalg_list[] = {
        }
 },
 {
-       .name = "md5",
+       .name = "hmac(md5)",
+       .compat = "md5",
 
        .uinfo = {
                .auth = {
@@ -64,7 +66,8 @@ static struct xfrm_algo_desc aalg_list[] = {
        }
 },
 {
-       .name = "sha1",
+       .name = "hmac(sha1)",
+       .compat = "sha1",
 
        .uinfo = {
                .auth = {
@@ -81,7 +84,8 @@ static struct xfrm_algo_desc aalg_list[] = {
        }
 },
 {
-       .name = "sha256",
+       .name = "hmac(sha256)",
+       .compat = "sha256",
 
        .uinfo = {
                .auth = {
@@ -98,7 +102,8 @@ static struct xfrm_algo_desc aalg_list[] = {
        }
 },
 {
-       .name = "ripemd160",
+       .name = "hmac(ripemd160)",
+       .compat = "ripemd160",
 
        .uinfo = {
                .auth = {
@@ -114,11 +119,29 @@ static struct xfrm_algo_desc aalg_list[] = {
                .sadb_alg_maxbits = 160
        }
 },
+{
+       .name = "xcbc(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
+       }
+},
 };
 
 static struct xfrm_algo_desc ealg_list[] = {
 {
-       .name = "cipher_null",
+       .name = "ecb(cipher_null)",
+       .compat = "cipher_null",
        
        .uinfo = {
                .encr = {
@@ -135,7 +158,8 @@ static struct xfrm_algo_desc ealg_list[] = {
        }
 },
 {
-       .name = "des",
+       .name = "cbc(des)",
+       .compat = "des",
 
        .uinfo = {
                .encr = {
@@ -152,7 +176,8 @@ static struct xfrm_algo_desc ealg_list[] = {
        }
 },
 {
-       .name = "des3_ede",
+       .name = "cbc(des3_ede)",
+       .compat = "des3_ede",
 
        .uinfo = {
                .encr = {
@@ -169,7 +194,8 @@ static struct xfrm_algo_desc ealg_list[] = {
        }
 },
 {
-       .name = "cast128",
+       .name = "cbc(cast128)",
+       .compat = "cast128",
 
        .uinfo = {
                .encr = {
@@ -186,7 +212,8 @@ static struct xfrm_algo_desc ealg_list[] = {
        }
 },
 {
-       .name = "blowfish",
+       .name = "cbc(blowfish)",
+       .compat = "blowfish",
 
        .uinfo = {
                .encr = {
@@ -203,7 +230,8 @@ static struct xfrm_algo_desc ealg_list[] = {
        }
 },
 {
-       .name = "aes",
+       .name = "cbc(aes)",
+       .compat = "aes",
 
        .uinfo = {
                .encr = {
@@ -220,7 +248,8 @@ static struct xfrm_algo_desc ealg_list[] = {
        }
 },
 {
-        .name = "serpent",
+        .name = "cbc(serpent)",
+        .compat = "serpent",
 
         .uinfo = {
                 .encr = {
@@ -237,7 +266,8 @@ static struct xfrm_algo_desc ealg_list[] = {
         }
 },
 {
-        .name = "twofish",
+        .name = "cbc(twofish)",
+        .compat = "twofish",
                  
         .uinfo = {
                 .encr = {
@@ -315,6 +345,7 @@ struct xfrm_algo_desc *xfrm_aalg_get_byid(int alg_id)
        }
        return NULL;
 }
+EXPORT_SYMBOL_GPL(xfrm_aalg_get_byid);
 
 struct xfrm_algo_desc *xfrm_ealg_get_byid(int alg_id)
 {
@@ -330,6 +361,7 @@ struct xfrm_algo_desc *xfrm_ealg_get_byid(int alg_id)
        }
        return NULL;
 }
+EXPORT_SYMBOL_GPL(xfrm_ealg_get_byid);
 
 struct xfrm_algo_desc *xfrm_calg_get_byid(int alg_id)
 {
@@ -345,60 +377,62 @@ struct xfrm_algo_desc *xfrm_calg_get_byid(int alg_id)
        }
        return NULL;
 }
+EXPORT_SYMBOL_GPL(xfrm_calg_get_byid);
 
-struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name)
+static struct xfrm_algo_desc *xfrm_get_byname(struct xfrm_algo_desc *list,
+                                             int entries, u32 type, u32 mask,
+                                             char *name, int probe)
 {
-       int i;
+       int i, status;
 
        if (!name)
                return NULL;
 
-       for (i=0; i < aalg_entries(); i++) {
-               if (strcmp(name, aalg_list[i].name) == 0) {
-                       if (aalg_list[i].available)
-                               return &aalg_list[i];
-                       else
-                               break;
-               }
-       }
-       return NULL;
-}
+       for (i = 0; i < entries; i++) {
+               if (strcmp(name, list[i].name) &&
+                   (!list[i].compat || strcmp(name, list[i].compat)))
+                       continue;
 
-struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name)
-{
-       int i;
+               if (list[i].available)
+                       return &list[i];
 
-       if (!name)
-               return NULL;
+               if (!probe)
+                       break;
 
-       for (i=0; i < ealg_entries(); i++) {
-               if (strcmp(name, ealg_list[i].name) == 0) {
-                       if (ealg_list[i].available)
-                               return &ealg_list[i];
-                       else
-                               break;
-               }
+               status = crypto_has_alg(list[i].name, type,
+                                       mask | CRYPTO_ALG_ASYNC);
+               if (!status)
+                       break;
+
+               list[i].available = status;
+               return &list[i];
        }
        return NULL;
 }
 
-struct xfrm_algo_desc *xfrm_calg_get_byname(char *name)
+struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name, int probe)
 {
-       int i;
+       return xfrm_get_byname(aalg_list, aalg_entries(),
+                              CRYPTO_ALG_TYPE_HASH, CRYPTO_ALG_TYPE_HASH_MASK,
+                              name, probe);
+}
+EXPORT_SYMBOL_GPL(xfrm_aalg_get_byname);
 
-       if (!name)
-               return NULL;
+struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name, int probe)
+{
+       return xfrm_get_byname(ealg_list, ealg_entries(),
+                              CRYPTO_ALG_TYPE_BLKCIPHER, CRYPTO_ALG_TYPE_MASK,
+                              name, probe);
+}
+EXPORT_SYMBOL_GPL(xfrm_ealg_get_byname);
 
-       for (i=0; i < calg_entries(); i++) {
-               if (strcmp(name, calg_list[i].name) == 0) {
-                       if (calg_list[i].available)
-                               return &calg_list[i];
-                       else
-                               break;
-               }
-       }
-       return NULL;
+struct xfrm_algo_desc *xfrm_calg_get_byname(char *name, int probe)
+{
+       return xfrm_get_byname(calg_list, calg_entries(),
+                              CRYPTO_ALG_TYPE_COMPRESS, CRYPTO_ALG_TYPE_MASK,
+                              name, probe);
 }
+EXPORT_SYMBOL_GPL(xfrm_calg_get_byname);
 
 struct xfrm_algo_desc *xfrm_aalg_get_byidx(unsigned int idx)
 {
@@ -407,6 +441,7 @@ struct xfrm_algo_desc *xfrm_aalg_get_byidx(unsigned int idx)
 
        return &aalg_list[idx];
 }
+EXPORT_SYMBOL_GPL(xfrm_aalg_get_byidx);
 
 struct xfrm_algo_desc *xfrm_ealg_get_byidx(unsigned int idx)
 {
@@ -415,14 +450,7 @@ struct xfrm_algo_desc *xfrm_ealg_get_byidx(unsigned int idx)
 
        return &ealg_list[idx];
 }
-
-struct xfrm_algo_desc *xfrm_calg_get_byidx(unsigned int idx)
-{
-       if (idx >= calg_entries())
-               return NULL;
-
-       return &calg_list[idx];
-}
+EXPORT_SYMBOL_GPL(xfrm_ealg_get_byidx);
 
 /*
  * Probe for the availability of crypto algorithms, and set the available
@@ -437,24 +465,28 @@ void xfrm_probe_algs(void)
        BUG_ON(in_softirq());
 
        for (i = 0; i < aalg_entries(); i++) {
-               status = crypto_alg_available(aalg_list[i].name, 0);
+               status = crypto_has_hash(aalg_list[i].name, 0,
+                                        CRYPTO_ALG_ASYNC);
                if (aalg_list[i].available != status)
                        aalg_list[i].available = status;
        }
        
        for (i = 0; i < ealg_entries(); i++) {
-               status = crypto_alg_available(ealg_list[i].name, 0);
+               status = crypto_has_blkcipher(ealg_list[i].name, 0,
+                                             CRYPTO_ALG_ASYNC);
                if (ealg_list[i].available != status)
                        ealg_list[i].available = status;
        }
        
        for (i = 0; i < calg_entries(); i++) {
-               status = crypto_alg_available(calg_list[i].name, 0);
+               status = crypto_has_comp(calg_list[i].name, 0,
+                                        CRYPTO_ALG_ASYNC);
                if (calg_list[i].available != status)
                        calg_list[i].available = status;
        }
 #endif
 }
+EXPORT_SYMBOL_GPL(xfrm_probe_algs);
 
 int xfrm_count_auth_supported(void)
 {
@@ -465,6 +497,7 @@ int xfrm_count_auth_supported(void)
                        n++;
        return n;
 }
+EXPORT_SYMBOL_GPL(xfrm_count_auth_supported);
 
 int xfrm_count_enc_supported(void)
 {
@@ -475,14 +508,16 @@ int xfrm_count_enc_supported(void)
                        n++;
        return n;
 }
+EXPORT_SYMBOL_GPL(xfrm_count_enc_supported);
 
 /* Move to common area: it is shared with AH. */
 
-void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm,
-                 int offset, int len, icv_update_fn_t icv_update)
+int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc,
+                int offset, int len, icv_update_fn_t icv_update)
 {
        int start = skb_headlen(skb);
        int i, copy = start - offset;
+       int err;
        struct scatterlist sg;
 
        /* Checksum header. */
@@ -494,10 +529,12 @@ void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm,
                sg.offset = (unsigned long)(skb->data + offset) % PAGE_SIZE;
                sg.length = copy;
                
-               icv_update(tfm, &sg, 1);
+               err = icv_update(desc, &sg, copy);
+               if (unlikely(err))
+                       return err;
                
                if ((len -= copy) == 0)
-                       return;
+                       return 0;
                offset += copy;
        }
 
@@ -517,10 +554,12 @@ void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm,
                        sg.offset = frag->page_offset + offset-start;
                        sg.length = copy;
                        
-                       icv_update(tfm, &sg, 1);
+                       err = icv_update(desc, &sg, copy);
+                       if (unlikely(err))
+                               return err;
 
                        if (!(len -= copy))
-                               return;
+                               return 0;
                        offset += copy;
                }
                start = end;
@@ -538,17 +577,21 @@ void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm,
                        if ((copy = end - offset) > 0) {
                                if (copy > len)
                                        copy = len;
-                               skb_icv_walk(list, tfm, offset-start, copy, icv_update);
+                               err = skb_icv_walk(list, desc, offset-start,
+                                                  copy, icv_update);
+                               if (unlikely(err))
+                                       return err;
                                if ((len -= copy) == 0)
-                                       return;
+                                       return 0;
                                offset += copy;
                        }
                        start = end;
                }
        }
-       if (len)
-               BUG();
+       BUG_ON(len);
+       return 0;
 }
+EXPORT_SYMBOL_GPL(skb_icv_walk);
 
 #if defined(CONFIG_INET_ESP) || defined(CONFIG_INET_ESP_MODULE) || defined(CONFIG_INET6_ESP) || defined(CONFIG_INET6_ESP_MODULE)
 
@@ -615,8 +658,7 @@ skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
                        start = end;
                }
        }
-       if (len)
-               BUG();
+       BUG_ON(len);
        return elt;
 }
 EXPORT_SYMBOL_GPL(skb_to_sgvec);
@@ -703,7 +745,7 @@ int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer)
                                return -ENOMEM;
 
                        if (skb1->sk)
-                               skb_set_owner_w(skb, skb1->sk);
+                               skb_set_owner_w(skb2, skb1->sk);
 
                        /* Looking around. Are we still alive?
                         * OK, link new skb, drop old one */