Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
authorLinus Torvalds <torvalds@woody.osdl.org>
Thu, 7 Dec 2006 17:05:15 +0000 (09:05 -0800)
committerLinus Torvalds <torvalds@woody.osdl.org>
Thu, 7 Dec 2006 17:05:15 +0000 (09:05 -0800)
* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6: (48 commits)
  [NETFILTER]: Fix non-ANSI func. decl.
  [TG3]: Identify Serdes devices more clearly.
  [TG3]: Use msleep.
  [TG3]: Use netif_msg_*.
  [TG3]: Allow partial speed advertisement.
  [TG3]: Add TG3_FLG2_IS_NIC flag.
  [TG3]: Add 5787F device ID.
  [TG3]: Fix Phy loopback.
  [WANROUTER]: Kill kmalloc debugging code.
  [TCP] inet_twdr_hangman: Delete unnecessary memory barrier().
  [NET]: Memory barrier cleanups
  [IPSEC]: Fix inetpeer leak in ipv4 xfrm dst entries.
  audit: disable ipsec auditing when CONFIG_AUDITSYSCALL=n
  audit: Add auditing to ipsec
  [IRDA] irlan: Fix compile warning when CONFIG_PROC_FS=n
  [IrDA]: Incorrect TTP header reservation
  [IrDA]: PXA FIR code device model conversion
  [GENETLINK]: Fix misplaced command flags.
  [NETLIK]: Add a pointer to the Generic Netlink wiki page.
  [IPV6] RAW: Don't release unlocked sock.
  ...

55 files changed:
Documentation/networking/00-INDEX
Documentation/networking/generic_netlink.txt [new file with mode: 0644]
crypto/Kconfig
crypto/Makefile
crypto/api.c
crypto/digest.c
crypto/gf128mul.c [new file with mode: 0644]
crypto/lrw.c [new file with mode: 0644]
crypto/tcrypt.c
crypto/tcrypt.h
crypto/xcbc.c [new file with mode: 0644]
drivers/atm/Makefile
drivers/block/Kconfig
drivers/crypto/Kconfig
drivers/crypto/Makefile
drivers/crypto/geode-aes.c [new file with mode: 0644]
drivers/crypto/geode-aes.h [new file with mode: 0644]
drivers/md/dm-crypt.c
drivers/net/irda/pxaficp_ir.c
drivers/net/tg3.c
drivers/net/tg3.h
include/crypto/b128ops.h [new file with mode: 0644]
include/crypto/gf128mul.h [new file with mode: 0644]
include/linux/audit.h
include/linux/crypto.h
include/linux/genetlink.h
include/linux/netfilter/nf_conntrack_pptp.h
include/linux/pci_ids.h
include/linux/pfkeyv2.h
include/net/irda/irlan_filter.h
include/net/xfrm.h
kernel/auditsc.c
net/bridge/br_netfilter.c
net/core/wireless.c
net/ipv4/inet_timewait_sock.c
net/ipv4/netfilter/arp_tables.c
net/ipv4/netfilter/ip_tables.c
net/ipv4/route.c
net/ipv4/tcp_input.c
net/ipv4/xfrm4_policy.c
net/ipv6/ip6_output.c
net/ipv6/netfilter/ip6_tables.c
net/ipv6/raw.c
net/irda/irttp.c
net/key/af_key.c
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_conntrack_expect.c
net/netlink/genetlink.c
net/packet/af_packet.c
net/sched/cls_fw.c
net/wanrouter/wanmain.c
net/xfrm/xfrm_algo.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_state.c
net/xfrm/xfrm_user.c

index b1181ce232d987453f13917904a3f1ba180125f2..e06b6e3c1db577d5fe513cc2ea045e3d57507564 100644 (file)
@@ -58,6 +58,8 @@ fore200e.txt
        - FORE Systems PCA-200E/SBA-200E ATM NIC driver info.
 framerelay.txt
        - info on using Frame Relay/Data Link Connection Identifier (DLCI).
+generic_netlink.txt
+       - info on Generic Netlink
 ip-sysctl.txt
        - /proc/sys/net/ipv4/* variables
 ip_dynaddr.txt
diff --git a/Documentation/networking/generic_netlink.txt b/Documentation/networking/generic_netlink.txt
new file mode 100644 (file)
index 0000000..d4f8b8b
--- /dev/null
@@ -0,0 +1,3 @@
+A wiki document on how to use Generic Netlink can be found here:
+
+ * http://linux-net.osdl.org/index.php/Generic_Netlink_HOWTO
index cbae8392ce11b848e5573194eb8591a175815822..92ba249f3a5bf6bfc64d4aca0200ad9812bac999 100644 (file)
@@ -39,6 +39,17 @@ config CRYPTO_HMAC
          HMAC: Keyed-Hashing for Message Authentication (RFC2104).
          This is required for IPSec.
 
+config CRYPTO_XCBC
+       tristate "XCBC support"
+       depends on EXPERIMENTAL
+       select CRYPTO_HASH
+       select CRYPTO_MANAGER
+       help
+         XCBC: Keyed-Hashing with encryption algorithm
+               http://www.ietf.org/rfc/rfc3566.txt
+               http://csrc.nist.gov/encryption/modes/proposedmodes/
+                xcbc-mac/xcbc-mac-spec.pdf
+
 config CRYPTO_NULL
        tristate "Null algorithms"
        select CRYPTO_ALGAPI
@@ -128,6 +139,16 @@ config CRYPTO_TGR192
          See also:
          <http://www.cs.technion.ac.il/~biham/Reports/Tiger/>.
 
+config CRYPTO_GF128MUL
+       tristate "GF(2^128) multiplication functions (EXPERIMENTAL)"
+       depends on EXPERIMENTAL
+       help
+         Efficient table driven implementation of multiplications in the
+         field GF(2^128).  This is needed by some cypher modes. This
+         option will be selected automatically if you select such a
+         cipher mode.  Only select this option by hand if you expect to load
+         an external module that requires these functions.
+
 config CRYPTO_ECB
        tristate "ECB support"
        select CRYPTO_BLKCIPHER
@@ -147,6 +168,19 @@ config CRYPTO_CBC
          CBC: Cipher Block Chaining mode
          This block cipher algorithm is required for IPSec.
 
+config CRYPTO_LRW
+       tristate "LRW support (EXPERIMENTAL)"
+       depends on EXPERIMENTAL
+       select CRYPTO_BLKCIPHER
+       select CRYPTO_MANAGER
+       select CRYPTO_GF128MUL
+       help
+         LRW: Liskov Rivest Wagner, a tweakable, non malleable, non movable
+         narrow block cipher mode for dm-crypt.  Use it with cipher
+         specification string aes-lrw-benbi, the key must be 256, 320 or 384.
+         The first 128, 192 or 256 bits in the key are used for AES and the
+         rest is used to tie each cipher block to its logical position.
+
 config CRYPTO_DES
        tristate "DES and Triple DES EDE cipher algorithms"
        select CRYPTO_ALGAPI
index 72366208e291cbbbbbfc89f5c4ddbbb26ec6e5ff..60e3d24f61f56a28c9c2e91eb84a4cac05671366 100644 (file)
@@ -15,6 +15,7 @@ obj-$(CONFIG_CRYPTO_HASH) += crypto_hash.o
 
 obj-$(CONFIG_CRYPTO_MANAGER) += cryptomgr.o
 obj-$(CONFIG_CRYPTO_HMAC) += hmac.o
+obj-$(CONFIG_CRYPTO_XCBC) += xcbc.o
 obj-$(CONFIG_CRYPTO_NULL) += crypto_null.o
 obj-$(CONFIG_CRYPTO_MD4) += md4.o
 obj-$(CONFIG_CRYPTO_MD5) += md5.o
@@ -23,8 +24,10 @@ obj-$(CONFIG_CRYPTO_SHA256) += sha256.o
 obj-$(CONFIG_CRYPTO_SHA512) += sha512.o
 obj-$(CONFIG_CRYPTO_WP512) += wp512.o
 obj-$(CONFIG_CRYPTO_TGR192) += tgr192.o
+obj-$(CONFIG_CRYPTO_GF128MUL) += gf128mul.o
 obj-$(CONFIG_CRYPTO_ECB) += ecb.o
 obj-$(CONFIG_CRYPTO_CBC) += cbc.o
+obj-$(CONFIG_CRYPTO_LRW) += lrw.o
 obj-$(CONFIG_CRYPTO_DES) += des.o
 obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o
 obj-$(CONFIG_CRYPTO_TWOFISH) += twofish.o
index 4fb7fa45cb0de649194262c5f6061669b3391a80..8c446871cd5b13998294850338bb4ce93930f069 100644 (file)
@@ -466,23 +466,8 @@ void crypto_free_tfm(struct crypto_tfm *tfm)
        kfree(tfm);
 }
 
-int crypto_alg_available(const char *name, u32 flags)
-{
-       int ret = 0;
-       struct crypto_alg *alg = crypto_alg_mod_lookup(name, 0,
-                                                      CRYPTO_ALG_ASYNC);
-       
-       if (!IS_ERR(alg)) {
-               crypto_mod_put(alg);
-               ret = 1;
-       }
-       
-       return ret;
-}
-
 EXPORT_SYMBOL_GPL(crypto_alloc_tfm);
 EXPORT_SYMBOL_GPL(crypto_free_tfm);
-EXPORT_SYMBOL_GPL(crypto_alg_available);
 
 int crypto_has_alg(const char *name, u32 type, u32 mask)
 {
index 0155a94e4b15432b636559124370436fa8edf5af..8f4593268ce0bf5c5ef2e9e47d8ab72789adb842 100644 (file)
 #include "internal.h"
 #include "scatterwalk.h"
 
-void crypto_digest_init(struct crypto_tfm *tfm)
-{
-       struct crypto_hash *hash = crypto_hash_cast(tfm);
-       struct hash_desc desc = { .tfm = hash, .flags = tfm->crt_flags };
-
-       crypto_hash_init(&desc);
-}
-EXPORT_SYMBOL_GPL(crypto_digest_init);
-
-void crypto_digest_update(struct crypto_tfm *tfm,
-                         struct scatterlist *sg, unsigned int nsg)
-{
-       struct crypto_hash *hash = crypto_hash_cast(tfm);
-       struct hash_desc desc = { .tfm = hash, .flags = tfm->crt_flags };
-       unsigned int nbytes = 0;
-       unsigned int i;
-
-       for (i = 0; i < nsg; i++)
-               nbytes += sg[i].length;
-
-       crypto_hash_update(&desc, sg, nbytes);
-}
-EXPORT_SYMBOL_GPL(crypto_digest_update);
-
-void crypto_digest_final(struct crypto_tfm *tfm, u8 *out)
-{
-       struct crypto_hash *hash = crypto_hash_cast(tfm);
-       struct hash_desc desc = { .tfm = hash, .flags = tfm->crt_flags };
-
-       crypto_hash_final(&desc, out);
-}
-EXPORT_SYMBOL_GPL(crypto_digest_final);
-
-void crypto_digest_digest(struct crypto_tfm *tfm,
-                         struct scatterlist *sg, unsigned int nsg, u8 *out)
-{
-       struct crypto_hash *hash = crypto_hash_cast(tfm);
-       struct hash_desc desc = { .tfm = hash, .flags = tfm->crt_flags };
-       unsigned int nbytes = 0;
-       unsigned int i;
-
-       for (i = 0; i < nsg; i++)
-               nbytes += sg[i].length;
-
-       crypto_hash_digest(&desc, sg, nbytes, out);
-}
-EXPORT_SYMBOL_GPL(crypto_digest_digest);
-
 static int init(struct hash_desc *desc)
 {
        struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm);
diff --git a/crypto/gf128mul.c b/crypto/gf128mul.c
new file mode 100644 (file)
index 0000000..0a2aadf
--- /dev/null
@@ -0,0 +1,466 @@
+/* gf128mul.c - GF(2^128) multiplication functions
+ *
+ * Copyright (c) 2003, Dr Brian Gladman, Worcester, UK.
+ * Copyright (c) 2006, Rik Snel <rsnel@cube.dyndns.org>
+ *
+ * Based on Dr Brian Gladman's (GPL'd) work published at
+ * http://fp.gladman.plus.com/cryptography_technology/index.htm
+ * See the original copyright notice below.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+/*
+ ---------------------------------------------------------------------------
+ Copyright (c) 2003, Dr Brian Gladman, Worcester, UK.   All rights reserved.
+
+ LICENSE TERMS
+
+ The free distribution and use of this software in both source and binary
+ form is allowed (with or without changes) provided that:
+
+   1. distributions of this source code include the above copyright
+      notice, this list of conditions and the following disclaimer;
+
+   2. distributions in binary form include the above copyright
+      notice, this list of conditions and the following disclaimer
+      in the documentation and/or other associated materials;
+
+   3. the copyright holder's name is not used to endorse products
+      built using this software without specific written permission.
+
+ ALTERNATIVELY, provided that this notice is retained in full, this product
+ may be distributed under the terms of the GNU General Public License (GPL),
+ in which case the provisions of the GPL apply INSTEAD OF those given above.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explicit or implied warranties
+ in respect of its properties, including, but not limited to, correctness
+ and/or fitness for purpose.
+ ---------------------------------------------------------------------------
+ Issue 31/01/2006
+
+ This file provides fast multiplication in GF(128) as required by several
+ cryptographic authentication modes
+*/
+
+#include <crypto/gf128mul.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#define gf128mul_dat(q) { \
+       q(0x00), q(0x01), q(0x02), q(0x03), q(0x04), q(0x05), q(0x06), q(0x07),\
+       q(0x08), q(0x09), q(0x0a), q(0x0b), q(0x0c), q(0x0d), q(0x0e), q(0x0f),\
+       q(0x10), q(0x11), q(0x12), q(0x13), q(0x14), q(0x15), q(0x16), q(0x17),\
+       q(0x18), q(0x19), q(0x1a), q(0x1b), q(0x1c), q(0x1d), q(0x1e), q(0x1f),\
+       q(0x20), q(0x21), q(0x22), q(0x23), q(0x24), q(0x25), q(0x26), q(0x27),\
+       q(0x28), q(0x29), q(0x2a), q(0x2b), q(0x2c), q(0x2d), q(0x2e), q(0x2f),\
+       q(0x30), q(0x31), q(0x32), q(0x33), q(0x34), q(0x35), q(0x36), q(0x37),\
+       q(0x38), q(0x39), q(0x3a), q(0x3b), q(0x3c), q(0x3d), q(0x3e), q(0x3f),\
+       q(0x40), q(0x41), q(0x42), q(0x43), q(0x44), q(0x45), q(0x46), q(0x47),\
+       q(0x48), q(0x49), q(0x4a), q(0x4b), q(0x4c), q(0x4d), q(0x4e), q(0x4f),\
+       q(0x50), q(0x51), q(0x52), q(0x53), q(0x54), q(0x55), q(0x56), q(0x57),\
+       q(0x58), q(0x59), q(0x5a), q(0x5b), q(0x5c), q(0x5d), q(0x5e), q(0x5f),\
+       q(0x60), q(0x61), q(0x62), q(0x63), q(0x64), q(0x65), q(0x66), q(0x67),\
+       q(0x68), q(0x69), q(0x6a), q(0x6b), q(0x6c), q(0x6d), q(0x6e), q(0x6f),\
+       q(0x70), q(0x71), q(0x72), q(0x73), q(0x74), q(0x75), q(0x76), q(0x77),\
+       q(0x78), q(0x79), q(0x7a), q(0x7b), q(0x7c), q(0x7d), q(0x7e), q(0x7f),\
+       q(0x80), q(0x81), q(0x82), q(0x83), q(0x84), q(0x85), q(0x86), q(0x87),\
+       q(0x88), q(0x89), q(0x8a), q(0x8b), q(0x8c), q(0x8d), q(0x8e), q(0x8f),\
+       q(0x90), q(0x91), q(0x92), q(0x93), q(0x94), q(0x95), q(0x96), q(0x97),\
+       q(0x98), q(0x99), q(0x9a), q(0x9b), q(0x9c), q(0x9d), q(0x9e), q(0x9f),\
+       q(0xa0), q(0xa1), q(0xa2), q(0xa3), q(0xa4), q(0xa5), q(0xa6), q(0xa7),\
+       q(0xa8), q(0xa9), q(0xaa), q(0xab), q(0xac), q(0xad), q(0xae), q(0xaf),\
+       q(0xb0), q(0xb1), q(0xb2), q(0xb3), q(0xb4), q(0xb5), q(0xb6), q(0xb7),\
+       q(0xb8), q(0xb9), q(0xba), q(0xbb), q(0xbc), q(0xbd), q(0xbe), q(0xbf),\
+       q(0xc0), q(0xc1), q(0xc2), q(0xc3), q(0xc4), q(0xc5), q(0xc6), q(0xc7),\
+       q(0xc8), q(0xc9), q(0xca), q(0xcb), q(0xcc), q(0xcd), q(0xce), q(0xcf),\
+       q(0xd0), q(0xd1), q(0xd2), q(0xd3), q(0xd4), q(0xd5), q(0xd6), q(0xd7),\
+       q(0xd8), q(0xd9), q(0xda), q(0xdb), q(0xdc), q(0xdd), q(0xde), q(0xdf),\
+       q(0xe0), q(0xe1), q(0xe2), q(0xe3), q(0xe4), q(0xe5), q(0xe6), q(0xe7),\
+       q(0xe8), q(0xe9), q(0xea), q(0xeb), q(0xec), q(0xed), q(0xee), q(0xef),\
+       q(0xf0), q(0xf1), q(0xf2), q(0xf3), q(0xf4), q(0xf5), q(0xf6), q(0xf7),\
+       q(0xf8), q(0xf9), q(0xfa), q(0xfb), q(0xfc), q(0xfd), q(0xfe), q(0xff) \
+}
+
+/*     Given the value i in 0..255 as the byte overflow when a field element
+    in GHASH is multipled by x^8, this function will return the values that
+    are generated in the lo 16-bit word of the field value by applying the
+    modular polynomial. The values lo_byte and hi_byte are returned via the
+    macro xp_fun(lo_byte, hi_byte) so that the values can be assembled into
+    memory as required by a suitable definition of this macro operating on
+    the table above
+*/
+
+#define xx(p, q)       0x##p##q
+
+#define xda_bbe(i) ( \
+       (i & 0x80 ? xx(43, 80) : 0) ^ (i & 0x40 ? xx(21, c0) : 0) ^ \
+       (i & 0x20 ? xx(10, e0) : 0) ^ (i & 0x10 ? xx(08, 70) : 0) ^ \
+       (i & 0x08 ? xx(04, 38) : 0) ^ (i & 0x04 ? xx(02, 1c) : 0) ^ \
+       (i & 0x02 ? xx(01, 0e) : 0) ^ (i & 0x01 ? xx(00, 87) : 0) \
+)
+
+#define xda_lle(i) ( \
+       (i & 0x80 ? xx(e1, 00) : 0) ^ (i & 0x40 ? xx(70, 80) : 0) ^ \
+       (i & 0x20 ? xx(38, 40) : 0) ^ (i & 0x10 ? xx(1c, 20) : 0) ^ \
+       (i & 0x08 ? xx(0e, 10) : 0) ^ (i & 0x04 ? xx(07, 08) : 0) ^ \
+       (i & 0x02 ? xx(03, 84) : 0) ^ (i & 0x01 ? xx(01, c2) : 0) \
+)
+
+static const u16 gf128mul_table_lle[256] = gf128mul_dat(xda_lle);
+static const u16 gf128mul_table_bbe[256] = gf128mul_dat(xda_bbe);
+
+/* These functions multiply a field element by x, by x^4 and by x^8
+ * in the polynomial field representation. It uses 32-bit word operations
+ * to gain speed but compensates for machine endianess and hence works
+ * correctly on both styles of machine.
+ */
+
+static void gf128mul_x_lle(be128 *r, const be128 *x)
+{
+       u64 a = be64_to_cpu(x->a);
+       u64 b = be64_to_cpu(x->b);
+       u64 _tt = gf128mul_table_lle[(b << 7) & 0xff];
+
+       r->b = cpu_to_be64((b >> 1) | (a << 63));
+       r->a = cpu_to_be64((a >> 1) ^ (_tt << 48));
+}
+
+static void gf128mul_x_bbe(be128 *r, const be128 *x)
+{
+       u64 a = be64_to_cpu(x->a);
+       u64 b = be64_to_cpu(x->b);
+       u64 _tt = gf128mul_table_bbe[a >> 63];
+
+       r->a = cpu_to_be64((a << 1) | (b >> 63));
+       r->b = cpu_to_be64((b << 1) ^ _tt);
+}
+
+static void gf128mul_x8_lle(be128 *x)
+{
+       u64 a = be64_to_cpu(x->a);
+       u64 b = be64_to_cpu(x->b);
+       u64 _tt = gf128mul_table_lle[b & 0xff];
+
+       x->b = cpu_to_be64((b >> 8) | (a << 56));
+       x->a = cpu_to_be64((a >> 8) ^ (_tt << 48));
+}
+
+static void gf128mul_x8_bbe(be128 *x)
+{
+       u64 a = be64_to_cpu(x->a);
+       u64 b = be64_to_cpu(x->b);
+       u64 _tt = gf128mul_table_bbe[a >> 56];
+
+       x->a = cpu_to_be64((a << 8) | (b >> 56));
+       x->b = cpu_to_be64((b << 8) ^ _tt);
+}
+
+void gf128mul_lle(be128 *r, const be128 *b)
+{
+       be128 p[8];
+       int i;
+
+       p[0] = *r;
+       for (i = 0; i < 7; ++i)
+               gf128mul_x_lle(&p[i + 1], &p[i]);
+
+       memset(r, 0, sizeof(r));
+       for (i = 0;;) {
+               u8 ch = ((u8 *)b)[15 - i];
+
+               if (ch & 0x80)
+                       be128_xor(r, r, &p[0]);
+               if (ch & 0x40)
+                       be128_xor(r, r, &p[1]);
+               if (ch & 0x20)
+                       be128_xor(r, r, &p[2]);
+               if (ch & 0x10)
+                       be128_xor(r, r, &p[3]);
+               if (ch & 0x08)
+                       be128_xor(r, r, &p[4]);
+               if (ch & 0x04)
+                       be128_xor(r, r, &p[5]);
+               if (ch & 0x02)
+                       be128_xor(r, r, &p[6]);
+               if (ch & 0x01)
+                       be128_xor(r, r, &p[7]);
+
+               if (++i >= 16)
+                       break;
+
+               gf128mul_x8_lle(r);
+       }
+}
+EXPORT_SYMBOL(gf128mul_lle);
+
+void gf128mul_bbe(be128 *r, const be128 *b)
+{
+       be128 p[8];
+       int i;
+
+       p[0] = *r;
+       for (i = 0; i < 7; ++i)
+               gf128mul_x_bbe(&p[i + 1], &p[i]);
+
+       memset(r, 0, sizeof(r));
+       for (i = 0;;) {
+               u8 ch = ((u8 *)b)[i];
+
+               if (ch & 0x80)
+                       be128_xor(r, r, &p[7]);
+               if (ch & 0x40)
+                       be128_xor(r, r, &p[6]);
+               if (ch & 0x20)
+                       be128_xor(r, r, &p[5]);
+               if (ch & 0x10)
+                       be128_xor(r, r, &p[4]);
+               if (ch & 0x08)
+                       be128_xor(r, r, &p[3]);
+               if (ch & 0x04)
+                       be128_xor(r, r, &p[2]);
+               if (ch & 0x02)
+                       be128_xor(r, r, &p[1]);
+               if (ch & 0x01)
+                       be128_xor(r, r, &p[0]);
+
+               if (++i >= 16)
+                       break;
+
+               gf128mul_x8_bbe(r);
+       }
+}
+EXPORT_SYMBOL(gf128mul_bbe);
+
+/*      This version uses 64k bytes of table space.
+    A 16 byte buffer has to be multiplied by a 16 byte key
+    value in GF(128).  If we consider a GF(128) value in
+    the buffer's lowest byte, we can construct a table of
+    the 256 16 byte values that result from the 256 values
+    of this byte.  This requires 4096 bytes. But we also
+    need tables for each of the 16 higher bytes in the
+    buffer as well, which makes 64 kbytes in total.
+*/
+/* additional explanation
+ * t[0][BYTE] contains g*BYTE
+ * t[1][BYTE] contains g*x^8*BYTE
+ *  ..
+ * t[15][BYTE] contains g*x^120*BYTE */
+struct gf128mul_64k *gf128mul_init_64k_lle(const be128 *g)
+{
+       struct gf128mul_64k *t;
+       int i, j, k;
+
+       t = kzalloc(sizeof(*t), GFP_KERNEL);
+       if (!t)
+               goto out;
+
+       for (i = 0; i < 16; i++) {
+               t->t[i] = kzalloc(sizeof(*t->t[i]), GFP_KERNEL);
+               if (!t->t[i]) {
+                       gf128mul_free_64k(t);
+                       t = NULL;
+                       goto out;
+               }
+       }
+
+       t->t[0]->t[128] = *g;
+       for (j = 64; j > 0; j >>= 1)
+               gf128mul_x_lle(&t->t[0]->t[j], &t->t[0]->t[j + j]);
+
+       for (i = 0;;) {
+               for (j = 2; j < 256; j += j)
+                       for (k = 1; k < j; ++k)
+                               be128_xor(&t->t[i]->t[j + k],
+                                         &t->t[i]->t[j], &t->t[i]->t[k]);
+
+               if (++i >= 16)
+                       break;
+
+               for (j = 128; j > 0; j >>= 1) {
+                       t->t[i]->t[j] = t->t[i - 1]->t[j];
+                       gf128mul_x8_lle(&t->t[i]->t[j]);
+               }
+       }
+
+out:
+       return t;
+}
+EXPORT_SYMBOL(gf128mul_init_64k_lle);
+
+struct gf128mul_64k *gf128mul_init_64k_bbe(const be128 *g)
+{
+       struct gf128mul_64k *t;
+       int i, j, k;
+
+       t = kzalloc(sizeof(*t), GFP_KERNEL);
+       if (!t)
+               goto out;
+
+       for (i = 0; i < 16; i++) {
+               t->t[i] = kzalloc(sizeof(*t->t[i]), GFP_KERNEL);
+               if (!t->t[i]) {
+                       gf128mul_free_64k(t);
+                       t = NULL;
+                       goto out;
+               }
+       }
+
+       t->t[0]->t[1] = *g;
+       for (j = 1; j <= 64; j <<= 1)
+               gf128mul_x_bbe(&t->t[0]->t[j + j], &t->t[0]->t[j]);
+
+       for (i = 0;;) {
+               for (j = 2; j < 256; j += j)
+                       for (k = 1; k < j; ++k)
+                               be128_xor(&t->t[i]->t[j + k],
+                                         &t->t[i]->t[j], &t->t[i]->t[k]);
+
+               if (++i >= 16)
+                       break;
+
+               for (j = 128; j > 0; j >>= 1) {
+                       t->t[i]->t[j] = t->t[i - 1]->t[j];
+                       gf128mul_x8_bbe(&t->t[i]->t[j]);
+               }
+       }
+
+out:
+       return t;
+}
+EXPORT_SYMBOL(gf128mul_init_64k_bbe);
+
+void gf128mul_free_64k(struct gf128mul_64k *t)
+{
+       int i;
+
+       for (i = 0; i < 16; i++)
+               kfree(t->t[i]);
+       kfree(t);
+}
+EXPORT_SYMBOL(gf128mul_free_64k);
+
+void gf128mul_64k_lle(be128 *a, struct gf128mul_64k *t)
+{
+       u8 *ap = (u8 *)a;
+       be128 r[1];
+       int i;
+
+       *r = t->t[0]->t[ap[0]];
+       for (i = 1; i < 16; ++i)
+               be128_xor(r, r, &t->t[i]->t[ap[i]]);
+       *a = *r;
+}
+EXPORT_SYMBOL(gf128mul_64k_lle);
+
+void gf128mul_64k_bbe(be128 *a, struct gf128mul_64k *t)
+{
+       u8 *ap = (u8 *)a;
+       be128 r[1];
+       int i;
+
+       *r = t->t[0]->t[ap[15]];
+       for (i = 1; i < 16; ++i)
+               be128_xor(r, r, &t->t[i]->t[ap[15 - i]]);
+       *a = *r;
+}
+EXPORT_SYMBOL(gf128mul_64k_bbe);
+
+/*      This version uses 4k bytes of table space.
+    A 16 byte buffer has to be multiplied by a 16 byte key
+    value in GF(128).  If we consider a GF(128) value in a
+    single byte, we can construct a table of the 256 16 byte
+    values that result from the 256 values of this byte.
+    This requires 4096 bytes. If we take the highest byte in
+    the buffer and use this table to get the result, we then
+    have to multiply by x^120 to get the final value. For the
+    next highest byte the result has to be multiplied by x^112
+    and so on. But we can do this by accumulating the result
+    in an accumulator starting with the result for the top
+    byte.  We repeatedly multiply the accumulator value by
+    x^8 and then add in (i.e. xor) the 16 bytes of the next
+    lower byte in the buffer, stopping when we reach the
+    lowest byte. This requires a 4096 byte table.
+*/
+struct gf128mul_4k *gf128mul_init_4k_lle(const be128 *g)
+{
+       struct gf128mul_4k *t;
+       int j, k;
+
+       t = kzalloc(sizeof(*t), GFP_KERNEL);
+       if (!t)
+               goto out;
+
+       t->t[128] = *g;
+       for (j = 64; j > 0; j >>= 1)
+               gf128mul_x_lle(&t->t[j], &t->t[j+j]);
+
+       for (j = 2; j < 256; j += j)
+               for (k = 1; k < j; ++k)
+                       be128_xor(&t->t[j + k], &t->t[j], &t->t[k]);
+
+out:
+       return t;
+}
+EXPORT_SYMBOL(gf128mul_init_4k_lle);
+
+struct gf128mul_4k *gf128mul_init_4k_bbe(const be128 *g)
+{
+       struct gf128mul_4k *t;
+       int j, k;
+
+       t = kzalloc(sizeof(*t), GFP_KERNEL);
+       if (!t)
+               goto out;
+
+       t->t[1] = *g;
+       for (j = 1; j <= 64; j <<= 1)
+               gf128mul_x_bbe(&t->t[j + j], &t->t[j]);
+
+       for (j = 2; j < 256; j += j)
+               for (k = 1; k < j; ++k)
+                       be128_xor(&t->t[j + k], &t->t[j], &t->t[k]);
+
+out:
+       return t;
+}
+EXPORT_SYMBOL(gf128mul_init_4k_bbe);
+
+void gf128mul_4k_lle(be128 *a, struct gf128mul_4k *t)
+{
+       u8 *ap = (u8 *)a;
+       be128 r[1];
+       int i = 15;
+
+       *r = t->t[ap[15]];
+       while (i--) {
+               gf128mul_x8_lle(r);
+               be128_xor(r, r, &t->t[ap[i]]);
+       }
+       *a = *r;
+}
+EXPORT_SYMBOL(gf128mul_4k_lle);
+
+void gf128mul_4k_bbe(be128 *a, struct gf128mul_4k *t)
+{
+       u8 *ap = (u8 *)a;
+       be128 r[1];
+       int i = 0;
+
+       *r = t->t[ap[0]];
+       while (++i < 16) {
+               gf128mul_x8_bbe(r);
+               be128_xor(r, r, &t->t[ap[i]]);
+       }
+       *a = *r;
+}
+EXPORT_SYMBOL(gf128mul_4k_bbe);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Functions for multiplying elements of GF(2^128)");
diff --git a/crypto/lrw.c b/crypto/lrw.c
new file mode 100644 (file)
index 0000000..5664258
--- /dev/null
@@ -0,0 +1,301 @@
+/* LRW: as defined by Cyril Guyot in
+ *     http://grouper.ieee.org/groups/1619/email/pdf00017.pdf
+ *
+ * Copyright (c) 2006 Rik Snel <rsnel@cube.dyndns.org>
+ *
+ * Based om ecb.c
+ * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+/* This implementation is checked against the test vectors in the above
+ * document and by a test vector provided by Ken Buchanan at
+ * http://www.mail-archive.com/stds-p1619@listserv.ieee.org/msg00173.html
+ *
+ * The test vectors are included in the testing module tcrypt.[ch] */
+#include <crypto/algapi.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/scatterlist.h>
+#include <linux/slab.h>
+
+#include <crypto/b128ops.h>
+#include <crypto/gf128mul.h>
+
+struct priv {
+       struct crypto_cipher *child;
+       /* optimizes multiplying a random (non incrementing, as at the
+        * start of a new sector) value with key2, we could also have
+        * used 4k optimization tables or no optimization at all. In the
+        * latter case we would have to store key2 here */
+       struct gf128mul_64k *table;
+       /* stores:
+        *  key2*{ 0,0,...0,0,0,0,1 }, key2*{ 0,0,...0,0,0,1,1 },
+        *  key2*{ 0,0,...0,0,1,1,1 }, key2*{ 0,0,...0,1,1,1,1 }
+        *  key2*{ 0,0,...1,1,1,1,1 }, etc
+        * needed for optimized multiplication of incrementing values
+        * with key2 */
+       be128 mulinc[128];
+};
+
+static inline void setbit128_bbe(void *b, int bit)
+{
+       __set_bit(bit ^ 0x78, b);
+}
+
+static int setkey(struct crypto_tfm *parent, const u8 *key,
+                 unsigned int keylen)
+{
+       struct priv *ctx = crypto_tfm_ctx(parent);
+       struct crypto_cipher *child = ctx->child;
+       int err, i;
+       be128 tmp = { 0 };
+       int bsize = crypto_cipher_blocksize(child);
+
+       crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
+       crypto_cipher_set_flags(child, crypto_tfm_get_flags(parent) &
+                                      CRYPTO_TFM_REQ_MASK);
+       if ((err = crypto_cipher_setkey(child, key, keylen - bsize)))
+               return err;
+       crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) &
+                                    CRYPTO_TFM_RES_MASK);
+
+       if (ctx->table)
+               gf128mul_free_64k(ctx->table);
+
+       /* initialize multiplication table for Key2 */
+       ctx->table = gf128mul_init_64k_bbe((be128 *)(key + keylen - bsize));
+       if (!ctx->table)
+               return -ENOMEM;
+
+       /* initialize optimization table */
+       for (i = 0; i < 128; i++) {
+               setbit128_bbe(&tmp, i);
+               ctx->mulinc[i] = tmp;
+               gf128mul_64k_bbe(&ctx->mulinc[i], ctx->table);
+       }
+
+       return 0;
+}
+
+struct sinfo {
+       be128 t;
+       struct crypto_tfm *tfm;
+       void (*fn)(struct crypto_tfm *, u8 *, const u8 *);
+};
+
+static inline void inc(be128 *iv)
+{
+       if (!(iv->b = cpu_to_be64(be64_to_cpu(iv->b) + 1)))
+               iv->a = cpu_to_be64(be64_to_cpu(iv->a) + 1);
+}
+
+static inline void lrw_round(struct sinfo *s, void *dst, const void *src)
+{
+       be128_xor(dst, &s->t, src);             /* PP <- T xor P */
+       s->fn(s->tfm, dst, dst);                /* CC <- E(Key2,PP) */
+       be128_xor(dst, dst, &s->t);             /* C <- T xor CC */
+}
+
+/* this returns the number of consequative 1 bits starting
+ * from the right, get_index128(00 00 00 00 00 00 ... 00 00 10 FB) = 2 */
+static inline int get_index128(be128 *block)
+{
+       int x;
+       __be32 *p = (__be32 *) block;
+
+       for (p += 3, x = 0; x < 128; p--, x += 32) {
+               u32 val = be32_to_cpup(p);
+
+               if (!~val)
+                       continue;
+
+               return x + ffz(val);
+       }
+
+       return x;
+}
+
+static int crypt(struct blkcipher_desc *d,
+                struct blkcipher_walk *w, struct priv *ctx,
+                void (*fn)(struct crypto_tfm *, u8 *, const u8 *))
+{
+       int err;
+       unsigned int avail;
+       const int bs = crypto_cipher_blocksize(ctx->child);
+       struct sinfo s = {
+               .tfm = crypto_cipher_tfm(ctx->child),
+               .fn = fn
+       };
+       be128 *iv;
+       u8 *wsrc;
+       u8 *wdst;
+
+       err = blkcipher_walk_virt(d, w);
+       if (!(avail = w->nbytes))
+               return err;
+
+       wsrc = w->src.virt.addr;
+       wdst = w->dst.virt.addr;
+
+       /* calculate first value of T */
+       iv = (be128 *)w->iv;
+       s.t = *iv;
+
+       /* T <- I*Key2 */
+       gf128mul_64k_bbe(&s.t, ctx->table);
+
+       goto first;
+
+       for (;;) {
+               do {
+                       /* T <- I*Key2, using the optimization
+                        * discussed in the specification */
+                       be128_xor(&s.t, &s.t, &ctx->mulinc[get_index128(iv)]);
+                       inc(iv);
+
+first:
+                       lrw_round(&s, wdst, wsrc);
+
+                       wsrc += bs;
+                       wdst += bs;
+               } while ((avail -= bs) >= bs);
+
+               err = blkcipher_walk_done(d, w, avail);
+               if (!(avail = w->nbytes))
+                       break;
+
+               wsrc = w->src.virt.addr;
+               wdst = w->dst.virt.addr;
+       }
+
+       return err;
+}
+
+static int encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+                  struct scatterlist *src, unsigned int nbytes)
+{
+       struct priv *ctx = crypto_blkcipher_ctx(desc->tfm);
+       struct blkcipher_walk w;
+
+       blkcipher_walk_init(&w, dst, src, nbytes);
+       return crypt(desc, &w, ctx,
+                    crypto_cipher_alg(ctx->child)->cia_encrypt);
+}
+
+static int decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+                  struct scatterlist *src, unsigned int nbytes)
+{
+       struct priv *ctx = crypto_blkcipher_ctx(desc->tfm);
+       struct blkcipher_walk w;
+
+       blkcipher_walk_init(&w, dst, src, nbytes);
+       return crypt(desc, &w, ctx,
+                    crypto_cipher_alg(ctx->child)->cia_decrypt);
+}
+
+static int init_tfm(struct crypto_tfm *tfm)
+{
+       struct crypto_instance *inst = (void *)tfm->__crt_alg;
+       struct crypto_spawn *spawn = crypto_instance_ctx(inst);
+       struct priv *ctx = crypto_tfm_ctx(tfm);
+       u32 *flags = &tfm->crt_flags;
+
+       tfm = crypto_spawn_tfm(spawn);
+       if (IS_ERR(tfm))
+               return PTR_ERR(tfm);
+
+       if (crypto_tfm_alg_blocksize(tfm) != 16) {
+               *flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
+               return -EINVAL;
+       }
+
+       ctx->child = crypto_cipher_cast(tfm);
+       return 0;
+}
+
+static void exit_tfm(struct crypto_tfm *tfm)
+{
+       struct priv *ctx = crypto_tfm_ctx(tfm);
+       if (ctx->table)
+               gf128mul_free_64k(ctx->table);
+       crypto_free_cipher(ctx->child);
+}
+
+static struct crypto_instance *alloc(void *param, unsigned int len)
+{
+       struct crypto_instance *inst;
+       struct crypto_alg *alg;
+
+       alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_CIPHER,
+                                 CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
+       if (IS_ERR(alg))
+               return ERR_PTR(PTR_ERR(alg));
+
+       inst = crypto_alloc_instance("lrw", alg);
+       if (IS_ERR(inst))
+               goto out_put_alg;
+
+       inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER;
+       inst->alg.cra_priority = alg->cra_priority;
+       inst->alg.cra_blocksize = alg->cra_blocksize;
+
+       if (alg->cra_alignmask < 7) inst->alg.cra_alignmask = 7;
+       else inst->alg.cra_alignmask = alg->cra_alignmask;
+       inst->alg.cra_type = &crypto_blkcipher_type;
+
+       if (!(alg->cra_blocksize % 4))
+               inst->alg.cra_alignmask |= 3;
+       inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize;
+       inst->alg.cra_blkcipher.min_keysize =
+               alg->cra_cipher.cia_min_keysize + alg->cra_blocksize;
+       inst->alg.cra_blkcipher.max_keysize =
+               alg->cra_cipher.cia_max_keysize + alg->cra_blocksize;
+
+       inst->alg.cra_ctxsize = sizeof(struct priv);
+
+       inst->alg.cra_init = init_tfm;
+       inst->alg.cra_exit = exit_tfm;
+
+       inst->alg.cra_blkcipher.setkey = setkey;
+       inst->alg.cra_blkcipher.encrypt = encrypt;
+       inst->alg.cra_blkcipher.decrypt = decrypt;
+
+out_put_alg:
+       crypto_mod_put(alg);
+       return inst;
+}
+
+static void free(struct crypto_instance *inst)
+{
+       crypto_drop_spawn(crypto_instance_ctx(inst));
+       kfree(inst);
+}
+
+static struct crypto_template crypto_tmpl = {
+       .name = "lrw",
+       .alloc = alloc,
+       .free = free,
+       .module = THIS_MODULE,
+};
+
+static int __init crypto_module_init(void)
+{
+       return crypto_register_template(&crypto_tmpl);
+}
+
+static void __exit crypto_module_exit(void)
+{
+       crypto_unregister_template(&crypto_tmpl);
+}
+
+module_init(crypto_module_init);
+module_exit(crypto_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("LRW block cipher mode");
index 83307420d31c873398006cbd85286ebcf50e2965..d671e8942b1f7d2c774a46a56aada52bf76dca39 100644 (file)
@@ -906,6 +906,10 @@ static void do_test(void)
                            AES_CBC_ENC_TEST_VECTORS);
                test_cipher("cbc(aes)", DECRYPT, aes_cbc_dec_tv_template,
                            AES_CBC_DEC_TEST_VECTORS);
+               test_cipher("lrw(aes)", ENCRYPT, aes_lrw_enc_tv_template,
+                           AES_LRW_ENC_TEST_VECTORS);
+               test_cipher("lrw(aes)", DECRYPT, aes_lrw_dec_tv_template,
+                           AES_LRW_DEC_TEST_VECTORS);
 
                //CAST5
                test_cipher("ecb(cast5)", ENCRYPT, cast5_enc_tv_template,
@@ -977,6 +981,9 @@ static void do_test(void)
                test_hash("hmac(sha256)", hmac_sha256_tv_template,
                          HMAC_SHA256_TEST_VECTORS);
 
+               test_hash("xcbc(aes)", aes_xcbc128_tv_template,
+                         XCBC_AES_TEST_VECTORS);
+
                test_hash("michael_mic", michael_mic_tv_template, MICHAEL_MIC_TEST_VECTORS);
                break;
 
@@ -1052,6 +1059,10 @@ static void do_test(void)
                            AES_CBC_ENC_TEST_VECTORS);
                test_cipher("cbc(aes)", DECRYPT, aes_cbc_dec_tv_template,
                            AES_CBC_DEC_TEST_VECTORS);
+               test_cipher("lrw(aes)", ENCRYPT, aes_lrw_enc_tv_template,
+                           AES_LRW_ENC_TEST_VECTORS);
+               test_cipher("lrw(aes)", DECRYPT, aes_lrw_dec_tv_template,
+                           AES_LRW_DEC_TEST_VECTORS);
                break;
 
        case 11:
@@ -1191,6 +1202,10 @@ static void do_test(void)
                                  aes_speed_template);
                test_cipher_speed("cbc(aes)", DECRYPT, sec, NULL, 0,
                                  aes_speed_template);
+               test_cipher_speed("lrw(aes)", ENCRYPT, sec, NULL, 0,
+                                 aes_lrw_speed_template);
+               test_cipher_speed("lrw(aes)", DECRYPT, sec, NULL, 0,
+                                 aes_lrw_speed_template);
                break;
 
        case 201:
index a40c4411729ee2ea9bc8cb192ca99105ee2d978e..48a81362cb851b7e0c9163191d2a61e14ca6d2ab 100644 (file)
@@ -39,15 +39,15 @@ struct hash_testvec {
 struct cipher_testvec {
        char key[MAX_KEYLEN] __attribute__ ((__aligned__(4)));
        char iv[MAX_IVLEN];
-       char input[48];
-       char result[48];
+       char input[512];
+       char result[512];
        unsigned char tap[MAX_TAP];
        int np;
        unsigned char fail;
        unsigned char wk; /* weak key flag */
        unsigned char klen;
-       unsigned char ilen;
-       unsigned char rlen;
+       unsigned short ilen;
+       unsigned short rlen;
 };
 
 struct cipher_speed {
@@ -933,6 +933,74 @@ static struct hash_testvec hmac_sha256_tv_template[] = {
        },
 };
 
+#define XCBC_AES_TEST_VECTORS 6
+
+static struct hash_testvec aes_xcbc128_tv_template[] = {
+       {
+               .key    = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                           0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+               .plaintext = { [0 ... 15] = 0 },
+               .digest = { 0x75, 0xf0, 0x25, 0x1d, 0x52, 0x8a, 0xc0, 0x1c,
+                           0x45, 0x73, 0xdf, 0xd5, 0x84, 0xd7, 0x9f, 0x29 },
+               .psize  = 0,
+               .ksize  = 16,
+       }, {
+               .key    = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                           0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+               .plaintext = { 0x00, 0x01, 0x02 },
+               .digest = { 0x5b, 0x37, 0x65, 0x80, 0xae, 0x2f, 0x19, 0xaf,
+                           0xe7, 0x21, 0x9c, 0xee, 0xf1, 0x72, 0x75, 0x6f },
+               .psize  = 3,
+               .ksize  = 16,
+       } , {
+               .key    = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                           0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+               .plaintext = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                              0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+               .digest = { 0xd2, 0xa2, 0x46, 0xfa, 0x34, 0x9b, 0x68, 0xa7,
+                           0x99, 0x98, 0xa4, 0x39, 0x4f, 0xf7, 0xa2, 0x63 },
+               .psize  = 16,
+               .ksize  = 16,
+       }, {
+               .key    = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                           0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+               .plaintext = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                              0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+                              0x10, 0x11, 0x12, 0x13 },
+               .digest = { 0x47, 0xf5, 0x1b, 0x45, 0x64, 0x96, 0x62, 0x15,
+                           0xb8, 0x98, 0x5c, 0x63, 0x05, 0x5e, 0xd3, 0x08 },
+               .tap    = { 10, 10 },
+               .psize  = 20,
+               .np     = 2,
+               .ksize  = 16,
+       }, {
+               .key    = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                           0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+               .plaintext = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                              0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+                              0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+                              0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
+               .digest = { 0xf5, 0x4f, 0x0e, 0xc8, 0xd2, 0xb9, 0xf3, 0xd3,
+                           0x68, 0x07, 0x73, 0x4b, 0xd5, 0x28, 0x3f, 0xd4 },
+               .psize  = 32,
+               .ksize  = 16,
+       }, {
+               .key    = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                           0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+               .plaintext = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                              0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+                              0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+                              0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+                              0x20, 0x21 },
+               .digest = { 0xbe, 0xcb, 0xb3, 0xbc, 0xcd, 0xb5, 0x18, 0xa3,
+                           0x06, 0x77, 0xd5, 0x48, 0x1f, 0xb6, 0xb4, 0xd8 },
+               .tap    = { 17, 17 },
+               .psize  = 34,
+               .np     = 2,
+               .ksize  = 16,
+       }
+};
+
 /*
  * DES test vectors.
  */
@@ -1831,6 +1899,8 @@ static struct cipher_testvec cast6_dec_tv_template[] = {
 #define AES_DEC_TEST_VECTORS 3
 #define AES_CBC_ENC_TEST_VECTORS 2
 #define AES_CBC_DEC_TEST_VECTORS 2
+#define AES_LRW_ENC_TEST_VECTORS 8
+#define AES_LRW_DEC_TEST_VECTORS 8
 
 static struct cipher_testvec aes_enc_tv_template[] = {
        { /* From FIPS-197 */
@@ -1968,6 +2038,509 @@ static struct cipher_testvec aes_cbc_dec_tv_template[] = {
        },
 };
 
+static struct cipher_testvec aes_lrw_enc_tv_template[] = {
+       /* from http://grouper.ieee.org/groups/1619/email/pdf00017.pdf */
+       { /* LRW-32-AES 1 */
+               .key    = { 0x45, 0x62, 0xac, 0x25, 0xf8, 0x28, 0x17, 0x6d,
+                           0x4c, 0x26, 0x84, 0x14, 0xb5, 0x68, 0x01, 0x85,
+                           0x25, 0x8e, 0x2a, 0x05, 0xe7, 0x3e, 0x9d, 0x03,
+                           0xee, 0x5a, 0x83, 0x0c, 0xcc, 0x09, 0x4c, 0x87 },
+               .klen   = 32,
+               .iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+               .input  = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+                           0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
+               .ilen   = 16,
+               .result = { 0xf1, 0xb2, 0x73, 0xcd, 0x65, 0xa3, 0xdf, 0x5f,
+                           0xe9, 0x5d, 0x48, 0x92, 0x54, 0x63, 0x4e, 0xb8 },
+               .rlen   = 16,
+       }, { /* LRW-32-AES 2 */
+               .key    = { 0x59, 0x70, 0x47, 0x14, 0xf5, 0x57, 0x47, 0x8c,
+                           0xd7, 0x79, 0xe8, 0x0f, 0x54, 0x88, 0x79, 0x44,
+                           0x0d, 0x48, 0xf0, 0xb7, 0xb1, 0x5a, 0x53, 0xea,
+                           0x1c, 0xaa, 0x6b, 0x29, 0xc2, 0xca, 0xfb, 0xaf
+               },
+               .klen   = 32,
+               .iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
+               .input  = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+                           0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
+               .ilen   = 16,
+               .result = { 0x00, 0xc8, 0x2b, 0xae, 0x95, 0xbb, 0xcd, 0xe5,
+                           0x27, 0x4f, 0x07, 0x69, 0xb2, 0x60, 0xe1, 0x36 },
+               .rlen   = 16,
+       }, { /* LRW-32-AES 3 */
+               .key    = { 0xd8, 0x2a, 0x91, 0x34, 0xb2, 0x6a, 0x56, 0x50,
+                           0x30, 0xfe, 0x69, 0xe2, 0x37, 0x7f, 0x98, 0x47,
+                           0xcd, 0xf9, 0x0b, 0x16, 0x0c, 0x64, 0x8f, 0xb6,
+                           0xb0, 0x0d, 0x0d, 0x1b, 0xae, 0x85, 0x87, 0x1f },
+               .klen   = 32,
+               .iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 },
+               .input  = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+                           0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
+               .ilen   = 16,
+               .result = { 0x76, 0x32, 0x21, 0x83, 0xed, 0x8f, 0xf1, 0x82,
+                           0xf9, 0x59, 0x62, 0x03, 0x69, 0x0e, 0x5e, 0x01 },
+               .rlen   = 16,
+       }, { /* LRW-32-AES 4 */
+               .key    = { 0x0f, 0x6a, 0xef, 0xf8, 0xd3, 0xd2, 0xbb, 0x15,
+                           0x25, 0x83, 0xf7, 0x3c, 0x1f, 0x01, 0x28, 0x74,
+                           0xca, 0xc6, 0xbc, 0x35, 0x4d, 0x4a, 0x65, 0x54,
+                           0x90, 0xae, 0x61, 0xcf, 0x7b, 0xae, 0xbd, 0xcc,
+                           0xad, 0xe4, 0x94, 0xc5, 0x4a, 0x29, 0xae, 0x70 },
+               .klen   = 40,
+               .iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+               .input  = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+                           0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
+               .ilen   = 16,
+               .result = { 0x9c, 0x0f, 0x15, 0x2f, 0x55, 0xa2, 0xd8, 0xf0,
+                           0xd6, 0x7b, 0x8f, 0x9e, 0x28, 0x22, 0xbc, 0x41 },
+               .rlen   = 16,
+       }, { /* LRW-32-AES 5 */
+               .key    = { 0x8a, 0xd4, 0xee, 0x10, 0x2f, 0xbd, 0x81, 0xff,
+                           0xf8, 0x86, 0xce, 0xac, 0x93, 0xc5, 0xad, 0xc6,
+                           0xa0, 0x19, 0x07, 0xc0, 0x9d, 0xf7, 0xbb, 0xdd,
+                           0x52, 0x13, 0xb2, 0xb7, 0xf0, 0xff, 0x11, 0xd8,
+                           0xd6, 0x08, 0xd0, 0xcd, 0x2e, 0xb1, 0x17, 0x6f },
+               .klen   = 40,
+               .iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 },
+               .input  = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+                           0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
+               .ilen   = 16,
+               .result = { 0xd4, 0x27, 0x6a, 0x7f, 0x14, 0x91, 0x3d, 0x65,
+                           0xc8, 0x60, 0x48, 0x02, 0x87, 0xe3, 0x34, 0x06 },
+               .rlen   = 16,
+       }, { /* LRW-32-AES 6 */
+               .key    = { 0xf8, 0xd4, 0x76, 0xff, 0xd6, 0x46, 0xee, 0x6c,
+                           0x23, 0x84, 0xcb, 0x1c, 0x77, 0xd6, 0x19, 0x5d,
+                           0xfe, 0xf1, 0xa9, 0xf3, 0x7b, 0xbc, 0x8d, 0x21,
+                           0xa7, 0x9c, 0x21, 0xf8, 0xcb, 0x90, 0x02, 0x89,
+                           0xa8, 0x45, 0x34, 0x8e, 0xc8, 0xc5, 0xb5, 0xf1,
+                           0x26, 0xf5, 0x0e, 0x76, 0xfe, 0xfd, 0x1b, 0x1e },
+               .klen   = 48,
+               .iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+               .input  = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+                           0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
+               .ilen   = 16,
+               .result = { 0xbd, 0x06, 0xb8, 0xe1, 0xdb, 0x98, 0x89, 0x9e,
+                           0xc4, 0x98, 0xe4, 0x91, 0xcf, 0x1c, 0x70, 0x2b },
+               .rlen   = 16,
+       }, { /* LRW-32-AES 7 */
+               .key    = { 0xfb, 0x76, 0x15, 0xb2, 0x3d, 0x80, 0x89, 0x1d,
+                           0xd4, 0x70, 0x98, 0x0b, 0xc7, 0x95, 0x84, 0xc8,
+                           0xb2, 0xfb, 0x64, 0xce, 0x60, 0x97, 0x87, 0x8d,
+                           0x17, 0xfc, 0xe4, 0x5a, 0x49, 0xe8, 0x30, 0xb7,
+                           0x6e, 0x78, 0x17, 0xe7, 0x2d, 0x5e, 0x12, 0xd4,
+                           0x60, 0x64, 0x04, 0x7a, 0xf1, 0x2f, 0x9e, 0x0c },
+               .klen   = 48,
+               .iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 },
+               .input  = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+                           0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
+               .ilen   = 16,
+               .result = { 0x5b, 0x90, 0x8e, 0xc1, 0xab, 0xdd, 0x67, 0x5f,
+                           0x3d, 0x69, 0x8a, 0x95, 0x53, 0xc8, 0x9c, 0xe5 },
+               .rlen   = 16,
+       }, {
+/* http://www.mail-archive.com/stds-p1619@listserv.ieee.org/msg00173.html */
+               .key    = { 0xf8, 0xd4, 0x76, 0xff, 0xd6, 0x46, 0xee, 0x6c,
+                           0x23, 0x84, 0xcb, 0x1c, 0x77, 0xd6, 0x19, 0x5d,
+                           0xfe, 0xf1, 0xa9, 0xf3, 0x7b, 0xbc, 0x8d, 0x21,
+                           0xa7, 0x9c, 0x21, 0xf8, 0xcb, 0x90, 0x02, 0x89,
+                           0xa8, 0x45, 0x34, 0x8e, 0xc8, 0xc5, 0xb5, 0xf1,
+                           0x26, 0xf5, 0x0e, 0x76, 0xfe, 0xfd, 0x1b, 0x1e },
+               .klen   = 48,
+               .iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+               .input  = { 0x05, 0x11, 0xb7, 0x18, 0xab, 0xc6, 0x2d, 0xac,
+                           0x70, 0x5d, 0xf6, 0x22, 0x94, 0xcd, 0xe5, 0x6c,
+                           0x17, 0x6b, 0xf6, 0x1c, 0xf0, 0xf3, 0x6e, 0xf8,
+                           0x50, 0x38, 0x1f, 0x71, 0x49, 0xb6, 0x57, 0xd6,
+                           0x8f, 0xcb, 0x8d, 0x6b, 0xe3, 0xa6, 0x29, 0x90,
+                           0xfe, 0x2a, 0x62, 0x82, 0xae, 0x6d, 0x8b, 0xf6,
+                           0xad, 0x1e, 0x9e, 0x20, 0x5f, 0x38, 0xbe, 0x04,
+                           0xda, 0x10, 0x8e, 0xed, 0xa2, 0xa4, 0x87, 0xab,
+                           0xda, 0x6b, 0xb4, 0x0c, 0x75, 0xba, 0xd3, 0x7c,
+                           0xc9, 0xac, 0x42, 0x31, 0x95, 0x7c, 0xc9, 0x04,
+                           0xeb, 0xd5, 0x6e, 0x32, 0x69, 0x8a, 0xdb, 0xa6,
+                           0x15, 0xd7, 0x3f, 0x4f, 0x2f, 0x66, 0x69, 0x03,
+                           0x9c, 0x1f, 0x54, 0x0f, 0xde, 0x1f, 0xf3, 0x65,
+                           0x4c, 0x96, 0x12, 0xed, 0x7c, 0x92, 0x03, 0x01,
+                           0x6f, 0xbc, 0x35, 0x93, 0xac, 0xf1, 0x27, 0xf1,
+                           0xb4, 0x96, 0x82, 0x5a, 0x5f, 0xb0, 0xa0, 0x50,
+                           0x89, 0xa4, 0x8e, 0x66, 0x44, 0x85, 0xcc, 0xfd,
+                           0x33, 0x14, 0x70, 0xe3, 0x96, 0xb2, 0xc3, 0xd3,
+                           0xbb, 0x54, 0x5a, 0x1a, 0xf9, 0x74, 0xa2, 0xc5,
+                           0x2d, 0x64, 0x75, 0xdd, 0xb4, 0x54, 0xe6, 0x74,
+                           0x8c, 0xd3, 0x9d, 0x9e, 0x86, 0xab, 0x51, 0x53,
+                           0xb7, 0x93, 0x3e, 0x6f, 0xd0, 0x4e, 0x2c, 0x40,
+                           0xf6, 0xa8, 0x2e, 0x3e, 0x9d, 0xf4, 0x66, 0xa5,
+                           0x76, 0x12, 0x73, 0x44, 0x1a, 0x56, 0xd7, 0x72,
+                           0x88, 0xcd, 0x21, 0x8c, 0x4c, 0x0f, 0xfe, 0xda,
+                           0x95, 0xe0, 0x3a, 0xa6, 0xa5, 0x84, 0x46, 0xcd,
+                           0xd5, 0x3e, 0x9d, 0x3a, 0xe2, 0x67, 0xe6, 0x60,
+                           0x1a, 0xe2, 0x70, 0x85, 0x58, 0xc2, 0x1b, 0x09,
+                           0xe1, 0xd7, 0x2c, 0xca, 0xad, 0xa8, 0x8f, 0xf9,
+                           0xac, 0xb3, 0x0e, 0xdb, 0xca, 0x2e, 0xe2, 0xb8,
+                           0x51, 0x71, 0xd9, 0x3c, 0x6c, 0xf1, 0x56, 0xf8,
+                           0xea, 0x9c, 0xf1, 0xfb, 0x0c, 0xe6, 0xb7, 0x10,
+                           0x1c, 0xf8, 0xa9, 0x7c, 0xe8, 0x53, 0x35, 0xc1,
+                           0x90, 0x3e, 0x76, 0x4a, 0x74, 0xa4, 0x21, 0x2c,
+                           0xf6, 0x2c, 0x4e, 0x0f, 0x94, 0x3a, 0x88, 0x2e,
+                           0x41, 0x09, 0x6a, 0x33, 0x7d, 0xf6, 0xdd, 0x3f,
+                           0x8d, 0x23, 0x31, 0x74, 0x84, 0xeb, 0x88, 0x6e,
+                           0xcc, 0xb9, 0xbc, 0x22, 0x83, 0x19, 0x07, 0x22,
+                           0xa5, 0x2d, 0xdf, 0xa5, 0xf3, 0x80, 0x85, 0x78,
+                           0x84, 0x39, 0x6a, 0x6d, 0x6a, 0x99, 0x4f, 0xa5,
+                           0x15, 0xfe, 0x46, 0xb0, 0xe4, 0x6c, 0xa5, 0x41,
+                           0x3c, 0xce, 0x8f, 0x42, 0x60, 0x71, 0xa7, 0x75,
+                           0x08, 0x40, 0x65, 0x8a, 0x82, 0xbf, 0xf5, 0x43,
+                           0x71, 0x96, 0xa9, 0x4d, 0x44, 0x8a, 0x20, 0xbe,
+                           0xfa, 0x4d, 0xbb, 0xc0, 0x7d, 0x31, 0x96, 0x65,
+                           0xe7, 0x75, 0xe5, 0x3e, 0xfd, 0x92, 0x3b, 0xc9,
+                           0x55, 0xbb, 0x16, 0x7e, 0xf7, 0xc2, 0x8c, 0xa4,
+                           0x40, 0x1d, 0xe5, 0xef, 0x0e, 0xdf, 0xe4, 0x9a,
+                           0x62, 0x73, 0x65, 0xfd, 0x46, 0x63, 0x25, 0x3d,
+                           0x2b, 0xaf, 0xe5, 0x64, 0xfe, 0xa5, 0x5c, 0xcf,
+                           0x24, 0xf3, 0xb4, 0xac, 0x64, 0xba, 0xdf, 0x4b,
+                           0xc6, 0x96, 0x7d, 0x81, 0x2d, 0x8d, 0x97, 0xf7,
+                           0xc5, 0x68, 0x77, 0x84, 0x32, 0x2b, 0xcc, 0x85,
+                           0x74, 0x96, 0xf0, 0x12, 0x77, 0x61, 0xb9, 0xeb,
+                           0x71, 0xaa, 0x82, 0xcb, 0x1c, 0xdb, 0x89, 0xc8,
+                           0xc6, 0xb5, 0xe3, 0x5c, 0x7d, 0x39, 0x07, 0x24,
+                           0xda, 0x39, 0x87, 0x45, 0xc0, 0x2b, 0xbb, 0x01,
+                           0xac, 0xbc, 0x2a, 0x5c, 0x7f, 0xfc, 0xe8, 0xce,
+                           0x6d, 0x9c, 0x6f, 0xed, 0xd3, 0xc1, 0xa1, 0xd6,
+                           0xc5, 0x55, 0xa9, 0x66, 0x2f, 0xe1, 0xc8, 0x32,
+                           0xa6, 0x5d, 0xa4, 0x3a, 0x98, 0x73, 0xe8, 0x45,
+                           0xa4, 0xc7, 0xa8, 0xb4, 0xf6, 0x13, 0x03, 0xf6,
+                           0xe9, 0x2e, 0xc4, 0x29, 0x0f, 0x84, 0xdb, 0xc4,
+                           0x21, 0xc4, 0xc2, 0x75, 0x67, 0x89, 0x37, 0x0a },
+               .ilen   = 512,
+               .result = { 0x1a, 0x1d, 0xa9, 0x30, 0xad, 0xf9, 0x2f, 0x9b,
+                           0xb6, 0x1d, 0xae, 0xef, 0xf0, 0x2f, 0xf8, 0x5a,
+                           0x39, 0x3c, 0xbf, 0x2a, 0xb2, 0x45, 0xb2, 0x23,
+                           0x1b, 0x63, 0x3c, 0xcf, 0xaa, 0xbe, 0xcf, 0x4e,
+                           0xfa, 0xe8, 0x29, 0xc2, 0x20, 0x68, 0x2b, 0x3c,
+                           0x2e, 0x8b, 0xf7, 0x6e, 0x25, 0xbd, 0xe3, 0x3d,
+                           0x66, 0x27, 0xd6, 0xaf, 0xd6, 0x64, 0x3e, 0xe3,
+                           0xe8, 0x58, 0x46, 0x97, 0x39, 0x51, 0x07, 0xde,
+                           0xcb, 0x37, 0xbc, 0xa9, 0xc0, 0x5f, 0x75, 0xc3,
+                           0x0e, 0x84, 0x23, 0x1d, 0x16, 0xd4, 0x1c, 0x59,
+                           0x9c, 0x1a, 0x02, 0x55, 0xab, 0x3a, 0x97, 0x1d,
+                           0xdf, 0xdd, 0xc7, 0x06, 0x51, 0xd7, 0x70, 0xae,
+                           0x23, 0xc6, 0x8c, 0xf5, 0x1e, 0xa0, 0xe5, 0x82,
+                           0xb8, 0xb2, 0xbf, 0x04, 0xa0, 0x32, 0x8e, 0x68,
+                           0xeb, 0xaf, 0x6e, 0x2d, 0x94, 0x22, 0x2f, 0xce,
+                           0x4c, 0xb5, 0x59, 0xe2, 0xa2, 0x2f, 0xa0, 0x98,
+                           0x1a, 0x97, 0xc6, 0xd4, 0xb5, 0x00, 0x59, 0xf2,
+                           0x84, 0x14, 0x72, 0xb1, 0x9a, 0x6e, 0xa3, 0x7f,
+                           0xea, 0x20, 0xe7, 0xcb, 0x65, 0x77, 0x3a, 0xdf,
+                           0xc8, 0x97, 0x67, 0x15, 0xc2, 0x2a, 0x27, 0xcc,
+                           0x18, 0x55, 0xa1, 0x24, 0x0b, 0x24, 0x24, 0xaf,
+                           0x5b, 0xec, 0x68, 0xb8, 0xc8, 0xf5, 0xba, 0x63,
+                           0xff, 0xed, 0x89, 0xce, 0xd5, 0x3d, 0x88, 0xf3,
+                           0x25, 0xef, 0x05, 0x7c, 0x3a, 0xef, 0xeb, 0xd8,
+                           0x7a, 0x32, 0x0d, 0xd1, 0x1e, 0x58, 0x59, 0x99,
+                           0x90, 0x25, 0xb5, 0x26, 0xb0, 0xe3, 0x2b, 0x6c,
+                           0x4c, 0xa9, 0x8b, 0x84, 0x4f, 0x5e, 0x01, 0x50,
+                           0x41, 0x30, 0x58, 0xc5, 0x62, 0x74, 0x52, 0x1d,
+                           0x45, 0x24, 0x6a, 0x42, 0x64, 0x4f, 0x97, 0x1c,
+                           0xa8, 0x66, 0xb5, 0x6d, 0x79, 0xd4, 0x0d, 0x48,
+                           0xc5, 0x5f, 0xf3, 0x90, 0x32, 0xdd, 0xdd, 0xe1,
+                           0xe4, 0xa9, 0x9f, 0xfc, 0xc3, 0x52, 0x5a, 0x46,
+                           0xe4, 0x81, 0x84, 0x95, 0x36, 0x59, 0x7a, 0x6b,
+                           0xaa, 0xb3, 0x60, 0xad, 0xce, 0x9f, 0x9f, 0x28,
+                           0xe0, 0x01, 0x75, 0x22, 0xc4, 0x4e, 0xa9, 0x62,
+                           0x5c, 0x62, 0x0d, 0x00, 0xcb, 0x13, 0xe8, 0x43,
+                           0x72, 0xd4, 0x2d, 0x53, 0x46, 0xb5, 0xd1, 0x16,
+                           0x22, 0x18, 0xdf, 0x34, 0x33, 0xf5, 0xd6, 0x1c,
+                           0xb8, 0x79, 0x78, 0x97, 0x94, 0xff, 0x72, 0x13,
+                           0x4c, 0x27, 0xfc, 0xcb, 0xbf, 0x01, 0x53, 0xa6,
+                           0xb4, 0x50, 0x6e, 0xde, 0xdf, 0xb5, 0x43, 0xa4,
+                           0x59, 0xdf, 0x52, 0xf9, 0x7c, 0xe0, 0x11, 0x6f,
+                           0x2d, 0x14, 0x8e, 0x24, 0x61, 0x2c, 0xe1, 0x17,
+                           0xcc, 0xce, 0x51, 0x0c, 0x19, 0x8a, 0x82, 0x30,
+                           0x94, 0xd5, 0x3d, 0x6a, 0x53, 0x06, 0x5e, 0xbd,
+                           0xb7, 0xeb, 0xfa, 0xfd, 0x27, 0x51, 0xde, 0x85,
+                           0x1e, 0x86, 0x53, 0x11, 0x53, 0x94, 0x00, 0xee,
+                           0x2b, 0x8c, 0x08, 0x2a, 0xbf, 0xdd, 0xae, 0x11,
+                           0xcb, 0x1e, 0xa2, 0x07, 0x9a, 0x80, 0xcf, 0x62,
+                           0x9b, 0x09, 0xdc, 0x95, 0x3c, 0x96, 0x8e, 0xb1,
+                           0x09, 0xbd, 0xe4, 0xeb, 0xdb, 0xca, 0x70, 0x7a,
+                           0x9e, 0xfa, 0x31, 0x18, 0x45, 0x3c, 0x21, 0x33,
+                           0xb0, 0xb3, 0x2b, 0xea, 0xf3, 0x71, 0x2d, 0xe1,
+                           0x03, 0xad, 0x1b, 0x48, 0xd4, 0x67, 0x27, 0xf0,
+                           0x62, 0xe4, 0x3d, 0xfb, 0x9b, 0x08, 0x76, 0xe7,
+                           0xdd, 0x2b, 0x01, 0x39, 0x04, 0x5a, 0x58, 0x7a,
+                           0xf7, 0x11, 0x90, 0xec, 0xbd, 0x51, 0x5c, 0x32,
+                           0x6b, 0xd7, 0x35, 0x39, 0x02, 0x6b, 0xf2, 0xa6,
+                           0xd0, 0x0d, 0x07, 0xe1, 0x06, 0xc4, 0x5b, 0x7d,
+                           0xe4, 0x6a, 0xd7, 0xee, 0x15, 0x1f, 0x83, 0xb4,
+                           0xa3, 0xa7, 0x5e, 0xc3, 0x90, 0xb7, 0xef, 0xd3,
+                           0xb7, 0x4f, 0xf8, 0x92, 0x4c, 0xb7, 0x3c, 0x29,
+                           0xcd, 0x7e, 0x2b, 0x5d, 0x43, 0xea, 0x42, 0xe7,
+                           0x74, 0x3f, 0x7d, 0x58, 0x88, 0x75, 0xde, 0x3e },
+               .rlen   = 512,
+       }
+};
+
+static struct cipher_testvec aes_lrw_dec_tv_template[] = {
+       /* from http://grouper.ieee.org/groups/1619/email/pdf00017.pdf */
+       /* same as enc vectors with input and result reversed */
+       { /* LRW-32-AES 1 */
+               .key    = { 0x45, 0x62, 0xac, 0x25, 0xf8, 0x28, 0x17, 0x6d,
+                           0x4c, 0x26, 0x84, 0x14, 0xb5, 0x68, 0x01, 0x85,
+                           0x25, 0x8e, 0x2a, 0x05, 0xe7, 0x3e, 0x9d, 0x03,
+                           0xee, 0x5a, 0x83, 0x0c, 0xcc, 0x09, 0x4c, 0x87 },
+               .klen   = 32,
+               .iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+               .input  = { 0xf1, 0xb2, 0x73, 0xcd, 0x65, 0xa3, 0xdf, 0x5f,
+                           0xe9, 0x5d, 0x48, 0x92, 0x54, 0x63, 0x4e, 0xb8 },
+               .ilen   = 16,
+               .result = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+                           0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
+               .rlen   = 16,
+       }, { /* LRW-32-AES 2 */
+               .key    = { 0x59, 0x70, 0x47, 0x14, 0xf5, 0x57, 0x47, 0x8c,
+                           0xd7, 0x79, 0xe8, 0x0f, 0x54, 0x88, 0x79, 0x44,
+                           0x0d, 0x48, 0xf0, 0xb7, 0xb1, 0x5a, 0x53, 0xea,
+                           0x1c, 0xaa, 0x6b, 0x29, 0xc2, 0xca, 0xfb, 0xaf
+               },
+               .klen   = 32,
+               .iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
+               .input  = { 0x00, 0xc8, 0x2b, 0xae, 0x95, 0xbb, 0xcd, 0xe5,
+                           0x27, 0x4f, 0x07, 0x69, 0xb2, 0x60, 0xe1, 0x36 },
+               .ilen   = 16,
+               .result  = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+                            0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
+               .rlen   = 16,
+       }, { /* LRW-32-AES 3 */
+               .key    = { 0xd8, 0x2a, 0x91, 0x34, 0xb2, 0x6a, 0x56, 0x50,
+                           0x30, 0xfe, 0x69, 0xe2, 0x37, 0x7f, 0x98, 0x47,
+                           0xcd, 0xf9, 0x0b, 0x16, 0x0c, 0x64, 0x8f, 0xb6,
+                           0xb0, 0x0d, 0x0d, 0x1b, 0xae, 0x85, 0x87, 0x1f },
+               .klen   = 32,
+               .iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 },
+               .input  = { 0x76, 0x32, 0x21, 0x83, 0xed, 0x8f, 0xf1, 0x82,
+                           0xf9, 0x59, 0x62, 0x03, 0x69, 0x0e, 0x5e, 0x01 },
+               .ilen   = 16,
+               .result = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+                           0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
+               .rlen   = 16,
+       }, { /* LRW-32-AES 4 */
+               .key    = { 0x0f, 0x6a, 0xef, 0xf8, 0xd3, 0xd2, 0xbb, 0x15,
+                           0x25, 0x83, 0xf7, 0x3c, 0x1f, 0x01, 0x28, 0x74,
+                           0xca, 0xc6, 0xbc, 0x35, 0x4d, 0x4a, 0x65, 0x54,
+                           0x90, 0xae, 0x61, 0xcf, 0x7b, 0xae, 0xbd, 0xcc,
+                           0xad, 0xe4, 0x94, 0xc5, 0x4a, 0x29, 0xae, 0x70 },
+               .klen   = 40,
+               .iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+               .input  = { 0x9c, 0x0f, 0x15, 0x2f, 0x55, 0xa2, 0xd8, 0xf0,
+                           0xd6, 0x7b, 0x8f, 0x9e, 0x28, 0x22, 0xbc, 0x41 },
+               .ilen   = 16,
+               .result = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+                           0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
+               .rlen   = 16,
+       }, { /* LRW-32-AES 5 */
+               .key    = { 0x8a, 0xd4, 0xee, 0x10, 0x2f, 0xbd, 0x81, 0xff,
+                           0xf8, 0x86, 0xce, 0xac, 0x93, 0xc5, 0xad, 0xc6,
+                           0xa0, 0x19, 0x07, 0xc0, 0x9d, 0xf7, 0xbb, 0xdd,
+                           0x52, 0x13, 0xb2, 0xb7, 0xf0, 0xff, 0x11, 0xd8,
+                           0xd6, 0x08, 0xd0, 0xcd, 0x2e, 0xb1, 0x17, 0x6f },
+               .klen   = 40,
+               .iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 },
+               .input  = { 0xd4, 0x27, 0x6a, 0x7f, 0x14, 0x91, 0x3d, 0x65,
+                           0xc8, 0x60, 0x48, 0x02, 0x87, 0xe3, 0x34, 0x06 },
+               .ilen   = 16,
+               .result = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+                           0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
+               .rlen   = 16,
+       }, { /* LRW-32-AES 6 */
+               .key    = { 0xf8, 0xd4, 0x76, 0xff, 0xd6, 0x46, 0xee, 0x6c,
+                           0x23, 0x84, 0xcb, 0x1c, 0x77, 0xd6, 0x19, 0x5d,
+                           0xfe, 0xf1, 0xa9, 0xf3, 0x7b, 0xbc, 0x8d, 0x21,
+                           0xa7, 0x9c, 0x21, 0xf8, 0xcb, 0x90, 0x02, 0x89,
+                           0xa8, 0x45, 0x34, 0x8e, 0xc8, 0xc5, 0xb5, 0xf1,
+                           0x26, 0xf5, 0x0e, 0x76, 0xfe, 0xfd, 0x1b, 0x1e },
+               .klen   = 48,
+               .iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+               .input  = { 0xbd, 0x06, 0xb8, 0xe1, 0xdb, 0x98, 0x89, 0x9e,
+                           0xc4, 0x98, 0xe4, 0x91, 0xcf, 0x1c, 0x70, 0x2b },
+               .ilen   = 16,
+               .result = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+                           0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
+               .rlen   = 16,
+       }, { /* LRW-32-AES 7 */
+               .key    = { 0xfb, 0x76, 0x15, 0xb2, 0x3d, 0x80, 0x89, 0x1d,
+                           0xd4, 0x70, 0x98, 0x0b, 0xc7, 0x95, 0x84, 0xc8,
+                           0xb2, 0xfb, 0x64, 0xce, 0x60, 0x97, 0x87, 0x8d,
+                           0x17, 0xfc, 0xe4, 0x5a, 0x49, 0xe8, 0x30, 0xb7,
+                           0x6e, 0x78, 0x17, 0xe7, 0x2d, 0x5e, 0x12, 0xd4,
+                           0x60, 0x64, 0x04, 0x7a, 0xf1, 0x2f, 0x9e, 0x0c },
+               .klen   = 48,
+               .iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 },
+               .input  = { 0x5b, 0x90, 0x8e, 0xc1, 0xab, 0xdd, 0x67, 0x5f,
+                           0x3d, 0x69, 0x8a, 0x95, 0x53, 0xc8, 0x9c, 0xe5 },
+               .ilen   = 16,
+               .result = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+                           0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
+               .rlen   = 16,
+       }, {
+/* http://www.mail-archive.com/stds-p1619@listserv.ieee.org/msg00173.html */
+               .key    = { 0xf8, 0xd4, 0x76, 0xff, 0xd6, 0x46, 0xee, 0x6c,
+                           0x23, 0x84, 0xcb, 0x1c, 0x77, 0xd6, 0x19, 0x5d,
+                           0xfe, 0xf1, 0xa9, 0xf3, 0x7b, 0xbc, 0x8d, 0x21,
+                           0xa7, 0x9c, 0x21, 0xf8, 0xcb, 0x90, 0x02, 0x89,
+                           0xa8, 0x45, 0x34, 0x8e, 0xc8, 0xc5, 0xb5, 0xf1,
+                           0x26, 0xf5, 0x0e, 0x76, 0xfe, 0xfd, 0x1b, 0x1e },
+               .klen   = 48,
+               .iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+               .input  = { 0x1a, 0x1d, 0xa9, 0x30, 0xad, 0xf9, 0x2f, 0x9b,
+                           0xb6, 0x1d, 0xae, 0xef, 0xf0, 0x2f, 0xf8, 0x5a,
+                           0x39, 0x3c, 0xbf, 0x2a, 0xb2, 0x45, 0xb2, 0x23,
+                           0x1b, 0x63, 0x3c, 0xcf, 0xaa, 0xbe, 0xcf, 0x4e,
+                           0xfa, 0xe8, 0x29, 0xc2, 0x20, 0x68, 0x2b, 0x3c,
+                           0x2e, 0x8b, 0xf7, 0x6e, 0x25, 0xbd, 0xe3, 0x3d,
+                           0x66, 0x27, 0xd6, 0xaf, 0xd6, 0x64, 0x3e, 0xe3,
+                           0xe8, 0x58, 0x46, 0x97, 0x39, 0x51, 0x07, 0xde,
+                           0xcb, 0x37, 0xbc, 0xa9, 0xc0, 0x5f, 0x75, 0xc3,
+                           0x0e, 0x84, 0x23, 0x1d, 0x16, 0xd4, 0x1c, 0x59,
+                           0x9c, 0x1a, 0x02, 0x55, 0xab, 0x3a, 0x97, 0x1d,
+                           0xdf, 0xdd, 0xc7, 0x06, 0x51, 0xd7, 0x70, 0xae,
+                           0x23, 0xc6, 0x8c, 0xf5, 0x1e, 0xa0, 0xe5, 0x82,
+                           0xb8, 0xb2, 0xbf, 0x04, 0xa0, 0x32, 0x8e, 0x68,
+                           0xeb, 0xaf, 0x6e, 0x2d, 0x94, 0x22, 0x2f, 0xce,
+                           0x4c, 0xb5, 0x59, 0xe2, 0xa2, 0x2f, 0xa0, 0x98,
+                           0x1a, 0x97, 0xc6, 0xd4, 0xb5, 0x00, 0x59, 0xf2,
+                           0x84, 0x14, 0x72, 0xb1, 0x9a, 0x6e, 0xa3, 0x7f,
+                           0xea, 0x20, 0xe7, 0xcb, 0x65, 0x77, 0x3a, 0xdf,
+                           0xc8, 0x97, 0x67, 0x15, 0xc2, 0x2a, 0x27, 0xcc,
+                           0x18, 0x55, 0xa1, 0x24, 0x0b, 0x24, 0x24, 0xaf,
+                           0x5b, 0xec, 0x68, 0xb8, 0xc8, 0xf5, 0xba, 0x63,
+                           0xff, 0xed, 0x89, 0xce, 0xd5, 0x3d, 0x88, 0xf3,
+                           0x25, 0xef, 0x05, 0x7c, 0x3a, 0xef, 0xeb, 0xd8,
+                           0x7a, 0x32, 0x0d, 0xd1, 0x1e, 0x58, 0x59, 0x99,
+                           0x90, 0x25, 0xb5, 0x26, 0xb0, 0xe3, 0x2b, 0x6c,
+                           0x4c, 0xa9, 0x8b, 0x84, 0x4f, 0x5e, 0x01, 0x50,
+                           0x41, 0x30, 0x58, 0xc5, 0x62, 0x74, 0x52, 0x1d,
+                           0x45, 0x24, 0x6a, 0x42, 0x64, 0x4f, 0x97, 0x1c,
+                           0xa8, 0x66, 0xb5, 0x6d, 0x79, 0xd4, 0x0d, 0x48,
+                           0xc5, 0x5f, 0xf3, 0x90, 0x32, 0xdd, 0xdd, 0xe1,
+                           0xe4, 0xa9, 0x9f, 0xfc, 0xc3, 0x52, 0x5a, 0x46,
+                           0xe4, 0x81, 0x84, 0x95, 0x36, 0x59, 0x7a, 0x6b,
+                           0xaa, 0xb3, 0x60, 0xad, 0xce, 0x9f, 0x9f, 0x28,
+                           0xe0, 0x01, 0x75, 0x22, 0xc4, 0x4e, 0xa9, 0x62,
+                           0x5c, 0x62, 0x0d, 0x00, 0xcb, 0x13, 0xe8, 0x43,
+                           0x72, 0xd4, 0x2d, 0x53, 0x46, 0xb5, 0xd1, 0x16,
+                           0x22, 0x18, 0xdf, 0x34, 0x33, 0xf5, 0xd6, 0x1c,
+                           0xb8, 0x79, 0x78, 0x97, 0x94, 0xff, 0x72, 0x13,
+                           0x4c, 0x27, 0xfc, 0xcb, 0xbf, 0x01, 0x53, 0xa6,
+                           0xb4, 0x50, 0x6e, 0xde, 0xdf, 0xb5, 0x43, 0xa4,
+                           0x59, 0xdf, 0x52, 0xf9, 0x7c, 0xe0, 0x11, 0x6f,
+                           0x2d, 0x14, 0x8e, 0x24, 0x61, 0x2c, 0xe1, 0x17,
+                           0xcc, 0xce, 0x51, 0x0c, 0x19, 0x8a, 0x82, 0x30,
+                           0x94, 0xd5, 0x3d, 0x6a, 0x53, 0x06, 0x5e, 0xbd,
+                           0xb7, 0xeb, 0xfa, 0xfd, 0x27, 0x51, 0xde, 0x85,
+                           0x1e, 0x86, 0x53, 0x11, 0x53, 0x94, 0x00, 0xee,
+                           0x2b, 0x8c, 0x08, 0x2a, 0xbf, 0xdd, 0xae, 0x11,
+                           0xcb, 0x1e, 0xa2, 0x07, 0x9a, 0x80, 0xcf, 0x62,
+                           0x9b, 0x09, 0xdc, 0x95, 0x3c, 0x96, 0x8e, 0xb1,
+                           0x09, 0xbd, 0xe4, 0xeb, 0xdb, 0xca, 0x70, 0x7a,
+                           0x9e, 0xfa, 0x31, 0x18, 0x45, 0x3c, 0x21, 0x33,
+                           0xb0, 0xb3, 0x2b, 0xea, 0xf3, 0x71, 0x2d, 0xe1,
+                           0x03, 0xad, 0x1b, 0x48, 0xd4, 0x67, 0x27, 0xf0,
+                           0x62, 0xe4, 0x3d, 0xfb, 0x9b, 0x08, 0x76, 0xe7,
+                           0xdd, 0x2b, 0x01, 0x39, 0x04, 0x5a, 0x58, 0x7a,
+                           0xf7, 0x11, 0x90, 0xec, 0xbd, 0x51, 0x5c, 0x32,
+                           0x6b, 0xd7, 0x35, 0x39, 0x02, 0x6b, 0xf2, 0xa6,
+                           0xd0, 0x0d, 0x07, 0xe1, 0x06, 0xc4, 0x5b, 0x7d,
+                           0xe4, 0x6a, 0xd7, 0xee, 0x15, 0x1f, 0x83, 0xb4,
+                           0xa3, 0xa7, 0x5e, 0xc3, 0x90, 0xb7, 0xef, 0xd3,
+                           0xb7, 0x4f, 0xf8, 0x92, 0x4c, 0xb7, 0x3c, 0x29,
+                           0xcd, 0x7e, 0x2b, 0x5d, 0x43, 0xea, 0x42, 0xe7,
+                           0x74, 0x3f, 0x7d, 0x58, 0x88, 0x75, 0xde, 0x3e },
+               .ilen   = 512,
+               .result = { 0x05, 0x11, 0xb7, 0x18, 0xab, 0xc6, 0x2d, 0xac,
+                           0x70, 0x5d, 0xf6, 0x22, 0x94, 0xcd, 0xe5, 0x6c,
+                           0x17, 0x6b, 0xf6, 0x1c, 0xf0, 0xf3, 0x6e, 0xf8,
+                           0x50, 0x38, 0x1f, 0x71, 0x49, 0xb6, 0x57, 0xd6,
+                           0x8f, 0xcb, 0x8d, 0x6b, 0xe3, 0xa6, 0x29, 0x90,
+                           0xfe, 0x2a, 0x62, 0x82, 0xae, 0x6d, 0x8b, 0xf6,
+                           0xad, 0x1e, 0x9e, 0x20, 0x5f, 0x38, 0xbe, 0x04,
+                           0xda, 0x10, 0x8e, 0xed, 0xa2, 0xa4, 0x87, 0xab,
+                           0xda, 0x6b, 0xb4, 0x0c, 0x75, 0xba, 0xd3, 0x7c,
+                           0xc9, 0xac, 0x42, 0x31, 0x95, 0x7c, 0xc9, 0x04,
+                           0xeb, 0xd5, 0x6e, 0x32, 0x69, 0x8a, 0xdb, 0xa6,
+                           0x15, 0xd7, 0x3f, 0x4f, 0x2f, 0x66, 0x69, 0x03,
+                           0x9c, 0x1f, 0x54, 0x0f, 0xde, 0x1f, 0xf3, 0x65,
+                           0x4c, 0x96, 0x12, 0xed, 0x7c, 0x92, 0x03, 0x01,
+                           0x6f, 0xbc, 0x35, 0x93, 0xac, 0xf1, 0x27, 0xf1,
+                           0xb4, 0x96, 0x82, 0x5a, 0x5f, 0xb0, 0xa0, 0x50,
+                           0x89, 0xa4, 0x8e, 0x66, 0x44, 0x85, 0xcc, 0xfd,
+                           0x33, 0x14, 0x70, 0xe3, 0x96, 0xb2, 0xc3, 0xd3,
+                           0xbb, 0x54, 0x5a, 0x1a, 0xf9, 0x74, 0xa2, 0xc5,
+                           0x2d, 0x64, 0x75, 0xdd, 0xb4, 0x54, 0xe6, 0x74,
+                           0x8c, 0xd3, 0x9d, 0x9e, 0x86, 0xab, 0x51, 0x53,
+                           0xb7, 0x93, 0x3e, 0x6f, 0xd0, 0x4e, 0x2c, 0x40,
+                           0xf6, 0xa8, 0x2e, 0x3e, 0x9d, 0xf4, 0x66, 0xa5,
+                           0x76, 0x12, 0x73, 0x44, 0x1a, 0x56, 0xd7, 0x72,
+                           0x88, 0xcd, 0x21, 0x8c, 0x4c, 0x0f, 0xfe, 0xda,
+                           0x95, 0xe0, 0x3a, 0xa6, 0xa5, 0x84, 0x46, 0xcd,
+                           0xd5, 0x3e, 0x9d, 0x3a, 0xe2, 0x67, 0xe6, 0x60,
+                           0x1a, 0xe2, 0x70, 0x85, 0x58, 0xc2, 0x1b, 0x09,
+                           0xe1, 0xd7, 0x2c, 0xca, 0xad, 0xa8, 0x8f, 0xf9,
+                           0xac, 0xb3, 0x0e, 0xdb, 0xca, 0x2e, 0xe2, 0xb8,
+                           0x51, 0x71, 0xd9, 0x3c, 0x6c, 0xf1, 0x56, 0xf8,
+                           0xea, 0x9c, 0xf1, 0xfb, 0x0c, 0xe6, 0xb7, 0x10,
+                           0x1c, 0xf8, 0xa9, 0x7c, 0xe8, 0x53, 0x35, 0xc1,
+                           0x90, 0x3e, 0x76, 0x4a, 0x74, 0xa4, 0x21, 0x2c,
+                           0xf6, 0x2c, 0x4e, 0x0f, 0x94, 0x3a, 0x88, 0x2e,
+                           0x41, 0x09, 0x6a, 0x33, 0x7d, 0xf6, 0xdd, 0x3f,
+                           0x8d, 0x23, 0x31, 0x74, 0x84, 0xeb, 0x88, 0x6e,
+                           0xcc, 0xb9, 0xbc, 0x22, 0x83, 0x19, 0x07, 0x22,
+                           0xa5, 0x2d, 0xdf, 0xa5, 0xf3, 0x80, 0x85, 0x78,
+                           0x84, 0x39, 0x6a, 0x6d, 0x6a, 0x99, 0x4f, 0xa5,
+                           0x15, 0xfe, 0x46, 0xb0, 0xe4, 0x6c, 0xa5, 0x41,
+                           0x3c, 0xce, 0x8f, 0x42, 0x60, 0x71, 0xa7, 0x75,
+                           0x08, 0x40, 0x65, 0x8a, 0x82, 0xbf, 0xf5, 0x43,
+                           0x71, 0x96, 0xa9, 0x4d, 0x44, 0x8a, 0x20, 0xbe,
+                           0xfa, 0x4d, 0xbb, 0xc0, 0x7d, 0x31, 0x96, 0x65,
+                           0xe7, 0x75, 0xe5, 0x3e, 0xfd, 0x92, 0x3b, 0xc9,
+                           0x55, 0xbb, 0x16, 0x7e, 0xf7, 0xc2, 0x8c, 0xa4,
+                           0x40, 0x1d, 0xe5, 0xef, 0x0e, 0xdf, 0xe4, 0x9a,
+                           0x62, 0x73, 0x65, 0xfd, 0x46, 0x63, 0x25, 0x3d,
+                           0x2b, 0xaf, 0xe5, 0x64, 0xfe, 0xa5, 0x5c, 0xcf,
+                           0x24, 0xf3, 0xb4, 0xac, 0x64, 0xba, 0xdf, 0x4b,
+                           0xc6, 0x96, 0x7d, 0x81, 0x2d, 0x8d, 0x97, 0xf7,
+                           0xc5, 0x68, 0x77, 0x84, 0x32, 0x2b, 0xcc, 0x85,
+                           0x74, 0x96, 0xf0, 0x12, 0x77, 0x61, 0xb9, 0xeb,
+                           0x71, 0xaa, 0x82, 0xcb, 0x1c, 0xdb, 0x89, 0xc8,
+                           0xc6, 0xb5, 0xe3, 0x5c, 0x7d, 0x39, 0x07, 0x24,
+                           0xda, 0x39, 0x87, 0x45, 0xc0, 0x2b, 0xbb, 0x01,
+                           0xac, 0xbc, 0x2a, 0x5c, 0x7f, 0xfc, 0xe8, 0xce,
+                           0x6d, 0x9c, 0x6f, 0xed, 0xd3, 0xc1, 0xa1, 0xd6,
+                           0xc5, 0x55, 0xa9, 0x66, 0x2f, 0xe1, 0xc8, 0x32,
+                           0xa6, 0x5d, 0xa4, 0x3a, 0x98, 0x73, 0xe8, 0x45,
+                           0xa4, 0xc7, 0xa8, 0xb4, 0xf6, 0x13, 0x03, 0xf6,
+                           0xe9, 0x2e, 0xc4, 0x29, 0x0f, 0x84, 0xdb, 0xc4,
+                           0x21, 0xc4, 0xc2, 0x75, 0x67, 0x89, 0x37, 0x0a },
+               .rlen   = 512,
+       }
+};
+
 /* Cast5 test vectors from RFC 2144 */
 #define CAST5_ENC_TEST_VECTORS 3
 #define CAST5_DEC_TEST_VECTORS 3
@@ -3084,6 +3657,27 @@ static struct cipher_speed aes_speed_template[] = {
        {  .klen = 0, .blen = 0, }
 };
 
+static struct cipher_speed aes_lrw_speed_template[] = {
+       { .klen = 32, .blen = 16, },
+       { .klen = 32, .blen = 64, },
+       { .klen = 32, .blen = 256, },
+       { .klen = 32, .blen = 1024, },
+       { .klen = 32, .blen = 8192, },
+       { .klen = 40, .blen = 16, },
+       { .klen = 40, .blen = 64, },
+       { .klen = 40, .blen = 256, },
+       { .klen = 40, .blen = 1024, },
+       { .klen = 40, .blen = 8192, },
+       { .klen = 48, .blen = 16, },
+       { .klen = 48, .blen = 64, },
+       { .klen = 48, .blen = 256, },
+       { .klen = 48, .blen = 1024, },
+       { .klen = 48, .blen = 8192, },
+
+       /* End marker */
+       {  .klen = 0, .blen = 0, }
+};
+
 static struct cipher_speed des3_ede_speed_template[] = {
        { .klen = 24, .blen = 16, },
        { .klen = 24, .blen = 64, },
diff --git a/crypto/xcbc.c b/crypto/xcbc.c
new file mode 100644 (file)
index 0000000..9347eb6
--- /dev/null
@@ -0,0 +1,348 @@
+/*
+ * Copyright (C)2006 USAGI/WIDE Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author:
+ *     Kazunori Miyazawa <miyazawa@linux-ipv6.org>
+ */
+
+#include <linux/crypto.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/rtnetlink.h>
+#include <linux/slab.h>
+#include <linux/scatterlist.h>
+#include "internal.h"
+
+static u_int32_t ks[12] = {0x01010101, 0x01010101, 0x01010101, 0x01010101,
+                          0x02020202, 0x02020202, 0x02020202, 0x02020202,
+                          0x03030303, 0x03030303, 0x03030303, 0x03030303};
+/*
+ * +------------------------
+ * | <parent tfm>
+ * +------------------------
+ * | crypto_xcbc_ctx
+ * +------------------------
+ * | odds (block size)
+ * +------------------------
+ * | prev (block size)
+ * +------------------------
+ * | key (block size)
+ * +------------------------
+ * | consts (block size * 3)
+ * +------------------------
+ */
+struct crypto_xcbc_ctx {
+       struct crypto_tfm *child;
+       u8 *odds;
+       u8 *prev;
+       u8 *key;
+       u8 *consts;
+       void (*xor)(u8 *a, const u8 *b, unsigned int bs);
+       unsigned int keylen;
+       unsigned int len;
+};
+
+static void xor_128(u8 *a, const u8 *b, unsigned int bs)
+{
+       ((u32 *)a)[0] ^= ((u32 *)b)[0];
+       ((u32 *)a)[1] ^= ((u32 *)b)[1];
+       ((u32 *)a)[2] ^= ((u32 *)b)[2];
+       ((u32 *)a)[3] ^= ((u32 *)b)[3];
+}
+
+static int _crypto_xcbc_digest_setkey(struct crypto_hash *parent,
+                                     struct crypto_xcbc_ctx *ctx)
+{
+       int bs = crypto_hash_blocksize(parent);
+       int err = 0;
+       u8 key1[bs];
+
+       if ((err = crypto_cipher_setkey(ctx->child, ctx->key, ctx->keylen)))
+           return err;
+
+       ctx->child->__crt_alg->cra_cipher.cia_encrypt(ctx->child, key1,
+                       ctx->consts);
+
+       return crypto_cipher_setkey(ctx->child, key1, bs);
+}
+
+static int crypto_xcbc_digest_setkey(struct crypto_hash *parent,
+                                    const u8 *inkey, unsigned int keylen)
+{
+       struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(parent);
+
+       if (keylen != crypto_tfm_alg_blocksize(ctx->child))
+               return -EINVAL;
+
+       ctx->keylen = keylen;
+       memcpy(ctx->key, inkey, keylen);
+       ctx->consts = (u8*)ks;
+
+       return _crypto_xcbc_digest_setkey(parent, ctx);
+}
+
+static int crypto_xcbc_digest_init(struct hash_desc *pdesc)
+{
+       struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(pdesc->tfm);
+       int bs = crypto_hash_blocksize(pdesc->tfm);
+
+       ctx->len = 0;
+       memset(ctx->odds, 0, bs);
+       memset(ctx->prev, 0, bs);
+
+       return 0;
+}
+
+static int crypto_xcbc_digest_update(struct hash_desc *pdesc,
+                                    struct scatterlist *sg,
+                                    unsigned int nbytes)
+{
+       struct crypto_hash *parent = pdesc->tfm;
+       struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(parent);
+       struct crypto_tfm *tfm = ctx->child;
+       int bs = crypto_hash_blocksize(parent);
+       unsigned int i = 0;
+
+       do {
+
+               struct page *pg = sg[i].page;
+               unsigned int offset = sg[i].offset;
+               unsigned int slen = sg[i].length;
+
+               while (slen > 0) {
+                       unsigned int len = min(slen, ((unsigned int)(PAGE_SIZE)) - offset);
+                       char *p = crypto_kmap(pg, 0) + offset;
+
+                       /* checking the data can fill the block */
+                       if ((ctx->len + len) <= bs) {
+                               memcpy(ctx->odds + ctx->len, p, len);
+                               ctx->len += len;
+                               slen -= len;
+
+                               /* checking the rest of the page */
+                               if (len + offset >= PAGE_SIZE) {
+                                       offset = 0;
+                                       pg++;
+                               } else
+                                       offset += len;
+
+                               crypto_kunmap(p, 0);
+                               crypto_yield(tfm->crt_flags);
+                               continue;
+                       }
+
+                       /* filling odds with new data and encrypting it */
+                       memcpy(ctx->odds + ctx->len, p, bs - ctx->len);
+                       len -= bs - ctx->len;
+                       p += bs - ctx->len;
+
+                       ctx->xor(ctx->prev, ctx->odds, bs);
+                       tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, ctx->prev, ctx->prev);
+
+                       /* clearing the length */
+                       ctx->len = 0;
+
+                       /* encrypting the rest of data */
+                       while (len > bs) {
+                               ctx->xor(ctx->prev, p, bs);
+                               tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, ctx->prev, ctx->prev);
+                               p += bs;
+                               len -= bs;
+                       }
+
+                       /* keeping the surplus of blocksize */
+                       if (len) {
+                               memcpy(ctx->odds, p, len);
+                               ctx->len = len;
+                       }
+                       crypto_kunmap(p, 0);
+                       crypto_yield(tfm->crt_flags);
+                       slen -= min(slen, ((unsigned int)(PAGE_SIZE)) - offset);
+                       offset = 0;
+                       pg++;
+               }
+               nbytes-=sg[i].length;
+               i++;
+       } while (nbytes>0);
+
+       return 0;
+}
+
+static int crypto_xcbc_digest_final(struct hash_desc *pdesc, u8 *out)
+{
+       struct crypto_hash *parent = pdesc->tfm;
+       struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(parent);
+       struct crypto_tfm *tfm = ctx->child;
+       int bs = crypto_hash_blocksize(parent);
+       int err = 0;
+
+       if (ctx->len == bs) {
+               u8 key2[bs];
+
+               if ((err = crypto_cipher_setkey(tfm, ctx->key, ctx->keylen)) != 0)
+                       return err;
+
+               tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, key2, (const u8*)(ctx->consts+bs));
+
+               ctx->xor(ctx->prev, ctx->odds, bs);
+               ctx->xor(ctx->prev, key2, bs);
+               _crypto_xcbc_digest_setkey(parent, ctx);
+
+               tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, out, ctx->prev);
+       } else {
+               u8 key3[bs];
+               unsigned int rlen;
+               u8 *p = ctx->odds + ctx->len;
+               *p = 0x80;
+               p++;
+
+               rlen = bs - ctx->len -1;
+               if (rlen)
+                       memset(p, 0, rlen);
+
+               if ((err = crypto_cipher_setkey(tfm, ctx->key, ctx->keylen)) != 0)
+                       return err;
+
+               tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, key3, (const u8*)(ctx->consts+bs*2));
+
+               ctx->xor(ctx->prev, ctx->odds, bs);
+               ctx->xor(ctx->prev, key3, bs);
+
+               _crypto_xcbc_digest_setkey(parent, ctx);
+
+               tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, out, ctx->prev);
+       }
+
+       return 0;
+}
+
+static int crypto_xcbc_digest(struct hash_desc *pdesc,
+                 struct scatterlist *sg, unsigned int nbytes, u8 *out)
+{
+       crypto_xcbc_digest_init(pdesc);
+       crypto_xcbc_digest_update(pdesc, sg, nbytes);
+       return crypto_xcbc_digest_final(pdesc, out);
+}
+
+static int xcbc_init_tfm(struct crypto_tfm *tfm)
+{
+       struct crypto_instance *inst = (void *)tfm->__crt_alg;
+       struct crypto_spawn *spawn = crypto_instance_ctx(inst);
+       struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(__crypto_hash_cast(tfm));
+       int bs = crypto_hash_blocksize(__crypto_hash_cast(tfm));
+
+       tfm = crypto_spawn_tfm(spawn);
+       if (IS_ERR(tfm))
+               return PTR_ERR(tfm);
+
+       switch(bs) {
+       case 16:
+               ctx->xor = xor_128;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       ctx->child = crypto_cipher_cast(tfm);
+       ctx->odds = (u8*)(ctx+1);
+       ctx->prev = ctx->odds + bs;
+       ctx->key = ctx->prev + bs;
+
+       return 0;
+};
+
+static void xcbc_exit_tfm(struct crypto_tfm *tfm)
+{
+       struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(__crypto_hash_cast(tfm));
+       crypto_free_cipher(ctx->child);
+}
+
+static struct crypto_instance *xcbc_alloc(void *param, unsigned int len)
+{
+       struct crypto_instance *inst;
+       struct crypto_alg *alg;
+       alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_CIPHER,
+                                 CRYPTO_ALG_TYPE_HASH_MASK | CRYPTO_ALG_ASYNC);
+       if (IS_ERR(alg))
+               return ERR_PTR(PTR_ERR(alg));
+
+       switch(alg->cra_blocksize) {
+       case 16:
+               break;
+       default:
+               return ERR_PTR(PTR_ERR(alg));
+       }
+
+       inst = crypto_alloc_instance("xcbc", alg);
+       if (IS_ERR(inst))
+               goto out_put_alg;
+
+       inst->alg.cra_flags = CRYPTO_ALG_TYPE_HASH;
+       inst->alg.cra_priority = alg->cra_priority;
+       inst->alg.cra_blocksize = alg->cra_blocksize;
+       inst->alg.cra_alignmask = alg->cra_alignmask;
+       inst->alg.cra_type = &crypto_hash_type;
+
+       inst->alg.cra_hash.digestsize =
+               (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
+               CRYPTO_ALG_TYPE_HASH ? alg->cra_hash.digestsize :
+                                      alg->cra_blocksize;
+       inst->alg.cra_ctxsize = sizeof(struct crypto_xcbc_ctx) +
+                               ALIGN(inst->alg.cra_blocksize * 3, sizeof(void *));
+       inst->alg.cra_init = xcbc_init_tfm;
+       inst->alg.cra_exit = xcbc_exit_tfm;
+
+       inst->alg.cra_hash.init = crypto_xcbc_digest_init;
+       inst->alg.cra_hash.update = crypto_xcbc_digest_update;
+       inst->alg.cra_hash.final = crypto_xcbc_digest_final;
+       inst->alg.cra_hash.digest = crypto_xcbc_digest;
+       inst->alg.cra_hash.setkey = crypto_xcbc_digest_setkey;
+
+out_put_alg:
+       crypto_mod_put(alg);
+       return inst;
+}
+
+static void xcbc_free(struct crypto_instance *inst)
+{
+       crypto_drop_spawn(crypto_instance_ctx(inst));
+       kfree(inst);
+}
+
+static struct crypto_template crypto_xcbc_tmpl = {
+       .name = "xcbc",
+       .alloc = xcbc_alloc,
+       .free = xcbc_free,
+       .module = THIS_MODULE,
+};
+
+static int __init crypto_xcbc_module_init(void)
+{
+       return crypto_register_template(&crypto_xcbc_tmpl);
+}
+
+static void __exit crypto_xcbc_module_exit(void)
+{
+       crypto_unregister_template(&crypto_xcbc_tmpl);
+}
+
+module_init(crypto_xcbc_module_init);
+module_exit(crypto_xcbc_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("XCBC keyed hash algorithm");
index b5077ce8cb4007b901716c89208e6b94f5012bd5..1b16f8166b094ae474b94f6da5401fe3a9179c19 100644 (file)
@@ -41,7 +41,7 @@ ifeq ($(CONFIG_ATM_FORE200E_PCA),y)
   # guess the target endianess to choose the right PCA-200E firmware image
   ifeq ($(CONFIG_ATM_FORE200E_PCA_DEFAULT_FW),y)
     byteorder.h                        := include$(if $(patsubst $(srctree),,$(objtree)),2)/asm/byteorder.h
-    CONFIG_ATM_FORE200E_PCA_FW := $(obj)/pca200e$(if $(shell $(CC) -E -dM $(byteorder.h) | grep ' __LITTLE_ENDIAN '),.bin,_ecd.bin2)
+    CONFIG_ATM_FORE200E_PCA_FW := $(obj)/pca200e$(if $(shell $(CC) $(CPPFLAGS) -E -dM $(byteorder.h) | grep ' __LITTLE_ENDIAN '),.bin,_ecd.bin2)
   endif
 endif
 
index 432c17e1e0e673e131a6800b06b90f42dcb395e1..85072446d772311ab1c9b4bb1d4b4dc64029d7c9 100644 (file)
@@ -306,6 +306,7 @@ config BLK_DEV_LOOP
 config BLK_DEV_CRYPTOLOOP
        tristate "Cryptoloop Support"
        select CRYPTO
+       select CRYPTO_CBC
        depends on BLK_DEV_LOOP
        ---help---
          Say Y here if you want to be able to use the ciphers that are 
index adb554153f672a48d2d4d9f711513ef93d5ce9c8..e816535ab305e33b06ec2368dc668fa43a4f3b21 100644 (file)
@@ -51,4 +51,17 @@ config CRYPTO_DEV_PADLOCK_SHA
          If unsure say M. The compiled module will be
          called padlock-sha.ko
 
+config CRYPTO_DEV_GEODE
+       tristate "Support for the Geode LX AES engine"
+       depends on CRYPTO && X86_32
+       select CRYPTO_ALGAPI
+       select CRYPTO_BLKCIPHER
+       default m
+       help
+         Say 'Y' here to use the AMD Geode LX processor on-board AES
+         engine for the CryptoAPI AES alogrithm.
+
+         To compile this driver as a module, choose M here: the module
+         will be called geode-aes.
+
 endmenu
index 4c3d0ec1cf805a8b8407d959b6e085e9a2864460..6059cf8694141c077dc592e3186865d815aa6097 100644 (file)
@@ -1,3 +1,4 @@
 obj-$(CONFIG_CRYPTO_DEV_PADLOCK) += padlock.o
 obj-$(CONFIG_CRYPTO_DEV_PADLOCK_AES) += padlock-aes.o
 obj-$(CONFIG_CRYPTO_DEV_PADLOCK_SHA) += padlock-sha.o
+obj-$(CONFIG_CRYPTO_DEV_GEODE) += geode-aes.o
diff --git a/drivers/crypto/geode-aes.c b/drivers/crypto/geode-aes.c
new file mode 100644 (file)
index 0000000..43a6839
--- /dev/null
@@ -0,0 +1,474 @@
+ /* Copyright (C) 2004-2006, Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/crypto.h>
+#include <linux/spinlock.h>
+#include <crypto/algapi.h>
+
+#include <asm/io.h>
+#include <asm/delay.h>
+
+#include "geode-aes.h"
+
+/* Register definitions */
+
+#define AES_CTRLA_REG  0x0000
+
+#define AES_CTRL_START     0x01
+#define AES_CTRL_DECRYPT   0x00
+#define AES_CTRL_ENCRYPT   0x02
+#define AES_CTRL_WRKEY     0x04
+#define AES_CTRL_DCA       0x08
+#define AES_CTRL_SCA       0x10
+#define AES_CTRL_CBC       0x20
+
+#define AES_INTR_REG  0x0008
+
+#define AES_INTRA_PENDING (1 << 16)
+#define AES_INTRB_PENDING (1 << 17)
+
+#define AES_INTR_PENDING  (AES_INTRA_PENDING | AES_INTRB_PENDING)
+#define AES_INTR_MASK     0x07
+
+#define AES_SOURCEA_REG   0x0010
+#define AES_DSTA_REG      0x0014
+#define AES_LENA_REG      0x0018
+#define AES_WRITEKEY0_REG 0x0030
+#define AES_WRITEIV0_REG  0x0040
+
+/*  A very large counter that is used to gracefully bail out of an
+ *  operation in case of trouble
+ */
+
+#define AES_OP_TIMEOUT    0x50000
+
+/* Static structures */
+
+static void __iomem * _iobase;
+static spinlock_t lock;
+
+/* Write a 128 bit field (either a writable key or IV) */
+static inline void
+_writefield(u32 offset, void *value)
+{
+       int i;
+       for(i = 0; i < 4; i++)
+               iowrite32(((u32 *) value)[i], _iobase + offset + (i * 4));
+}
+
+/* Read a 128 bit field (either a writable key or IV) */
+static inline void
+_readfield(u32 offset, void *value)
+{
+       int i;
+       for(i = 0; i < 4; i++)
+               ((u32 *) value)[i] = ioread32(_iobase + offset + (i * 4));
+}
+
+static int
+do_crypt(void *src, void *dst, int len, u32 flags)
+{
+       u32 status;
+       u32 counter = AES_OP_TIMEOUT;
+
+       iowrite32(virt_to_phys(src), _iobase + AES_SOURCEA_REG);
+       iowrite32(virt_to_phys(dst), _iobase + AES_DSTA_REG);
+       iowrite32(len,  _iobase + AES_LENA_REG);
+
+       /* Start the operation */
+       iowrite32(AES_CTRL_START | flags, _iobase + AES_CTRLA_REG);
+
+       do
+               status = ioread32(_iobase + AES_INTR_REG);
+       while(!(status & AES_INTRA_PENDING) && --counter);
+
+       /* Clear the event */
+       iowrite32((status & 0xFF) | AES_INTRA_PENDING, _iobase + AES_INTR_REG);
+       return counter ? 0 : 1;
+}
+
+static unsigned int
+geode_aes_crypt(struct geode_aes_op *op)
+{
+
+       u32 flags = 0;
+       int iflags;
+
+       if (op->len == 0 || op->src == op->dst)
+               return 0;
+
+       if (op->flags & AES_FLAGS_COHERENT)
+               flags |= (AES_CTRL_DCA | AES_CTRL_SCA);
+
+       if (op->dir == AES_DIR_ENCRYPT)
+               flags |= AES_CTRL_ENCRYPT;
+
+       /* Start the critical section */
+
+       spin_lock_irqsave(&lock, iflags);
+
+       if (op->mode == AES_MODE_CBC) {
+               flags |= AES_CTRL_CBC;
+               _writefield(AES_WRITEIV0_REG, op->iv);
+       }
+
+       if (op->flags & AES_FLAGS_USRKEY) {
+               flags |= AES_CTRL_WRKEY;
+               _writefield(AES_WRITEKEY0_REG, op->key);
+       }
+
+       do_crypt(op->src, op->dst, op->len, flags);
+
+       if (op->mode == AES_MODE_CBC)
+               _readfield(AES_WRITEIV0_REG, op->iv);
+
+       spin_unlock_irqrestore(&lock, iflags);
+
+       return op->len;
+}
+
+/* CRYPTO-API Functions */
+
+static int
+geode_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int len)
+{
+       struct geode_aes_op *op = crypto_tfm_ctx(tfm);
+
+       if (len != AES_KEY_LENGTH) {
+               tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+               return -EINVAL;
+       }
+
+       memcpy(op->key, key, len);
+       return 0;
+}
+
+static void
+geode_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
+{
+       struct geode_aes_op *op = crypto_tfm_ctx(tfm);
+
+       if ((out == NULL) || (in == NULL))
+               return;
+
+       op->src = (void *) in;
+       op->dst = (void *) out;
+       op->mode = AES_MODE_ECB;
+       op->flags = 0;
+       op->len = AES_MIN_BLOCK_SIZE;
+       op->dir = AES_DIR_ENCRYPT;
+
+       geode_aes_crypt(op);
+}
+
+
+static void
+geode_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
+{
+       struct geode_aes_op *op = crypto_tfm_ctx(tfm);
+
+       if ((out == NULL) || (in == NULL))
+               return;
+
+       op->src = (void *) in;
+       op->dst = (void *) out;
+       op->mode = AES_MODE_ECB;
+       op->flags = 0;
+       op->len = AES_MIN_BLOCK_SIZE;
+       op->dir = AES_DIR_DECRYPT;
+
+       geode_aes_crypt(op);
+}
+
+
+static struct crypto_alg geode_alg = {
+       .cra_name               =       "aes",
+       .cra_driver_name        =       "geode-aes-128",
+       .cra_priority           =       300,
+       .cra_alignmask          =       15,
+       .cra_flags              =       CRYPTO_ALG_TYPE_CIPHER,
+       .cra_blocksize          =       AES_MIN_BLOCK_SIZE,
+       .cra_ctxsize            =       sizeof(struct geode_aes_op),
+       .cra_module             =       THIS_MODULE,
+       .cra_list               =       LIST_HEAD_INIT(geode_alg.cra_list),
+       .cra_u                  =       {
+               .cipher = {
+                       .cia_min_keysize        =  AES_KEY_LENGTH,
+                       .cia_max_keysize        =  AES_KEY_LENGTH,
+                       .cia_setkey             =  geode_setkey,
+                       .cia_encrypt            =  geode_encrypt,
+                       .cia_decrypt            =  geode_decrypt
+               }
+       }
+};
+
+static int
+geode_cbc_decrypt(struct blkcipher_desc *desc,
+                 struct scatterlist *dst, struct scatterlist *src,
+                 unsigned int nbytes)
+{
+       struct geode_aes_op *op = crypto_blkcipher_ctx(desc->tfm);
+       struct blkcipher_walk walk;
+       int err, ret;
+
+       blkcipher_walk_init(&walk, dst, src, nbytes);
+       err = blkcipher_walk_virt(desc, &walk);
+
+       while((nbytes = walk.nbytes)) {
+               op->src = walk.src.virt.addr,
+               op->dst = walk.dst.virt.addr;
+               op->mode = AES_MODE_CBC;
+               op->len = nbytes - (nbytes % AES_MIN_BLOCK_SIZE);
+               op->dir = AES_DIR_DECRYPT;
+
+               memcpy(op->iv, walk.iv, AES_IV_LENGTH);
+
+               ret = geode_aes_crypt(op);
+
+               memcpy(walk.iv, op->iv, AES_IV_LENGTH);
+               nbytes -= ret;
+
+               err = blkcipher_walk_done(desc, &walk, nbytes);
+       }
+
+       return err;
+}
+
+static int
+geode_cbc_encrypt(struct blkcipher_desc *desc,
+                 struct scatterlist *dst, struct scatterlist *src,
+                 unsigned int nbytes)
+{
+       struct geode_aes_op *op = crypto_blkcipher_ctx(desc->tfm);
+       struct blkcipher_walk walk;
+       int err, ret;
+
+       blkcipher_walk_init(&walk, dst, src, nbytes);
+       err = blkcipher_walk_virt(desc, &walk);
+
+       while((nbytes = walk.nbytes)) {
+               op->src = walk.src.virt.addr,
+               op->dst = walk.dst.virt.addr;
+               op->mode = AES_MODE_CBC;
+               op->len = nbytes - (nbytes % AES_MIN_BLOCK_SIZE);
+               op->dir = AES_DIR_ENCRYPT;
+
+               memcpy(op->iv, walk.iv, AES_IV_LENGTH);
+
+               ret = geode_aes_crypt(op);
+               nbytes -= ret;
+               err = blkcipher_walk_done(desc, &walk, nbytes);
+       }
+
+       return err;
+}
+
+static struct crypto_alg geode_cbc_alg = {
+       .cra_name               =       "cbc(aes)",
+       .cra_driver_name        =       "cbc-aes-geode-128",
+       .cra_priority           =       400,
+       .cra_flags              =       CRYPTO_ALG_TYPE_BLKCIPHER,
+       .cra_blocksize          =       AES_MIN_BLOCK_SIZE,
+       .cra_ctxsize            =       sizeof(struct geode_aes_op),
+       .cra_alignmask          =       15,
+       .cra_type               =       &crypto_blkcipher_type,
+       .cra_module             =       THIS_MODULE,
+       .cra_list               =       LIST_HEAD_INIT(geode_cbc_alg.cra_list),
+       .cra_u                  =       {
+               .blkcipher = {
+                       .min_keysize            =       AES_KEY_LENGTH,
+                       .max_keysize            =       AES_KEY_LENGTH,
+                       .setkey                 =       geode_setkey,
+                       .encrypt                =       geode_cbc_encrypt,
+                       .decrypt                =       geode_cbc_decrypt,
+               }
+       }
+};
+
+static int
+geode_ecb_decrypt(struct blkcipher_desc *desc,
+                 struct scatterlist *dst, struct scatterlist *src,
+                 unsigned int nbytes)
+{
+       struct geode_aes_op *op = crypto_blkcipher_ctx(desc->tfm);
+       struct blkcipher_walk walk;
+       int err, ret;
+
+       blkcipher_walk_init(&walk, dst, src, nbytes);
+       err = blkcipher_walk_virt(desc, &walk);
+
+       while((nbytes = walk.nbytes)) {
+               op->src = walk.src.virt.addr,
+               op->dst = walk.dst.virt.addr;
+               op->mode = AES_MODE_ECB;
+               op->len = nbytes - (nbytes % AES_MIN_BLOCK_SIZE);
+               op->dir = AES_DIR_DECRYPT;
+
+               ret = geode_aes_crypt(op);
+               nbytes -= ret;
+               err = blkcipher_walk_done(desc, &walk, nbytes);
+       }
+
+       return err;
+}
+
+static int
+geode_ecb_encrypt(struct blkcipher_desc *desc,
+                 struct scatterlist *dst, struct scatterlist *src,
+                 unsigned int nbytes)
+{
+       struct geode_aes_op *op = crypto_blkcipher_ctx(desc->tfm);
+       struct blkcipher_walk walk;
+       int err, ret;
+
+       blkcipher_walk_init(&walk, dst, src, nbytes);
+       err = blkcipher_walk_virt(desc, &walk);
+
+       while((nbytes = walk.nbytes)) {
+               op->src = walk.src.virt.addr,
+               op->dst = walk.dst.virt.addr;
+               op->mode = AES_MODE_ECB;
+               op->len = nbytes - (nbytes % AES_MIN_BLOCK_SIZE);
+               op->dir = AES_DIR_ENCRYPT;
+
+               ret = geode_aes_crypt(op);
+               nbytes -= ret;
+               ret =  blkcipher_walk_done(desc, &walk, nbytes);
+       }
+
+       return err;
+}
+
+static struct crypto_alg geode_ecb_alg = {
+       .cra_name               =       "ecb(aes)",
+       .cra_driver_name        =       "ecb-aes-geode-128",
+       .cra_priority           =       400,
+       .cra_flags              =       CRYPTO_ALG_TYPE_BLKCIPHER,
+       .cra_blocksize          =       AES_MIN_BLOCK_SIZE,
+       .cra_ctxsize            =       sizeof(struct geode_aes_op),
+       .cra_alignmask          =       15,
+       .cra_type               =       &crypto_blkcipher_type,
+       .cra_module             =       THIS_MODULE,
+       .cra_list               =       LIST_HEAD_INIT(geode_ecb_alg.cra_list),
+       .cra_u                  =       {
+               .blkcipher = {
+                       .min_keysize            =       AES_KEY_LENGTH,
+                       .max_keysize            =       AES_KEY_LENGTH,
+                       .setkey                 =       geode_setkey,
+                       .encrypt                =       geode_ecb_encrypt,
+                       .decrypt                =       geode_ecb_decrypt,
+               }
+       }
+};
+
+static void
+geode_aes_remove(struct pci_dev *dev)
+{
+       crypto_unregister_alg(&geode_alg);
+       crypto_unregister_alg(&geode_ecb_alg);
+       crypto_unregister_alg(&geode_cbc_alg);
+
+       pci_iounmap(dev, _iobase);
+       _iobase = NULL;
+
+       pci_release_regions(dev);
+       pci_disable_device(dev);
+}
+
+
+static int
+geode_aes_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       int ret;
+
+       if ((ret = pci_enable_device(dev)))
+               return ret;
+
+       if ((ret = pci_request_regions(dev, "geode-aes-128")))
+               goto eenable;
+
+       _iobase = pci_iomap(dev, 0, 0);
+
+       if (_iobase == NULL) {
+               ret = -ENOMEM;
+               goto erequest;
+       }
+
+       spin_lock_init(&lock);
+
+       /* Clear any pending activity */
+       iowrite32(AES_INTR_PENDING | AES_INTR_MASK, _iobase + AES_INTR_REG);
+
+       if ((ret = crypto_register_alg(&geode_alg)))
+               goto eiomap;
+
+       if ((ret = crypto_register_alg(&geode_ecb_alg)))
+               goto ealg;
+
+       if ((ret = crypto_register_alg(&geode_cbc_alg)))
+               goto eecb;
+
+       printk(KERN_NOTICE "geode-aes: GEODE AES engine enabled.\n");
+       return 0;
+
+ eecb:
+       crypto_unregister_alg(&geode_ecb_alg);
+
+ ealg:
+       crypto_unregister_alg(&geode_alg);
+
+ eiomap:
+       pci_iounmap(dev, _iobase);
+
+ erequest:
+       pci_release_regions(dev);
+
+ eenable:
+       pci_disable_device(dev);
+
+       printk(KERN_ERR "geode-aes:  GEODE AES initialization failed.\n");
+       return ret;
+}
+
+static struct pci_device_id geode_aes_tbl[] = {
+       { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LX_AES, PCI_ANY_ID, PCI_ANY_ID} ,
+       { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, geode_aes_tbl);
+
+static struct pci_driver geode_aes_driver = {
+       .name = "Geode LX AES",
+       .id_table = geode_aes_tbl,
+       .probe = geode_aes_probe,
+       .remove = __devexit_p(geode_aes_remove)
+};
+
+static int __init
+geode_aes_init(void)
+{
+       return pci_module_init(&geode_aes_driver);
+}
+
+static void __exit
+geode_aes_exit(void)
+{
+       pci_unregister_driver(&geode_aes_driver);
+}
+
+MODULE_AUTHOR("Advanced Micro Devices, Inc.");
+MODULE_DESCRIPTION("Geode LX Hardware AES driver");
+MODULE_LICENSE("GPL");
+
+module_init(geode_aes_init);
+module_exit(geode_aes_exit);
diff --git a/drivers/crypto/geode-aes.h b/drivers/crypto/geode-aes.h
new file mode 100644 (file)
index 0000000..8003a36
--- /dev/null
@@ -0,0 +1,40 @@
+/* Copyright (C) 2003-2006, Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef _GEODE_AES_H_
+#define _GEODE_AES_H_
+
+#define AES_KEY_LENGTH 16
+#define AES_IV_LENGTH  16
+
+#define AES_MIN_BLOCK_SIZE 16
+
+#define AES_MODE_ECB 0
+#define AES_MODE_CBC 1
+
+#define AES_DIR_DECRYPT 0
+#define AES_DIR_ENCRYPT 1
+
+#define AES_FLAGS_USRKEY   (1 << 0)
+#define AES_FLAGS_COHERENT (1 << 1)
+
+struct geode_aes_op {
+
+       void *src;
+       void *dst;
+
+       u32 mode;
+       u32 dir;
+       u32 flags;
+       int len;
+
+       u8 key[AES_KEY_LENGTH];
+       u8 iv[AES_IV_LENGTH];
+};
+
+#endif
index c7bee4f2eedbeedd77dadc7e42ea2fe61709e1bd..a1086ee8cccde1828860a24ee8667100e88dd701 100644 (file)
@@ -20,6 +20,7 @@
 #include <asm/atomic.h>
 #include <linux/scatterlist.h>
 #include <asm/page.h>
+#include <asm/unaligned.h>
 
 #include "dm.h"
 
@@ -85,7 +86,10 @@ struct crypt_config {
         */
        struct crypt_iv_operations *iv_gen_ops;
        char *iv_mode;
-       struct crypto_cipher *iv_gen_private;
+       union {
+               struct crypto_cipher *essiv_tfm;
+               int benbi_shift;
+       } iv_gen_private;
        sector_t iv_offset;
        unsigned int iv_size;
 
@@ -113,6 +117,9 @@ static struct kmem_cache *_crypt_io_pool;
  *        encrypted with the bulk cipher using a salt as key. The salt
  *        should be derived from the bulk cipher's key via hashing.
  *
+ * benbi: the 64-bit "big-endian 'narrow block'-count", starting at 1
+ *        (needed for LRW-32-AES and possible other narrow block modes)
+ *
  * plumb: unimplemented, see:
  * http://article.gmane.org/gmane.linux.kernel.device-mapper.dm-crypt/454
  */
@@ -191,21 +198,61 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti,
        }
        kfree(salt);
 
-       cc->iv_gen_private = essiv_tfm;
+       cc->iv_gen_private.essiv_tfm = essiv_tfm;
        return 0;
 }
 
 static void crypt_iv_essiv_dtr(struct crypt_config *cc)
 {
-       crypto_free_cipher(cc->iv_gen_private);
-       cc->iv_gen_private = NULL;
+       crypto_free_cipher(cc->iv_gen_private.essiv_tfm);
+       cc->iv_gen_private.essiv_tfm = NULL;
 }
 
 static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv, sector_t sector)
 {
        memset(iv, 0, cc->iv_size);
        *(u64 *)iv = cpu_to_le64(sector);
-       crypto_cipher_encrypt_one(cc->iv_gen_private, iv, iv);
+       crypto_cipher_encrypt_one(cc->iv_gen_private.essiv_tfm, iv, iv);
+       return 0;
+}
+
+static int crypt_iv_benbi_ctr(struct crypt_config *cc, struct dm_target *ti,
+                             const char *opts)
+{
+       unsigned int bs = crypto_blkcipher_blocksize(cc->tfm);
+       int log = long_log2(bs);
+
+       /* we need to calculate how far we must shift the sector count
+        * to get the cipher block count, we use this shift in _gen */
+
+       if (1 << log != bs) {
+               ti->error = "cypher blocksize is not a power of 2";
+               return -EINVAL;
+       }
+
+       if (log > 9) {
+               ti->error = "cypher blocksize is > 512";
+               return -EINVAL;
+       }
+
+       cc->iv_gen_private.benbi_shift = 9 - log;
+
+       return 0;
+}
+
+static void crypt_iv_benbi_dtr(struct crypt_config *cc)
+{
+}
+
+static int crypt_iv_benbi_gen(struct crypt_config *cc, u8 *iv, sector_t sector)
+{
+       __be64 val;
+
+       memset(iv, 0, cc->iv_size - sizeof(u64)); /* rest is cleared below */
+
+       val = cpu_to_be64(((u64)sector << cc->iv_gen_private.benbi_shift) + 1);
+       put_unaligned(val, (__be64 *)(iv + cc->iv_size - sizeof(u64)));
+
        return 0;
 }
 
@@ -219,13 +266,18 @@ static struct crypt_iv_operations crypt_iv_essiv_ops = {
        .generator = crypt_iv_essiv_gen
 };
 
+static struct crypt_iv_operations crypt_iv_benbi_ops = {
+       .ctr       = crypt_iv_benbi_ctr,
+       .dtr       = crypt_iv_benbi_dtr,
+       .generator = crypt_iv_benbi_gen
+};
 
 static int
 crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist *out,
                           struct scatterlist *in, unsigned int length,
                           int write, sector_t sector)
 {
-       u8 iv[cc->iv_size];
+       u8 iv[cc->iv_size] __attribute__ ((aligned(__alignof__(u64))));
        struct blkcipher_desc desc = {
                .tfm = cc->tfm,
                .info = iv,
@@ -768,7 +820,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        cc->tfm = tfm;
 
        /*
-        * Choose ivmode. Valid modes: "plain", "essiv:<esshash>".
+        * Choose ivmode. Valid modes: "plain", "essiv:<esshash>", "benbi".
         * See comments at iv code
         */
 
@@ -778,6 +830,8 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
                cc->iv_gen_ops = &crypt_iv_plain_ops;
        else if (strcmp(ivmode, "essiv") == 0)
                cc->iv_gen_ops = &crypt_iv_essiv_ops;
+       else if (strcmp(ivmode, "benbi") == 0)
+               cc->iv_gen_ops = &crypt_iv_benbi_ops;
        else {
                ti->error = "Invalid IV mode";
                goto bad2;
index f9a1c88a42831c542d59931b55ce6c74397d60e5..9137e239fac2e55120fed2520db2dccbe5bfcbe9 100644 (file)
@@ -704,9 +704,9 @@ static int pxa_irda_stop(struct net_device *dev)
        return 0;
 }
 
-static int pxa_irda_suspend(struct device *_dev, pm_message_t state)
+static int pxa_irda_suspend(struct platform_device *_dev, pm_message_t state)
 {
-       struct net_device *dev = dev_get_drvdata(_dev);
+       struct net_device *dev = platform_get_drvdata(_dev);
        struct pxa_irda *si;
 
        if (dev && netif_running(dev)) {
@@ -718,9 +718,9 @@ static int pxa_irda_suspend(struct device *_dev, pm_message_t state)
        return 0;
 }
 
-static int pxa_irda_resume(struct device *_dev)
+static int pxa_irda_resume(struct platform_device *_dev)
 {
-       struct net_device *dev = dev_get_drvdata(_dev);
+       struct net_device *dev = platform_get_drvdata(_dev);
        struct pxa_irda *si;
 
        if (dev && netif_running(dev)) {
@@ -746,9 +746,8 @@ static int pxa_irda_init_iobuf(iobuff_t *io, int size)
        return io->head ? 0 : -ENOMEM;
 }
 
-static int pxa_irda_probe(struct device *_dev)
+static int pxa_irda_probe(struct platform_device *pdev)
 {
-       struct platform_device *pdev = to_platform_device(_dev);
        struct net_device *dev;
        struct pxa_irda *si;
        unsigned int baudrate_mask;
@@ -822,9 +821,9 @@ err_mem_1:
        return err;
 }
 
-static int pxa_irda_remove(struct device *_dev)
+static int pxa_irda_remove(struct platform_device *_dev)
 {
-       struct net_device *dev = dev_get_drvdata(_dev);
+       struct net_device *dev = platform_get_drvdata(_dev);
 
        if (dev) {
                struct pxa_irda *si = netdev_priv(dev);
@@ -840,9 +839,10 @@ static int pxa_irda_remove(struct device *_dev)
        return 0;
 }
 
-static struct device_driver pxa_ir_driver = {
-       .name           = "pxa2xx-ir",
-       .bus            = &platform_bus_type,
+static struct platform_driver pxa_ir_driver = {
+       .driver         = {
+               .name   = "pxa2xx-ir",
+       },
        .probe          = pxa_irda_probe,
        .remove         = pxa_irda_remove,
        .suspend        = pxa_irda_suspend,
@@ -851,12 +851,12 @@ static struct device_driver pxa_ir_driver = {
 
 static int __init pxa_irda_init(void)
 {
-       return driver_register(&pxa_ir_driver);
+       return platform_driver_register(&pxa_ir_driver);
 }
 
 static void __exit pxa_irda_exit(void)
 {
-       driver_unregister(&pxa_ir_driver);
+       platform_driver_unregister(&pxa_ir_driver);
 }
 
 module_init(pxa_irda_init);
index d9123c9adc1e347d796af84b87f5cd2487fc54fd..571320ae87abf4ca106767846b9a57657c1366fd 100644 (file)
@@ -68,8 +68,8 @@
 
 #define DRV_MODULE_NAME                "tg3"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "3.69"
-#define DRV_MODULE_RELDATE     "November 15, 2006"
+#define DRV_MODULE_VERSION     "3.70"
+#define DRV_MODULE_RELDATE     "December 1, 2006"
 
 #define TG3_DEF_MAC_MODE       0
 #define TG3_DEF_RX_MODE                0
@@ -192,6 +192,7 @@ static struct pci_device_id tg3_pci_tbl[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5786)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787F)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714S)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715)},
@@ -1061,7 +1062,7 @@ static void tg3_frob_aux_power(struct tg3 *tp)
 {
        struct tg3 *tp_peer = tp;
 
-       if ((tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) != 0)
+       if ((tp->tg3_flags2 & TG3_FLG2_IS_NIC) == 0)
                return;
 
        if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) ||
@@ -1212,8 +1213,8 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
                                      power_control);
                udelay(100);    /* Delay after power state change */
 
-               /* Switch out of Vaux if it is not a LOM */
-               if (!(tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT))
+               /* Switch out of Vaux if it is a NIC */
+               if (tp->tg3_flags2 & TG3_FLG2_IS_NIC)
                        tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl, 100);
 
                return 0;
@@ -1401,8 +1402,10 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
 static void tg3_link_report(struct tg3 *tp)
 {
        if (!netif_carrier_ok(tp->dev)) {
-               printk(KERN_INFO PFX "%s: Link is down.\n", tp->dev->name);
-       } else {
+               if (netif_msg_link(tp))
+                       printk(KERN_INFO PFX "%s: Link is down.\n",
+                              tp->dev->name);
+       } else if (netif_msg_link(tp)) {
                printk(KERN_INFO PFX "%s: Link is up at %d Mbps, %s duplex.\n",
                       tp->dev->name,
                       (tp->link_config.active_speed == SPEED_1000 ?
@@ -1557,12 +1560,6 @@ static void tg3_phy_copper_begin(struct tg3 *tp)
 
                tg3_writephy(tp, MII_ADVERTISE, new_adv);
        } else if (tp->link_config.speed == SPEED_INVALID) {
-               tp->link_config.advertising =
-                       (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
-                        ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
-                        ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full |
-                        ADVERTISED_Autoneg | ADVERTISED_MII);
-
                if (tp->tg3_flags & TG3_FLAG_10_100_ONLY)
                        tp->link_config.advertising &=
                                ~(ADVERTISED_1000baseT_Half |
@@ -1706,25 +1703,36 @@ static int tg3_init_5401phy_dsp(struct tg3 *tp)
        return err;
 }
 
-static int tg3_copper_is_advertising_all(struct tg3 *tp)
+static int tg3_copper_is_advertising_all(struct tg3 *tp, u32 mask)
 {
-       u32 adv_reg, all_mask;
+       u32 adv_reg, all_mask = 0;
+
+       if (mask & ADVERTISED_10baseT_Half)
+               all_mask |= ADVERTISE_10HALF;
+       if (mask & ADVERTISED_10baseT_Full)
+               all_mask |= ADVERTISE_10FULL;
+       if (mask & ADVERTISED_100baseT_Half)
+               all_mask |= ADVERTISE_100HALF;
+       if (mask & ADVERTISED_100baseT_Full)
+               all_mask |= ADVERTISE_100FULL;
 
        if (tg3_readphy(tp, MII_ADVERTISE, &adv_reg))
                return 0;
 
-       all_mask = (ADVERTISE_10HALF | ADVERTISE_10FULL |
-                   ADVERTISE_100HALF | ADVERTISE_100FULL);
        if ((adv_reg & all_mask) != all_mask)
                return 0;
        if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY)) {
                u32 tg3_ctrl;
 
+               all_mask = 0;
+               if (mask & ADVERTISED_1000baseT_Half)
+                       all_mask |= ADVERTISE_1000HALF;
+               if (mask & ADVERTISED_1000baseT_Full)
+                       all_mask |= ADVERTISE_1000FULL;
+
                if (tg3_readphy(tp, MII_TG3_CTRL, &tg3_ctrl))
                        return 0;
 
-               all_mask = (MII_TG3_CTRL_ADV_1000_HALF |
-                           MII_TG3_CTRL_ADV_1000_FULL);
                if ((tg3_ctrl & all_mask) != all_mask)
                        return 0;
        }
@@ -1884,7 +1892,8 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
                                /* Force autoneg restart if we are exiting
                                 * low power mode.
                                 */
-                               if (!tg3_copper_is_advertising_all(tp))
+                               if (!tg3_copper_is_advertising_all(tp,
+                                               tp->link_config.advertising))
                                        current_link_up = 0;
                        } else {
                                current_link_up = 0;
@@ -3703,8 +3712,9 @@ static void tg3_tx_timeout(struct net_device *dev)
 {
        struct tg3 *tp = netdev_priv(dev);
 
-       printk(KERN_ERR PFX "%s: transmit timed out, resetting\n",
-              dev->name);
+       if (netif_msg_tx_err(tp))
+               printk(KERN_ERR PFX "%s: transmit timed out, resetting\n",
+                      dev->name);
 
        schedule_work(&tp->reset_task);
 }
@@ -6396,16 +6406,17 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
        udelay(40);
 
        /* tp->grc_local_ctrl is partially set up during tg3_get_invariants().
-        * If TG3_FLAG_EEPROM_WRITE_PROT is set, we should read the
+        * If TG3_FLG2_IS_NIC is zero, we should read the
         * register to preserve the GPIO settings for LOMs. The GPIOs,
         * whether used as inputs or outputs, are set by boot code after
         * reset.
         */
-       if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) {
+       if (!(tp->tg3_flags2 & TG3_FLG2_IS_NIC)) {
                u32 gpio_mask;
 
-               gpio_mask = GRC_LCLCTRL_GPIO_OE0 | GRC_LCLCTRL_GPIO_OE2 |
-                           GRC_LCLCTRL_GPIO_OUTPUT0 | GRC_LCLCTRL_GPIO_OUTPUT2;
+               gpio_mask = GRC_LCLCTRL_GPIO_OE0 | GRC_LCLCTRL_GPIO_OE1 |
+                           GRC_LCLCTRL_GPIO_OE2 | GRC_LCLCTRL_GPIO_OUTPUT0 |
+                           GRC_LCLCTRL_GPIO_OUTPUT1 | GRC_LCLCTRL_GPIO_OUTPUT2;
 
                if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752)
                        gpio_mask |= GRC_LCLCTRL_GPIO_OE3 |
@@ -6417,8 +6428,9 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
                tp->grc_local_ctrl |= tr32(GRC_LOCAL_CTRL) & gpio_mask;
 
                /* GPIO1 must be driven high for eeprom write protect */
-               tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 |
-                                      GRC_LCLCTRL_GPIO_OUTPUT1);
+               if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT)
+                       tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 |
+                                              GRC_LCLCTRL_GPIO_OUTPUT1);
        }
        tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
        udelay(100);
@@ -8656,7 +8668,9 @@ static int tg3_test_registers(struct tg3 *tp)
        return 0;
 
 out:
-       printk(KERN_ERR PFX "Register test failed at offset %x\n", offset);
+       if (netif_msg_hw(tp))
+               printk(KERN_ERR PFX "Register test failed at offset %x\n",
+                      offset);
        tw32(offset, save_val);
        return -EIO;
 }
@@ -8781,17 +8795,20 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
                                        tg3_writephy(tp, 0x10, phy & ~0x4000);
                                tg3_writephy(tp, MII_TG3_EPHY_TEST, phytest);
                        }
-               }
-               val = BMCR_LOOPBACK | BMCR_FULLDPLX;
-               if (tp->tg3_flags & TG3_FLAG_10_100_ONLY)
-                       val |= BMCR_SPEED100;
-               else
-                       val |= BMCR_SPEED1000;
+                       val = BMCR_LOOPBACK | BMCR_FULLDPLX | BMCR_SPEED100;
+               } else
+                       val = BMCR_LOOPBACK | BMCR_FULLDPLX | BMCR_SPEED1000;
 
                tg3_writephy(tp, MII_BMCR, val);
                udelay(40);
-               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+
+               mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
+                          MAC_MODE_LINK_POLARITY;
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
                        tg3_writephy(tp, MII_TG3_EPHY_PTEST, 0x1800);
+                       mac_mode |= MAC_MODE_PORT_MODE_MII;
+               } else
+                       mac_mode |= MAC_MODE_PORT_MODE_GMII;
 
                /* reset to prevent losing 1st rx packet intermittently */
                if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) {
@@ -8799,12 +8816,6 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
                        udelay(10);
                        tw32_f(MAC_RX_MODE, tp->rx_mode);
                }
-               mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
-                          MAC_MODE_LINK_POLARITY;
-               if (tp->tg3_flags & TG3_FLAG_10_100_ONLY)
-                       mac_mode |= MAC_MODE_PORT_MODE_MII;
-               else
-                       mac_mode |= MAC_MODE_PORT_MODE_GMII;
                if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) {
                        mac_mode &= ~MAC_MODE_LINK_POLARITY;
                        tg3_writephy(tp, MII_TG3_EXT_CTRL,
@@ -9456,16 +9467,12 @@ static void __devinit tg3_get_5906_nvram_info(struct tg3 *tp)
 /* Chips other than 5700/5701 use the NVRAM for fetching info. */
 static void __devinit tg3_nvram_init(struct tg3 *tp)
 {
-       int j;
-
        tw32_f(GRC_EEPROM_ADDR,
             (EEPROM_ADDR_FSM_RESET |
              (EEPROM_DEFAULT_CLOCK_PERIOD <<
               EEPROM_ADDR_CLKPERD_SHIFT)));
 
-       /* XXX schedule_timeout() ... */
-       for (j = 0; j < 100; j++)
-               udelay(10);
+       msleep(1);
 
        /* Enable seeprom accesses. */
        tw32_f(GRC_LOCAL_CTRL,
@@ -9526,12 +9533,12 @@ static int tg3_nvram_read_using_eeprom(struct tg3 *tp,
              EEPROM_ADDR_ADDR_MASK) |
             EEPROM_ADDR_READ | EEPROM_ADDR_START);
 
-       for (i = 0; i < 10000; i++) {
+       for (i = 0; i < 1000; i++) {
                tmp = tr32(GRC_EEPROM_ADDR);
 
                if (tmp & EEPROM_ADDR_COMPLETE)
                        break;
-               udelay(100);
+               msleep(1);
        }
        if (!(tmp & EEPROM_ADDR_COMPLETE))
                return -EBUSY;
@@ -9656,12 +9663,12 @@ static int tg3_nvram_write_block_using_eeprom(struct tg3 *tp,
                        EEPROM_ADDR_START |
                        EEPROM_ADDR_WRITE);
 
-               for (j = 0; j < 10000; j++) {
+               for (j = 0; j < 1000; j++) {
                        val = tr32(GRC_EEPROM_ADDR);
 
                        if (val & EEPROM_ADDR_COMPLETE)
                                break;
-                       udelay(100);
+                       msleep(1);
                }
                if (!(val & EEPROM_ADDR_COMPLETE)) {
                        rc = -EBUSY;
@@ -9965,8 +9972,10 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
        tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
 
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
-               if (!(tr32(PCIE_TRANSACTION_CFG) & PCIE_TRANS_CFG_LOM))
+               if (!(tr32(PCIE_TRANSACTION_CFG) & PCIE_TRANS_CFG_LOM)) {
                        tp->tg3_flags &= ~TG3_FLAG_EEPROM_WRITE_PROT;
+                       tp->tg3_flags2 |= TG3_FLG2_IS_NIC;
+               }
                return;
        }
 
@@ -10066,10 +10075,17 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
                    tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL)
                        tp->led_ctrl = LED_CTRL_MODE_PHY_2;
 
-               if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP)
+               if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP) {
                        tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
-               else
+                       if ((tp->pdev->subsystem_vendor ==
+                            PCI_VENDOR_ID_ARIMA) &&
+                           (tp->pdev->subsystem_device == 0x205a ||
+                            tp->pdev->subsystem_device == 0x2063))
+                               tp->tg3_flags &= ~TG3_FLAG_EEPROM_WRITE_PROT;
+               } else {
                        tp->tg3_flags &= ~TG3_FLAG_EEPROM_WRITE_PROT;
+                       tp->tg3_flags2 |= TG3_FLG2_IS_NIC;
+               }
 
                if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) {
                        tp->tg3_flags |= TG3_FLAG_ENABLE_ASF;
@@ -10147,7 +10163,7 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
 
        if (!(tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) &&
            !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
-               u32 bmsr, adv_reg, tg3_ctrl;
+               u32 bmsr, adv_reg, tg3_ctrl, mask;
 
                tg3_readphy(tp, MII_BMSR, &bmsr);
                if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
@@ -10171,7 +10187,10 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
                                             MII_TG3_CTRL_ENABLE_AS_MASTER);
                }
 
-               if (!tg3_copper_is_advertising_all(tp)) {
+               mask = (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
+                       ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
+                       ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full);
+               if (!tg3_copper_is_advertising_all(tp, mask)) {
                        tg3_writephy(tp, MII_ADVERTISE, adv_reg);
 
                        if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY))
@@ -10695,7 +10714,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                tp->tg3_flags |= TG3_FLAG_SRAM_USE_CONFIG;
 
        /* Get eeprom hw config before calling tg3_set_power_state().
-        * In particular, the TG3_FLAG_EEPROM_WRITE_PROT flag must be
+        * In particular, the TG3_FLG2_IS_NIC flag must be
         * determined before calling tg3_set_power_state() so that
         * we know whether or not to switch out of Vaux power.
         * When the flag is set, it means that GPIO1 is used for eeprom
@@ -10862,7 +10881,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
              tp->pdev->device == PCI_DEVICE_ID_TIGON3_5705F)) ||
            (tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM &&
             (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5751F ||
-             tp->pdev->device == PCI_DEVICE_ID_TIGON3_5753F)) ||
+             tp->pdev->device == PCI_DEVICE_ID_TIGON3_5753F ||
+             tp->pdev->device == PCI_DEVICE_ID_TIGON3_5787F)) ||
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
                tp->tg3_flags |= TG3_FLAG_10_100_ONLY;
 
@@ -11912,13 +11932,15 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 
        pci_set_drvdata(pdev, dev);
 
-       printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (%s) %sBaseT Ethernet ",
+       printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (%s) %s Ethernet ",
               dev->name,
               tp->board_part_number,
               tp->pci_chip_rev_id,
               tg3_phy_string(tp),
               tg3_bus_string(tp, str),
-              (tp->tg3_flags & TG3_FLAG_10_100_ONLY) ? "10/100" : "10/100/1000");
+              ((tp->tg3_flags & TG3_FLAG_10_100_ONLY) ? "10/100Base-TX" :
+               ((tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) ? "1000Base-SX" :
+                "10/100/1000Base-T")));
 
        for (i = 0; i < 6; i++)
                printk("%2.2x%c", dev->dev_addr[i],
index 92f53000bce69f2895dad2183ac37013de7e58cb..dfaf4ed127bd712378168eb1b64b82b4bd5f39ef 100644 (file)
@@ -2233,6 +2233,7 @@ struct tg3 {
 #define TG3_FLG2_PCI_EXPRESS           0x00000200
 #define TG3_FLG2_ASF_NEW_HANDSHAKE     0x00000400
 #define TG3_FLG2_HW_AUTONEG            0x00000800
+#define TG3_FLG2_IS_NIC                        0x00001000
 #define TG3_FLG2_PHY_SERDES            0x00002000
 #define TG3_FLG2_CAPACITIVE_COUPLING   0x00004000
 #define TG3_FLG2_FLASH                 0x00008000
diff --git a/include/crypto/b128ops.h b/include/crypto/b128ops.h
new file mode 100644 (file)
index 0000000..0b8e6bc
--- /dev/null
@@ -0,0 +1,80 @@
+/* b128ops.h - common 128-bit block operations
+ *
+ * Copyright (c) 2003, Dr Brian Gladman, Worcester, UK.
+ * Copyright (c) 2006, Rik Snel <rsnel@cube.dyndns.org>
+ *
+ * Based on Dr Brian Gladman's (GPL'd) work published at
+ * http://fp.gladman.plus.com/cryptography_technology/index.htm
+ * See the original copyright notice below.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+/*
+ ---------------------------------------------------------------------------
+ Copyright (c) 2003, Dr Brian Gladman, Worcester, UK.   All rights reserved.
+
+ LICENSE TERMS
+
+ The free distribution and use of this software in both source and binary
+ form is allowed (with or without changes) provided that:
+
+   1. distributions of this source code include the above copyright
+      notice, this list of conditions and the following disclaimer;
+
+   2. distributions in binary form include the above copyright
+      notice, this list of conditions and the following disclaimer
+      in the documentation and/or other associated materials;
+
+   3. the copyright holder's name is not used to endorse products
+      built using this software without specific written permission.
+
+ ALTERNATIVELY, provided that this notice is retained in full, this product
+ may be distributed under the terms of the GNU General Public License (GPL),
+ in which case the provisions of the GPL apply INSTEAD OF those given above.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explicit or implied warranties
+ in respect of its properties, including, but not limited to, correctness
+ and/or fitness for purpose.
+ ---------------------------------------------------------------------------
+ Issue Date: 13/06/2006
+*/
+
+#ifndef _CRYPTO_B128OPS_H
+#define _CRYPTO_B128OPS_H
+
+#include <linux/types.h>
+
+typedef struct {
+       u64 a, b;
+} u128;
+
+typedef struct {
+       __be64 a, b;
+} be128;
+
+typedef struct {
+       __le64 b, a;
+} le128;
+
+static inline void u128_xor(u128 *r, const u128 *p, const u128 *q)
+{
+       r->a = p->a ^ q->a;
+       r->b = p->b ^ q->b;
+}
+
+static inline void be128_xor(be128 *r, const be128 *p, const be128 *q)
+{
+       u128_xor((u128 *)r, (u128 *)p, (u128 *)q);
+}
+
+static inline void le128_xor(le128 *r, const le128 *p, const le128 *q)
+{
+       u128_xor((u128 *)r, (u128 *)p, (u128 *)q);
+}
+
+#endif /* _CRYPTO_B128OPS_H */
diff --git a/include/crypto/gf128mul.h b/include/crypto/gf128mul.h
new file mode 100644 (file)
index 0000000..4fd3152
--- /dev/null
@@ -0,0 +1,198 @@
+/* gf128mul.h - GF(2^128) multiplication functions
+ *
+ * Copyright (c) 2003, Dr Brian Gladman, Worcester, UK.
+ * Copyright (c) 2006 Rik Snel <rsnel@cube.dyndns.org>
+ *
+ * Based on Dr Brian Gladman's (GPL'd) work published at
+ * http://fp.gladman.plus.com/cryptography_technology/index.htm
+ * See the original copyright notice below.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+/*
+ ---------------------------------------------------------------------------
+ Copyright (c) 2003, Dr Brian Gladman, Worcester, UK.   All rights reserved.
+
+ LICENSE TERMS
+
+ The free distribution and use of this software in both source and binary
+ form is allowed (with or without changes) provided that:
+
+   1. distributions of this source code include the above copyright
+      notice, this list of conditions and the following disclaimer;
+
+   2. distributions in binary form include the above copyright
+      notice, this list of conditions and the following disclaimer
+      in the documentation and/or other associated materials;
+
+   3. the copyright holder's name is not used to endorse products
+      built using this software without specific written permission.
+
+ ALTERNATIVELY, provided that this notice is retained in full, this product
+ may be distributed under the terms of the GNU General Public License (GPL),
+ in which case the provisions of the GPL apply INSTEAD OF those given above.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explicit or implied warranties
+ in respect of its properties, including, but not limited to, correctness
+ and/or fitness for purpose.
+ ---------------------------------------------------------------------------
+ Issue Date: 31/01/2006
+
+ An implementation of field multiplication in Galois Field GF(128)
+*/
+
+#ifndef _CRYPTO_GF128MUL_H
+#define _CRYPTO_GF128MUL_H
+
+#include <crypto/b128ops.h>
+#include <linux/slab.h>
+
+/* Comment by Rik:
+ *
+ * For some background on GF(2^128) see for example: http://-
+ * csrc.nist.gov/CryptoToolkit/modes/proposedmodes/gcm/gcm-revised-spec.pdf
+ *
+ * The elements of GF(2^128) := GF(2)[X]/(X^128-X^7-X^2-X^1-1) can
+ * be mapped to computer memory in a variety of ways. Let's examine
+ * three common cases.
+ *
+ * Take a look at the 16 binary octets below in memory order. The msb's
+ * are left and the lsb's are right. char b[16] is an array and b[0] is
+ * the first octet.
+ *
+ * 80000000 00000000 00000000 00000000 .... 00000000 00000000 00000000
+ *   b[0]     b[1]     b[2]     b[3]          b[13]    b[14]    b[15]
+ *
+ * Every bit is a coefficient of some power of X. We can store the bits
+ * in every byte in little-endian order and the bytes themselves also in
+ * little endian order. I will call this lle (little-little-endian).
+ * The above buffer represents the polynomial 1, and X^7+X^2+X^1+1 looks
+ * like 11100001 00000000 .... 00000000 = { 0xE1, 0x00, }.
+ * This format was originally implemented in gf128mul and is used
+ * in GCM (Galois/Counter mode) and in ABL (Arbitrary Block Length).
+ *
+ * Another convention says: store the bits in bigendian order and the
+ * bytes also. This is bbe (big-big-endian). Now the buffer above
+ * represents X^127. X^7+X^2+X^1+1 looks like 00000000 .... 10000111,
+ * b[15] = 0x87 and the rest is 0. LRW uses this convention and bbe
+ * is partly implemented.
+ *
+ * Both of the above formats are easy to implement on big-endian
+ * machines.
+ *
+ * EME (which is patent encumbered) uses the ble format (bits are stored
+ * in big endian order and the bytes in little endian). The above buffer
+ * represents X^7 in this case and the primitive polynomial is b[0] = 0x87.
+ *
+ * The common machine word-size is smaller than 128 bits, so to make
+ * an efficient implementation we must split into machine word sizes.
+ * This file uses one 32bit for the moment. Machine endianness comes into
+ * play. The lle format in relation to machine endianness is discussed
+ * below by the original author of gf128mul Dr Brian Gladman.
+ *
+ * Let's look at the bbe and ble format on a little endian machine.
+ *
+ * bbe on a little endian machine u32 x[4]:
+ *
+ *  MS            x[0]           LS  MS            x[1]                  LS
+ *  ms   ls ms   ls ms   ls ms   ls  ms   ls ms   ls ms   ls ms   ls
+ *  103..96 111.104 119.112 127.120  71...64 79...72 87...80 95...88
+ *
+ *  MS            x[2]           LS  MS            x[3]                  LS
+ *  ms   ls ms   ls ms   ls ms   ls  ms   ls ms   ls ms   ls ms   ls
+ *  39...32 47...40 55...48 63...56  07...00 15...08 23...16 31...24
+ *
+ * ble on a little endian machine
+ *
+ *  MS            x[0]           LS  MS            x[1]                  LS
+ *  ms   ls ms   ls ms   ls ms   ls  ms   ls ms   ls ms   ls ms   ls
+ *  31...24 23...16 15...08 07...00  63...56 55...48 47...40 39...32
+ *
+ *  MS            x[2]           LS  MS            x[3]                  LS
+ *  ms   ls ms   ls ms   ls ms   ls  ms   ls ms   ls ms   ls ms   ls
+ *  95...88 87...80 79...72 71...64  127.120 199.112 111.104 103..96
+ *
+ * Multiplications in GF(2^128) are mostly bit-shifts, so you see why
+ * ble (and lbe also) are easier to implement on a little-endian
+ * machine than on a big-endian machine. The converse holds for bbe
+ * and lle.
+ *
+ * Note: to have good alignment, it seems to me that it is sufficient
+ * to keep elements of GF(2^128) in type u64[2]. On 32-bit wordsize
+ * machines this will automatically aligned to wordsize and on a 64-bit
+ * machine also.
+ */
+/*     Multiply a GF128 field element by x. Field elements are held in arrays
+    of bytes in which field bits 8n..8n + 7 are held in byte[n], with lower
+    indexed bits placed in the more numerically significant bit positions
+    within bytes.
+
+    On little endian machines the bit indexes translate into the bit
+    positions within four 32-bit words in the following way
+
+    MS            x[0]           LS  MS            x[1]                  LS
+    ms   ls ms   ls ms   ls ms   ls  ms   ls ms   ls ms   ls ms   ls
+    24...31 16...23 08...15 00...07  56...63 48...55 40...47 32...39
+
+    MS            x[2]           LS  MS            x[3]                  LS
+    ms   ls ms   ls ms   ls ms   ls  ms   ls ms   ls ms   ls ms   ls
+    88...95 80...87 72...79 64...71  120.127 112.119 104.111 96..103
+
+    On big endian machines the bit indexes translate into the bit
+    positions within four 32-bit words in the following way
+
+    MS            x[0]           LS  MS            x[1]                  LS
+    ms   ls ms   ls ms   ls ms   ls  ms   ls ms   ls ms   ls ms   ls
+    00...07 08...15 16...23 24...31  32...39 40...47 48...55 56...63
+
+    MS            x[2]           LS  MS            x[3]                  LS
+    ms   ls ms   ls ms   ls ms   ls  ms   ls ms   ls ms   ls ms   ls
+    64...71 72...79 80...87 88...95  96..103 104.111 112.119 120.127
+*/
+
+/*     A slow generic version of gf_mul, implemented for lle and bbe
+ *     It multiplies a and b and puts the result in a */
+void gf128mul_lle(be128 *a, const be128 *b);
+
+void gf128mul_bbe(be128 *a, const be128 *b);
+
+
+/* 4k table optimization */
+
+struct gf128mul_4k {
+       be128 t[256];
+};
+
+struct gf128mul_4k *gf128mul_init_4k_lle(const be128 *g);
+struct gf128mul_4k *gf128mul_init_4k_bbe(const be128 *g);
+void gf128mul_4k_lle(be128 *a, struct gf128mul_4k *t);
+void gf128mul_4k_bbe(be128 *a, struct gf128mul_4k *t);
+
+static inline void gf128mul_free_4k(struct gf128mul_4k *t)
+{
+       kfree(t);
+}
+
+
+/* 64k table optimization, implemented for lle and bbe */
+
+struct gf128mul_64k {
+       struct gf128mul_4k *t[16];
+};
+
+/* first initialize with the constant factor with which you
+ * want to multiply and then call gf128_64k_lle with the other
+ * factor in the first argument, the table in the second and a
+ * scratch register in the third. Afterwards *a = *r. */
+struct gf128mul_64k *gf128mul_init_64k_lle(const be128 *g);
+struct gf128mul_64k *gf128mul_init_64k_bbe(const be128 *g);
+void gf128mul_free_64k(struct gf128mul_64k *t);
+void gf128mul_64k_lle(be128 *a, struct gf128mul_64k *t);
+void gf128mul_64k_bbe(be128 *a, struct gf128mul_64k *t);
+
+#endif /* _CRYPTO_GF128MUL_H */
index b2ca666d9997ce35025fd85f57c655639bdab0d2..0e07db6cc0d0eeefc1c58e2f4980016afe713d05 100644 (file)
 #define AUDIT_MAC_CIPSOV4_DEL  1408    /* NetLabel: del CIPSOv4 DOI entry */
 #define AUDIT_MAC_MAP_ADD      1409    /* NetLabel: add LSM domain mapping */
 #define AUDIT_MAC_MAP_DEL      1410    /* NetLabel: del LSM domain mapping */
+#define AUDIT_MAC_IPSEC_ADDSA  1411    /* Add a XFRM state */
+#define AUDIT_MAC_IPSEC_DELSA  1412    /* Delete a XFRM state */
+#define AUDIT_MAC_IPSEC_ADDSPD 1413    /* Add a XFRM policy */
+#define AUDIT_MAC_IPSEC_DELSPD 1414    /* Delete a XFRM policy */
 
 #define AUDIT_FIRST_KERN_ANOM_MSG   1700
 #define AUDIT_LAST_KERN_ANOM_MSG    1799
@@ -377,6 +381,7 @@ extern void auditsc_get_stamp(struct audit_context *ctx,
                              struct timespec *t, unsigned int *serial);
 extern int  audit_set_loginuid(struct task_struct *task, uid_t loginuid);
 extern uid_t audit_get_loginuid(struct audit_context *ctx);
+extern void audit_log_task_context(struct audit_buffer *ab);
 extern int __audit_ipc_obj(struct kern_ipc_perm *ipcp);
 extern int __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode);
 extern int audit_bprm(struct linux_binprm *bprm);
@@ -449,6 +454,7 @@ extern int audit_n_rules;
 #define audit_inode_update(i) do { ; } while (0)
 #define auditsc_get_stamp(c,t,s) do { BUG(); } while (0)
 #define audit_get_loginuid(c) ({ -1; })
+#define audit_log_task_context(b) do { ; } while (0)
 #define audit_ipc_obj(i) ({ 0; })
 #define audit_ipc_set_perm(q,u,g,m) ({ 0; })
 #define audit_bprm(p) ({ 0; })
index 6485e9716b36abbc9e0998a95eb35d3b313d41ae..4aa9046601da18e8c7d18a26b661197887bd6aec 100644 (file)
@@ -241,12 +241,8 @@ int crypto_unregister_alg(struct crypto_alg *alg);
  * Algorithm query interface.
  */
 #ifdef CONFIG_CRYPTO
-int crypto_alg_available(const char *name, u32 flags)
-       __deprecated_for_modules;
 int crypto_has_alg(const char *name, u32 type, u32 mask);
 #else
-static int crypto_alg_available(const char *name, u32 flags)
-       __deprecated_for_modules;
 static inline int crypto_alg_available(const char *name, u32 flags)
 {
        return 0;
@@ -707,16 +703,6 @@ static inline void crypto_cipher_decrypt_one(struct crypto_cipher *tfm,
                                                dst, src);
 }
 
-void crypto_digest_init(struct crypto_tfm *tfm) __deprecated_for_modules;
-void crypto_digest_update(struct crypto_tfm *tfm,
-                         struct scatterlist *sg, unsigned int nsg)
-       __deprecated_for_modules;
-void crypto_digest_final(struct crypto_tfm *tfm, u8 *out)
-       __deprecated_for_modules;
-void crypto_digest_digest(struct crypto_tfm *tfm,
-                         struct scatterlist *sg, unsigned int nsg, u8 *out)
-       __deprecated_for_modules;
-
 static inline struct crypto_hash *__crypto_hash_cast(struct crypto_tfm *tfm)
 {
        return (struct crypto_hash *)tfm;
@@ -729,14 +715,6 @@ static inline struct crypto_hash *crypto_hash_cast(struct crypto_tfm *tfm)
        return __crypto_hash_cast(tfm);
 }
 
-static int crypto_digest_setkey(struct crypto_tfm *tfm, const u8 *key,
-                               unsigned int keylen) __deprecated;
-static inline int crypto_digest_setkey(struct crypto_tfm *tfm,
-                                       const u8 *key, unsigned int keylen)
-{
-       return tfm->crt_hash.setkey(crypto_hash_cast(tfm), key, keylen);
-}
-
 static inline struct crypto_hash *crypto_alloc_hash(const char *alg_name,
                                                    u32 type, u32 mask)
 {
index 9049dc65ae51b6b34751c4011e43e36646d56bcb..f7a93770e1be864cd6f1ddb152784597fdac0101 100644 (file)
@@ -17,6 +17,9 @@ struct genlmsghdr {
 #define GENL_HDRLEN    NLMSG_ALIGN(sizeof(struct genlmsghdr))
 
 #define GENL_ADMIN_PERM                0x01
+#define GENL_CMD_CAP_DO                0x02
+#define GENL_CMD_CAP_DUMP      0x04
+#define GENL_CMD_CAP_HASPOL    0x08
 
 /*
  * List of reserved static generic netlink identifiers:
@@ -58,9 +61,6 @@ enum {
        CTRL_ATTR_OP_UNSPEC,
        CTRL_ATTR_OP_ID,
        CTRL_ATTR_OP_FLAGS,
-       CTRL_ATTR_OP_POLICY,
-       CTRL_ATTR_OP_DOIT,
-       CTRL_ATTR_OP_DUMPIT,
        __CTRL_ATTR_OP_MAX,
 };
 
index fb049ec11ff26ab6e6230a884fd57e7c4b9afed3..9d8144a488cd5bfa5a29910b8d1684cb0ace2386 100644 (file)
@@ -2,6 +2,8 @@
 #ifndef _NF_CONNTRACK_PPTP_H
 #define _NF_CONNTRACK_PPTP_H
 
+#include <linux/netfilter/nf_conntrack_common.h>
+
 /* state of the control session */
 enum pptp_ctrlsess_state {
        PPTP_SESSION_NONE,                      /* no session present */
@@ -295,7 +297,6 @@ union pptp_ctrl_union {
 /* crap needed for nf_conntrack_compat.h */
 struct nf_conn;
 struct nf_conntrack_expect;
-enum ip_conntrack_info;
 
 extern int
 (*nf_nat_pptp_hook_outbound)(struct sk_buff **pskb,
index ff2dcb436cd0606d997b69fe6c7803bd2f36859a..4d972bbef31610e877a4b5739a7299d291009d9a 100644 (file)
 #define PCI_DEVICE_ID_TIGON3_5750M     0x167c
 #define PCI_DEVICE_ID_TIGON3_5751M     0x167d
 #define PCI_DEVICE_ID_TIGON3_5751F     0x167e
+#define PCI_DEVICE_ID_TIGON3_5787F     0x167f
 #define PCI_DEVICE_ID_TIGON3_5787M     0x1693
 #define PCI_DEVICE_ID_TIGON3_5782      0x1696
 #define PCI_DEVICE_ID_TIGON3_5786      0x169a
 #define PCI_DEVICE_ID_FARSITE_TE1       0x1610
 #define PCI_DEVICE_ID_FARSITE_TE1C      0x1612
 
+#define PCI_VENDOR_ID_ARIMA            0x161f
+
 #define PCI_VENDOR_ID_SIBYTE           0x166d
 #define PCI_DEVICE_ID_BCM1250_PCI      0x0001
 #define PCI_DEVICE_ID_BCM1250_HT       0x0002
index 0f0b880c428034f66f9a6203fa58d1f5962541fe..265bafab64941225f0cad5900e349e4849bdde42 100644 (file)
@@ -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
 
index 492dedaa8ac16dacd4cbab84484293a61e636f72..1720539ac2c1b0270e1358e6a6541e34dc709005 100644 (file)
@@ -28,6 +28,8 @@
 void irlan_check_command_param(struct irlan_cb *self, char *param, 
                               char *value);
 void irlan_filter_request(struct irlan_cb *self, struct sk_buff *skb);
+#ifdef CONFIG_PROC_FS
 void irlan_print_filter(struct seq_file *seq, int filter_type);
+#endif
 
 #endif /* IRLAN_FILTER_H */
index 15ec19dcf9c886864374a044e636c941ab8e0903..e4765413cf80c7ee9a5f4997796f6ee7ef93a206 100644 (file)
@@ -392,6 +392,20 @@ extern int xfrm_unregister_km(struct xfrm_mgr *km);
 
 extern unsigned int xfrm_policy_count[XFRM_POLICY_MAX*2];
 
+/* Audit Information */
+struct xfrm_audit
+{
+       uid_t   loginuid;
+       u32     secid;
+};
+
+#ifdef CONFIG_AUDITSYSCALL
+extern void xfrm_audit_log(uid_t auid, u32 secid, int type, int result,
+                   struct xfrm_policy *xp, struct xfrm_state *x);
+#else
+#define xfrm_audit_log(a,s,t,r,p,x) do { ; } while (0)
+#endif /* CONFIG_AUDITSYSCALL */
+
 static inline void xfrm_pol_hold(struct xfrm_policy *policy)
 {
        if (likely(policy != NULL))
@@ -906,7 +920,7 @@ static inline int xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **s
 #endif
 extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq);
 extern int xfrm_state_delete(struct xfrm_state *x);
-extern void xfrm_state_flush(u8 proto);
+extern void xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info);
 extern int xfrm_replay_check(struct xfrm_state *x, __be32 seq);
 extern void xfrm_replay_advance(struct xfrm_state *x, __be32 seq);
 extern void xfrm_replay_notify(struct xfrm_state *x, int event);
@@ -959,13 +973,13 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir,
                                          struct xfrm_selector *sel,
                                          struct xfrm_sec_ctx *ctx, int delete);
 struct xfrm_policy *xfrm_policy_byid(u8, int dir, u32 id, int delete);
-void xfrm_policy_flush(u8 type);
+void xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info);
 u32 xfrm_get_acqseq(void);
 void xfrm_alloc_spi(struct xfrm_state *x, __be32 minspi, __be32 maxspi);
-struct xfrm_state * xfrm_find_acq(u8 mode, u32 reqid, u8 proto, 
-                                 xfrm_address_t *daddr, xfrm_address_t *saddr, 
+struct xfrm_state * xfrm_find_acq(u8 mode, u32 reqid, u8 proto,
+                                 xfrm_address_t *daddr, xfrm_address_t *saddr,
                                  int create, unsigned short family);
-extern void xfrm_policy_flush(u8 type);
+extern void xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info);
 extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
 extern int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *xdst,
                          struct flowi *fl, int family, int strict);
index ab97e51012325b24191ec5a6f2c1e2514968dd02..40722e26de98e285c1f90ff810b20aff6d3cb9a2 100644 (file)
@@ -731,7 +731,7 @@ static inline void audit_free_context(struct audit_context *context)
                printk(KERN_ERR "audit: freed %d contexts\n", count);
 }
 
-static void audit_log_task_context(struct audit_buffer *ab)
+void audit_log_task_context(struct audit_buffer *ab)
 {
        char *ctx = NULL;
        ssize_t len = 0;
@@ -760,6 +760,8 @@ error_path:
        return;
 }
 
+EXPORT_SYMBOL(audit_log_task_context);
+
 static void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk)
 {
        char name[sizeof(tsk->comm)];
@@ -1488,6 +1490,8 @@ uid_t audit_get_loginuid(struct audit_context *ctx)
        return ctx ? ctx->loginuid : -1;
 }
 
+EXPORT_SYMBOL(audit_get_loginuid);
+
 /**
  * __audit_mq_open - record audit data for a POSIX MQ open
  * @oflag: open flag
index ac47ba2ba0284c9f22150305a54ac7b0ab9a6504..bd221ad52eaf76e46aa8522b4db1a75176e53ecc 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/netfilter_ipv6.h>
 #include <linux/netfilter_arp.h>
 #include <linux/in_route.h>
+#include <linux/inetdevice.h>
 
 #include <net/ip.h>
 #include <net/ipv6.h>
@@ -221,10 +222,14 @@ static void __br_dnat_complain(void)
  *
  * Otherwise, the packet is considered to be routed and we just
  * change the destination MAC address so that the packet will
- * later be passed up to the IP stack to be routed.
+ * later be passed up to the IP stack to be routed. For a redirected
+ * packet, ip_route_input() will give back the localhost as output device,
+ * which differs from the bridge device.
  *
  * Let us now consider the case that ip_route_input() fails:
  *
+ * This can be because the destination address is martian, in which case
+ * the packet will be dropped.
  * After a "echo '0' > /proc/sys/net/ipv4/ip_forward" ip_route_input()
  * will fail, while __ip_route_output_key() will return success. The source
  * address for __ip_route_output_key() is set to zero, so __ip_route_output_key
@@ -237,7 +242,8 @@ static void __br_dnat_complain(void)
  *
  * --Lennert, 20020411
  * --Bart, 20020416 (updated)
- * --Bart, 20021007 (updated) */
+ * --Bart, 20021007 (updated)
+ * --Bart, 20062711 (updated) */
 static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb)
 {
        if (skb->pkt_type == PACKET_OTHERHOST) {
@@ -264,15 +270,15 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb)
        struct net_device *dev = skb->dev;
        struct iphdr *iph = skb->nh.iph;
        struct nf_bridge_info *nf_bridge = skb->nf_bridge;
+       int err;
 
        if (nf_bridge->mask & BRNF_PKT_TYPE) {
                skb->pkt_type = PACKET_OTHERHOST;
                nf_bridge->mask ^= BRNF_PKT_TYPE;
        }
        nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING;
-
        if (dnat_took_place(skb)) {
-               if (ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev)) {
+               if ((err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev))) {
                        struct rtable *rt;
                        struct flowi fl = {
                                .nl_u = {
@@ -283,19 +289,33 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb)
                                },
                                .proto = 0,
                        };
+                       struct in_device *in_dev = in_dev_get(dev);
+
+                       /* If err equals -EHOSTUNREACH the error is due to a
+                        * martian destination or due to the fact that
+                        * forwarding is disabled. For most martian packets,
+                        * ip_route_output_key() will fail. It won't fail for 2 types of
+                        * martian destinations: loopback destinations and destination
+                        * 0.0.0.0. In both cases the packet will be dropped because the
+                        * destination is the loopback device and not the bridge. */
+                       if (err != -EHOSTUNREACH || !in_dev || IN_DEV_FORWARD(in_dev))
+                               goto free_skb;
 
                        if (!ip_route_output_key(&rt, &fl)) {
                                /* - Bridged-and-DNAT'ed traffic doesn't
-                                *   require ip_forwarding.
-                                * - Deal with redirected traffic. */
-                               if (((struct dst_entry *)rt)->dev == dev ||
-                                   rt->rt_type == RTN_LOCAL) {
+                                *   require ip_forwarding. */
+                               if (((struct dst_entry *)rt)->dev == dev) {
                                        skb->dst = (struct dst_entry *)rt;
                                        goto bridged_dnat;
                                }
+                               /* we are sure that forwarding is disabled, so printing
+                                * this message is no problem. Note that the packet could
+                                * still have a martian destination address, in which case
+                                * the packet could be dropped even if forwarding were enabled */
                                __br_dnat_complain();
                                dst_release((struct dst_entry *)rt);
                        }
+free_skb:
                        kfree_skb(skb);
                        return 0;
                } else {
index cb1b8728d7eec0c55c6151da9fba7d00f42747e9..f69ab7b4408ecca979e5e6f43aefd2a051577c06 100644 (file)
@@ -2130,7 +2130,7 @@ int iw_handler_set_spy(struct net_device *        dev,
         * The rtnl_lock() make sure we don't race with the other iw_handlers.
         * This make sure wireless_spy_update() "see" that the spy list
         * is temporarily disabled. */
-       wmb();
+       smp_wmb();
 
        /* Are there are addresses to copy? */
        if(wrqu->data.length > 0) {
@@ -2159,7 +2159,7 @@ int iw_handler_set_spy(struct net_device *        dev,
        }
 
        /* Make sure above is updated before re-enabling */
-       wmb();
+       smp_wmb();
 
        /* Enable addresses */
        spydata->spy_number = wrqu->data.length;
index e28330aa41390ef3a86865a106365d1224d9aa12..9f414e35c488fe2c1464b1aae47363b17968fb5f 100644 (file)
@@ -178,7 +178,6 @@ void inet_twdr_hangman(unsigned long data)
        need_timer = 0;
        if (inet_twdr_do_twkill_work(twdr, twdr->slot)) {
                twdr->thread_slots |= (1 << twdr->slot);
-               mb();
                schedule_work(&twdr->twkill_work);
                need_timer = 1;
        } else {
index 413c2d0a1f3dee117db48289865279113f70e348..71b76ade00e13fa9dee0bd00ec05578e910825b5 100644 (file)
@@ -375,6 +375,13 @@ static int mark_source_chains(struct xt_table_info *newinfo,
                            && unconditional(&e->arp)) {
                                unsigned int oldpos, size;
 
+                               if (t->verdict < -NF_MAX_VERDICT - 1) {
+                                       duprintf("mark_source_chains: bad "
+                                               "negative verdict (%i)\n",
+                                                               t->verdict);
+                                       return 0;
+                               }
+
                                /* Return: backtrack through the last
                                 * big jump.
                                 */
@@ -404,6 +411,14 @@ static int mark_source_chains(struct xt_table_info *newinfo,
                                if (strcmp(t->target.u.user.name,
                                           ARPT_STANDARD_TARGET) == 0
                                    && newpos >= 0) {
+                                       if (newpos > newinfo->size -
+                                               sizeof(struct arpt_entry)) {
+                                               duprintf("mark_source_chains: "
+                                                       "bad verdict (%i)\n",
+                                                               newpos);
+                                               return 0;
+                                       }
+
                                        /* This a jump; chase it. */
                                        duprintf("Jump rule %u -> %u\n",
                                                 pos, newpos);
@@ -426,8 +441,6 @@ static int mark_source_chains(struct xt_table_info *newinfo,
 static inline int standard_check(const struct arpt_entry_target *t,
                                 unsigned int max_offset)
 {
-       struct arpt_standard_target *targ = (void *)t;
-
        /* Check standard info. */
        if (t->u.target_size
            != ARPT_ALIGN(sizeof(struct arpt_standard_target))) {
@@ -437,18 +450,6 @@ static inline int standard_check(const struct arpt_entry_target *t,
                return 0;
        }
 
-       if (targ->verdict >= 0
-           && targ->verdict > max_offset - sizeof(struct arpt_entry)) {
-               duprintf("arpt_standard_check: bad verdict (%i)\n",
-                        targ->verdict);
-               return 0;
-       }
-
-       if (targ->verdict < -NF_MAX_VERDICT - 1) {
-               duprintf("arpt_standard_check: bad negative verdict (%i)\n",
-                        targ->verdict);
-               return 0;
-       }
        return 1;
 }
 
@@ -627,18 +628,20 @@ static int translate_table(const char *name,
                }
        }
 
+       if (!mark_source_chains(newinfo, valid_hooks, entry0)) {
+               duprintf("Looping hook\n");
+               return -ELOOP;
+       }
+
        /* Finally, each sanity check must pass */
        i = 0;
        ret = ARPT_ENTRY_ITERATE(entry0, newinfo->size,
                                 check_entry, name, size, &i);
 
-       if (ret != 0)
-               goto cleanup;
-
-       ret = -ELOOP;
-       if (!mark_source_chains(newinfo, valid_hooks, entry0)) {
-               duprintf("Looping hook\n");
-               goto cleanup;
+       if (ret != 0) {
+               ARPT_ENTRY_ITERATE(entry0, newinfo->size,
+                               cleanup_entry, &i);
+               return ret;
        }
 
        /* And one copy for every other CPU */
@@ -647,9 +650,6 @@ static int translate_table(const char *name,
                        memcpy(newinfo->entries[i], entry0, newinfo->size);
        }
 
-       return 0;
-cleanup:
-       ARPT_ENTRY_ITERATE(entry0, newinfo->size, cleanup_entry, &i);
        return ret;
 }
 
index 8a455439b128258de3e42926640834975579d5af..0ff2956d35e5ab876d531efd2fe274c276ad5208 100644 (file)
@@ -401,6 +401,13 @@ mark_source_chains(struct xt_table_info *newinfo,
                            && unconditional(&e->ip)) {
                                unsigned int oldpos, size;
 
+                               if (t->verdict < -NF_MAX_VERDICT - 1) {
+                                       duprintf("mark_source_chains: bad "
+                                               "negative verdict (%i)\n",
+                                                               t->verdict);
+                                       return 0;
+                               }
+
                                /* Return: backtrack through the last
                                   big jump. */
                                do {
@@ -438,6 +445,13 @@ mark_source_chains(struct xt_table_info *newinfo,
                                if (strcmp(t->target.u.user.name,
                                           IPT_STANDARD_TARGET) == 0
                                    && newpos >= 0) {
+                                       if (newpos > newinfo->size -
+                                               sizeof(struct ipt_entry)) {
+                                               duprintf("mark_source_chains: "
+                                                       "bad verdict (%i)\n",
+                                                               newpos);
+                                               return 0;
+                                       }
                                        /* This a jump; chase it. */
                                        duprintf("Jump rule %u -> %u\n",
                                                 pos, newpos);
@@ -469,27 +483,6 @@ cleanup_match(struct ipt_entry_match *m, unsigned int *i)
        return 0;
 }
 
-static inline int
-standard_check(const struct ipt_entry_target *t,
-              unsigned int max_offset)
-{
-       struct ipt_standard_target *targ = (void *)t;
-
-       /* Check standard info. */
-       if (targ->verdict >= 0
-           && targ->verdict > max_offset - sizeof(struct ipt_entry)) {
-               duprintf("ipt_standard_check: bad verdict (%i)\n",
-                        targ->verdict);
-               return 0;
-       }
-       if (targ->verdict < -NF_MAX_VERDICT - 1) {
-               duprintf("ipt_standard_check: bad negative verdict (%i)\n",
-                        targ->verdict);
-               return 0;
-       }
-       return 1;
-}
-
 static inline int
 check_match(struct ipt_entry_match *m,
            const char *name,
@@ -576,12 +569,7 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size,
        if (ret)
                goto err;
 
-       if (t->u.kernel.target == &ipt_standard_target) {
-               if (!standard_check(t, size)) {
-                       ret = -EINVAL;
-                       goto err;
-               }
-       } else if (t->u.kernel.target->checkentry
+       if (t->u.kernel.target->checkentry
                   && !t->u.kernel.target->checkentry(name, e, target, t->data,
                                                      e->comefrom)) {
                duprintf("ip_tables: check failed for `%s'.\n",
@@ -718,17 +706,19 @@ translate_table(const char *name,
                }
        }
 
+       if (!mark_source_chains(newinfo, valid_hooks, entry0))
+               return -ELOOP;
+
        /* Finally, each sanity check must pass */
        i = 0;
        ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
                                check_entry, name, size, &i);
 
-       if (ret != 0)
-               goto cleanup;
-
-       ret = -ELOOP;
-       if (!mark_source_chains(newinfo, valid_hooks, entry0))
-               goto cleanup;
+       if (ret != 0) {
+               IPT_ENTRY_ITERATE(entry0, newinfo->size,
+                               cleanup_entry, &i);
+               return ret;
+       }
 
        /* And one copy for every other CPU */
        for_each_possible_cpu(i) {
@@ -736,9 +726,6 @@ translate_table(const char *name,
                        memcpy(newinfo->entries[i], entry0, newinfo->size);
        }
 
-       return 0;
-cleanup:
-       IPT_ENTRY_ITERATE(entry0, newinfo->size, cleanup_entry, &i);
        return ret;
 }
 
@@ -1529,25 +1516,8 @@ static inline int compat_copy_match_from_user(struct ipt_entry_match *m,
        void **dstptr, compat_uint_t *size, const char *name,
        const struct ipt_ip *ip, unsigned int hookmask)
 {
-       struct ipt_entry_match *dm;
-       struct ipt_match *match;
-       int ret;
-
-       dm = (struct ipt_entry_match *)*dstptr;
-       match = m->u.kernel.match;
        xt_compat_match_from_user(m, dstptr, size);
-
-       ret = xt_check_match(match, AF_INET, dm->u.match_size - sizeof(*dm),
-                            name, hookmask, ip->proto,
-                            ip->invflags & IPT_INV_PROTO);
-       if (!ret && m->u.kernel.match->checkentry
-           && !m->u.kernel.match->checkentry(name, ip, match, dm->data,
-                                             hookmask)) {
-               duprintf("ip_tables: check failed for `%s'.\n",
-                        m->u.kernel.match->name);
-               ret = -EINVAL;
-       }
-       return ret;
+       return 0;
 }
 
 static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr,
@@ -1569,7 +1539,7 @@ static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr,
        ret = IPT_MATCH_ITERATE(e, compat_copy_match_from_user, dstptr, size,
                        name, &de->ip, de->comefrom);
        if (ret)
-               goto err;
+               return ret;
        de->target_offset = e->target_offset - (origsize - *size);
        t = ipt_get_target(e);
        target = t->u.kernel.target;
@@ -1582,31 +1552,62 @@ static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr,
                if ((unsigned char *)de - base < newinfo->underflow[h])
                        newinfo->underflow[h] -= origsize - *size;
        }
+       return ret;
+}
+
+static inline int compat_check_match(struct ipt_entry_match *m, const char *name,
+                               const struct ipt_ip *ip, unsigned int hookmask)
+{
+       struct ipt_match *match;
+       int ret;
+
+       match = m->u.kernel.match;
+       ret = xt_check_match(match, AF_INET, m->u.match_size - sizeof(*m),
+                            name, hookmask, ip->proto,
+                            ip->invflags & IPT_INV_PROTO);
+       if (!ret && m->u.kernel.match->checkentry
+           && !m->u.kernel.match->checkentry(name, ip, match, m->data,
+                                             hookmask)) {
+               duprintf("ip_tables: compat: check failed for `%s'.\n",
+                        m->u.kernel.match->name);
+               ret = -EINVAL;
+       }
+       return ret;
+}
+
+static inline int compat_check_target(struct ipt_entry *e, const char *name)
+{
+       struct ipt_entry_target *t;
+       struct ipt_target *target;
+       int ret;
 
-       t = ipt_get_target(de);
+       t = ipt_get_target(e);
        target = t->u.kernel.target;
        ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
                              name, e->comefrom, e->ip.proto,
                              e->ip.invflags & IPT_INV_PROTO);
-       if (ret)
-               goto err;
-
-       ret = -EINVAL;
-       if (t->u.kernel.target == &ipt_standard_target) {
-               if (!standard_check(t, *size))
-                       goto err;
-       } else if (t->u.kernel.target->checkentry
-                  && !t->u.kernel.target->checkentry(name, de, target,
-                                                     t->data, de->comefrom)) {
+       if (!ret && t->u.kernel.target->checkentry
+                  && !t->u.kernel.target->checkentry(name, e, target,
+                                                     t->data, e->comefrom)) {
                duprintf("ip_tables: compat: check failed for `%s'.\n",
                         t->u.kernel.target->name);
-               goto err;
+               ret = -EINVAL;
        }
-       ret = 0;
-err:
        return ret;
 }
 
+static inline int compat_check_entry(struct ipt_entry *e, const char *name)
+{
+       int ret;
+
+       ret = IPT_MATCH_ITERATE(e, compat_check_match, name, &e->ip,
+                                                               e->comefrom);
+       if (ret)
+               return ret;
+
+       return compat_check_target(e, name);
+}
+
 static int
 translate_compat_table(const char *name,
                unsigned int valid_hooks,
@@ -1695,6 +1696,11 @@ translate_compat_table(const char *name,
        if (!mark_source_chains(newinfo, valid_hooks, entry1))
                goto free_newinfo;
 
+       ret = IPT_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry,
+                                                                       name);
+       if (ret)
+               goto free_newinfo;
+
        /* And one copy for every other CPU */
        for_each_possible_cpu(i)
                if (newinfo->entries[i] && newinfo->entries[i] != entry1)
index 9f3924c4905e213fcd2c9dcf23f011eadbb00e92..11c167118e87fa87ecfd7898a6190c06fd24d7a0 100644 (file)
@@ -1780,7 +1780,7 @@ static inline int __mkroute_input(struct sk_buff *skb,
 #endif
        if (in_dev->cnf.no_policy)
                rth->u.dst.flags |= DST_NOPOLICY;
-       if (in_dev->cnf.no_xfrm)
+       if (out_dev->cnf.no_xfrm)
                rth->u.dst.flags |= DST_NOXFRM;
        rth->fl.fl4_dst = daddr;
        rth->rt_dst     = daddr;
index 9304034c0c471cf376fb13e5fe41754ea707c2be..c701f6abbfc14a3ab05ba52c7469dc8cb5875df8 100644 (file)
@@ -4235,7 +4235,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
                 * Change state from SYN-SENT only after copied_seq
                 * is initialized. */
                tp->copied_seq = tp->rcv_nxt;
-               mb();
+               smp_mb();
                tcp_set_state(sk, TCP_ESTABLISHED);
 
                security_inet_conn_established(sk, skb);
@@ -4483,7 +4483,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
                case TCP_SYN_RECV:
                        if (acceptable) {
                                tp->copied_seq = tp->rcv_nxt;
-                               mb();
+                               smp_mb();
                                tcp_set_state(sk, TCP_ESTABLISHED);
                                sk->sk_state_change(sk);
 
index d4107bb701b58ba4492c68b51d902fb6e286b05a..fb9f69c616f5c3dbf43af6db14a8178aba46419b 100644 (file)
@@ -274,6 +274,8 @@ static void xfrm4_dst_destroy(struct dst_entry *dst)
 
        if (likely(xdst->u.rt.idev))
                in_dev_put(xdst->u.rt.idev);
+       if (likely(xdst->u.rt.peer))
+               inet_putpeer(xdst->u.rt.peer);
        xfrm_dst_destroy(xdst);
 }
 
index e05ecbb1412ddaa91777333cf358217eb3e08be7..e9212c7ff5cf9cd38d0599b8a8bb479ab626ce27 100644 (file)
@@ -624,13 +624,13 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
                skb_shinfo(skb)->frag_list = NULL;
                /* BUILD HEADER */
 
+               *prevhdr = NEXTHDR_FRAGMENT;
                tmp_hdr = kmemdup(skb->nh.raw, hlen, GFP_ATOMIC);
                if (!tmp_hdr) {
                        IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS);
                        return -ENOMEM;
                }
 
-               *prevhdr = NEXTHDR_FRAGMENT;
                __skb_pull(skb, hlen);
                fh = (struct frag_hdr*)__skb_push(skb, sizeof(struct frag_hdr));
                skb->nh.raw = __skb_push(skb, hlen);
index f63fb86d7c7b56732a108bcf1cfeae6b9f81472b..4eec4b3988b824af9b763cb615d4e2ee148d9127 100644 (file)
@@ -440,6 +440,13 @@ mark_source_chains(struct xt_table_info *newinfo,
                            && unconditional(&e->ipv6)) {
                                unsigned int oldpos, size;
 
+                               if (t->verdict < -NF_MAX_VERDICT - 1) {
+                                       duprintf("mark_source_chains: bad "
+                                               "negative verdict (%i)\n",
+                                                               t->verdict);
+                                       return 0;
+                               }
+
                                /* Return: backtrack through the last
                                   big jump. */
                                do {
@@ -477,6 +484,13 @@ mark_source_chains(struct xt_table_info *newinfo,
                                if (strcmp(t->target.u.user.name,
                                           IP6T_STANDARD_TARGET) == 0
                                    && newpos >= 0) {
+                                       if (newpos > newinfo->size -
+                                               sizeof(struct ip6t_entry)) {
+                                               duprintf("mark_source_chains: "
+                                                       "bad verdict (%i)\n",
+                                                               newpos);
+                                               return 0;
+                                       }
                                        /* This a jump; chase it. */
                                        duprintf("Jump rule %u -> %u\n",
                                                 pos, newpos);
@@ -508,27 +522,6 @@ cleanup_match(struct ip6t_entry_match *m, unsigned int *i)
        return 0;
 }
 
-static inline int
-standard_check(const struct ip6t_entry_target *t,
-              unsigned int max_offset)
-{
-       struct ip6t_standard_target *targ = (void *)t;
-
-       /* Check standard info. */
-       if (targ->verdict >= 0
-           && targ->verdict > max_offset - sizeof(struct ip6t_entry)) {
-               duprintf("ip6t_standard_check: bad verdict (%i)\n",
-                        targ->verdict);
-               return 0;
-       }
-       if (targ->verdict < -NF_MAX_VERDICT - 1) {
-               duprintf("ip6t_standard_check: bad negative verdict (%i)\n",
-                        targ->verdict);
-               return 0;
-       }
-       return 1;
-}
-
 static inline int
 check_match(struct ip6t_entry_match *m,
            const char *name,
@@ -616,12 +609,7 @@ check_entry(struct ip6t_entry *e, const char *name, unsigned int size,
        if (ret)
                goto err;
 
-       if (t->u.kernel.target == &ip6t_standard_target) {
-               if (!standard_check(t, size)) {
-                       ret = -EINVAL;
-                       goto err;
-               }
-       } else if (t->u.kernel.target->checkentry
+       if (t->u.kernel.target->checkentry
                   && !t->u.kernel.target->checkentry(name, e, target, t->data,
                                                      e->comefrom)) {
                duprintf("ip_tables: check failed for `%s'.\n",
@@ -758,17 +746,19 @@ translate_table(const char *name,
                }
        }
 
+       if (!mark_source_chains(newinfo, valid_hooks, entry0))
+               return -ELOOP;
+
        /* Finally, each sanity check must pass */
        i = 0;
        ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size,
                                check_entry, name, size, &i);
 
-       if (ret != 0)
-               goto cleanup;
-
-       ret = -ELOOP;
-       if (!mark_source_chains(newinfo, valid_hooks, entry0))
-               goto cleanup;
+       if (ret != 0) {
+               IP6T_ENTRY_ITERATE(entry0, newinfo->size,
+                                  cleanup_entry, &i);
+               return ret;
+       }
 
        /* And one copy for every other CPU */
        for_each_possible_cpu(i) {
@@ -777,9 +767,6 @@ translate_table(const char *name,
        }
 
        return 0;
-cleanup:
-       IP6T_ENTRY_ITERATE(entry0, newinfo->size, cleanup_entry, &i);
-       return ret;
 }
 
 /* Gets counters. */
index c2e629d6aea40e5519c3b865d62e1a092e6c9b60..4ae1b19ada5d3eb9e3c3c7f0b1b7a8030002eacb 100644 (file)
@@ -854,7 +854,8 @@ back_from_confirm:
        }
 done:
        dst_release(dst);
-       release_sock(sk);
+       if (!inet->hdrincl)
+               release_sock(sk);
 out:   
        fl6_sock_release(flowlabel);
        return err<0?err:len;
index 252f11012566ca1758851ef9489785ca8fe95ce7..03504f3e4990cb82bb8592845d79c7525d172b09 100644 (file)
@@ -1100,7 +1100,7 @@ int irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel,
                        return -ENOMEM;
 
                /* Reserve space for MUX_CONTROL and LAP header */
-               skb_reserve(tx_skb, TTP_MAX_HEADER);
+               skb_reserve(tx_skb, TTP_MAX_HEADER + TTP_SAR_HEADER);
        } else {
                tx_skb = userdata;
                /*
@@ -1349,7 +1349,7 @@ int irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size,
                        return -ENOMEM;
 
                /* Reserve space for MUX_CONTROL and LAP header */
-               skb_reserve(tx_skb, TTP_MAX_HEADER);
+               skb_reserve(tx_skb, TTP_MAX_HEADER + TTP_SAR_HEADER);
        } else {
                tx_skb = userdata;
                /*
index 0e1dbfbb9b109ae6e2be92bbac0a592ec4a2ecb0..5dd5094659a186655d88a50a44ba2849a44bc776 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/proc_fs.h>
 #include <linux/init.h>
 #include <net/xfrm.h>
+#include <linux/audit.h>
 
 #include <net/sock.h>
 
@@ -1420,6 +1421,9 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr,
        else
                err = xfrm_state_update(x);
 
+       xfrm_audit_log(audit_get_loginuid(current->audit_context), 0,
+                      AUDIT_MAC_IPSEC_ADDSA, err ? 0 : 1, NULL, x);
+
        if (err < 0) {
                x->km.state = XFRM_STATE_DEAD;
                __xfrm_state_put(x);
@@ -1460,8 +1464,12 @@ static int pfkey_delete(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
                err = -EPERM;
                goto out;
        }
-       
+
        err = xfrm_state_delete(x);
+
+       xfrm_audit_log(audit_get_loginuid(current->audit_context), 0,
+                      AUDIT_MAC_IPSEC_DELSA, err ? 0 : 1, NULL, x);
+
        if (err < 0)
                goto out;
 
@@ -1637,12 +1645,15 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hd
 {
        unsigned proto;
        struct km_event c;
+       struct xfrm_audit audit_info;
 
        proto = pfkey_satype2proto(hdr->sadb_msg_satype);
        if (proto == 0)
                return -EINVAL;
 
-       xfrm_state_flush(proto);
+       audit_info.loginuid = audit_get_loginuid(current->audit_context);
+       audit_info.secid = 0;
+       xfrm_state_flush(proto, &audit_info);
        c.data.proto = proto;
        c.seq = hdr->sadb_msg_seq;
        c.pid = hdr->sadb_msg_pid;
@@ -2205,6 +2216,9 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
        err = xfrm_policy_insert(pol->sadb_x_policy_dir-1, xp,
                                 hdr->sadb_msg_type != SADB_X_SPDUPDATE);
 
+       xfrm_audit_log(audit_get_loginuid(current->audit_context), 0,
+                      AUDIT_MAC_IPSEC_ADDSPD, err ? 0 : 1, xp, NULL);
+
        if (err)
                goto out;
 
@@ -2282,6 +2296,10 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg
        xp = xfrm_policy_bysel_ctx(XFRM_POLICY_TYPE_MAIN, pol->sadb_x_policy_dir-1,
                                   &sel, tmp.security, 1);
        security_xfrm_policy_free(&tmp);
+
+       xfrm_audit_log(audit_get_loginuid(current->audit_context), 0,
+                      AUDIT_MAC_IPSEC_DELSPD, (xp) ? 1 : 0, xp, NULL);
+
        if (xp == NULL)
                return -ENOENT;
 
@@ -2416,8 +2434,11 @@ static int key_notify_policy_flush(struct km_event *c)
 static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
 {
        struct km_event c;
+       struct xfrm_audit audit_info;
 
-       xfrm_policy_flush(XFRM_POLICY_TYPE_MAIN);
+       audit_info.loginuid = audit_get_loginuid(current->audit_context);
+       audit_info.secid = 0;
+       xfrm_policy_flush(XFRM_POLICY_TYPE_MAIN, &audit_info);
        c.data.type = XFRM_POLICY_TYPE_MAIN;
        c.event = XFRM_MSG_FLUSHPOLICY;
        c.pid = hdr->sadb_msg_pid;
index a9638ff52a72eefa48f6a13328af537a1cf6ac36..9b02ec4012fb3f4ab515d089cd4f3b1b14a20808 100644 (file)
@@ -1093,7 +1093,7 @@ static void free_conntrack_hash(struct list_head *hash, int vmalloced, int size)
                           get_order(sizeof(struct list_head) * size));
 }
 
-void nf_conntrack_flush()
+void nf_conntrack_flush(void)
 {
        nf_ct_iterate_cleanup(kill_all, NULL);
 }
index c20f901fa177dbf2936b00a9506082ffeb5308d9..9cbf926cdd14fb0d6af92917339e1cd1d3f23b23 100644 (file)
@@ -91,25 +91,28 @@ EXPORT_SYMBOL_GPL(nf_conntrack_expect_find_get);
 struct nf_conntrack_expect *
 find_expectation(const struct nf_conntrack_tuple *tuple)
 {
-       struct nf_conntrack_expect *i;
+       struct nf_conntrack_expect *exp;
+
+       exp = __nf_conntrack_expect_find(tuple);
+       if (!exp)
+               return NULL;
 
-       list_for_each_entry(i, &nf_conntrack_expect_list, list) {
        /* If master is not in hash table yet (ie. packet hasn't left
           this machine yet), how can other end know about expected?
           Hence these are not the droids you are looking for (if
           master ct never got confirmed, we'd hold a reference to it
           and weird things would happen to future packets). */
-               if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)
-                   && nf_ct_is_confirmed(i->master)) {
-                       if (i->flags & NF_CT_EXPECT_PERMANENT) {
-                               atomic_inc(&i->use);
-                               return i;
-                       } else if (del_timer(&i->timeout)) {
-                               nf_ct_unlink_expect(i);
-                               return i;
-                       }
-               }
+       if (!nf_ct_is_confirmed(exp->master))
+               return NULL;
+
+       if (exp->flags & NF_CT_EXPECT_PERMANENT) {
+               atomic_inc(&exp->use);
+               return exp;
+       } else if (del_timer(&exp->timeout)) {
+               nf_ct_unlink_expect(exp);
+               return exp;
        }
+
        return NULL;
 }
 
index b9b03747c1f39e5882c702e0cdde95c6a61dcfbd..548e4e6e698f041f3802a28339b4ed69ba971b7c 100644 (file)
@@ -143,6 +143,13 @@ int genl_register_ops(struct genl_family *family, struct genl_ops *ops)
                goto errout;
        }
 
+       if (ops->dumpit)
+               ops->flags |= GENL_CMD_CAP_DUMP;
+       if (ops->doit)
+               ops->flags |= GENL_CMD_CAP_DO;
+       if (ops->policy)
+               ops->flags |= GENL_CMD_CAP_HASPOL;
+
        genl_lock();
        list_add_tail(&ops->ops_list, &family->ops_list);
        genl_unlock();
@@ -387,7 +394,7 @@ static void genl_rcv(struct sock *sk, int len)
 static struct genl_family genl_ctrl = {
        .id = GENL_ID_CTRL,
        .name = "nlctrl",
-       .version = 0x1,
+       .version = 0x2,
        .maxattr = CTRL_ATTR_MAX,
 };
 
@@ -425,15 +432,6 @@ static int ctrl_fill_info(struct genl_family *family, u32 pid, u32 seq,
                        NLA_PUT_U32(skb, CTRL_ATTR_OP_ID, ops->cmd);
                        NLA_PUT_U32(skb, CTRL_ATTR_OP_FLAGS, ops->flags);
 
-                       if (ops->policy)
-                               NLA_PUT_FLAG(skb, CTRL_ATTR_OP_POLICY);
-
-                       if (ops->doit)
-                               NLA_PUT_FLAG(skb, CTRL_ATTR_OP_DOIT);
-
-                       if (ops->dumpit)
-                               NLA_PUT_FLAG(skb, CTRL_ATTR_OP_DUMPIT);
-
                        nla_nest_end(skb, nest);
                }
 
index 08e68b67bbf642cedac2b537b79028c7f157bfaa..da73e8a8c18de58377376237907b32cf3baee35e 100644 (file)
@@ -660,7 +660,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
        sll->sll_ifindex = dev->ifindex;
 
        h->tp_status = status;
-       mb();
+       smp_mb();
 
        {
                struct page *p_start, *p_end;
index f59a2c4aa039b463e6c4c7d4fc867ce6da8a7dcb..c797d6ada7de06948ef1fab1e225a224ffdc057d 100644 (file)
@@ -101,9 +101,10 @@ static int fw_classify(struct sk_buff *skb, struct tcf_proto *tp,
        struct fw_head *head = (struct fw_head*)tp->root;
        struct fw_filter *f;
        int r;
-       u32 id = skb->mark & head->mask;
+       u32 id = skb->mark;
 
        if (head != NULL) {
+               id &= head->mask;
                for (f=head->ht[fw_hash(id)]; f; f=f->next) {
                        if (f->id == id) {
                                *res = f->res;
index 316211d9f17d97ffeab6823778c03113cdd5a76a..769cdd62c1bbab511af3c675433e2af191174840 100644 (file)
 
 #define KMEM_SAFETYZONE 8
 
-/***********FOR DEBUGGING PURPOSES*********************************************
-static void * dbg_kmalloc(unsigned int size, int prio, int line) {
-       int i = 0;
-       void * v = kmalloc(size+sizeof(unsigned int)+2*KMEM_SAFETYZONE*8,prio);
-       char * c1 = v;
-       c1 += sizeof(unsigned int);
-       *((unsigned int *)v) = size;
-
-       for (i = 0; i < KMEM_SAFETYZONE; i++) {
-               c1[0] = 'D'; c1[1] = 'E'; c1[2] = 'A'; c1[3] = 'D';
-               c1[4] = 'B'; c1[5] = 'E'; c1[6] = 'E'; c1[7] = 'F';
-               c1 += 8;
-       }
-       c1 += size;
-       for (i = 0; i < KMEM_SAFETYZONE; i++) {
-               c1[0] = 'M'; c1[1] = 'U'; c1[2] = 'N'; c1[3] = 'G';
-               c1[4] = 'W'; c1[5] = 'A'; c1[6] = 'L'; c1[7] = 'L';
-               c1 += 8;
-       }
-       v = ((char *)v) + sizeof(unsigned int) + KMEM_SAFETYZONE*8;
-       printk(KERN_INFO "line %d  kmalloc(%d,%d) = %p\n",line,size,prio,v);
-       return v;
-}
-static void dbg_kfree(void * v, int line) {
-       unsigned int * sp = (unsigned int *)(((char *)v) - (sizeof(unsigned int) + KMEM_SAFETYZONE*8));
-       unsigned int size = *sp;
-       char * c1 = ((char *)v) - KMEM_SAFETYZONE*8;
-       int i = 0;
-       for (i = 0; i < KMEM_SAFETYZONE; i++) {
-               if (   c1[0] != 'D' || c1[1] != 'E' || c1[2] != 'A' || c1[3] != 'D'
-                   || c1[4] != 'B' || c1[5] != 'E' || c1[6] != 'E' || c1[7] != 'F') {
-                       printk(KERN_INFO "kmalloced block at %p has been corrupted (underrun)!\n",v);
-                       printk(KERN_INFO " %4x: %2x %2x %2x %2x %2x %2x %2x %2x\n", i*8,
-                                       c1[0],c1[1],c1[2],c1[3],c1[4],c1[5],c1[6],c1[7] );
-               }
-               c1 += 8;
-       }
-       c1 += size;
-       for (i = 0; i < KMEM_SAFETYZONE; i++) {
-               if (   c1[0] != 'M' || c1[1] != 'U' || c1[2] != 'N' || c1[3] != 'G'
-                   || c1[4] != 'W' || c1[5] != 'A' || c1[6] != 'L' || c1[7] != 'L'
-                  ) {
-                       printk(KERN_INFO "kmalloced block at %p has been corrupted (overrun):\n",v);
-                       printk(KERN_INFO " %4x: %2x %2x %2x %2x %2x %2x %2x %2x\n", i*8,
-                                       c1[0],c1[1],c1[2],c1[3],c1[4],c1[5],c1[6],c1[7] );
-               }
-               c1 += 8;
-       }
-       printk(KERN_INFO "line %d  kfree(%p)\n",line,v);
-       v = ((char *)v) - (sizeof(unsigned int) + KMEM_SAFETYZONE*8);
-       kfree(v);
-}
-
-#define kmalloc(x,y) dbg_kmalloc(x,y,__LINE__)
-#define kfree(x) dbg_kfree(x,__LINE__)
-*****************************************************************************/
-
 /*
  *     Function Prototypes
  */
index 5a0dbeb6bbe817f02c7750ea75e5f3e6713680cf..6b381fc0383d1ea7bde417f5c4665c03a4db418b 100644 (file)
@@ -119,6 +119,23 @@ 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[] = {
index 3f3f563eb4ab8d48e65b283812c46271314dea97..bebd40e5a62e161f03f630adac629d8baa014d99 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/cache.h>
 #include <net/xfrm.h>
 #include <net/ip.h>
+#include <linux/audit.h>
 
 #include "xfrm_hash.h"
 
@@ -804,7 +805,7 @@ struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete)
 }
 EXPORT_SYMBOL(xfrm_policy_byid);
 
-void xfrm_policy_flush(u8 type)
+void xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info)
 {
        int dir;
 
@@ -824,6 +825,9 @@ void xfrm_policy_flush(u8 type)
                        hlist_del(&pol->byidx);
                        write_unlock_bh(&xfrm_policy_lock);
 
+                       xfrm_audit_log(audit_info->loginuid, audit_info->secid,
+                                      AUDIT_MAC_IPSEC_DELSPD, 1, pol, NULL);
+
                        xfrm_policy_kill(pol);
                        killed++;
 
@@ -842,6 +846,11 @@ void xfrm_policy_flush(u8 type)
                                hlist_del(&pol->byidx);
                                write_unlock_bh(&xfrm_policy_lock);
 
+                               xfrm_audit_log(audit_info->loginuid,
+                                              audit_info->secid,
+                                              AUDIT_MAC_IPSEC_DELSPD, 1,
+                                              pol, NULL);
+
                                xfrm_policy_kill(pol);
                                killed++;
 
@@ -860,33 +869,12 @@ EXPORT_SYMBOL(xfrm_policy_flush);
 int xfrm_policy_walk(u8 type, int (*func)(struct xfrm_policy *, int, int, void*),
                     void *data)
 {
-       struct xfrm_policy *pol;
+       struct xfrm_policy *pol, *last = NULL;
        struct hlist_node *entry;
-       int dir, count, error;
+       int dir, last_dir = 0, count, error;
 
        read_lock_bh(&xfrm_policy_lock);
        count = 0;
-       for (dir = 0; dir < 2*XFRM_POLICY_MAX; dir++) {
-               struct hlist_head *table = xfrm_policy_bydst[dir].table;
-               int i;
-
-               hlist_for_each_entry(pol, entry,
-                                    &xfrm_policy_inexact[dir], bydst) {
-                       if (pol->type == type)
-                               count++;
-               }
-               for (i = xfrm_policy_bydst[dir].hmask; i >= 0; i--) {
-                       hlist_for_each_entry(pol, entry, table + i, bydst) {
-                               if (pol->type == type)
-                                       count++;
-                       }
-               }
-       }
-
-       if (count == 0) {
-               error = -ENOENT;
-               goto out;
-       }
 
        for (dir = 0; dir < 2*XFRM_POLICY_MAX; dir++) {
                struct hlist_head *table = xfrm_policy_bydst[dir].table;
@@ -896,21 +884,37 @@ int xfrm_policy_walk(u8 type, int (*func)(struct xfrm_policy *, int, int, void*)
                                     &xfrm_policy_inexact[dir], bydst) {
                        if (pol->type != type)
                                continue;
-                       error = func(pol, dir % XFRM_POLICY_MAX, --count, data);
-                       if (error)
-                               goto out;
+                       if (last) {
+                               error = func(last, last_dir % XFRM_POLICY_MAX,
+                                            count, data);
+                               if (error)
+                                       goto out;
+                       }
+                       last = pol;
+                       last_dir = dir;
+                       count++;
                }
                for (i = xfrm_policy_bydst[dir].hmask; i >= 0; i--) {
                        hlist_for_each_entry(pol, entry, table + i, bydst) {
                                if (pol->type != type)
                                        continue;
-                               error = func(pol, dir % XFRM_POLICY_MAX, --count, data);
-                               if (error)
-                                       goto out;
+                               if (last) {
+                                       error = func(last, last_dir % XFRM_POLICY_MAX,
+                                                    count, data);
+                                       if (error)
+                                               goto out;
+                               }
+                               last = pol;
+                               last_dir = dir;
+                               count++;
                        }
                }
        }
-       error = 0;
+       if (count == 0) {
+               error = -ENOENT;
+               goto out;
+       }
+       error = func(last, last_dir % XFRM_POLICY_MAX, 0, data);
 out:
        read_unlock_bh(&xfrm_policy_lock);
        return error;
@@ -1982,6 +1986,117 @@ int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first,
 
 EXPORT_SYMBOL(xfrm_bundle_ok);
 
+#ifdef CONFIG_AUDITSYSCALL
+/* Audit addition and deletion of SAs and ipsec policy */
+
+void xfrm_audit_log(uid_t auid, u32 sid, int type, int result,
+                   struct xfrm_policy *xp, struct xfrm_state *x)
+{
+
+       char *secctx;
+       u32 secctx_len;
+       struct xfrm_sec_ctx *sctx = NULL;
+       struct audit_buffer *audit_buf;
+       int family;
+       extern int audit_enabled;
+
+       if (audit_enabled == 0)
+               return;
+
+       audit_buf = audit_log_start(current->audit_context, GFP_ATOMIC, type);
+       if (audit_buf == NULL)
+       return;
+
+       switch(type) {
+       case AUDIT_MAC_IPSEC_ADDSA:
+               audit_log_format(audit_buf, "SAD add: auid=%u", auid);
+               break;
+       case AUDIT_MAC_IPSEC_DELSA:
+               audit_log_format(audit_buf, "SAD delete: auid=%u", auid);
+               break;
+       case AUDIT_MAC_IPSEC_ADDSPD:
+               audit_log_format(audit_buf, "SPD add: auid=%u", auid);
+               break;
+       case AUDIT_MAC_IPSEC_DELSPD:
+               audit_log_format(audit_buf, "SPD delete: auid=%u", auid);
+               break;
+       default:
+               return;
+       }
+
+       if (sid != 0 &&
+               security_secid_to_secctx(sid, &secctx, &secctx_len) == 0)
+               audit_log_format(audit_buf, " subj=%s", secctx);
+       else
+               audit_log_task_context(audit_buf);
+
+       if (xp) {
+               family = xp->selector.family;
+               if (xp->security)
+                       sctx = xp->security;
+       } else {
+               family = x->props.family;
+               if (x->security)
+                       sctx = x->security;
+       }
+
+       if (sctx)
+               audit_log_format(audit_buf,
+                               " sec_alg=%u sec_doi=%u sec_obj=%s",
+                               sctx->ctx_alg, sctx->ctx_doi, sctx->ctx_str);
+
+       switch(family) {
+       case AF_INET:
+               {
+                       struct in_addr saddr, daddr;
+                       if (xp) {
+                               saddr.s_addr = xp->selector.saddr.a4;
+                               daddr.s_addr = xp->selector.daddr.a4;
+                       } else {
+                               saddr.s_addr = x->props.saddr.a4;
+                               daddr.s_addr = x->id.daddr.a4;
+                       }
+                       audit_log_format(audit_buf,
+                                        " src=%u.%u.%u.%u dst=%u.%u.%u.%u",
+                                        NIPQUAD(saddr), NIPQUAD(daddr));
+               }
+                       break;
+       case AF_INET6:
+               {
+                       struct in6_addr saddr6, daddr6;
+                       if (xp) {
+                               memcpy(&saddr6, xp->selector.saddr.a6,
+                                       sizeof(struct in6_addr));
+                               memcpy(&daddr6, xp->selector.daddr.a6,
+                                       sizeof(struct in6_addr));
+                       } else {
+                               memcpy(&saddr6, x->props.saddr.a6,
+                                       sizeof(struct in6_addr));
+                               memcpy(&daddr6, x->id.daddr.a6,
+                                       sizeof(struct in6_addr));
+                       }
+                       audit_log_format(audit_buf,
+                                        " src=" NIP6_FMT "dst=" NIP6_FMT,
+                                        NIP6(saddr6), NIP6(daddr6));
+               }
+               break;
+       }
+
+       if (x)
+               audit_log_format(audit_buf, " spi=%lu(0x%lx) protocol=%s",
+                               (unsigned long)ntohl(x->id.spi),
+                               (unsigned long)ntohl(x->id.spi),
+                               x->id.proto == IPPROTO_AH ? "AH" :
+                               (x->id.proto == IPPROTO_ESP ?
+                               "ESP" : "IPCOMP"));
+
+       audit_log_format(audit_buf, " res=%u", result);
+       audit_log_end(audit_buf);
+}
+
+EXPORT_SYMBOL(xfrm_audit_log);
+#endif /* CONFIG_AUDITSYSCALL */
+
 int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
 {
        int err = 0;
index da54a64ccfa3b9ffb4d4401ad3fac881591ce2dd..fdb08d9f34aa684b1180985e031e77f1de116f55 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/module.h>
 #include <linux/cache.h>
 #include <asm/uaccess.h>
+#include <linux/audit.h>
 
 #include "xfrm_hash.h"
 
@@ -238,6 +239,7 @@ static void xfrm_timer_handler(unsigned long data)
        unsigned long now = (unsigned long)xtime.tv_sec;
        long next = LONG_MAX;
        int warn = 0;
+       int err = 0;
 
        spin_lock(&x->lock);
        if (x->km.state == XFRM_STATE_DEAD)
@@ -295,9 +297,14 @@ expired:
                next = 2;
                goto resched;
        }
-       if (!__xfrm_state_delete(x) && x->id.spi)
+
+       err = __xfrm_state_delete(x);
+       if (!err && x->id.spi)
                km_state_expired(x, 1, 0);
 
+       xfrm_audit_log(audit_get_loginuid(current->audit_context), 0,
+                      AUDIT_MAC_IPSEC_DELSA, err ? 0 : 1, NULL, x);
+
 out:
        spin_unlock(&x->lock);
 }
@@ -384,9 +391,10 @@ int xfrm_state_delete(struct xfrm_state *x)
 }
 EXPORT_SYMBOL(xfrm_state_delete);
 
-void xfrm_state_flush(u8 proto)
+void xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info)
 {
        int i;
+       int err = 0;
 
        spin_lock_bh(&xfrm_state_lock);
        for (i = 0; i <= xfrm_state_hmask; i++) {
@@ -399,7 +407,11 @@ restart:
                                xfrm_state_hold(x);
                                spin_unlock_bh(&xfrm_state_lock);
 
-                               xfrm_state_delete(x);
+                               err = xfrm_state_delete(x);
+                               xfrm_audit_log(audit_info->loginuid,
+                                              audit_info->secid,
+                                              AUDIT_MAC_IPSEC_DELSA,
+                                              err ? 0 : 1, NULL, x);
                                xfrm_state_put(x);
 
                                spin_lock_bh(&xfrm_state_lock);
@@ -1099,7 +1111,7 @@ int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*),
                    void *data)
 {
        int i;
-       struct xfrm_state *x;
+       struct xfrm_state *x, *last = NULL;
        struct hlist_node *entry;
        int count = 0;
        int err = 0;
@@ -1107,24 +1119,22 @@ int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*),
        spin_lock_bh(&xfrm_state_lock);
        for (i = 0; i <= xfrm_state_hmask; i++) {
                hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) {
-                       if (xfrm_id_proto_match(x->id.proto, proto))
-                               count++;
+                       if (!xfrm_id_proto_match(x->id.proto, proto))
+                               continue;
+                       if (last) {
+                               err = func(last, count, data);
+                               if (err)
+                                       goto out;
+                       }
+                       last = x;
+                       count++;
                }
        }
        if (count == 0) {
                err = -ENOENT;
                goto out;
        }
-
-       for (i = 0; i <= xfrm_state_hmask; i++) {
-               hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) {
-                       if (!xfrm_id_proto_match(x->id.proto, proto))
-                               continue;
-                       err = func(x, --count, data);
-                       if (err)
-                               goto out;
-               }
-       }
+       err = func(last, 0, data);
 out:
        spin_unlock_bh(&xfrm_state_lock);
        return err;
index 311205ffa7750747197135e23984f0adb6e5178c..e5372b11fc8f105bd4ecf6071c0418f71855760c 100644 (file)
@@ -31,6 +31,7 @@
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 #include <linux/in6.h>
 #endif
+#include <linux/audit.h>
 
 static int verify_one_alg(struct rtattr **xfrma, enum xfrm_attr_type_t type)
 {
@@ -454,6 +455,9 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
        else
                err = xfrm_state_update(x);
 
+       xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid,
+                      AUDIT_MAC_IPSEC_ADDSA, err ? 0 : 1, NULL, x);
+
        if (err < 0) {
                x->km.state = XFRM_STATE_DEAD;
                __xfrm_state_put(x);
@@ -523,6 +527,10 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
        }
 
        err = xfrm_state_delete(x);
+
+       xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid,
+                      AUDIT_MAC_IPSEC_DELSA, err ? 0 : 1, NULL, x);
+
        if (err < 0)
                goto out;
 
@@ -1030,6 +1038,9 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
         * a type XFRM_MSG_UPDPOLICY - JHS */
        excl = nlh->nlmsg_type == XFRM_MSG_NEWPOLICY;
        err = xfrm_policy_insert(p->dir, xp, excl);
+       xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid,
+                      AUDIT_MAC_IPSEC_DELSPD, err ? 0 : 1, xp, NULL);
+
        if (err) {
                security_xfrm_policy_free(xp);
                kfree(xp);
@@ -1257,6 +1268,10 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
                xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security, delete);
                security_xfrm_policy_free(&tmp);
        }
+       if (delete)
+               xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid,
+                              AUDIT_MAC_IPSEC_DELSPD, (xp) ? 1 : 0, xp, NULL);
+
        if (xp == NULL)
                return -ENOENT;
 
@@ -1291,8 +1306,11 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma
 {
        struct km_event c;
        struct xfrm_usersa_flush *p = NLMSG_DATA(nlh);
+       struct xfrm_audit audit_info;
 
-       xfrm_state_flush(p->proto);
+       audit_info.loginuid = NETLINK_CB(skb).loginuid;
+       audit_info.secid = NETLINK_CB(skb).sid;
+       xfrm_state_flush(p->proto, &audit_info);
        c.data.proto = p->proto;
        c.event = nlh->nlmsg_type;
        c.seq = nlh->nlmsg_seq;
@@ -1442,12 +1460,15 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **x
        struct km_event c;
        u8 type = XFRM_POLICY_TYPE_MAIN;
        int err;
+       struct xfrm_audit audit_info;
 
        err = copy_from_user_policy_type(&type, (struct rtattr **)xfrma);
        if (err)
                return err;
 
-       xfrm_policy_flush(type);
+       audit_info.loginuid = NETLINK_CB(skb).loginuid;
+       audit_info.secid = NETLINK_CB(skb).sid;
+       xfrm_policy_flush(type, &audit_info);
        c.data.type = type;
        c.event = nlh->nlmsg_type;
        c.seq = nlh->nlmsg_seq;
@@ -1502,6 +1523,9 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, void *
        err = 0;
        if (up->hard) {
                xfrm_policy_delete(xp, p->dir);
+               xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid,
+                               AUDIT_MAC_IPSEC_DELSPD, 1, xp, NULL);
+
        } else {
                // reset the timers here?
                printk("Dont know what to do with soft policy expire\n");
@@ -1533,8 +1557,11 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh, void **
                goto out;
        km_state_expired(x, ue->hard, current->pid);
 
-       if (ue->hard)
+       if (ue->hard) {
                __xfrm_state_delete(x);
+               xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid,
+                              AUDIT_MAC_IPSEC_DELSA, 1, NULL, x);
+       }
 out:
        spin_unlock_bh(&x->lock);
        xfrm_state_put(x);