2004-03-06 18:48:46

by Jouni Malinen

[permalink] [raw]
Subject: Crypto API and keyed non-HMAC digest algorithms / Michael MIC

Current Linux crypto API does not seem to have generic mechanism for
adding keyed digest algorithms that are not using HMAC construction.
IEEE 802.11i/WPA uses such an algorithm in TKIP and getting this to
crypto API would be useful in order to be able to share more code of
TKIP implementation.

One straightforward way of adding support for Michael MIC is to add an
optional setkey operation for digest algorithms. The included patch
(against Linux 2.6.4-rc2) does exactly this and also includes an
implementation of Michael MIC. Another option would be to add a new
algorithm type for keyed hash algorithms, but that seemed unnecessary
for this purpose. Is the modification of digest type acceptable way of
adding support for a keyed digest algorithm that does not use HMAC?

The patch includes test vectors for Michael MIC and I have tested this
with the Host AP driver and TKIP. Getting this into crypto API is one of
the first steps in replacing the internal crypto algorithm
implementation in the Host AP driver code and I would appreciate it if
this would be applied to Linux 2.6 tree.



diff -upr linux-2.6.4-rc2.orig/Documentation/crypto/api-intro.txt linux-2.6.4-rc2/Documentation/crypto/api-intro.txt
--- linux-2.6.4-rc2.orig/Documentation/crypto/api-intro.txt 2004-03-05 21:55:12.000000000 -0800
+++ linux-2.6.4-rc2/Documentation/crypto/api-intro.txt 2004-03-05 22:28:38.090693088 -0800
@@ -186,6 +186,7 @@ Original developers of the crypto algori
Dag Arne Osvik (Serpent)
Brian Gladman (AES)
Kartikey Mahendra Bhatt (CAST6)
+ Jouni Malinen (Michael MIC)

SHA1 algorithm contributors:
Jean-Francois Dive
diff -upr linux-2.6.4-rc2.orig/crypto/Kconfig linux-2.6.4-rc2/crypto/Kconfig
--- linux-2.6.4-rc2.orig/crypto/Kconfig 2004-03-05 22:12:13.347396824 -0800
+++ linux-2.6.4-rc2/crypto/Kconfig 2004-03-05 22:11:00.152524136 -0800
@@ -151,6 +151,15 @@ config CRYPTO_DEFLATE

You will most probably want this if using IPSec.

+config CRYPTO_MICHAEL_MIC
+ tristate "Michael MIC keyed digest algorithm"
+ depends on CRYPTO
+ help
+ Michael MIC is used for message integrity protection in TKIP
+ (IEEE 802.11i). This algorithm is required for TKIP, but it
+ should not be used for other purposes because of the weakness
+ of the algorithm.
+
config CRYPTO_TEST
tristate "Testing module"
depends on CRYPTO
diff -upr linux-2.6.4-rc2.orig/crypto/Makefile linux-2.6.4-rc2/crypto/Makefile
--- linux-2.6.4-rc2.orig/crypto/Makefile 2004-03-05 22:13:30.891608312 -0800
+++ linux-2.6.4-rc2/crypto/Makefile 2004-03-05 22:07:55.211639424 -0800
@@ -22,5 +22,6 @@ obj-$(CONFIG_CRYPTO_AES) += aes.o
obj-$(CONFIG_CRYPTO_CAST5) += cast5.o
obj-$(CONFIG_CRYPTO_CAST6) += cast6.o
obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o
+obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o

obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
diff -upr linux-2.6.4-rc2.orig/crypto/digest.c linux-2.6.4-rc2/crypto/digest.c
--- linux-2.6.4-rc2.orig/crypto/digest.c 2004-02-17 19:57:12.000000000 -0800
+++ linux-2.6.4-rc2/crypto/digest.c 2004-03-05 22:18:14.429504000 -0800
@@ -42,6 +42,15 @@ static void final(struct crypto_tfm *tfm
tfm->__crt_alg->cra_digest.dia_final(crypto_tfm_ctx(tfm), out);
}

+static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
+{
+ u32 flags;
+ if (tfm->__crt_alg->cra_digest.dia_setkey == NULL)
+ return -1;
+ return tfm->__crt_alg->cra_digest.dia_setkey(crypto_tfm_ctx(tfm),
+ key, keylen, &flags);
+}
+
static void digest(struct crypto_tfm *tfm,
struct scatterlist *sg, unsigned int nsg, u8 *out)
{
@@ -72,6 +81,7 @@ int crypto_init_digest_ops(struct crypto
ops->dit_update = update;
ops->dit_final = final;
ops->dit_digest = digest;
+ ops->dit_setkey = setkey;

return crypto_alloc_hmac_block(tfm);
}
diff -upr linux-2.6.4-rc2.orig/crypto/tcrypt.c linux-2.6.4-rc2/crypto/tcrypt.c
--- linux-2.6.4-rc2.orig/crypto/tcrypt.c 2004-02-17 19:59:11.000000000 -0800
+++ linux-2.6.4-rc2/crypto/tcrypt.c 2004-03-05 22:53:14.400259920 -0800
@@ -112,6 +112,10 @@ test_hash (char * algo, struct hash_test
sg[0].length = hash_tv[i].psize;

crypto_digest_init (tfm);
+ if (tfm->crt_u.digest.dit_setkey) {
+ crypto_digest_setkey (tfm, hash_tv[i].key,
+ hash_tv[i].ksize);
+ }
crypto_digest_update (tfm, sg, 1);
crypto_digest_final (tfm, result);

@@ -564,6 +568,8 @@ do_test(void)
test_hmac("sha1", hmac_sha1_tv_template, HMAC_SHA1_TEST_VECTORS);
test_hmac("sha256", hmac_sha256_tv_template, HMAC_SHA256_TEST_VECTORS);
#endif
+
+ test_hash("michael_mic", michael_mic_tv_template, MICHAEL_MIC_TEST_VECTORS);
break;

case 1:
@@ -638,6 +644,10 @@ do_test(void)
test_cipher ("cast6", MODE_ECB, DECRYPT, cast6_dec_tv_template, CAST6_DEC_TEST_VECTORS);
break;

+ case 16:
+ test_hash("michael_mic", michael_mic_tv_template, MICHAEL_MIC_TEST_VECTORS);
+ break;
+
#ifdef CONFIG_CRYPTO_HMAC
case 100:
test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS);
diff -upr linux-2.6.4-rc2.orig/crypto/tcrypt.h linux-2.6.4-rc2/crypto/tcrypt.h
--- linux-2.6.4-rc2.orig/crypto/tcrypt.h 2004-02-17 19:59:27.000000000 -0800
+++ linux-2.6.4-rc2/crypto/tcrypt.h 2004-03-05 22:53:36.807853448 -0800
@@ -30,6 +30,8 @@ struct hash_testvec {
char digest[MAX_DIGEST_SIZE];
unsigned char np;
unsigned char tap[MAX_TAP];
+ char key[128]; /* only used with keyed hash algorithms */
+ unsigned char ksize;
};

struct hmac_testvec {
@@ -1578,4 +1580,54 @@ struct comp_testvec deflate_decomp_tv_te
},
};

+/*
+ * Michael MIC test vectors from IEEE 802.11i
+ */
+#define MICHAEL_MIC_TEST_VECTORS 6
+
+struct hash_testvec michael_mic_tv_template[] =
+{
+ {
+ .key = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ .ksize = 8,
+ .plaintext = { },
+ .psize = 0,
+ .digest = { 0x82, 0x92, 0x5c, 0x1c, 0xa1, 0xd1, 0x30, 0xb8 }
+ },
+ {
+ .key = { 0x82, 0x92, 0x5c, 0x1c, 0xa1, 0xd1, 0x30, 0xb8 },
+ .ksize = 8,
+ .plaintext = { 'M' },
+ .psize = 1,
+ .digest = { 0x43, 0x47, 0x21, 0xca, 0x40, 0x63, 0x9b, 0x3f }
+ },
+ {
+ .key = { 0x43, 0x47, 0x21, 0xca, 0x40, 0x63, 0x9b, 0x3f },
+ .ksize = 8,
+ .plaintext = { 'M', 'i' },
+ .psize = 2,
+ .digest = { 0xe8, 0xf9, 0xbe, 0xca, 0xe9, 0x7e, 0x5d, 0x29 }
+ },
+ {
+ .key = { 0xe8, 0xf9, 0xbe, 0xca, 0xe9, 0x7e, 0x5d, 0x29 },
+ .ksize = 8,
+ .plaintext = { 'M', 'i', 'c' },
+ .psize = 3,
+ .digest = { 0x90, 0x03, 0x8f, 0xc6, 0xcf, 0x13, 0xc1, 0xdb }
+ },
+ {
+ .key = { 0x90, 0x03, 0x8f, 0xc6, 0xcf, 0x13, 0xc1, 0xdb },
+ .ksize = 8,
+ .plaintext = { 'M', 'i', 'c', 'h' },
+ .psize = 4,
+ .digest = { 0xd5, 0x5e, 0x10, 0x05, 0x10, 0x12, 0x89, 0x86 }
+ },
+ {
+ .key = { 0xd5, 0x5e, 0x10, 0x05, 0x10, 0x12, 0x89, 0x86 },
+ .ksize = 8,
+ .plaintext = { 'M', 'i', 'c', 'h', 'a', 'e', 'l' },
+ .psize = 7,
+ .digest = { 0x0a, 0x94, 0x2b, 0x12, 0x4e, 0xca, 0xa5, 0x46 },
+ }
+};
#endif /* _CRYPTO_TCRYPT_H */
diff -upr linux-2.6.4-rc2.orig/include/linux/crypto.h linux-2.6.4-rc2/include/linux/crypto.h
--- linux-2.6.4-rc2.orig/include/linux/crypto.h 2004-02-17 19:57:21.000000000 -0800
+++ linux-2.6.4-rc2/include/linux/crypto.h 2004-03-05 22:15:16.142607728 -0800
@@ -76,6 +76,8 @@ struct digest_alg {
void (*dia_init)(void *ctx);
void (*dia_update)(void *ctx, const u8 *data, unsigned int len);
void (*dia_final)(void *ctx, u8 *out);
+ int (*dia_setkey)(void *ctx, const u8 *key,
+ unsigned int keylen, u32 *flags);
};

struct compress_alg {
@@ -157,6 +159,8 @@ struct digest_tfm {
void (*dit_final)(struct crypto_tfm *tfm, u8 *out);
void (*dit_digest)(struct crypto_tfm *tfm, struct scatterlist *sg,
unsigned int nsg, u8 *out);
+ int (*dit_setkey)(struct crypto_tfm *tfm,
+ const u8 *key, unsigned int keylen);
#ifdef CONFIG_CRYPTO_HMAC
void *dit_hmac_block;
#endif
@@ -282,6 +286,15 @@ static inline void crypto_digest_digest(
tfm->crt_digest.dit_digest(tfm, sg, nsg, out);
}

+static inline int crypto_digest_setkey(struct crypto_tfm *tfm,
+ const u8 *key, unsigned int keylen)
+{
+ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
+ if (tfm->crt_digest.dit_setkey == NULL)
+ return -1;
+ return tfm->crt_digest.dit_setkey(tfm, key, keylen);
+}
+
static inline int crypto_cipher_setkey(struct crypto_tfm *tfm,
const u8 *key, unsigned int keylen)
{
--- linux-2.6.4-rc2.orig/crypto/michael_mic.c 1969-12-31 16:00:00.000000000 -0800
+++ linux-2.6.4-rc2/crypto/michael_mic.c 2004-03-05 22:07:06.956975248 -0800
@@ -0,0 +1,193 @@
+/*
+ * Cryptographic API
+ *
+ * Michael MIC (IEEE 802.11i/TKIP) keyed digest
+ *
+ * Copyright (c) 2004 Jouni Malinen <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/crypto.h>
+
+
+struct michael_mic_ctx {
+ u8 pending[4];
+ size_t pending_len;
+
+ u32 l, r;
+};
+
+
+static inline u32 rotl(u32 val, int bits)
+{
+ return (val << bits) | (val >> (32 - bits));
+}
+
+
+static inline u32 rotr(u32 val, int bits)
+{
+ return (val >> bits) | (val << (32 - bits));
+}
+
+
+static inline u32 xswap(u32 val)
+{
+ return ((val & 0x00ff00ff) << 8) | ((val & 0xff00ff00) >> 8);
+}
+
+
+#define michael_block(l, r) \
+do { \
+ r ^= rotl(l, 17); \
+ l += r; \
+ r ^= xswap(l); \
+ l += r; \
+ r ^= rotl(l, 3); \
+ l += r; \
+ r ^= rotr(l, 2); \
+ l += r; \
+} while (0)
+
+
+static inline u32 get_le32(const u8 *p)
+{
+ return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
+}
+
+
+static inline void put_le32(u8 *p, u32 v)
+{
+ p[0] = v;
+ p[1] = v >> 8;
+ p[2] = v >> 16;
+ p[3] = v >> 24;
+}
+
+
+static void michael_init(void *ctx)
+{
+ struct michael_mic_ctx *mctx = ctx;
+ mctx->pending_len = 0;
+}
+
+
+static void michael_update(void *ctx, const u8 *data, unsigned int len)
+{
+ struct michael_mic_ctx *mctx = ctx;
+
+ if (mctx->pending_len) {
+ int flen = 4 - mctx->pending_len;
+ if (flen > len)
+ flen = len;
+ memcpy(&mctx->pending[mctx->pending_len], data, flen);
+ mctx->pending_len += flen;
+ data += flen;
+ len -= flen;
+
+ if (mctx->pending_len < 4)
+ return;
+
+ mctx->l ^= get_le32(mctx->pending);
+ michael_block(mctx->l, mctx->r);
+ mctx->pending_len = 0;
+ }
+
+ while (len >= 4) {
+ mctx->l ^= get_le32(data);
+ michael_block(mctx->l, mctx->r);
+ data += 4;
+ len -= 4;
+ }
+
+ if (len > 0) {
+ mctx->pending_len = len;
+ memcpy(mctx->pending, data, len);
+ }
+}
+
+
+static void michael_final(void *ctx, u8 *out)
+{
+ struct michael_mic_ctx *mctx = ctx;
+ u8 *data = mctx->pending;
+
+ /* Last block and padding (0x5a, 4..7 x 0) */
+ switch (mctx->pending_len) {
+ case 0:
+ mctx->l ^= 0x5a;
+ break;
+ case 1:
+ mctx->l ^= data[0] | 0x5a00;
+ break;
+ case 2:
+ mctx->l ^= data[0] | (data[1] << 8) | 0x5a0000;
+ break;
+ case 3:
+ mctx->l ^= data[0] | (data[1] << 8) | (data[2] << 16) |
+ 0x5a000000;
+ break;
+ }
+ michael_block(mctx->l, mctx->r);
+ /* l ^= 0; */
+ michael_block(mctx->l, mctx->r);
+
+ put_le32(out, mctx->l);
+ put_le32(out + 4, mctx->r);
+}
+
+
+static int michael_setkey(void *ctx, const u8 *key, unsigned int keylen,
+ u32 *flags)
+{
+ struct michael_mic_ctx *mctx = ctx;
+ if (keylen != 8) {
+ if (flags)
+ *flags = CRYPTO_TFM_RES_BAD_KEY_LEN;
+ return -1;
+ }
+ mctx->l = get_le32(key);
+ mctx->r = get_le32(key + 4);
+ return 0;
+}
+
+
+static struct crypto_alg michael_mic_alg = {
+ .cra_name = "michael_mic",
+ .cra_flags = CRYPTO_ALG_TYPE_DIGEST,
+ .cra_blocksize = 8,
+ .cra_ctxsize = sizeof(struct michael_mic_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(michael_mic_alg.cra_list),
+ .cra_u = { .digest = {
+ .dia_digestsize = 8,
+ .dia_init = michael_init,
+ .dia_update = michael_update,
+ .dia_final = michael_final,
+ .dia_setkey = michael_setkey } }
+};
+
+
+static int __init michael_mic_init(void)
+{
+ return crypto_register_alg(&michael_mic_alg);
+}
+
+
+static void __exit michael_mic_exit(void)
+{
+ crypto_unregister_alg(&michael_mic_alg);
+}
+
+
+module_init(michael_mic_init);
+module_exit(michael_mic_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Michael MIC");
+MODULE_AUTHOR("Jouni Malinen <[email protected]>");



--
Jouni Malinen PGP id EFC895FA


2004-03-08 14:44:59

by James Morris

[permalink] [raw]
Subject: Re: Crypto API and keyed non-HMAC digest algorithms / Michael MIC

On Sat, 6 Mar 2004, Jouni Malinen wrote:

> Current Linux crypto API does not seem to have generic mechanism for
> adding keyed digest algorithms that are not using HMAC construction.
> IEEE 802.11i/WPA uses such an algorithm in TKIP and getting this to
> crypto API would be useful in order to be able to share more code of
> TKIP implementation.
>
> One straightforward way of adding support for Michael MIC is to add an
> optional setkey operation for digest algorithms. The included patch
> (against Linux 2.6.4-rc2) does exactly this and also includes an
> implementation of Michael MIC. Another option would be to add a new
> algorithm type for keyed hash algorithms, but that seemed unnecessary
> for this purpose. Is the modification of digest type acceptable way of
> adding support for a keyed digest algorithm that does not use HMAC?

I think it would be better to do the latter, add another mode for
simple keyed digest processing (KMAC?), where a function called something
like kmac_init() takes the tfm/key/kelen paramters. The kmac_update() and
kmac_final() methods are just wrappers around the digest methods, and we
also kmac_kmac() similar to the HMAC method.

This would be a config option.

> The patch includes test vectors for Michael MIC and I have tested this
> with the Host AP driver and TKIP. Getting this into crypto API is one of
> the first steps in replacing the internal crypto algorithm
> implementation in the Host AP driver code and I would appreciate it if
> this would be applied to Linux 2.6 tree.

Is there an 802.11i spec available? It seems like there are only drafts
available which require payment. I'd like to see the Micheal MIC
algorithm description & know of any potential IP rights issues.

Also, is there any mainline kernel code which would use this feature?


- James
--
James Morris
<[email protected]>


2004-03-09 03:40:24

by Jouni Malinen

[permalink] [raw]
Subject: Re: Crypto API and keyed non-HMAC digest algorithms / Michael MIC

On Mon, Mar 08, 2004 at 09:45:39AM -0500, James Morris wrote:

> On Sat, 6 Mar 2004, Jouni Malinen wrote:
> > One straightforward way of adding support for Michael MIC is to add an
> > optional setkey operation for digest algorithms. The included patch
> > (against Linux 2.6.4-rc2) does exactly this and also includes an
> > implementation of Michael MIC. Another option would be to add a new
> > algorithm type for keyed hash algorithms, but that seemed unnecessary
> > for this purpose.

> I think it would be better to do the latter, add another mode for
> simple keyed digest processing (KMAC?), where a function called something
> like kmac_init() takes the tfm/key/kelen paramters. The kmac_update() and
> kmac_final() methods are just wrappers around the digest methods, and we
> also kmac_kmac() similar to the HMAC method.

Hmm.. HMAC can do this easily, since that construction uses plain digest
functions and just hashes the key with them. Michael MIC initializes
some of the internal state (L and R in the implementation) with the key.
This would mean that the kmac_init() would need to know something about
the used digest algorithm or we would need to have setkey handler for
the digests (which is actually the way I implemented Michael MIC in the
original patch).

crypto_kmac() can be implemented, if that is considered useful wrapper
for Michael MIC. However, I'm not sure whether the other part of this
would work very well with Michael MIC. In addition, I'm not sure whether
there would be another algorithm using this new keyed has method. HMAC
and CBC-MAC (which, btw, is also on my list of crypto API things to do
for IEEE 802.11i) are using more generic mechanism and can be used with
multiple algorithms and are probably prefered for anything that requires
real security.

If you prefer, I can make a new type crypto alg type
(CRYPTO_ALG_TYPE_KEYED_DIGEST) and make it a clone of the
CRYPTO_ALG_TYPE_DIGEST with the only change of adding a new callback,
setkey, in the way I added in the patch for CRYPTO_ALG_TYPE_DIGEST. This
would leave the digest type unmodified, but would result in copying most
of the digest code. I do not see much benefit of this because the
dia_setkey function pointer does not seem to change the old digest
functionality at all since it is optional and since this function
pointer does not even enlarge struct crypto_alg due to the cra_u union
already being a bit larger than the current struct digest_alg.


> Is there an 802.11i spec available? It seems like there are only drafts
> available which require payment. I'd like to see the Micheal MIC
> algorithm description & know of any potential IP rights issues.

IEEE 802.11i draft is not freely available. The finalized standard is
likely to become freely available six month after its publications (I
would guess this would be about early 2005 or so). However, the proposal
for Michael MIC is available from
http://grouper.ieee.org/groups/802/11/Documents/DocumentHolder/2-020.zip.
This includes full description of the algorithm, analysis of it and
reasoning for the compromises needed for TKIP. I haven't verified, but I
would assume that this matches with the algorithm as defined in the
current IEEE 802.11i draft.

As far as IP rights (I would assume you mean patents, in this case) are
concerned, IEEE has a policy* of requiring a statement about potential
patent application on the algorithms used in the standards. I do not
remember seeing such a statement about Michael MIC (of course this does
not mean that there is not one, but at least I haven't seen one) and
could not find such a statement in the IEEE 802.11 patent statements**.
In addition, the author of Michael MIC proposal has put the reference
implementation code in the public domain.

*) http://standards.ieee.org/guides/bylaws/sect6-7.html#6
**) http://standards.ieee.org/db/patents/pat802_11.html


> Also, is there any mainline kernel code which would use this feature?

Well, the main goal for me here is to get Host AP driver in shape for
mainline inclusion.. ;-)

The only use for Michael MIC seems to be in implementing TKIP since it
is not very secure (due to compromises needed to support old legacy wlan
hardware). This is needed for wireless LAN cards that cannot or at least
do not implement TKIP in hardware/firmware. It may also be useful, if
the hardware implementation does not support all needed modes (e.g., AP)
or is considered too slow. Some of the current IEEE 802.11b drivers in
the mainline kernel would be likely canditates for using this when
WPA/IEEE 802.11i support is added.

--
Jouni Malinen PGP id EFC895FA

2004-03-09 05:55:09

by James Morris

[permalink] [raw]
Subject: Re: Crypto API and keyed non-HMAC digest algorithms / Michael MIC

On Mon, 8 Mar 2004, Jouni Malinen wrote:

> This would mean that the kmac_init() would need to know something about
> the used digest algorithm or we would need to have setkey handler for
> the digests (which is actually the way I implemented Michael MIC in the
> original patch).

You're correct.

> In addition, I'm not sure whether there would be another algorithm using
> this new keyed has method. HMAC and CBC-MAC (which, btw, is also on my
> list of crypto API things to do for IEEE 802.11i) are using more generic
> mechanism and can be used with multiple algorithms and are probably
> prefered for anything that requires real security.

There are several potential MAC processing modes to be added, XCBC-MAC,
OMAC, RMAC etc. Do you know if any are likely to benefit from a setkey
method for digests?

> If you prefer, I can make a new type crypto alg type
> (CRYPTO_ALG_TYPE_KEYED_DIGEST) and make it a clone of the
> CRYPTO_ALG_TYPE_DIGEST with the only change of adding a new callback,
> setkey, in the way I added in the patch for CRYPTO_ALG_TYPE_DIGEST. This
> would leave the digest type unmodified, but would result in copying most
> of the digest code. I do not see much benefit of this because the
> dia_setkey function pointer does not seem to change the old digest
> functionality at all since it is optional and since this function
> pointer does not even enlarge struct crypto_alg due to the cra_u union
> already being a bit larger than the current struct digest_alg.

Agreed. I really wanted to keep digests 'pure', and not implement a
setkey method, but it seems like the simplest way at this stage.


> would guess this would be about early 2005 or so). However, the proposal
> for Michael MIC is available from
> http://grouper.ieee.org/groups/802/11/Documents/DocumentHolder/2-020.zip.

Thanks for the pointer.


- James
--
James Morris
<[email protected]>


2004-03-09 17:30:43

by Clay Haapala

[permalink] [raw]
Subject: Re: Crypto API and keyed non-HMAC digest algorithms / Michael MIC

On Tue, 9 Mar 2004, James Morris uttered the following:
> On Mon, 8 Mar 2004, Jouni Malinen wrote:
>> If you prefer, I can make a new type crypto alg type
>> (CRYPTO_ALG_TYPE_KEYED_DIGEST) and make it a clone of the
>> CRYPTO_ALG_TYPE_DIGEST with the only change of adding a new
>> callback, setkey, in the way I added in the patch for
>> CRYPTO_ALG_TYPE_DIGEST. This would leave the digest type
>> unmodified, but would result in copying most of the digest code. I
>> do not see much benefit of this because the dia_setkey function
>> pointer does not seem to change the old digest functionality at all
>> since it is optional and since this function pointer does not even
>> enlarge struct crypto_alg due to the cra_u union already being a
>> bit larger than the current struct digest_alg.
>
> Agreed. I really wanted to keep digests 'pure', and not implement a
> setkey method, but it seems like the simplest way at this stage.
>
I had the same thought in my attempt at adding CRC32C to the crypto
routines, that what was needed was "digests + setkey". But I didn't
want to add the key baggage to digests, and so created a new alg type
(CHKSUM), with pretty much identical code to digest, but with a
modified init and a new setkey interface.

So, we could modify digests now, or perhaps Jouni and I could combine
our code into a new KEYED_DIGEST type and leave digests 'pure'.
What's best?

--
Clay Haapala ([email protected]) Cisco Systems SRBU +1 763-398-1056
6450 Wedgwood Rd, Suite 130 Maple Grove MN 55311 PGP: C89240AD
Windows XP 'Reloaded'? *Reloaded?* Have they no sense of irony?

2004-03-09 20:32:26

by James Morris

[permalink] [raw]
Subject: Re: Crypto API and keyed non-HMAC digest algorithms / Michael MIC

On Tue, 9 Mar 2004, Clay Haapala wrote:

> On Tue, 9 Mar 2004, James Morris uttered the following:
> > Agreed. I really wanted to keep digests 'pure', and not implement a
> > setkey method, but it seems like the simplest way at this stage.
> >
> I had the same thought in my attempt at adding CRC32C to the crypto
> routines, that what was needed was "digests + setkey". But I didn't
> want to add the key baggage to digests, and so created a new alg type
> (CHKSUM), with pretty much identical code to digest, but with a
> modified init and a new setkey interface.
>
> So, we could modify digests now, or perhaps Jouni and I could combine
> our code into a new KEYED_DIGEST type and leave digests 'pure'.
> What's best?

I think that adding a setkey method for digests is the simplest approach.


- James
--
James Morris
<[email protected]>


2004-03-10 03:42:59

by Jouni Malinen

[permalink] [raw]
Subject: Re: Crypto API and keyed non-HMAC digest algorithms / Michael MIC

> On Tue, 9 Mar 2004, Clay Haapala wrote:
> > I had the same thought in my attempt at adding CRC32C to the crypto
> > routines, that what was needed was "digests + setkey". But I didn't
> > want to add the key baggage to digests, and so created a new alg type
> > (CHKSUM), with pretty much identical code to digest, but with a
> > modified init and a new setkey interface.

On Tue, Mar 09, 2004 at 03:32:58PM -0500, James Morris wrote:
> I think that adding a setkey method for digests is the simplest approach.


I took a quick look at the CRC32C patch and it looked like the only
needed change for the digest type was the new handler for setting a
32-bit seed. I used setkey handler that takes an arbitrary key data and
length (Michael MIC uses 64-bit key/seed). As far as I could tell, this
setkey function should be enough for CRC32C needs, too. Clay, please let
me know if I missed something here. James, please consider merging this
into Linux 2.6 tree if there are no issues with CRC32C.

The patch below includes only the setkey addition from my previous
patch. This is against current linus-2.5 BK tree. I will re-diff and
send Michael MIC portion of the patch separately. Re-diffing was needed
anyway, since ARC4 addition had a small conflict with the Michael MIC
patch.


You can import this changeset into BK by piping this whole message to:
'| bk receive [path to repository]' or apply the patch as usual.

===================================================================


[email protected], 2004-03-09 18:54:50-08:00, [email protected]
Added support for using keyed digest with an optional dit_setkey handler.
This does not change the behavior of the existing digest algorithms, but
allows new ones to add setkey handler that can be used to initialize the
algorithm with a key or seed. setkey is to be called after init, but before
any of the update call(s).


crypto/digest.c | 10 ++++++++++
crypto/tcrypt.c | 4 ++++
crypto/tcrypt.h | 2 ++
include/linux/crypto.h | 13 +++++++++++++
4 files changed, 29 insertions(+)


diff -Nru a/crypto/digest.c b/crypto/digest.c
--- a/crypto/digest.c Tue Mar 9 18:58:22 2004
+++ b/crypto/digest.c Tue Mar 9 18:58:22 2004
@@ -42,6 +42,15 @@
tfm->__crt_alg->cra_digest.dia_final(crypto_tfm_ctx(tfm), out);
}

+static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
+{
+ u32 flags;
+ if (tfm->__crt_alg->cra_digest.dia_setkey == NULL)
+ return -1;
+ return tfm->__crt_alg->cra_digest.dia_setkey(crypto_tfm_ctx(tfm),
+ key, keylen, &flags);
+}
+
static void digest(struct crypto_tfm *tfm,
struct scatterlist *sg, unsigned int nsg, u8 *out)
{
@@ -72,6 +81,7 @@
ops->dit_update = update;
ops->dit_final = final;
ops->dit_digest = digest;
+ ops->dit_setkey = setkey;

return crypto_alloc_hmac_block(tfm);
}
diff -Nru a/crypto/tcrypt.c b/crypto/tcrypt.c
--- a/crypto/tcrypt.c Tue Mar 9 18:58:22 2004
+++ b/crypto/tcrypt.c Tue Mar 9 18:58:22 2004
@@ -112,6 +112,10 @@
sg[0].length = hash_tv[i].psize;

crypto_digest_init (tfm);
+ if (tfm->crt_u.digest.dit_setkey) {
+ crypto_digest_setkey (tfm, hash_tv[i].key,
+ hash_tv[i].ksize);
+ }
crypto_digest_update (tfm, sg, 1);
crypto_digest_final (tfm, result);

diff -Nru a/crypto/tcrypt.h b/crypto/tcrypt.h
--- a/crypto/tcrypt.h Tue Mar 9 18:58:22 2004
+++ b/crypto/tcrypt.h Tue Mar 9 18:58:22 2004
@@ -30,6 +30,8 @@
char digest[MAX_DIGEST_SIZE];
unsigned char np;
unsigned char tap[MAX_TAP];
+ char key[128]; /* only used with keyed hash algorithms */
+ unsigned char ksize;
};

struct hmac_testvec {
diff -Nru a/include/linux/crypto.h b/include/linux/crypto.h
--- a/include/linux/crypto.h Tue Mar 9 18:58:22 2004
+++ b/include/linux/crypto.h Tue Mar 9 18:58:22 2004
@@ -76,6 +76,8 @@
void (*dia_init)(void *ctx);
void (*dia_update)(void *ctx, const u8 *data, unsigned int len);
void (*dia_final)(void *ctx, u8 *out);
+ int (*dia_setkey)(void *ctx, const u8 *key,
+ unsigned int keylen, u32 *flags);
};

struct compress_alg {
@@ -157,6 +159,8 @@
void (*dit_final)(struct crypto_tfm *tfm, u8 *out);
void (*dit_digest)(struct crypto_tfm *tfm, struct scatterlist *sg,
unsigned int nsg, u8 *out);
+ int (*dit_setkey)(struct crypto_tfm *tfm,
+ const u8 *key, unsigned int keylen);
#ifdef CONFIG_CRYPTO_HMAC
void *dit_hmac_block;
#endif
@@ -280,6 +284,15 @@
{
BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
tfm->crt_digest.dit_digest(tfm, sg, nsg, out);
+}
+
+static inline int crypto_digest_setkey(struct crypto_tfm *tfm,
+ const u8 *key, unsigned int keylen)
+{
+ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
+ if (tfm->crt_digest.dit_setkey == NULL)
+ return -1;
+ return tfm->crt_digest.dit_setkey(tfm, key, keylen);
}

static inline int crypto_cipher_setkey(struct crypto_tfm *tfm,

===================================================================


This BitKeeper patch contains the following changesets:
1.1689
## Wrapped with gzip_uu ##


M'XL( $Z$3D ]586T_C.!1^CG^%5R.MVBY-[<1IDR(0<T$L&C0@!AY&LZ/(
M==PFT,;=V(%AI_/?]^324B!<=QX6ETOK.-_Y?/R=2_H&GVJ9#:VS\QF?)JE$
M;_"?2INA)80=Y\8>)S!SK!3,]/[NG<UZH_.>3OE<Q\IT'=M#</F(&Q'C"YGI
MH45M=S5CKN9R:!WO[IT>O#U&:&L+OX]Y.I&?I<%;6\BH[()/([W#33Q5J6TR
MGNJ9--P6:K98+5TXA#CP\NC )5Y_0?N$#1:"1I1R1F5$'.;WV37:?"Z" ;&5
MCJ:VRB8W@1AQ*2&4N)ZWH)X[<-$'3&W:]P-,6(^X/1)@Z@\]-O1(E_A#0O#2
M,SLKC^ _&.X2] [_VAV\1P*_C2(989W/YRHS>*PRG.LDG>!S>07S43*1VN#+
MQ,28IUC-3:)2/H5Y$VII8!$&F]%49C9@G<2)QI&2&J?*8%&RP2:6>"1C?I$
MMAJ7G^7W1)O"2HW/IQ.5@8V9WL"CW 4GT[5)>#(2ZQ2 #0*\PAXWK )6!SL
M +&1!-K %Y8E:6(2\-\_I>D2J@:OMU%L#0,7+65D+Q&3T@3 "+ ,0'QL +_
M*AG!%7!-B99>+7>1SR-NJCM:NFVCCYBR@3- 1]>J0]UG#H0()V@;1_Q"SG;2
MW&@[3=)S;J=PJB*[FAO5,^5_.RY/F<)94CAC%BR<XMW"8](+N.SW)1UY;M D
MIR:@2J<."URV8(/ "^XCD:1BFD>R!Y#Y]UZ%=(L+*,YA ]=;^"0@A 14B&@D
M/"&;N-R/MT[)<3S7?<0OE9AL<<<OQ'/I(G $%1!VCO <'OG. WY9!UHGT:>>
M\QB)VJ=W25 WH LN!9R*&(]&Q.4C-G[\<.Z0 #_X3IG;;K$M,MRO<P\ZFZDL
M2_1.DD(D"!7)(L78/&^"<XGK!)32ON<OW $E09WD;J0X%@Q=]D"*H^3_G^,^
MXDH#A[B;7=8_$.^W7/*"J-]G# =(&VX2 6G'U'FII4V6"U,;",UXACOP9P,+
ME0+GW,<=6+6!\U0GDQ0V4]P*,U.9MM$/9.6N@\=3/M&;R$K&N 7W=K?#4&0F
MA+38W189#VO64<*7VP5M?3H].&@CR\JDR;,4=RD U.^?A-&Z9AP*\[TPW-X
MO&+@8I2T*Z8;^/>28WL3_41_H?T!PQ19:JZ[V]=G8&W5+ME<U_XR2![3_O.B
M$IVI=&>L(+''JCA/D%US4,*O3QES%PQBTB]%#PY_CNA?05W_B*N4TZSYI4=>
MHGE*&68@BI4R"TWE]DI,2RYM_*.03BVIZO*29JL,AYCK.#077Y-O=B$L=*VS
M&Y<T= 6@,LOZV2"B^(DB>F+=?51$\1T108X?5)DS>):(G-<@HJJI>%!$\4M$
M! 'G( N:S:R@]94Z_K=-W.M VSB]JIK"DF!%N1##6K>).SW(D<O<66$4&JER
M3'-G<J]*_DMCA&97._-")KD!+VM;RP?@7-"+3ZM'"O#JH$X\Y'G5UGT-HJG:
MOENB:?;,2[0S\ OM%#6SU;FN7>W6A4HBW(&Z=;O0HCJIK(^&V@L%&63965:U
M?>H%ZX96>>V^\MYDY@D5'RPYT-@&91E=]1+%R9>KFO+GO0SN$F@<3^Q#WIWN
MA8>?UIL"",*P>%PO.P/\&SRI'W\Y.CD,WQ[LA2=?CG;##_M[NY]/VNN-2U$>
I[A2'IW0KC3=6E6.M#P%;JV\21"S%N<YG6R/6'Y$Q<=&_I7&6K[@0


--
Jouni Malinen PGP id EFC895FA

2004-03-10 04:06:31

by Jouni Malinen

[permalink] [raw]
Subject: [PATCH] Crypto API and Michael MIC

On Tue, Mar 09, 2004 at 07:40:14PM -0800, Jouni Malinen wrote:

> The patch below includes only the setkey addition from my previous
> patch. This is against current linus-2.5 BK tree. I will re-diff and
> send Michael MIC portion of the patch separately. Re-diffing was needed
> anyway, since ARC4 addition had a small conflict with the Michael MIC
> patch.

And here's the re-diffed patch for adding Michael MIC. This requires the
setkey patch for digest type that I just sent. I tested this new patch
of Michael MIC with Linux 2.6.4-rc3 and Host AP driver. The patch is
against linus-2.5 BK tree. Please consider merging into Linux 2.6.


You can import this changeset into BK by piping this whole message to:
'| bk receive [path to repository]' or apply the patch as usual.

===================================================================


[email protected], 2004-03-09 19:17:59-08:00, [email protected]
Added Michael MIC keyed digest for TKIP (IEEE 802.11i/WPA). This algorithm
is quite weak due to the requirements for compatibility with old legacy
wireless LAN hardware that does not have much CPU power. Consequently, this
should not really be used with anything else than TKIP.

Michael MIC is calculated over the payload of the IEEE 802.11 header which
makes it easier to add TKIP support for old wireless LAN cards. An additional
authenticated data area is used (but not send separately) to authenticate
source and destination addresses.


Documentation/crypto/api-intro.txt | 1
crypto/Kconfig | 9 +
crypto/Makefile | 1
crypto/michael_mic.c | 193 +++++++++++++++++++++++++++++++++++++
crypto/tcrypt.c | 8 +
crypto/tcrypt.h | 50 +++++++++
6 files changed, 261 insertions(+), 1 deletion(-)


diff -Nru a/Documentation/crypto/api-intro.txt b/Documentation/crypto/api-intro.txt
--- a/Documentation/crypto/api-intro.txt Tue Mar 9 19:20:04 2004
+++ b/Documentation/crypto/api-intro.txt Tue Mar 9 19:20:04 2004
@@ -187,6 +187,7 @@
Brian Gladman (AES)
Kartikey Mahendra Bhatt (CAST6)
Jon Oberheide (ARC4)
+ Jouni Malinen (Michael MIC)

SHA1 algorithm contributors:
Jean-Francois Dive
diff -Nru a/crypto/Kconfig b/crypto/Kconfig
--- a/crypto/Kconfig Tue Mar 9 19:20:04 2004
+++ b/crypto/Kconfig Tue Mar 9 19:20:04 2004
@@ -161,6 +161,15 @@

You will most probably want this if using IPSec.

+config CRYPTO_MICHAEL_MIC
+ tristate "Michael MIC keyed digest algorithm"
+ depends on CRYPTO
+ help
+ Michael MIC is used for message integrity protection in TKIP
+ (IEEE 802.11i). This algorithm is required for TKIP, but it
+ should not be used for other purposes because of the weakness
+ of the algorithm.
+
config CRYPTO_TEST
tristate "Testing module"
depends on CRYPTO
diff -Nru a/crypto/Makefile b/crypto/Makefile
--- a/crypto/Makefile Tue Mar 9 19:20:04 2004
+++ b/crypto/Makefile Tue Mar 9 19:20:04 2004
@@ -23,5 +23,6 @@
obj-$(CONFIG_CRYPTO_CAST6) += cast6.o
obj-$(CONFIG_CRYPTO_ARC4) += arc4.o
obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o
+obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o

obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
diff -Nru a/crypto/michael_mic.c b/crypto/michael_mic.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/crypto/michael_mic.c Tue Mar 9 19:20:04 2004
@@ -0,0 +1,193 @@
+/*
+ * Cryptographic API
+ *
+ * Michael MIC (IEEE 802.11i/TKIP) keyed digest
+ *
+ * Copyright (c) 2004 Jouni Malinen <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/crypto.h>
+
+
+struct michael_mic_ctx {
+ u8 pending[4];
+ size_t pending_len;
+
+ u32 l, r;
+};
+
+
+static inline u32 rotl(u32 val, int bits)
+{
+ return (val << bits) | (val >> (32 - bits));
+}
+
+
+static inline u32 rotr(u32 val, int bits)
+{
+ return (val >> bits) | (val << (32 - bits));
+}
+
+
+static inline u32 xswap(u32 val)
+{
+ return ((val & 0x00ff00ff) << 8) | ((val & 0xff00ff00) >> 8);
+}
+
+
+#define michael_block(l, r) \
+do { \
+ r ^= rotl(l, 17); \
+ l += r; \
+ r ^= xswap(l); \
+ l += r; \
+ r ^= rotl(l, 3); \
+ l += r; \
+ r ^= rotr(l, 2); \
+ l += r; \
+} while (0)
+
+
+static inline u32 get_le32(const u8 *p)
+{
+ return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
+}
+
+
+static inline void put_le32(u8 *p, u32 v)
+{
+ p[0] = v;
+ p[1] = v >> 8;
+ p[2] = v >> 16;
+ p[3] = v >> 24;
+}
+
+
+static void michael_init(void *ctx)
+{
+ struct michael_mic_ctx *mctx = ctx;
+ mctx->pending_len = 0;
+}
+
+
+static void michael_update(void *ctx, const u8 *data, unsigned int len)
+{
+ struct michael_mic_ctx *mctx = ctx;
+
+ if (mctx->pending_len) {
+ int flen = 4 - mctx->pending_len;
+ if (flen > len)
+ flen = len;
+ memcpy(&mctx->pending[mctx->pending_len], data, flen);
+ mctx->pending_len += flen;
+ data += flen;
+ len -= flen;
+
+ if (mctx->pending_len < 4)
+ return;
+
+ mctx->l ^= get_le32(mctx->pending);
+ michael_block(mctx->l, mctx->r);
+ mctx->pending_len = 0;
+ }
+
+ while (len >= 4) {
+ mctx->l ^= get_le32(data);
+ michael_block(mctx->l, mctx->r);
+ data += 4;
+ len -= 4;
+ }
+
+ if (len > 0) {
+ mctx->pending_len = len;
+ memcpy(mctx->pending, data, len);
+ }
+}
+
+
+static void michael_final(void *ctx, u8 *out)
+{
+ struct michael_mic_ctx *mctx = ctx;
+ u8 *data = mctx->pending;
+
+ /* Last block and padding (0x5a, 4..7 x 0) */
+ switch (mctx->pending_len) {
+ case 0:
+ mctx->l ^= 0x5a;
+ break;
+ case 1:
+ mctx->l ^= data[0] | 0x5a00;
+ break;
+ case 2:
+ mctx->l ^= data[0] | (data[1] << 8) | 0x5a0000;
+ break;
+ case 3:
+ mctx->l ^= data[0] | (data[1] << 8) | (data[2] << 16) |
+ 0x5a000000;
+ break;
+ }
+ michael_block(mctx->l, mctx->r);
+ /* l ^= 0; */
+ michael_block(mctx->l, mctx->r);
+
+ put_le32(out, mctx->l);
+ put_le32(out + 4, mctx->r);
+}
+
+
+static int michael_setkey(void *ctx, const u8 *key, unsigned int keylen,
+ u32 *flags)
+{
+ struct michael_mic_ctx *mctx = ctx;
+ if (keylen != 8) {
+ if (flags)
+ *flags = CRYPTO_TFM_RES_BAD_KEY_LEN;
+ return -1;
+ }
+ mctx->l = get_le32(key);
+ mctx->r = get_le32(key + 4);
+ return 0;
+}
+
+
+static struct crypto_alg michael_mic_alg = {
+ .cra_name = "michael_mic",
+ .cra_flags = CRYPTO_ALG_TYPE_DIGEST,
+ .cra_blocksize = 8,
+ .cra_ctxsize = sizeof(struct michael_mic_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(michael_mic_alg.cra_list),
+ .cra_u = { .digest = {
+ .dia_digestsize = 8,
+ .dia_init = michael_init,
+ .dia_update = michael_update,
+ .dia_final = michael_final,
+ .dia_setkey = michael_setkey } }
+};
+
+
+static int __init michael_mic_init(void)
+{
+ return crypto_register_alg(&michael_mic_alg);
+}
+
+
+static void __exit michael_mic_exit(void)
+{
+ crypto_unregister_alg(&michael_mic_alg);
+}
+
+
+module_init(michael_mic_init);
+module_exit(michael_mic_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Michael MIC");
+MODULE_AUTHOR("Jouni Malinen <[email protected]>");
diff -Nru a/crypto/tcrypt.c b/crypto/tcrypt.c
--- a/crypto/tcrypt.c Tue Mar 9 19:20:04 2004
+++ b/crypto/tcrypt.c Tue Mar 9 19:20:04 2004
@@ -61,7 +61,7 @@
static char *check[] = {
"des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
"twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6",
- "arc4", "deflate", NULL
+ "arc4", "michael_mic", "deflate", NULL
};

static void
@@ -572,6 +572,8 @@
test_hmac("sha1", hmac_sha1_tv_template, HMAC_SHA1_TEST_VECTORS);
test_hmac("sha256", hmac_sha256_tv_template, HMAC_SHA256_TEST_VECTORS);
#endif
+
+ test_hash("michael_mic", michael_mic_tv_template, MICHAEL_MIC_TEST_VECTORS);
break;

case 1:
@@ -649,6 +651,10 @@
case 16:
test_cipher ("arc4", MODE_ECB, ENCRYPT, arc4_enc_tv_template, ARC4_ENC_TEST_VECTORS);
test_cipher ("arc4", MODE_ECB, DECRYPT, arc4_dec_tv_template, ARC4_DEC_TEST_VECTORS);
+ break;
+
+ case 17:
+ test_hash("michael_mic", michael_mic_tv_template, MICHAEL_MIC_TEST_VECTORS);
break;

#ifdef CONFIG_CRYPTO_HMAC
diff -Nru a/crypto/tcrypt.h b/crypto/tcrypt.h
--- a/crypto/tcrypt.h Tue Mar 9 19:20:04 2004
+++ b/crypto/tcrypt.h Tue Mar 9 19:20:04 2004
@@ -1721,4 +1721,54 @@
},
};

+/*
+ * Michael MIC test vectors from IEEE 802.11i
+ */
+#define MICHAEL_MIC_TEST_VECTORS 6
+
+struct hash_testvec michael_mic_tv_template[] =
+{
+ {
+ .key = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ .ksize = 8,
+ .plaintext = { },
+ .psize = 0,
+ .digest = { 0x82, 0x92, 0x5c, 0x1c, 0xa1, 0xd1, 0x30, 0xb8 }
+ },
+ {
+ .key = { 0x82, 0x92, 0x5c, 0x1c, 0xa1, 0xd1, 0x30, 0xb8 },
+ .ksize = 8,
+ .plaintext = { 'M' },
+ .psize = 1,
+ .digest = { 0x43, 0x47, 0x21, 0xca, 0x40, 0x63, 0x9b, 0x3f }
+ },
+ {
+ .key = { 0x43, 0x47, 0x21, 0xca, 0x40, 0x63, 0x9b, 0x3f },
+ .ksize = 8,
+ .plaintext = { 'M', 'i' },
+ .psize = 2,
+ .digest = { 0xe8, 0xf9, 0xbe, 0xca, 0xe9, 0x7e, 0x5d, 0x29 }
+ },
+ {
+ .key = { 0xe8, 0xf9, 0xbe, 0xca, 0xe9, 0x7e, 0x5d, 0x29 },
+ .ksize = 8,
+ .plaintext = { 'M', 'i', 'c' },
+ .psize = 3,
+ .digest = { 0x90, 0x03, 0x8f, 0xc6, 0xcf, 0x13, 0xc1, 0xdb }
+ },
+ {
+ .key = { 0x90, 0x03, 0x8f, 0xc6, 0xcf, 0x13, 0xc1, 0xdb },
+ .ksize = 8,
+ .plaintext = { 'M', 'i', 'c', 'h' },
+ .psize = 4,
+ .digest = { 0xd5, 0x5e, 0x10, 0x05, 0x10, 0x12, 0x89, 0x86 }
+ },
+ {
+ .key = { 0xd5, 0x5e, 0x10, 0x05, 0x10, 0x12, 0x89, 0x86 },
+ .ksize = 8,
+ .plaintext = { 'M', 'i', 'c', 'h', 'a', 'e', 'l' },
+ .psize = 7,
+ .digest = { 0x0a, 0x94, 0x2b, 0x12, 0x4e, 0xca, 0xa5, 0x46 },
+ }
+};
#endif /* _CRYPTO_TCRYPT_H */

===================================================================


This BitKeeper patch contains the following changesets:
1.1690
## Wrapped with gzip_uu ##


M'XL( &2)3D ]U:>5/;2!;_V_H4;\G6C,U@6Z</"%08<(@W7 5F=J=(UM66
M6K:"+&ET )Z8[[[OM61;OL!0DZJIY9#=U^^=_?IUJ]_!3<3#W<*WNR%S'8]+
M[^"3'\6[!=.L#)*X8CM8<^7[6%/]H_IM6.W=52./!=' C\MJQ9"P^9+%Y@#N
M>1CM%I2*-JV)1P'?+5RU3FY.#Z\D:7\?C@;,Z_-K'L/^OA3[X3USK>@#BP>N
M[U7BD'G1D,>L8OK#\;3K6)5E%7\-I:[)1FVLU&2]/C852U&8KG!+5O5&39<F
M GR8,CX/H<N:@D"&;LAC1:^K=>D8E(I2:\H@ZU59J\I-4)J[2GW7:);EQJXL
MPS(D_%*#LBS]"G\M[T>2"8>6Q2TX<\P!XRZ<M8_@CH^PQG+Z/(K!]D/H?&Y?
M0K'=:K6@(:L517&J_[X\+%6@,W B8&[?#YUX,$0P+/Z1.#&'!\[NP$HX,@SQ
M@$/(L3[D0^[%D<!$=@,6.SW'=>(1/.!X\%T+7-YGY@B1'K"WRZ,(3@_/8<!"
MZX&%B#9@,5@^C\#S8ZR^YS!,T.)'ES<0^ \\K,"1[T5(# FYHQT<X$2(AEZ3
M(#H-"CESW1'T."01BBDH,V^$';T^<#<21#PA<P5'XE]>-RB@R5PS<5F,@WWT
M/2%>P$:NS[#"%L6<JF# F86]'@:(@F!#=H?<.S%P%CDTV@=F6:F*HR0(_##5
M.2EC3@<FZB"JP*%'_9W8\3WF(AY+D* 7.Z9@R&(Q U04(T:%?,5>$@NY(^Y9
M^ A8B#W=44E0S@TF+?E):'+4!@*A[1V/$1FB%R(7/*I(GT&M*:HF7<YFE%1^
MY8\DR4R6#E9X^=@,1T'L5X>IPKOX63%G<TA3ZC2'ZGJS-M;LAF9:6MVL:0U+
M,^IO0U/&JMJ4:\B,A:XT_. E<53Q'.^.53R<1!E +#XK S&I%)PZ"DXIO8EC
M\=O8T+G19+Q6XTK/T)JK9N\JH+Q(LJ(H&C+QIQ,$W/V @Y/'\K#6N*OX8?]V
M,N6_3F ^F[YG._V,'0VQ-%5KC)6&WFR,C5I-J<N&H=E*LZY;VC/LY'#FN-%T
M57M!)6?HQ;;C\D65* W-4,<-;O;JNEHS=,O06>,9%O(X>1YJNEY;R\.Q;R84
M2(1W5C,D%CAEQXM#OQ(_QA.VFHJ"]E709QI*<VSWM)Y=MPQ5MU7-UE>QM1ET
MGE.CB:%],P<REQQ(T9K*F'$3/<>T>SU98SW=?MF!EN:$K)$7TT+WL@"T OY(
MM4K??.^#[6.4'.!Z+I:EC;6*_PU%US7TXD9=3A?*YM(R*3^S3"I_PV42HV;J
M)1=0#A^R/PRA+ZOE#;&UK31041+ O_S$<^!,:,B#8H[SDO"4A1FXUBW>,N-7
M^,#J"3\U>$VNR:G!5>W_P>!I %LP^((.WF)=U4#C^KUOY7\6CR[./[9/ND=7
MOU]V+KK(X*?#UBE]EN"7?<BO>G[>X),8\I+!7Q>T5J7!:X.6JC<U?6QH6D,5
M)M=>9_(ZE)6_H<E%#%YM\8D*WF#QXYJ.%F^+9V&+A::^M0-;.>M2T>(V):3X
M]?SF]%1J&W4=5.F+5"C$R'AWP*)!<6%,KM2-[[LQ'P8$L0,Y1^IV6M>=[F^M
MH\[%U75I#[DP%- 1M8<9YMT>$3 9)LQHL+^:U++##C9TV W3M)<==K#HL'J]
M:333&+6\=WO.80WY1P6IO*^2_G$S;"(5W&*%_C"_#7'(0T6:^:R'#MZTXM0Q
M9ANR5-V68/L5+&'OJO0.?1?5M=87H(9N%L5A8M)^+QIT"1,AUWG5[5?8E[Y+
M!?PK5'#ZPCY\!_E1EG<V?L+3CA@<.7_BL@@-44)P7)8YY4\(F/8(LAZR*&51
M(J774 FK*9Z&24]%/)E"3TL\-4&OUX GJ4" "RR_#N)%EG\^^WF!;669;5TC
M/+U.3U50,)FH$71JHK79$Y3M-6R_#F(3MG?@9V>1=W69=]X@4+LI-,)GA+FH
MJ8L:PQ)L-=?P_CJ(C7G'A[DH@+8L0#/U/Z&AABVHU\13?%=$O9D:O[=&@-=!
MO$X ? P6I="7I; ,H26A*R5EQYA]5X0[-X0^&[4U4KP.X@U2X(/1@]/#712J
MOBR4+-R@J0O3]V9<Z#DG88)'/>7H27J:6\3F#B%H)3OG#T!)X.[*'I(-'%?:
MW_#_F87J#><D8OEZW>KU0Q8O$WYUXL^<!SP4:H"5A[S5E;K!A8QDFRU>\\U7
ML"3T?T0X5=ZPN/T [2NOV]\TM1^3/'S$A/(SI.=?LYR@7%ZGUC<D!C(*J&5I
MP9' [(<L&#B8:5^VL7(Q79C/JRG5+LUEX-F0(S\8A4Y_$$/1+ $I?F&S^WY9
MD0?96'%B'83$R)#.2.V0<XA\.Z;CY3T8^0F8S(.06PXF'4XOB3D=UC+/JF+V
M/_0MQQX1#M8EGI6=_L8\'$:3L]^3\QLXX1X/F0N72<]%:4\=DWN8)].;"CI0
M58%%!!)0<S1 ^7HC,?8C<7.=<0,?42A+' Y41*KT17KG>*:;6!S>BS/"JN,Y
MF+,=+-4CGXG+5[604%Y_54MJ=&KY,LNX\DF6&3\"!NJD 0'W+$2YU;_N204*
MFMUX4M=UN2<V!HFF@KL#X1X%PA0113'!\<@P0,VA'[M%^H)^O8,-,?2<."I1
M]A;R. D]*&(+O'^?UL,X+1\<0!$'E=-:W"L\K<</-\!'O#E\I+<9_F/TP(()
M@3E8@?.32"9MF_Y+A-H0)*9M:8LLEXB#QI3.)"&>J+[G^N9=D519*GR1+!^^
M%_ '-1S"?_=3'6*C4B_M4:5+>_]P+]<CY=+%YM7M$P1M'8!0(W90ESL\T6L-
M#-Y%N;1&1WT>HTMH:M'T/5Q-T7FV@[RJ@EOY*VDEN%6^SG04W*JBI-2RHB:*
MJK[&&O>^8^%LRD@)(CN"_+V@)8CLP_T>?57$5Z%S45:G9:4F*K1IA:HOD!-T
M)H:AR5<4-=LX-02A-;-F>TA/S 7B1Z1 A?)!;K[0#N(Y0DF 48#/2.W 3)GT
MP@=%]2*G[V$<(2='Q(V907LZ-A276"K13"\0FITRJ.-\6.JU1WUPN.ASD!)&
MO\B&9!V&?&@&H^)/<Z-OE["^[D J"XTNB8%+>D+'LS-4\:(K5Z;F\J3X)>-K
M&>$]Z(+%U/O2GFDOEUQ]ZJUS(U-NYJ9C-F8GTTFXAF%AV )9MI!-%*$I5&>J
MX%6D2;)-*4ZTH.=4H$\HD@92P\AY:O/\S1MIKL?$()D]GI[Q4 Q8S,T[*+FF
MG\2;3XJ)+V/%'!/"1-5M.&7H\$(3XO5D0.] O3X&GD<#6=0KE3H\DIRX3!:B
M!X=N :SQ:G%B)>_.:Y]@]F8'6]FQUD(GXB\-5]1=EI<&J&L'"*OF0UR*L )#
MVQPCK<A%2O+L"? \-.ZS7G8G5'.JC#VAQA<'H&6F,1>-/6ER"2O? +_@/C$W
M;B&"SUPCXC&F>ZL#'38LQ#FL09O27JT (MAOVR[K1YO['$V0% 3^L4\J_3Z-
M9P('@5-(')&=LG<^GG6O6M?=7P^/NY];OW=/6^>DYFPQ*RN9JC/SY68UTBE-
M8W^XT$(*HM8,9G$QR(1)$[0N<_MS<E%YGUBOF"'K>FS("_L+!\19FY"E,)7E
M\/2DV_G]LM4];I^TKCN37L+<E-05TMVTJ$2VLRKZ\.WB:@67)OW3!!2[=SZU
MK[MG%\<WIZU)&Z:\,;:<MJ\[W4\M5&3[O-TI+H@T[3F%3 H%VHOG]N42;=)9
M-ZW(<TRUM#H7]N<6ZTE3NI[F&M.*2;,(9KE649XTIBZ::TTKX F>EA+=&+J"
M[IR6IEE#/@O*3!OR/DK,0U( +ICS&EF<.&*6=+O\<8$ 5<P(9,B)MQEV:K>4
MR46NL5/6+$@LTA0!(;5T][1]U#J_;A6W3BY/X5[=PK:LY;AU?735ONRT+\Z+
M6[F]7Z[+X4WGT\55<>OE/=W6_(N"[#X#G:[\B)L4ZU]JSE^DF+[3U-6:KJ7O
M"]17[?F;?\]WFN)>R.JC@DP#;WI[4-.@*66F6WZ9*15PQTHNSV%K+>/3*VA;
M4L'BM.+C=MS+T*3"@+N!A(O$PD4N<3^*9![R*&)]3E.6]T.ZCQ;@IH>;XO:3
MD]X%H_%S:EFZ_D:0V34W:ZK*':#[5TY,PW.7T":WS\1-+]SYA[A["0,_XA$V
MF0S;)L<)=)'.0_X((*N:4JS@C)M>>C0''.-V,MRORS;7ZCU3^A\%*@6E8RD
!


--
Jouni Malinen PGP id EFC895FA

2004-03-10 04:20:29

by James Morris

[permalink] [raw]
Subject: Re: Crypto API and keyed non-HMAC digest algorithms / Michael MIC

On Tue, 9 Mar 2004, Jouni Malinen wrote:

> +static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
> +{
> + u32 flags;
> + if (tfm->__crt_alg->cra_digest.dia_setkey == NULL)
> + return -1;

In both patches, these 'return -1' statements should be -EINVAL, or
whatever is appropriate (probably -ENOSYS for this one).


- James
--
James Morris
<[email protected]>


2004-03-10 05:38:14

by Jouni Malinen

[permalink] [raw]
Subject: Re: Crypto API and keyed non-HMAC digest algorithms / Michael MIC

On Tue, Mar 09, 2004 at 11:21:03PM -0500, James Morris wrote:

> In both patches, these 'return -1' statements should be -EINVAL, or
> whatever is appropriate (probably -ENOSYS for this one).

Fixed. The included patch combines changesets for both the setkey
addition and Michael MIC. Please let me know if you want to get these as
separate patch files.


You can import this changeset into BK by piping this whole message to:
'| bk receive [path to repository]' or apply the patch as usual.

===================================================================


[email protected], 2004-03-09 21:12:44-08:00, [email protected]
Fixed the error return value for Michael MIC.

[email protected], 2004-03-09 21:08:17-08:00, [email protected]
Fixed error codes in return values of the digest setkey handler.

[email protected], 2004-03-09 19:17:59-08:00, [email protected]
Added Michael MIC keyed digest for TKIP (IEEE 802.11i/WPA). This algorithm
is quite weak due to the requirements for compatibility with old legacy
wireless LAN hardware that does not have much CPU power. Consequently, this
should not really be used with anything else than TKIP.

Michael MIC is calculated over the payload of the IEEE 802.11 header which
makes it easier to add TKIP support for old wireless LAN cards. An additional
authenticated data area is used (but not send separately) to authenticate
source and destination addresses.

[email protected], 2004-03-09 18:54:50-08:00, [email protected]
Added support for using keyed digest with an optional dit_setkey handler.
This does not change the behavior of the existing digest algorithms, but
allows new ones to add setkey handler that can be used to initialize the
algorithm with a key or seed. setkey is to be called after init, but before
any of the update call(s).


Documentation/crypto/api-intro.txt | 1
crypto/Kconfig | 9 +
crypto/Makefile | 1
crypto/digest.c | 10 +
crypto/michael_mic.c | 193 +++++++++++++++++++++++++++++++++++++
crypto/tcrypt.c | 12 ++
crypto/tcrypt.h | 52 +++++++++
include/linux/crypto.h | 13 ++
8 files changed, 290 insertions(+), 1 deletion(-)


diff -Nru a/Documentation/crypto/api-intro.txt b/Documentation/crypto/api-intro.txt
--- a/Documentation/crypto/api-intro.txt Tue Mar 9 21:25:13 2004
+++ b/Documentation/crypto/api-intro.txt Tue Mar 9 21:25:13 2004
@@ -187,6 +187,7 @@
Brian Gladman (AES)
Kartikey Mahendra Bhatt (CAST6)
Jon Oberheide (ARC4)
+ Jouni Malinen (Michael MIC)

SHA1 algorithm contributors:
Jean-Francois Dive
diff -Nru a/crypto/Kconfig b/crypto/Kconfig
--- a/crypto/Kconfig Tue Mar 9 21:25:13 2004
+++ b/crypto/Kconfig Tue Mar 9 21:25:13 2004
@@ -161,6 +161,15 @@

You will most probably want this if using IPSec.

+config CRYPTO_MICHAEL_MIC
+ tristate "Michael MIC keyed digest algorithm"
+ depends on CRYPTO
+ help
+ Michael MIC is used for message integrity protection in TKIP
+ (IEEE 802.11i). This algorithm is required for TKIP, but it
+ should not be used for other purposes because of the weakness
+ of the algorithm.
+
config CRYPTO_TEST
tristate "Testing module"
depends on CRYPTO
diff -Nru a/crypto/Makefile b/crypto/Makefile
--- a/crypto/Makefile Tue Mar 9 21:25:13 2004
+++ b/crypto/Makefile Tue Mar 9 21:25:13 2004
@@ -23,5 +23,6 @@
obj-$(CONFIG_CRYPTO_CAST6) += cast6.o
obj-$(CONFIG_CRYPTO_ARC4) += arc4.o
obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o
+obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o

obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
diff -Nru a/crypto/digest.c b/crypto/digest.c
--- a/crypto/digest.c Tue Mar 9 21:25:13 2004
+++ b/crypto/digest.c Tue Mar 9 21:25:13 2004
@@ -42,6 +42,15 @@
tfm->__crt_alg->cra_digest.dia_final(crypto_tfm_ctx(tfm), out);
}

+static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
+{
+ u32 flags;
+ if (tfm->__crt_alg->cra_digest.dia_setkey == NULL)
+ return -ENOSYS;
+ return tfm->__crt_alg->cra_digest.dia_setkey(crypto_tfm_ctx(tfm),
+ key, keylen, &flags);
+}
+
static void digest(struct crypto_tfm *tfm,
struct scatterlist *sg, unsigned int nsg, u8 *out)
{
@@ -72,6 +81,7 @@
ops->dit_update = update;
ops->dit_final = final;
ops->dit_digest = digest;
+ ops->dit_setkey = setkey;

return crypto_alloc_hmac_block(tfm);
}
diff -Nru a/crypto/michael_mic.c b/crypto/michael_mic.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/crypto/michael_mic.c Tue Mar 9 21:25:13 2004
@@ -0,0 +1,193 @@
+/*
+ * Cryptographic API
+ *
+ * Michael MIC (IEEE 802.11i/TKIP) keyed digest
+ *
+ * Copyright (c) 2004 Jouni Malinen <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/crypto.h>
+
+
+struct michael_mic_ctx {
+ u8 pending[4];
+ size_t pending_len;
+
+ u32 l, r;
+};
+
+
+static inline u32 rotl(u32 val, int bits)
+{
+ return (val << bits) | (val >> (32 - bits));
+}
+
+
+static inline u32 rotr(u32 val, int bits)
+{
+ return (val >> bits) | (val << (32 - bits));
+}
+
+
+static inline u32 xswap(u32 val)
+{
+ return ((val & 0x00ff00ff) << 8) | ((val & 0xff00ff00) >> 8);
+}
+
+
+#define michael_block(l, r) \
+do { \
+ r ^= rotl(l, 17); \
+ l += r; \
+ r ^= xswap(l); \
+ l += r; \
+ r ^= rotl(l, 3); \
+ l += r; \
+ r ^= rotr(l, 2); \
+ l += r; \
+} while (0)
+
+
+static inline u32 get_le32(const u8 *p)
+{
+ return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
+}
+
+
+static inline void put_le32(u8 *p, u32 v)
+{
+ p[0] = v;
+ p[1] = v >> 8;
+ p[2] = v >> 16;
+ p[3] = v >> 24;
+}
+
+
+static void michael_init(void *ctx)
+{
+ struct michael_mic_ctx *mctx = ctx;
+ mctx->pending_len = 0;
+}
+
+
+static void michael_update(void *ctx, const u8 *data, unsigned int len)
+{
+ struct michael_mic_ctx *mctx = ctx;
+
+ if (mctx->pending_len) {
+ int flen = 4 - mctx->pending_len;
+ if (flen > len)
+ flen = len;
+ memcpy(&mctx->pending[mctx->pending_len], data, flen);
+ mctx->pending_len += flen;
+ data += flen;
+ len -= flen;
+
+ if (mctx->pending_len < 4)
+ return;
+
+ mctx->l ^= get_le32(mctx->pending);
+ michael_block(mctx->l, mctx->r);
+ mctx->pending_len = 0;
+ }
+
+ while (len >= 4) {
+ mctx->l ^= get_le32(data);
+ michael_block(mctx->l, mctx->r);
+ data += 4;
+ len -= 4;
+ }
+
+ if (len > 0) {
+ mctx->pending_len = len;
+ memcpy(mctx->pending, data, len);
+ }
+}
+
+
+static void michael_final(void *ctx, u8 *out)
+{
+ struct michael_mic_ctx *mctx = ctx;
+ u8 *data = mctx->pending;
+
+ /* Last block and padding (0x5a, 4..7 x 0) */
+ switch (mctx->pending_len) {
+ case 0:
+ mctx->l ^= 0x5a;
+ break;
+ case 1:
+ mctx->l ^= data[0] | 0x5a00;
+ break;
+ case 2:
+ mctx->l ^= data[0] | (data[1] << 8) | 0x5a0000;
+ break;
+ case 3:
+ mctx->l ^= data[0] | (data[1] << 8) | (data[2] << 16) |
+ 0x5a000000;
+ break;
+ }
+ michael_block(mctx->l, mctx->r);
+ /* l ^= 0; */
+ michael_block(mctx->l, mctx->r);
+
+ put_le32(out, mctx->l);
+ put_le32(out + 4, mctx->r);
+}
+
+
+static int michael_setkey(void *ctx, const u8 *key, unsigned int keylen,
+ u32 *flags)
+{
+ struct michael_mic_ctx *mctx = ctx;
+ if (keylen != 8) {
+ if (flags)
+ *flags = CRYPTO_TFM_RES_BAD_KEY_LEN;
+ return -EINVAL;
+ }
+ mctx->l = get_le32(key);
+ mctx->r = get_le32(key + 4);
+ return 0;
+}
+
+
+static struct crypto_alg michael_mic_alg = {
+ .cra_name = "michael_mic",
+ .cra_flags = CRYPTO_ALG_TYPE_DIGEST,
+ .cra_blocksize = 8,
+ .cra_ctxsize = sizeof(struct michael_mic_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(michael_mic_alg.cra_list),
+ .cra_u = { .digest = {
+ .dia_digestsize = 8,
+ .dia_init = michael_init,
+ .dia_update = michael_update,
+ .dia_final = michael_final,
+ .dia_setkey = michael_setkey } }
+};
+
+
+static int __init michael_mic_init(void)
+{
+ return crypto_register_alg(&michael_mic_alg);
+}
+
+
+static void __exit michael_mic_exit(void)
+{
+ crypto_unregister_alg(&michael_mic_alg);
+}
+
+
+module_init(michael_mic_init);
+module_exit(michael_mic_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Michael MIC");
+MODULE_AUTHOR("Jouni Malinen <[email protected]>");
diff -Nru a/crypto/tcrypt.c b/crypto/tcrypt.c
--- a/crypto/tcrypt.c Tue Mar 9 21:25:13 2004
+++ b/crypto/tcrypt.c Tue Mar 9 21:25:13 2004
@@ -61,7 +61,7 @@
static char *check[] = {
"des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
"twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6",
- "arc4", "deflate", NULL
+ "arc4", "michael_mic", "deflate", NULL
};

static void
@@ -112,6 +112,10 @@
sg[0].length = hash_tv[i].psize;

crypto_digest_init (tfm);
+ if (tfm->crt_u.digest.dit_setkey) {
+ crypto_digest_setkey (tfm, hash_tv[i].key,
+ hash_tv[i].ksize);
+ }
crypto_digest_update (tfm, sg, 1);
crypto_digest_final (tfm, result);

@@ -568,6 +572,8 @@
test_hmac("sha1", hmac_sha1_tv_template, HMAC_SHA1_TEST_VECTORS);
test_hmac("sha256", hmac_sha256_tv_template, HMAC_SHA256_TEST_VECTORS);
#endif
+
+ test_hash("michael_mic", michael_mic_tv_template, MICHAEL_MIC_TEST_VECTORS);
break;

case 1:
@@ -645,6 +651,10 @@
case 16:
test_cipher ("arc4", MODE_ECB, ENCRYPT, arc4_enc_tv_template, ARC4_ENC_TEST_VECTORS);
test_cipher ("arc4", MODE_ECB, DECRYPT, arc4_dec_tv_template, ARC4_DEC_TEST_VECTORS);
+ break;
+
+ case 17:
+ test_hash("michael_mic", michael_mic_tv_template, MICHAEL_MIC_TEST_VECTORS);
break;

#ifdef CONFIG_CRYPTO_HMAC
diff -Nru a/crypto/tcrypt.h b/crypto/tcrypt.h
--- a/crypto/tcrypt.h Tue Mar 9 21:25:13 2004
+++ b/crypto/tcrypt.h Tue Mar 9 21:25:13 2004
@@ -30,6 +30,8 @@
char digest[MAX_DIGEST_SIZE];
unsigned char np;
unsigned char tap[MAX_TAP];
+ char key[128]; /* only used with keyed hash algorithms */
+ unsigned char ksize;
};

struct hmac_testvec {
@@ -1719,4 +1721,54 @@
},
};

+/*
+ * Michael MIC test vectors from IEEE 802.11i
+ */
+#define MICHAEL_MIC_TEST_VECTORS 6
+
+struct hash_testvec michael_mic_tv_template[] =
+{
+ {
+ .key = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ .ksize = 8,
+ .plaintext = { },
+ .psize = 0,
+ .digest = { 0x82, 0x92, 0x5c, 0x1c, 0xa1, 0xd1, 0x30, 0xb8 }
+ },
+ {
+ .key = { 0x82, 0x92, 0x5c, 0x1c, 0xa1, 0xd1, 0x30, 0xb8 },
+ .ksize = 8,
+ .plaintext = { 'M' },
+ .psize = 1,
+ .digest = { 0x43, 0x47, 0x21, 0xca, 0x40, 0x63, 0x9b, 0x3f }
+ },
+ {
+ .key = { 0x43, 0x47, 0x21, 0xca, 0x40, 0x63, 0x9b, 0x3f },
+ .ksize = 8,
+ .plaintext = { 'M', 'i' },
+ .psize = 2,
+ .digest = { 0xe8, 0xf9, 0xbe, 0xca, 0xe9, 0x7e, 0x5d, 0x29 }
+ },
+ {
+ .key = { 0xe8, 0xf9, 0xbe, 0xca, 0xe9, 0x7e, 0x5d, 0x29 },
+ .ksize = 8,
+ .plaintext = { 'M', 'i', 'c' },
+ .psize = 3,
+ .digest = { 0x90, 0x03, 0x8f, 0xc6, 0xcf, 0x13, 0xc1, 0xdb }
+ },
+ {
+ .key = { 0x90, 0x03, 0x8f, 0xc6, 0xcf, 0x13, 0xc1, 0xdb },
+ .ksize = 8,
+ .plaintext = { 'M', 'i', 'c', 'h' },
+ .psize = 4,
+ .digest = { 0xd5, 0x5e, 0x10, 0x05, 0x10, 0x12, 0x89, 0x86 }
+ },
+ {
+ .key = { 0xd5, 0x5e, 0x10, 0x05, 0x10, 0x12, 0x89, 0x86 },
+ .ksize = 8,
+ .plaintext = { 'M', 'i', 'c', 'h', 'a', 'e', 'l' },
+ .psize = 7,
+ .digest = { 0x0a, 0x94, 0x2b, 0x12, 0x4e, 0xca, 0xa5, 0x46 },
+ }
+};
#endif /* _CRYPTO_TCRYPT_H */
diff -Nru a/include/linux/crypto.h b/include/linux/crypto.h
--- a/include/linux/crypto.h Tue Mar 9 21:25:13 2004
+++ b/include/linux/crypto.h Tue Mar 9 21:25:13 2004
@@ -76,6 +76,8 @@
void (*dia_init)(void *ctx);
void (*dia_update)(void *ctx, const u8 *data, unsigned int len);
void (*dia_final)(void *ctx, u8 *out);
+ int (*dia_setkey)(void *ctx, const u8 *key,
+ unsigned int keylen, u32 *flags);
};

struct compress_alg {
@@ -157,6 +159,8 @@
void (*dit_final)(struct crypto_tfm *tfm, u8 *out);
void (*dit_digest)(struct crypto_tfm *tfm, struct scatterlist *sg,
unsigned int nsg, u8 *out);
+ int (*dit_setkey)(struct crypto_tfm *tfm,
+ const u8 *key, unsigned int keylen);
#ifdef CONFIG_CRYPTO_HMAC
void *dit_hmac_block;
#endif
@@ -280,6 +284,15 @@
{
BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
tfm->crt_digest.dit_digest(tfm, sg, nsg, out);
+}
+
+static inline int crypto_digest_setkey(struct crypto_tfm *tfm,
+ const u8 *key, unsigned int keylen)
+{
+ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
+ if (tfm->crt_digest.dit_setkey == NULL)
+ return -ENOSYS;
+ return tfm->crt_digest.dit_setkey(tfm, key, keylen);
}

static inline int crypto_cipher_setkey(struct crypto_tfm *tfm,

===================================================================


This BitKeeper patch contains the following changesets:
1.1688..
## Wrapped with gzip_uu ##


M'XL( +FF3D ]U<>5?C1A+_V_H4O61?8A.PU3IL"08>!)@9[W ]8+*;Q\SZ
MR5+;UB!+B@[ B?GN6]4MV?*)36"S6;(C4!]5U575OZZN;NUWY'/,HIW2M[N^
MY;D^D[XC'X,XV2G9=K67)M6."R5700 EM5]KW_JU]ETM]JTP[@7)ME+5):B^
MM!*[1^Y9%.^4:%4=E22#D.V4KDX^?#X]O)*DO3URU+/\+KMF"=G;DY(@NK<\
M)SZPDIX7^-4DLORXSQ*K:@?]X:CI4)%E!?[3:4.5]?J0UF6M,;2I0ZFE4>;(
MBF;4M3&U,+3-AEP-8L>K!E%WDI FJU26J:PJ!KRJT.^8T"JM&P:1M9JLUF23
MT,:.K.[H^K9L[,@R6428_"B3;5GZB;SN.(XDFYRQJ,M(^VZG5KMCD<^\:ONN
M[29QU6=)S;'N6;\&?X'ZZ]#8]9. 3,FV4^L%?5;+):O=@Z5J8-[T47+)7727
M]JWH((VK;KL_*R3H2#855=%T?2@W#%6%/L&=&QW$:<RJ#IO?NJXK0UE7=$7Z
M1*BN-E3I;*U>EV/GD+;7_)&D=<T/0Q-"9N8W"^8W=G1M1Y<S\^<3XV T(<B/
MVEL9_M!QF$/B- R#*"&=(")I[/I=<L<&4.ZX718GY,%->L3R21 F;N!;'I0G
MK9@ET(@ 3\=C415HW?3<F#@!BXD?),3FTI"D!W[%>M:]"[2##G]GCVZ<()>,
MON5U@PAX].,MTDX3(&5Y7O =-@#"7P@" YG.2#G!$^@90$?$*S-0&R0%YJY
MOINXH+_?.&M.*B.>#0.'1D"6F#&GFE-T.0L@8P-G(&1U$J"/M+A$4 .JX=3\
M03Z*-'2L1/0HQY4J>J'64!I_T*]D2Y;V"9]R!WZ*,]#U[RR<AT,[&H1)4$OX
M[VJ/6YF"+2G86#.'"OXUU#6FFQ:KUQEMZZHYSYWF$1)^JFBFJ@VUAJF;BX1P
M?=M+'2;F=DU0FI(%/$[1&JH^-&13EF63VK;3MG6;S9-E,;VB2(JB RHLUXMP
MIJH]HQ=95^G05&QJP[13;%VQ'$-9HI<BH:(0=:HKSPF1Z716"*J:=&@Q&ZQB
M=]IM6;7:6N=YX\P( 7HP%$F:TW$.[BBZILM#X98"=\ AQKAC[L#*HYM+<*?^
MMKASY@)*,(^<-8\F$0>!Z.93\Y*4FR<G)\20E2JE;NV?EX>5JL"9T;3&!2DF
MOZ8NS,4'9MT1)V4XF7&*1@S*(]9G?A)SFB!N:"5NV_7<9" (? <XK&N90^
[email protected]]E@<D]/#<X"9R'FP(B9P9@1L@&6,]%,(-XXN/Y,P> #T(T>!'P,S8.0-
MMJ"#&P,U"%E2H(Z=(@8P,1@!58:H V@(,,B\F#/Q^9@12G%)+N@&!@@P8Z<>
M (Y#@GN.?8R$UL ++"<'I(*J2(]9#K1ZZ $5(-:W[D!Z-R',BEWL+?"4J[@(
M_JB,"1W8H(.X2@Y];.\*^$<83(&AG[@V%PAPT"*@* L%Y>,K(VCBN&/F(VR'
M5@0MO4&%<RYT1BT%:038 )A.'(;K@H5LD%\$4K 8D56I4YAZKX&LBV=<7RB\
M!;^+TTZE#9Q##<VL#]6.H=J.VK#KJN&H>N-EU"C F2G7_SR8%T.2*:4(9[^Y
M8<B\ P[ V_VZ<8=1S&T^Y;_F9#[9@=]QNYDX*M!2%=484D,SC:%>K].&K.MJ
MAYH-S5&7B%.@,R&-JCT+KF?@Q1W78],JH88*49W!['9#@P!/<W3-,I:(4*13
ME*&N:?6%,AP'=HI PKTS6ZAJ5NAN0S@<!=7D,<G%,BD%^U+P&8.:PTY;;7<:
MCJYH'47M://$6HUT45+=!&C_\Y:BW&3HQ2LN1=@%>/-YG"U%=+P4*70'%B':
M6+(4*6^U%+UW'P&Q6!3Q]<%!G/0!KY,T\@FP2J$@ ]AL<9J.?#D\J6\8^/VW
M8RY=-N0&@E1=__-B+B%$G9JZOJJ/01?:& IC9#ZF3/@8578T;8F/T;?U,;[W
MX7Y6="^^\!96^WR]J_\_K'<ZS'=EJ*BJK/%\S/-0AXF:MP1@Z5O@'W0"B*=Z
M 7H<6'1E_(5_!M4T%=8[HR$+'S-G NIE&_DW\[ _$%"#OXGUY()L1P_9_\#Y
MGE?+"[RR20U0E$3(/X+4=\D9UY!/R@7)*]Q3IM;JA6[QDMA@C@_,#PU&!J_+
M=5D87%'_'PPN0ITI@T_IX"76570P;M#^MOWW\M'%^?OFA];1U2^7-Q<M$/#C
MX<DI_JZ0'_=($2^"HL'SE> Y@Z^W]$C?^D$4N?$!^"Z+<)E'Q5>M=!XY5581
M0VA=-X9J@\IFMII,I.PT<T==NI:\6;+V]7)VX <\IS'?#W*5O,0/-(V84HS0
MP?/%6<Q4CI,HM9.,02OI],DF/+8@[O)!YM0@F]!JBZ1^['9]& QVA1*/^17I
M=ZF4J@KI>%8WWI5*;H>4H>_V?JME1TG+\KK;^W9DM3*I'=?*APN^=?[Y]+0B
ME4K9NKM-@4#V]THTRF.)6W;RB(PK6T /?PC^<+&%I%OD>RYC95=ZDKY(S88&
M4Z(4A/'V_M@&I;U,);MS@YN5,E'<*1O30;2\+(@&-*+_JT&T"/5>W16/-5QO
MFOPY=H"3\XOK7ZYWB\"3;W.> Y[U]E6+EYJI;=5HJ=%40S&X<55E+<3Y"QP2
M0*3!\Y?SK9QKY$5A!=6(!@8>P0).Z+0ZFLFY+!7R.\[;;#Z+ZES,,L>BGA7W
M6LG]K?NUBK-:&D_RB:K8_8W!%"^5GI;-X.5I7&[D]>*)QEO-X#\63_!4P*M;
M];B.V-GDS]*&%=G:QA;9*(0.^.JP#N9%X4]$>:FI ^ J +RE4H*V19N5I_H4
MWL"<K83U0R2Q10I12NOFY/JF]?/)T<W%U348NEG7*?>P=L2LNUUD8%LQP\/;
MUV8U"TJ]%4%IQ6SALZ#4FP$E\-S&[(;G>5!ZL[3-:X*2./%:ZKZ]EX 2 +@"
M;M*S(A3KEBK&UUU2VR2![PT*!P%"9/2>PE$HV:Q!P),'0H(&8L[2@&'YD1[?
MOLP> "V#&_WMKAP4D 9G#[EG-G")22<*^L6S#)<?K6*N^O4-1!NPG=-EJ;8I
MD<TU1)+0.M\!\H"Z%LYD4@>0R")>L7( 32"Y"!-NOY(]C')Q@:KRP)7\3N1'
M6=Y:^4F>MGAG=!3H;O W((Z['DRM $'1(LQ:R/PMFRV"GZ$@+9,_=1N?E#\M
MBD^'/U7.KVV0)ZF$!*=$7H_$LR+_</;#E-AT5FQ-17I: Y\*YV!;O(3SJ?-:
ML\TY=Q:(O1Z)5<3>(C^XT[(KL[(S XEV3*X1-F;,>$F#E^@.%\M<(/MZ)%:6
M'1[V] #4V0&8PO^XAHP.YU[G3_XWY>6V,'Y[P0#6(['> .#1FQZ%-CL*1^=:
MXKJB0AQ]_#?E[FQP?1KU!:-8C\0+1@$/"Q\,'][TH!JS@Y*Y&Y@:-WU[+(56
M<!*+RZ@)B9ZD)Q&"S#\F6!B)_)%3"JD_. @Q%$D36,GC:LR6D%,A)C&HN%,%
M"ULCVRS)ZZ5GU+]"8"+NO4RM>_,U\Y+EKV%@?())EO+F.-E1*=\'KD,V[>1Q
M.C,C91NAXL^<9,T6P4S-9IX&:5+=+#(:[<46Y8/FL5DA102<%$,A)L^[C))/
M:'G>:MZ>;Z$$LP+,_5DQ<?73YP^MB_-B%@D"O19>5^6I)/*W/9+E20]//[1N
M?KD\:1TW/T L42EFNG!+.[.A726]-;>CV.T6$E>5^:'E.C>T^$2<.=?]RZ:D
MQ!'H6TV_8\7DVUOQ:VEN:N)T#1'XG#T0S-'OS&TA=0B#O>K/\&_)9N$%!X#<
MP.OM(-YD V&3G]SD$V,AB[@:R-RKXK6YNH'-!(YMO(&8K+XB,X/^%P]IZ4MN
M";^^]NEZQT_F&ZUS[\%E^029R/ML;R]2Z_JZ:\HP0#7;FAUQFMW("GL ZH>7
M32B<WK)-9J8P65696'2S+D=!.(C<;@_6(KM"4/%39Y'O9A6YG_7E5P_#" 7I
MXV6W3L08B8-.@O<$=\D@2/E]Y(@Y+BPL;CM-&-ZZ T2I 0KU \?M#) .E*6^
MDUWC2UC4'V'1A_//Y /S600QP67:]F"TIZ[-_)CQ[QWP9IQ"K!B)A%@=]V!\
M[0'O^QZEN<ZD(>]A4 X_NZWR[>H7Z;L,NL@[@5UXO[G:VY\I!SE3C\VKP4'Y
MW7DU.0[N Y_1KK>XT85H E.OL%2&S'> RJWV%98I#%Q;25[6@F6(I]8P?O"V
M2+2+P>B7F>4<JZ,@\<KX!_CU%E]P\8L%OMQF2%J&&O+NG2@G0_&^OT_*T&E;
ME&:'- OH1RO0!WH3]('?:O0?XP<KS!E,D.5TON<;^DX'_U60JL%9C.I$C2Q7
M4 )CQ"=/2N2J;WN!?5=&559*7R0G(+]C.ALT')%_[PD=0B5M5':QT,.CV6BW
MT$)(Z4'U_/J<@KJ( %<C-%!F&SSA_50 [[)<6:"C+DO )52E/(ZSPJ*JPEOY
M*VHEO*5?QSH*;Q7^1NO9J\I?%6V!-7BX&Z89*\Y$1+#WG!=GLD?N=_%/RO_D
M.N?ORNB=UGF!.BI0M"EVG$]N&)Q\XT";,UHP:S;[^(18('D$#OBRO5^8+YC%
M6<9(?*<P/Z;'F[M346L>LJXBS!<1G,Z() Y9D%I'"*C!?)AIM9L=U_ V^X(Q
M^$76)6O09WT[')2_G^A].T/KZQ818^F(0+8T1T_@>)V,*K^Q7'C'ZNW\]4LF
MURR%=T3C(@KO$RU%*P]=?>2M$SV%-!/3,>NSE>DD6B P-VP)+5O*)@K7%*A3
M*'@>:QS9JAQS+6@%%6@Y1]2 ,(Q<Y#8IWZ21)EKD!LGL\;3$0P&P+*_HH.B:
M09JL/BER7X:""2&XB6J;Y-0"A^>:X/?,0[S,#EORLORH@XA:[email protected]+G'
ML#>W>XN\FI_YR#N3VD<RN^.CH>Q@:*H1RB?@"IO+\DP'96$';M4BQ D*<VBH
MJ],0!06D1,_."4^2?I)6<"=0LU#&+E?CLQW ,B/,!6/G51[2*E:0'XE6[#>%
MX&/7R+:U"Y,7<S,5$C_<+:0K5O8YG""""&[?C0SS.)YQ.D!8D"2CS?W-^[/6
MU<EUZZ?#X]:GDU]:IR?GNU/;]B=I9+["K,9DR0C[HZD:5%!EO..?7@PF,QR6
MUYT8%[[OH>A5O/CB6WU6VILZ8LWJ^%A*BQ(5>2MN;@SJ2B*CR0M![*P(?P6=
M\GP%5_+V(@"%YC<?F]>MLXOCSZ<G>1V$O G4G#:O;UH?3T"1S?/F37EJ2*.6
M(Y)IJ83YT$)N5"KQ"SZBH"@QEN+J7-J;6*SS*K&>%BI%05[-P:Q0R]_SRM'E
MGTF?)4_D:2;034B+\YW0TBAJ*$9!F6DCUH41LP@5 OFI$:F)PZ?):T6>YQB
M@ 5C!AGEU%^-MK";$')::FB457,6TSPY( A+MTZ;1R?GUR?EC0^7I^1>V8"Z
MK.;XY/KHJGEYT[PX+V\4]GZ%)H>?;SY>7)4WGM_3;2Q(>*W^!0\_4)V^8:XJ
M?UZV:XT;YOQ*]MOLW(^IKF!B2_PJ)+::YS\?GDXDMK*O@3"E]1;?(2V^Z##Y
M&=+XGH-2UT0:4U'62K28_YOW?/E75?.MG&G@1<?F=9684F:ZV0N^4BF)7,09
M1C86"CZZZ; AE1R&859, C^C)I5ZS OQ&&#J,TA^:0+'W&=Q;'5Y8I]U(_R:
M,X2=)K/YMX.N^)(2^T^H9>;C4229?23JC%0I/OEV$^Q>^(0S_W:3?R<)$RV"
M+6,4!C&+H<JVH"[/X>!GJ#[(AP2RHA''*L#<Z/^OPNXQ6"S3_AY5C$['T!WI
)/Y!&5#P>0P


--
Jouni Malinen PGP id EFC895FA

2004-03-10 15:44:51

by James Morris

[permalink] [raw]
Subject: Re: Crypto API and keyed non-HMAC digest algorithms / Michael MIC

On Tue, 9 Mar 2004, Jouni Malinen wrote:

> On Tue, Mar 09, 2004 at 11:21:03PM -0500, James Morris wrote:
>
> > In both patches, these 'return -1' statements should be -EINVAL, or
> > whatever is appropriate (probably -ENOSYS for this one).
>
> Fixed. The included patch combines changesets for both the setkey
> addition and Michael MIC. Please let me know if you want to get these as
> separate patch files.

This is oopsing on 'modprobe tcrypt'.

Separate patches would be preferred.


- James
--
James Morris
<[email protected]>


2004-03-10 16:04:22

by Clay Haapala

[permalink] [raw]
Subject: Re: Crypto API and keyed non-HMAC digest algorithms / Michael MIC

On Tue, 9 Mar 2004, Jouni Malinen outgrape:
>> On Tue, 9 Mar 2004, Clay Haapala wrote:
>> > I had the same thought in my attempt at adding CRC32C to the
>> > crypto routines, that what was needed was "digests + setkey".
>> > But I didn't want to add the key baggage to digests, and so
>> > created a new alg type (CHKSUM), with pretty much identical code
>> > to digest, but with a modified init and a new setkey interface.
>
> On Tue, Mar 09, 2004 at 03:32:58PM -0500, James Morris wrote:
>> I think that adding a setkey method for digests is the simplest
>> approach.
>
>
> I took a quick look at the CRC32C patch and it looked like the only
> needed change for the digest type was the new handler for setting a
> 32-bit seed. I used setkey handler that takes an arbitrary key data
> and length (Michael MIC uses 64-bit key/seed). As far as I could
> tell, this setkey function should be enough for CRC32C needs,
> too. Clay, please let me know if I missed something here. James,
> please consider merging this into Linux 2.6 tree if there are no
> issues with CRC32C.
>

I believe that is all that CRC32C requires. I had hesitated to add
the setkey/setseed method because I mentally had it tied to "init",
which is not necessary, as your patch shows. I also didn't know what
to do with the "&flags" parameter, but I gather that passing it in and
not using it is fine. Should "unsigned int keylen" be also "const" or
does that matter?

>
> +static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned
> +int keylen) { u32 flags; if (tfm->__crt_alg->cra_digest.dia_setkey
> +== NULL) return -1; return
> +tfm->__crt_alg->cra_digest.dia_setkey(crypto_tfm_ctx(tfm), key,
> +keylen, &flags);
> +}
> +

--
Clay Haapala ([email protected]) Cisco Systems SRBU +1 763-398-1056
6450 Wedgwood Rd, Suite 130 Maple Grove MN 55311 PGP: C89240AD
Windows XP 'Reloaded'? *Reloaded?* Have they no sense of irony?

2004-03-11 03:03:23

by Jouni Malinen

[permalink] [raw]
Subject: Re: Crypto API and keyed non-HMAC digest algorithms / Michael MIC

On Wed, Mar 10, 2004 at 10:45:28AM -0500, James Morris wrote:

> On Tue, 9 Mar 2004, Jouni Malinen wrote:
> > Fixed. The included patch combines changesets for both the setkey
> > addition and Michael MIC. Please let me know if you want to get these as
> > separate patch files.
>
> This is oopsing on 'modprobe tcrypt'.
>
> Separate patches would be preferred.

I was unable to reproduce the oops by loading tcrypt. All tests passed
and the kernel was fine. I did this testing with Linux 2.6.4-rc3 and
all crypto algs compiled as modules. I will try this again with the
latest linus-2.5 BK tree just in case. Anyway, if you happen to have any
more details from the oops like backtrace or any ideas of what might be
causing the difference in our results, they would be very helpful.

I will also send separate patches once I figure out what caused the oops
with tcrypt.

--
Jouni Malinen PGP id EFC895FA

2004-03-11 04:05:57

by James Morris

[permalink] [raw]
Subject: Re: Crypto API and keyed non-HMAC digest algorithms / Michael MIC

On Wed, 10 Mar 2004, Jouni Malinen wrote:

> On Wed, Mar 10, 2004 at 10:45:28AM -0500, James Morris wrote:
>
> I was unable to reproduce the oops by loading tcrypt. All tests passed
> and the kernel was fine. I did this testing with Linux 2.6.4-rc3 and
> all crypto algs compiled as modules. I will try this again with the
> latest linus-2.5 BK tree just in case. Anyway, if you happen to have any
> more details from the oops like backtrace or any ideas of what might be
> causing the difference in our results, they would be very helpful.
>

I can't reproduce it now either (AFAICR, it oopsed in test_hash().

I suspect it may have been caused by loading tcrypt module which was out
of sync with the digest setkey change.


- James
--
James Morris
<[email protected]>


2004-03-11 06:10:59

by Jouni Malinen

[permalink] [raw]
Subject: Re: Crypto API and keyed non-HMAC digest algorithms / Michael MIC

On Wed, Mar 10, 2004 at 11:06:37PM -0500, James Morris wrote:

> I can't reproduce it now either (AFAICR, it oopsed in test_hash().
>
> I suspect it may have been caused by loading tcrypt module which was out
> of sync with the digest setkey change.

That's possible. It didn't fail in my test with an updated version from
the BK repository either, so I would assume this issue can be called
resolved.

Here's the digest setkey part of the previous combined patch; I'll send
a patch for Michael MIC separately.



Added support for using keyed digest with an optional dit_setkey handler.
This does not change the behavior of the existing digest algorithms, but
allows new ones to add setkey handler that can be used to initialize the
algorithm with a key or seed. setkey is to be called after init, but before
any of the update call(s).


diff -Nru a/crypto/digest.c b/crypto/digest.c
--- a/crypto/digest.c Tue Mar 9 21:25:13 2004
+++ b/crypto/digest.c Tue Mar 9 21:25:13 2004
@@ -42,6 +42,15 @@
tfm->__crt_alg->cra_digest.dia_final(crypto_tfm_ctx(tfm), out);
}

+static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
+{
+ u32 flags;
+ if (tfm->__crt_alg->cra_digest.dia_setkey == NULL)
+ return -ENOSYS;
+ return tfm->__crt_alg->cra_digest.dia_setkey(crypto_tfm_ctx(tfm),
+ key, keylen, &flags);
+}
+
static void digest(struct crypto_tfm *tfm,
struct scatterlist *sg, unsigned int nsg, u8 *out)
{
@@ -72,6 +81,7 @@
ops->dit_update = update;
ops->dit_final = final;
ops->dit_digest = digest;
+ ops->dit_setkey = setkey;

return crypto_alloc_hmac_block(tfm);
}
diff -Nru a/crypto/tcrypt.c b/crypto/tcrypt.c
--- a/crypto/tcrypt.c Tue Mar 9 21:25:13 2004
+++ b/crypto/tcrypt.c Tue Mar 9 21:25:13 2004
@@ -112,6 +112,10 @@
sg[0].length = hash_tv[i].psize;

crypto_digest_init (tfm);
+ if (tfm->crt_u.digest.dit_setkey) {
+ crypto_digest_setkey (tfm, hash_tv[i].key,
+ hash_tv[i].ksize);
+ }
crypto_digest_update (tfm, sg, 1);
crypto_digest_final (tfm, result);

diff -Nru a/crypto/tcrypt.h b/crypto/tcrypt.h
--- a/crypto/tcrypt.h Tue Mar 9 21:25:13 2004
+++ b/crypto/tcrypt.h Tue Mar 9 21:25:13 2004
@@ -30,6 +30,8 @@
char digest[MAX_DIGEST_SIZE];
unsigned char np;
unsigned char tap[MAX_TAP];
+ char key[128]; /* only used with keyed hash algorithms */
+ unsigned char ksize;
};

struct hmac_testvec {
diff -Nru a/include/linux/crypto.h b/include/linux/crypto.h
--- a/include/linux/crypto.h Tue Mar 9 21:25:13 2004
+++ b/include/linux/crypto.h Tue Mar 9 21:25:13 2004
@@ -76,6 +76,8 @@
void (*dia_init)(void *ctx);
void (*dia_update)(void *ctx, const u8 *data, unsigned int len);
void (*dia_final)(void *ctx, u8 *out);
+ int (*dia_setkey)(void *ctx, const u8 *key,
+ unsigned int keylen, u32 *flags);
};

struct compress_alg {
@@ -157,6 +159,8 @@
void (*dit_final)(struct crypto_tfm *tfm, u8 *out);
void (*dit_digest)(struct crypto_tfm *tfm, struct scatterlist *sg,
unsigned int nsg, u8 *out);
+ int (*dit_setkey)(struct crypto_tfm *tfm,
+ const u8 *key, unsigned int keylen);
#ifdef CONFIG_CRYPTO_HMAC
void *dit_hmac_block;
#endif
@@ -280,6 +284,15 @@
{
BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
tfm->crt_digest.dit_digest(tfm, sg, nsg, out);
+}
+
+static inline int crypto_digest_setkey(struct crypto_tfm *tfm,
+ const u8 *key, unsigned int keylen)
+{
+ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
+ if (tfm->crt_digest.dit_setkey == NULL)
+ return -ENOSYS;
+ return tfm->crt_digest.dit_setkey(tfm, key, keylen);
}

static inline int crypto_cipher_setkey(struct crypto_tfm *tfm,


--
Jouni Malinen PGP id EFC895FA

2004-03-11 06:14:31

by Jouni Malinen

[permalink] [raw]
Subject: Re: Crypto API and keyed non-HMAC digest algorithms / Michael MIC

This is the Michael MIC part of the previous combined patch. This
requires the digest setkey patch from my previous email.



Added Michael MIC keyed digest for TKIP (IEEE 802.11i/WPA). This algorithm
is quite weak due to the requirements for compatibility with old legacy
wireless LAN hardware that does not have much CPU power. Consequently, this
should not really be used with anything else than TKIP.

Michael MIC is calculated over the payload of the IEEE 802.11 header which
makes it easier to add TKIP support for old wireless LAN cards. An additional
authenticated data area is used (but not send separately) to authenticate
source and destination addresses.



diff -Nru a/Documentation/crypto/api-intro.txt b/Documentation/crypto/api-intro.txt
--- a/Documentation/crypto/api-intro.txt Tue Mar 9 21:25:13 2004
+++ b/Documentation/crypto/api-intro.txt Tue Mar 9 21:25:13 2004
@@ -187,6 +187,7 @@
Brian Gladman (AES)
Kartikey Mahendra Bhatt (CAST6)
Jon Oberheide (ARC4)
+ Jouni Malinen (Michael MIC)

SHA1 algorithm contributors:
Jean-Francois Dive
diff -Nru a/crypto/Kconfig b/crypto/Kconfig
--- a/crypto/Kconfig Tue Mar 9 21:25:13 2004
+++ b/crypto/Kconfig Tue Mar 9 21:25:13 2004
@@ -161,6 +161,15 @@

You will most probably want this if using IPSec.

+config CRYPTO_MICHAEL_MIC
+ tristate "Michael MIC keyed digest algorithm"
+ depends on CRYPTO
+ help
+ Michael MIC is used for message integrity protection in TKIP
+ (IEEE 802.11i). This algorithm is required for TKIP, but it
+ should not be used for other purposes because of the weakness
+ of the algorithm.
+
config CRYPTO_TEST
tristate "Testing module"
depends on CRYPTO
diff -Nru a/crypto/Makefile b/crypto/Makefile
--- a/crypto/Makefile Tue Mar 9 21:25:13 2004
+++ b/crypto/Makefile Tue Mar 9 21:25:13 2004
@@ -23,5 +23,6 @@
obj-$(CONFIG_CRYPTO_CAST6) += cast6.o
obj-$(CONFIG_CRYPTO_ARC4) += arc4.o
obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o
+obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o

obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
diff -Nru a/crypto/michael_mic.c b/crypto/michael_mic.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/crypto/michael_mic.c Tue Mar 9 21:25:13 2004
@@ -0,0 +1,193 @@
+/*
+ * Cryptographic API
+ *
+ * Michael MIC (IEEE 802.11i/TKIP) keyed digest
+ *
+ * Copyright (c) 2004 Jouni Malinen <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/crypto.h>
+
+
+struct michael_mic_ctx {
+ u8 pending[4];
+ size_t pending_len;
+
+ u32 l, r;
+};
+
+
+static inline u32 rotl(u32 val, int bits)
+{
+ return (val << bits) | (val >> (32 - bits));
+}
+
+
+static inline u32 rotr(u32 val, int bits)
+{
+ return (val >> bits) | (val << (32 - bits));
+}
+
+
+static inline u32 xswap(u32 val)
+{
+ return ((val & 0x00ff00ff) << 8) | ((val & 0xff00ff00) >> 8);
+}
+
+
+#define michael_block(l, r) \
+do { \
+ r ^= rotl(l, 17); \
+ l += r; \
+ r ^= xswap(l); \
+ l += r; \
+ r ^= rotl(l, 3); \
+ l += r; \
+ r ^= rotr(l, 2); \
+ l += r; \
+} while (0)
+
+
+static inline u32 get_le32(const u8 *p)
+{
+ return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
+}
+
+
+static inline void put_le32(u8 *p, u32 v)
+{
+ p[0] = v;
+ p[1] = v >> 8;
+ p[2] = v >> 16;
+ p[3] = v >> 24;
+}
+
+
+static void michael_init(void *ctx)
+{
+ struct michael_mic_ctx *mctx = ctx;
+ mctx->pending_len = 0;
+}
+
+
+static void michael_update(void *ctx, const u8 *data, unsigned int len)
+{
+ struct michael_mic_ctx *mctx = ctx;
+
+ if (mctx->pending_len) {
+ int flen = 4 - mctx->pending_len;
+ if (flen > len)
+ flen = len;
+ memcpy(&mctx->pending[mctx->pending_len], data, flen);
+ mctx->pending_len += flen;
+ data += flen;
+ len -= flen;
+
+ if (mctx->pending_len < 4)
+ return;
+
+ mctx->l ^= get_le32(mctx->pending);
+ michael_block(mctx->l, mctx->r);
+ mctx->pending_len = 0;
+ }
+
+ while (len >= 4) {
+ mctx->l ^= get_le32(data);
+ michael_block(mctx->l, mctx->r);
+ data += 4;
+ len -= 4;
+ }
+
+ if (len > 0) {
+ mctx->pending_len = len;
+ memcpy(mctx->pending, data, len);
+ }
+}
+
+
+static void michael_final(void *ctx, u8 *out)
+{
+ struct michael_mic_ctx *mctx = ctx;
+ u8 *data = mctx->pending;
+
+ /* Last block and padding (0x5a, 4..7 x 0) */
+ switch (mctx->pending_len) {
+ case 0:
+ mctx->l ^= 0x5a;
+ break;
+ case 1:
+ mctx->l ^= data[0] | 0x5a00;
+ break;
+ case 2:
+ mctx->l ^= data[0] | (data[1] << 8) | 0x5a0000;
+ break;
+ case 3:
+ mctx->l ^= data[0] | (data[1] << 8) | (data[2] << 16) |
+ 0x5a000000;
+ break;
+ }
+ michael_block(mctx->l, mctx->r);
+ /* l ^= 0; */
+ michael_block(mctx->l, mctx->r);
+
+ put_le32(out, mctx->l);
+ put_le32(out + 4, mctx->r);
+}
+
+
+static int michael_setkey(void *ctx, const u8 *key, unsigned int keylen,
+ u32 *flags)
+{
+ struct michael_mic_ctx *mctx = ctx;
+ if (keylen != 8) {
+ if (flags)
+ *flags = CRYPTO_TFM_RES_BAD_KEY_LEN;
+ return -EINVAL;
+ }
+ mctx->l = get_le32(key);
+ mctx->r = get_le32(key + 4);
+ return 0;
+}
+
+
+static struct crypto_alg michael_mic_alg = {
+ .cra_name = "michael_mic",
+ .cra_flags = CRYPTO_ALG_TYPE_DIGEST,
+ .cra_blocksize = 8,
+ .cra_ctxsize = sizeof(struct michael_mic_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(michael_mic_alg.cra_list),
+ .cra_u = { .digest = {
+ .dia_digestsize = 8,
+ .dia_init = michael_init,
+ .dia_update = michael_update,
+ .dia_final = michael_final,
+ .dia_setkey = michael_setkey } }
+};
+
+
+static int __init michael_mic_init(void)
+{
+ return crypto_register_alg(&michael_mic_alg);
+}
+
+
+static void __exit michael_mic_exit(void)
+{
+ crypto_unregister_alg(&michael_mic_alg);
+}
+
+
+module_init(michael_mic_init);
+module_exit(michael_mic_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Michael MIC");
+MODULE_AUTHOR("Jouni Malinen <[email protected]>");
diff -Nru a/crypto/tcrypt.c b/crypto/tcrypt.c
--- a/crypto/tcrypt.c Tue Mar 9 21:25:13 2004
+++ b/crypto/tcrypt.c Tue Mar 9 21:25:13 2004
@@ -61,7 +61,7 @@
static char *check[] = {
"des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
"twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6",
- "arc4", "deflate", NULL
+ "arc4", "michael_mic", "deflate", NULL
};

static void
@@ -572,6 +576,8 @@
test_hmac("sha1", hmac_sha1_tv_template, HMAC_SHA1_TEST_VECTORS);
test_hmac("sha256", hmac_sha256_tv_template, HMAC_SHA256_TEST_VECTORS);
#endif
+
+ test_hash("michael_mic", michael_mic_tv_template, MICHAEL_MIC_TEST_VECTORS);
break;

case 1:
@@ -649,6 +655,10 @@
case 16:
test_cipher ("arc4", MODE_ECB, ENCRYPT, arc4_enc_tv_template, ARC4_ENC_TEST_VECTORS);
test_cipher ("arc4", MODE_ECB, DECRYPT, arc4_dec_tv_template, ARC4_DEC_TEST_VECTORS);
+ break;
+
+ case 17:
+ test_hash("michael_mic", michael_mic_tv_template, MICHAEL_MIC_TEST_VECTORS);
break;

#ifdef CONFIG_CRYPTO_HMAC
diff -Nru a/crypto/tcrypt.h b/crypto/tcrypt.h
--- a/crypto/tcrypt.h Tue Mar 9 21:25:13 2004
+++ b/crypto/tcrypt.h Tue Mar 9 21:25:13 2004
@@ -1721,4 +1723,54 @@
},
};

+/*
+ * Michael MIC test vectors from IEEE 802.11i
+ */
+#define MICHAEL_MIC_TEST_VECTORS 6
+
+struct hash_testvec michael_mic_tv_template[] =
+{
+ {
+ .key = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ .ksize = 8,
+ .plaintext = { },
+ .psize = 0,
+ .digest = { 0x82, 0x92, 0x5c, 0x1c, 0xa1, 0xd1, 0x30, 0xb8 }
+ },
+ {
+ .key = { 0x82, 0x92, 0x5c, 0x1c, 0xa1, 0xd1, 0x30, 0xb8 },
+ .ksize = 8,
+ .plaintext = { 'M' },
+ .psize = 1,
+ .digest = { 0x43, 0x47, 0x21, 0xca, 0x40, 0x63, 0x9b, 0x3f }
+ },
+ {
+ .key = { 0x43, 0x47, 0x21, 0xca, 0x40, 0x63, 0x9b, 0x3f },
+ .ksize = 8,
+ .plaintext = { 'M', 'i' },
+ .psize = 2,
+ .digest = { 0xe8, 0xf9, 0xbe, 0xca, 0xe9, 0x7e, 0x5d, 0x29 }
+ },
+ {
+ .key = { 0xe8, 0xf9, 0xbe, 0xca, 0xe9, 0x7e, 0x5d, 0x29 },
+ .ksize = 8,
+ .plaintext = { 'M', 'i', 'c' },
+ .psize = 3,
+ .digest = { 0x90, 0x03, 0x8f, 0xc6, 0xcf, 0x13, 0xc1, 0xdb }
+ },
+ {
+ .key = { 0x90, 0x03, 0x8f, 0xc6, 0xcf, 0x13, 0xc1, 0xdb },
+ .ksize = 8,
+ .plaintext = { 'M', 'i', 'c', 'h' },
+ .psize = 4,
+ .digest = { 0xd5, 0x5e, 0x10, 0x05, 0x10, 0x12, 0x89, 0x86 }
+ },
+ {
+ .key = { 0xd5, 0x5e, 0x10, 0x05, 0x10, 0x12, 0x89, 0x86 },
+ .ksize = 8,
+ .plaintext = { 'M', 'i', 'c', 'h', 'a', 'e', 'l' },
+ .psize = 7,
+ .digest = { 0x0a, 0x94, 0x2b, 0x12, 0x4e, 0xca, 0xa5, 0x46 },
+ }
+};
#endif /* _CRYPTO_TCRYPT_H */


--
Jouni Malinen PGP id EFC895FA

2004-03-11 16:35:11

by Clay Haapala

[permalink] [raw]
Subject: Re: Crypto API and keyed non-HMAC digest algorithms / Michael MIC

On Wed, 10 Mar 2004, Jouni Malinen outgrape:
> On Wed, Mar 10, 2004 at 11:06:37PM -0500, James Morris wrote:
>
>> I can't reproduce it now either (AFAICR, it oopsed in test_hash().
>>
>> I suspect it may have been caused by loading tcrypt module which
>> was out of sync with the digest setkey change.
>
> That's possible. It didn't fail in my test with an updated version
> from the BK repository either, so I would assume this issue can be
> called resolved.
>
> Here's the digest setkey part of the previous combined patch; I'll
> send a patch for Michael MIC separately.
>
>
>
> Added support for using keyed digest with an optional dit_setkey
> handler. This does not change the behavior of the existing digest
> algorithms, but allows new ones to add setkey handler that can be
> used to initialize the algorithm with a key or seed. setkey is to be
> called after init, but before any of the update call(s).
>
> [ ... patch omitted ... ]

OK, so I should recode CRC32C to be a variation of digest that employs
a setkey() handler, right? Should be no problem.

Can I get to a reasonable development environment by starting with
2.6.3, and adding the patch you just sent? Or, do I need the Michael
MIC patch, as well?
--
Clay Haapala ([email protected]) Cisco Systems SRBU +1 763-398-1056
6450 Wedgwood Rd, Suite 130 Maple Grove MN 55311 PGP: C89240AD
Windows XP 'Reloaded'? *Reloaded?* Have they no sense of irony?

2004-03-11 20:14:02

by James Morris

[permalink] [raw]
Subject: Re: Crypto API and keyed non-HMAC digest algorithms / Michael MIC

On Thu, 11 Mar 2004, Clay Haapala wrote:

> OK, so I should recode CRC32C to be a variation of digest that employs
> a setkey() handler, right? Should be no problem.

Give it a try and see.

> Can I get to a reasonable development environment by starting with
> 2.6.3, and adding the patch you just sent? Or, do I need the Michael
> MIC patch, as well?

Yes, please apply the first two patches first.


- James
--
James Morris
<[email protected]>


2004-03-18 23:19:56

by Clay Haapala

[permalink] [raw]
Subject: Re: Crypto API and keyed non-HMAC digest algorithms / Michael MIC

On Thu, 11 Mar 2004, James Morris outgrape:
> On Thu, 11 Mar 2004, Clay Haapala wrote:
>
>> OK, so I should recode CRC32C to be a variation of digest that
>> employs a setkey() handler, right? Should be no problem.
>
> Give it a try and see.
>
>> Can I get to a reasonable development environment by starting with
>> 2.6.3, and adding the patch you just sent? Or, do I need the
>> Michael MIC patch, as well?
>
> Yes, please apply the first two patches first.
>
>
> - James

I've redone the crypto crc32c implementation to make use of Jouni's
setkey() digest api. So now crypto crc32c checksums are just another
type of digest, rather than a new CRYPTO_ALG type.

This implementation is still a wrapper for the actual computation
routine in lib/libcrc32c, per previous requests. The patch below
includes the code under lib and crypto. It requires Jouni's previous
patches to be applied, and was tested on 2.6.4 kernel source.

Let me know how it looks, especially if I should add further tests in
tcrypt.

Regards,
--
Clay Haapala ([email protected]) Cisco Systems SRBU +1 763-398-1056
6450 Wedgwood Rd, Suite 130 Maple Grove MN 55311 PGP: C89240AD
Of course the drugs advertised in all those emails are safe.
Show me the dead spammers!
(Please!)

diff -urN linux-2.6.4.orig/crypto/crc32c.c linux/crypto/crc32c.c
--- linux-2.6.4.orig/crypto/crc32c.c 1969-12-31 18:00:00.000000000 -0600
+++ linux/crypto/crc32c.c 2004-03-18 16:09:05.000000000 -0600
@@ -0,0 +1,110 @@
+/*
+ * Cryptographic API.
+ *
+ * CRC32C chksum
+ *
+ * This module file is a wrapper to invoke the lib/crc32c routines.
+ *
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/crypto.h>
+#include <linux/crc32c.h>
+#include <asm/byteorder.h>
+
+#define CHKSUM_BLOCK_SIZE 32
+#define CHKSUM_DIGEST_SIZE 4
+
+struct chksum_ctx {
+ u32 crc;
+};
+
+/*
+ * Steps through buffer one byte at at time, calculates reflected
+ * crc using table.
+ */
+
+static void chksum_init(void *ctx)
+{
+ struct chksum_ctx *mctx = ctx;
+
+ mctx->crc = ~(u32)0; /* common usage */
+}
+
+/*
+ * Setting the seed allows arbitrary accumulators and flexible XOR policy
+ * If your algorithm starts with ~0, then XOR with ~0 before you set
+ * the seed.
+ */
+static int chksum_setkey(void *ctx, const u8 *key, unsigned int keylen,
+ u32 *flags)
+{
+ struct chksum_ctx *mctx = ctx;
+
+ if (keylen != sizeof(mctx->crc)) {
+ if (flags)
+ *flags = CRYPTO_TFM_RES_BAD_KEY_LEN;
+ return -EINVAL;
+ }
+ mctx->crc = __cpu_to_le32(*(u32 *)key);
+ return 0;
+}
+
+static void chksum_update(void *ctx, const u8 *data, size_t length)
+{
+ struct chksum_ctx *mctx = ctx;
+ u32 mcrc;
+
+ mcrc = crc32c(mctx->crc, data, length);
+
+ mctx->crc = mcrc;
+}
+
+static void chksum_final(void *ctx, u8 *out)
+{
+ struct chksum_ctx *mctx = ctx;
+ u32 mcrc = (mctx->crc ^ ~(u32)0);
+
+ *(u32 *)out = __le32_to_cpu(mcrc);
+}
+
+static struct crypto_alg alg = {
+ .cra_name = "crc32c",
+ .cra_flags = CRYPTO_ALG_TYPE_DIGEST,
+ .cra_blocksize = CHKSUM_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct chksum_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(alg.cra_list),
+ .cra_u = {
+ .digest = {
+ .dia_digestsize= CHKSUM_DIGEST_SIZE,
+ .dia_setkey = chksum_setkey,
+ .dia_init = chksum_init,
+ .dia_update = chksum_update,
+ .dia_final = chksum_final
+ }
+ }
+};
+
+static int __init init(void)
+{
+ return crypto_register_alg(&alg);
+}
+
+static void __exit fini(void)
+{
+ crypto_unregister_alg(&alg);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_AUTHOR("Clay Haapala <[email protected]>");
+MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations wrapper for lib/crc32c");
+MODULE_LICENSE("GPL");
diff -urN linux-2.6.4.orig/crypto/Kconfig linux/crypto/Kconfig
--- linux-2.6.4.orig/crypto/Kconfig 2004-03-17 15:23:06.000000000 -0600
+++ linux/crypto/Kconfig 2004-03-18 15:24:57.000000000 -0600
@@ -170,6 +170,16 @@
should not be used for other purposes because of the weakness
of the algorithm.

+config CRYPTO_CRC32C
+ tristate "CRC32c CRC algorithm"
+ depends on CRYPTO
+ select LIBCRC32C
+ help
+ Castagnoli, et al Cyclic Redundancy-Check Algorithm. Used
+ by iSCSI for header and data digests and by others.
+ See Castagnoli93. This implementation uses lib/crc32c.
+ Module will be crc32c.
+
config CRYPTO_TEST
tristate "Testing module"
depends on CRYPTO
diff -urN linux-2.6.4.orig/crypto/Makefile linux/crypto/Makefile
--- linux-2.6.4.orig/crypto/Makefile 2004-03-17 15:23:06.000000000 -0600
+++ linux/crypto/Makefile 2004-03-18 15:44:54.000000000 -0600
@@ -24,5 +24,6 @@
obj-$(CONFIG_CRYPTO_ARC4) += arc4.o
obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o
obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
+obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o

obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
diff -urN linux-2.6.4.orig/crypto/tcrypt.c linux/crypto/tcrypt.c
--- linux-2.6.4.orig/crypto/tcrypt.c 2004-03-17 15:23:06.000000000 -0600
+++ linux/crypto/tcrypt.c 2004-03-18 16:36:41.000000000 -0600
@@ -61,7 +61,7 @@
static char *check[] = {
"des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
"twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6",
- "arc4", "michael_mic", "deflate", NULL
+ "arc4", "michael_mic", "deflate", "crc32c", NULL
};

static void
@@ -496,6 +496,107 @@
}

static void
+test_crc32c(void)
+{
+#define NUMVEC 6
+#define VECSIZE 40
+
+ int i, j, pass;
+ u32 crc;
+ u8 b, test_vec[NUMVEC][VECSIZE];
+ static u32 vec_results[NUMVEC] = {
+ 0x0e2c157f, 0xe980ebf6, 0xde74bded,
+ 0xd579c862, 0xba979ad0, 0x2b29d913
+ };
+ static u32 tot_vec_results = 0x24c5d375;
+
+ struct scatterlist sg[NUMVEC];
+ struct crypto_tfm *tfm;
+ char *fmtdata = "testing crc32c initialized to %08x: %s\n";
+#define SEEDTESTVAL 0xedcba987
+ u32 seed;
+
+ printk("\ntesting crc32c\n");
+
+ tfm = crypto_alloc_tfm("crc32c", 0);
+ if (tfm == NULL) {
+ printk("failed to load transform for crc32c\n");
+ return;
+ }
+
+ crypto_digest_init(tfm);
+ crypto_digest_final(tfm, (u8*)&crc);
+ printk(fmtdata, crc, (crc == 0) ? "pass" : "ERROR");
+
+ /*
+ * stuff test_vec with known values, simple incrementing
+ * byte values.
+ */
+ b = 0;
+ for (i = 0; i < NUMVEC; i++) {
+ for (j = 0; j < VECSIZE; j++)
+ test_vec[i][j] = ++b;
+ sg[i].page = virt_to_page(test_vec[i]);
+ sg[i].offset = offset_in_page(test_vec[i]);
+ sg[i].length = VECSIZE;
+ }
+
+ seed = SEEDTESTVAL;
+ (void)crypto_digest_setkey(tfm, (const u8*)&seed, sizeof(u32));
+ crypto_digest_final(tfm, (u8*)&crc);
+ printk("testing crc32c setkey returns %08x : %s\n", crc, (crc == (SEEDTESTVAL ^ ~(u32)0)) ?
+ "pass" : "ERROR");
+
+ printk("testing crc32c using update/final:\n");
+
+ pass = 1; /* assume all is well */
+
+ for (i = 0; i < NUMVEC; i++) {
+ seed = ~(u32)0;
+ (void)crypto_digest_setkey(tfm, (const u8*)&seed, sizeof(u32));
+ crypto_digest_update(tfm, &sg[i], 1);
+ crypto_digest_final(tfm, (u8*)&crc);
+ if (crc == vec_results[i]) {
+ printk(" %08x:OK", crc);
+ } else {
+ printk(" %08x:BAD, wanted %08x\n", crc, vec_results[i]);
+ pass = 0;
+ }
+ }
+
+ printk("\ntesting crc32c using incremental accumulator:\n");
+ crc = 0;
+ for (i = 0; i < NUMVEC; i++) {
+ seed = (crc ^ ~(u32)0);
+ (void)crypto_digest_setkey(tfm, (const u8*)&seed, sizeof(u32));
+ crypto_digest_update(tfm, &sg[i], 1);
+ crypto_digest_final(tfm, (u8*)&crc);
+ }
+ if (crc == tot_vec_results) {
+ printk(" %08x:OK", crc);
+ } else {
+ printk(" %08x:BAD, wanted %08x\n", crc, tot_vec_results);
+ pass = 0;
+ }
+
+ printk("\ntesting crc32c using digest:\n");
+ seed = ~(u32)0;
+ (void)crypto_digest_setkey(tfm, (const u8*)&seed, sizeof(u32));
+ crypto_digest_digest(tfm, sg, NUMVEC, (u8*)&crc);
+ if (crc == tot_vec_results) {
+ printk(" %08x:OK", crc);
+ } else {
+ printk(" %08x:BAD, wanted %08x\n", crc, tot_vec_results);
+ pass = 0;
+ }
+
+ printk("\n%s\n", pass ? "pass" : "ERROR");
+
+ crypto_free_tfm(tfm);
+ printk("crc32c test complete\n");
+}
+
+static void
test_available(void)
{
char **name = check;
@@ -566,7 +667,8 @@

test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS);
test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS);
- test_deflate();
+ test_deflate();
+ test_crc32c();
#ifdef CONFIG_CRYPTO_HMAC
test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS);
test_hmac("sha1", hmac_sha1_tv_template, HMAC_SHA1_TEST_VECTORS);
@@ -657,6 +759,10 @@
test_hash("michael_mic", michael_mic_tv_template, MICHAEL_MIC_TEST_VECTORS);
break;

+ case 18:
+ test_crc32c();
+ break;
+
#ifdef CONFIG_CRYPTO_HMAC
case 100:
test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS);
diff -urN linux-2.6.4.orig/include/linux/crc32c.h linux/include/linux/crc32c.h
--- linux-2.6.4.orig/include/linux/crc32c.h 1969-12-31 18:00:00.000000000 -0600
+++ linux/include/linux/crc32c.h 2004-03-18 15:34:18.000000000 -0600
@@ -0,0 +1,11 @@
+#ifndef _LINUX_CRC32C_H
+#define _LINUX_CRC32C_H
+
+#include <linux/types.h>
+
+extern u32 crc32c_le(u32 crc, unsigned char const *address, size_t length);
+extern u32 crc32c_be(u32 crc, unsigned char const *address, size_t length);
+
+#define crc32c(seed, data, length) crc32c_le(seed, (unsigned char const *)data, length)
+
+#endif /* _LINUX_CRC32C_H */
diff -urN linux-2.6.4.orig/lib/Kconfig linux/lib/Kconfig
--- linux-2.6.4.orig/lib/Kconfig 2004-03-10 20:55:33.000000000 -0600
+++ linux/lib/Kconfig 2004-03-18 16:28:42.000000000 -0600
@@ -12,6 +12,15 @@
kernel tree does. Such modules that use library CRC32 functions
require M here.

+config LIBCRC32C
+ tristate "CRC32c (Castagnoli, et al) Cyclic Redundancy-Check"
+ help
+ This option is provided for the case where no in-kernel-tree
+ modules require CRC32c functions, but a module built outside the
+ kernel tree does. Such modules that use library CRC32c functions
+ require M here. See Castagnoli93.
+ Module will be libcrc32c.
+
#
# compression support is select'ed if needed
#
diff -urN linux-2.6.4.orig/lib/libcrc32c.c linux/lib/libcrc32c.c
--- linux-2.6.4.orig/lib/libcrc32c.c 1969-12-31 18:00:00.000000000 -0600
+++ linux/lib/libcrc32c.c 2004-03-18 16:27:54.000000000 -0600
@@ -0,0 +1,205 @@
+/*
+ * CRC32C
+ *@Article{castagnoli-crc,
+ * author = { Guy Castagnoli and Stefan Braeuer and Martin Herrman},
+ * title = {{Optimization of Cyclic Redundancy-Check Codes with 24
+ * and 32 Parity Bits}},
+ * journal = IEEE Transactions on Communication,
+ * year = {1993},
+ * volume = {41},
+ * number = {6},
+ * pages = {},
+ * month = {June},
+ *}
+ * Used by the iSCSI driver, possibly others, and derived from the
+ * the iscsi-crc.c module of the linux-iscsi driver at
+ * http://linux-iscsi.sourceforge.net.
+ *
+ * Following the example of lib/crc32, this function is intended to be
+ * flexible and useful for all users. Modules that currently have their
+ * own crc32c, but hopefully may be able to use this one are:
+ * net/sctp (please add all your doco to here if you change to
+ * use this one!)
+ * <endoflist>
+ *
+ * Copyright (c) 2003 Cisco Systems, 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/crc32c.h>
+#include <linux/module.h>
+#include <asm/byteorder.h>
+
+MODULE_AUTHOR("Clay Haapala <[email protected]>");
+MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations");
+MODULE_LICENSE("GPL");
+
+#if __GNUC__ >= 3 /* 2.x has "attribute", but only 3.0 has "pure */
+#define attribute(x) __attribute__(x)
+#else
+#define attribute(x)
+#endif
+
+#define CRC32C_POLY_BE 0x1EDC6F41
+#define CRC32C_POLY_LE 0x82F63B78
+
+#ifndef CRC_LE_BITS
+# define CRC_LE_BITS 8
+#endif
+
+
+/*
+ * Haven't generated a big-endian table yet, but the bit-wise version
+ * should at least work.
+ */
+#if defined CRC_BE_BITS && CRC_BE_BITS != 1
+#undef CRC_BE_BITS
+#endif
+#ifndef CRC_BE_BITS
+# define CRC_BE_BITS 1
+#endif
+
+EXPORT_SYMBOL(crc32c_le);
+
+#if CRC_LE_BITS == 1
+/*
+ * Compute things bit-wise, as done in crc32.c. We could share the tight
+ * loop below with crc32 and vary the POLY if we don't find value in terms
+ * of space and maintainability in keeping the two modules separate.
+ */
+u32 attribute((pure))
+crc32c_le(u32 crc, unsigned char const *p, size_t len)
+{
+ int i;
+ while (len--) {
+ crc ^= *p++;
+ for (i = 0; i < 8; i++)
+ crc = (crc >> 1) ^ ((crc & 1) ? CRC32C_POLY_LE : 0);
+ }
+ return crc;
+}
+#else
+
+/*
+ * This is the CRC-32C table
+ * Generated with:
+ * width = 32 bits
+ * poly = 0x1EDC6F41
+ * reflect input bytes = true
+ * reflect output bytes = true
+ */
+
+static u32 crc32c_table[256] = {
+ 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
+ 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
+ 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
+ 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
+ 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
+ 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
+ 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
+ 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
+ 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
+ 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
+ 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
+ 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
+ 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
+ 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
+ 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
+ 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
+ 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
+ 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
+ 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
+ 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
+ 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
+ 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
+ 0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
+ 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
+ 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
+ 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
+ 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
+ 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
+ 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
+ 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
+ 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
+ 0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
+ 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
+ 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
+ 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
+ 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
+ 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
+ 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
+ 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
+ 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
+ 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
+ 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
+ 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
+ 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
+ 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
+ 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
+ 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
+ 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
+ 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
+ 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
+ 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
+ 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
+ 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
+ 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
+ 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
+ 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
+ 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
+ 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
+ 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
+ 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
+ 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
+ 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
+ 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
+ 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
+};
+
+/*
+ * Steps through buffer one byte at at time, calculates reflected
+ * crc using table.
+ */
+
+u32 attribute((pure))
+crc32c_le(u32 seed, unsigned char const *data, size_t length)
+{
+ u32 crc = __cpu_to_le32(seed);
+
+ while (length--)
+ crc =
+ crc32c_table[(crc ^ *data++) & 0xFFL] ^ (crc >> 8);
+
+ return __le32_to_cpu(crc);
+}
+
+#endif /* CRC_LE_BITS == 8 */
+
+/*EXPORT_SYMBOL(crc32c_be);*/
+
+#if CRC_BE_BITS == 1
+u32 attribute((pure))
+crc32_be(u32 crc, unsigned char const *p, size_t len)
+{
+ int i;
+ while (len--) {
+ crc ^= *p++ << 24;
+ for (i = 0; i < 8; i++)
+ crc =
+ (crc << 1) ^ ((crc & 0x80000000) ? CRC32C_POLY_BE :
+ 0);
+ }
+ return crc;
+}
+#endif
+
+/*
+ * Unit test
+ *
+ * A small unit test suite is implemented as part of the crypto suite.
+ * Select CRYPTO_CRC32C and use the tcrypt module to run the tests.
+ */
diff -urN linux-2.6.4.orig/lib/Makefile linux/lib/Makefile
--- linux-2.6.4.orig/lib/Makefile 2004-03-10 20:55:21.000000000 -0600
+++ linux/lib/Makefile 2004-03-18 15:59:55.000000000 -0600
@@ -16,6 +16,7 @@
endif

obj-$(CONFIG_CRC32) += crc32.o
+obj-$(CONFIG_LIBCRC32C) += libcrc32c.o

obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/
obj-$(CONFIG_ZLIB_DEFLATE) += zlib_deflate/

2004-03-21 15:07:06

by James Morris

[permalink] [raw]
Subject: Re: Crypto API and keyed non-HMAC digest algorithms / Michael MIC

On Thu, 18 Mar 2004, Clay Haapala wrote:

> I've redone the crypto crc32c implementation to make use of Jouni's
> setkey() digest api. So now crypto crc32c checksums are just another
> type of digest, rather than a new CRYPTO_ALG type.
>
> This implementation is still a wrapper for the actual computation
> routine in lib/libcrc32c, per previous requests. The patch below
> includes the code under lib and crypto. It requires Jouni's previous
> patches to be applied, and was tested on 2.6.4 kernel source.
>
> Let me know how it looks, especially if I should add further tests in
> tcrypt.

This looks fine, could you split it into two patches, one with the
libcrc32c code and then one with the crypto algorithm?

Also, in the configuration help, "This implementation uses lib/crc32c"
should be ""This implementation uses lib/libcrc32c".


- James
--
James Morris
<[email protected]>


2004-03-22 16:50:32

by Clay Haapala

[permalink] [raw]
Subject: [PATCH] lib/libcrc32c implementation

This patch agains 2.6.4 kernel code implements the CRC32C algorithm.
The routines are based on the same design as the existing CRC32 code.
Licensing is intended to be identical (GPL).

The immediate customer of this code is the wrapper code in
crypto/crc32c, available in another patch.

And the immediate customer of the crypto code is the linux-iscsi
driver module, currently in review. See the linux-iscsi project on
SourceForge for details.
--
Clay Haapala ([email protected]) Cisco Systems SRBU +1 763-398-1056
6450 Wedgwood Rd, Suite 130 Maple Grove MN 55311 PGP: C89240AD
Of course the drugs advertised in all those emails are safe.
Show me the dead spammers!
(Please!)

diff -urN linux-2.6.4.orig/include/linux/crc32c.h linux/include/linux/crc32c.h
--- linux-2.6.4.orig/include/linux/crc32c.h 1969-12-31 18:00:00.000000000 -0600
+++ linux/include/linux/crc32c.h 2004-03-18 15:34:18.000000000 -0600
@@ -0,0 +1,11 @@
+#ifndef _LINUX_CRC32C_H
+#define _LINUX_CRC32C_H
+
+#include <linux/types.h>
+
+extern u32 crc32c_le(u32 crc, unsigned char const *address, size_t length);
+extern u32 crc32c_be(u32 crc, unsigned char const *address, size_t length);
+
+#define crc32c(seed, data, length) crc32c_le(seed, (unsigned char const *)data, length)
+
+#endif /* _LINUX_CRC32C_H */
diff -urN linux-2.6.4.orig/lib/Kconfig linux/lib/Kconfig
--- linux-2.6.4.orig/lib/Kconfig 2004-03-10 20:55:33.000000000 -0600
+++ linux/lib/Kconfig 2004-03-18 16:28:42.000000000 -0600
@@ -12,6 +12,15 @@
kernel tree does. Such modules that use library CRC32 functions
require M here.

+config LIBCRC32C
+ tristate "CRC32c (Castagnoli, et al) Cyclic Redundancy-Check"
+ help
+ This option is provided for the case where no in-kernel-tree
+ modules require CRC32c functions, but a module built outside the
+ kernel tree does. Such modules that use library CRC32c functions
+ require M here. See Castagnoli93.
+ Module will be libcrc32c.
+
#
# compression support is select'ed if needed
#
diff -urN linux-2.6.4.orig/lib/libcrc32c.c linux/lib/libcrc32c.c
--- linux-2.6.4.orig/lib/libcrc32c.c 1969-12-31 18:00:00.000000000 -0600
+++ linux/lib/libcrc32c.c 2004-03-18 16:27:54.000000000 -0600
@@ -0,0 +1,205 @@
+/*
+ * CRC32C
+ *@Article{castagnoli-crc,
+ * author = { Guy Castagnoli and Stefan Braeuer and Martin Herrman},
+ * title = {{Optimization of Cyclic Redundancy-Check Codes with 24
+ * and 32 Parity Bits}},
+ * journal = IEEE Transactions on Communication,
+ * year = {1993},
+ * volume = {41},
+ * number = {6},
+ * pages = {},
+ * month = {June},
+ *}
+ * Used by the iSCSI driver, possibly others, and derived from the
+ * the iscsi-crc.c module of the linux-iscsi driver at
+ * http://linux-iscsi.sourceforge.net.
+ *
+ * Following the example of lib/crc32, this function is intended to be
+ * flexible and useful for all users. Modules that currently have their
+ * own crc32c, but hopefully may be able to use this one are:
+ * net/sctp (please add all your doco to here if you change to
+ * use this one!)
+ * <endoflist>
+ *
+ * Copyright (c) 2003 Cisco Systems, 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/crc32c.h>
+#include <linux/module.h>
+#include <asm/byteorder.h>
+
+MODULE_AUTHOR("Clay Haapala <[email protected]>");
+MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations");
+MODULE_LICENSE("GPL");
+
+#if __GNUC__ >= 3 /* 2.x has "attribute", but only 3.0 has "pure */
+#define attribute(x) __attribute__(x)
+#else
+#define attribute(x)
+#endif
+
+#define CRC32C_POLY_BE 0x1EDC6F41
+#define CRC32C_POLY_LE 0x82F63B78
+
+#ifndef CRC_LE_BITS
+# define CRC_LE_BITS 8
+#endif
+
+
+/*
+ * Haven't generated a big-endian table yet, but the bit-wise version
+ * should at least work.
+ */
+#if defined CRC_BE_BITS && CRC_BE_BITS != 1
+#undef CRC_BE_BITS
+#endif
+#ifndef CRC_BE_BITS
+# define CRC_BE_BITS 1
+#endif
+
+EXPORT_SYMBOL(crc32c_le);
+
+#if CRC_LE_BITS == 1
+/*
+ * Compute things bit-wise, as done in crc32.c. We could share the tight
+ * loop below with crc32 and vary the POLY if we don't find value in terms
+ * of space and maintainability in keeping the two modules separate.
+ */
+u32 attribute((pure))
+crc32c_le(u32 crc, unsigned char const *p, size_t len)
+{
+ int i;
+ while (len--) {
+ crc ^= *p++;
+ for (i = 0; i < 8; i++)
+ crc = (crc >> 1) ^ ((crc & 1) ? CRC32C_POLY_LE : 0);
+ }
+ return crc;
+}
+#else
+
+/*
+ * This is the CRC-32C table
+ * Generated with:
+ * width = 32 bits
+ * poly = 0x1EDC6F41
+ * reflect input bytes = true
+ * reflect output bytes = true
+ */
+
+static u32 crc32c_table[256] = {
+ 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
+ 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
+ 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
+ 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
+ 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
+ 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
+ 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
+ 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
+ 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
+ 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
+ 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
+ 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
+ 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
+ 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
+ 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
+ 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
+ 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
+ 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
+ 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
+ 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
+ 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
+ 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
+ 0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
+ 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
+ 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
+ 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
+ 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
+ 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
+ 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
+ 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
+ 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
+ 0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
+ 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
+ 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
+ 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
+ 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
+ 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
+ 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
+ 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
+ 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
+ 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
+ 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
+ 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
+ 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
+ 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
+ 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
+ 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
+ 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
+ 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
+ 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
+ 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
+ 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
+ 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
+ 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
+ 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
+ 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
+ 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
+ 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
+ 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
+ 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
+ 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
+ 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
+ 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
+ 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
+};
+
+/*
+ * Steps through buffer one byte at at time, calculates reflected
+ * crc using table.
+ */
+
+u32 attribute((pure))
+crc32c_le(u32 seed, unsigned char const *data, size_t length)
+{
+ u32 crc = __cpu_to_le32(seed);
+
+ while (length--)
+ crc =
+ crc32c_table[(crc ^ *data++) & 0xFFL] ^ (crc >> 8);
+
+ return __le32_to_cpu(crc);
+}
+
+#endif /* CRC_LE_BITS == 8 */
+
+/*EXPORT_SYMBOL(crc32c_be);*/
+
+#if CRC_BE_BITS == 1
+u32 attribute((pure))
+crc32_be(u32 crc, unsigned char const *p, size_t len)
+{
+ int i;
+ while (len--) {
+ crc ^= *p++ << 24;
+ for (i = 0; i < 8; i++)
+ crc =
+ (crc << 1) ^ ((crc & 0x80000000) ? CRC32C_POLY_BE :
+ 0);
+ }
+ return crc;
+}
+#endif
+
+/*
+ * Unit test
+ *
+ * A small unit test suite is implemented as part of the crypto suite.
+ * Select CRYPTO_CRC32C and use the tcrypt module to run the tests.
+ */
diff -urN linux-2.6.4.orig/lib/Makefile linux/lib/Makefile
--- linux-2.6.4.orig/lib/Makefile 2004-03-10 20:55:21.000000000 -0600
+++ linux/lib/Makefile 2004-03-18 15:59:55.000000000 -0600
@@ -16,6 +16,7 @@
endif

obj-$(CONFIG_CRC32) += crc32.o
+obj-$(CONFIG_LIBCRC32C) += libcrc32c.o

obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/
obj-$(CONFIG_ZLIB_DEFLATE) += zlib_deflate/

2004-03-22 16:57:12

by Clay Haapala

[permalink] [raw]
Subject: [PATCH] crypto/crc32c support

This patch agains 2.6.4 kernel code implements the CRC32C checksum/crc
algorithm as an additional type of digest. The implementation is a
wrapper for routines found under lib/libcrc32c, available in another
patch.

This crypto patch requires the digest setkey() interface implemented
by Jouni Malinen <[email protected]>, and supercedes an earlier patch
that implemented chksum as an additional CRYPTO_ALG_TYPE.

The immediate customer of these routines is the linux-iscsi driver,
currently in review. Please see the linux-iscsi project on
SourceForge for details.

--
Clay Haapala ([email protected]) Cisco Systems SRBU +1 763-398-1056
6450 Wedgwood Rd, Suite 130 Maple Grove MN 55311 PGP: C89240AD
Of course the drugs advertised in all those emails are safe.
Show me the dead spammers!
(Please!)

diff -urN linux-2.6.4.orig/crypto/crc32c.c linux/crypto/crc32c.c
--- linux-2.6.4.orig/crypto/crc32c.c 1969-12-31 18:00:00.000000000 -0600
+++ linux/crypto/crc32c.c 2004-03-18 16:09:05.000000000 -0600
@@ -0,0 +1,110 @@
+/*
+ * Cryptographic API.
+ *
+ * CRC32C chksum
+ *
+ * This module file is a wrapper to invoke the lib/crc32c routines.
+ *
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/crypto.h>
+#include <linux/crc32c.h>
+#include <asm/byteorder.h>
+
+#define CHKSUM_BLOCK_SIZE 32
+#define CHKSUM_DIGEST_SIZE 4
+
+struct chksum_ctx {
+ u32 crc;
+};
+
+/*
+ * Steps through buffer one byte at at time, calculates reflected
+ * crc using table.
+ */
+
+static void chksum_init(void *ctx)
+{
+ struct chksum_ctx *mctx = ctx;
+
+ mctx->crc = ~(u32)0; /* common usage */
+}
+
+/*
+ * Setting the seed allows arbitrary accumulators and flexible XOR policy
+ * If your algorithm starts with ~0, then XOR with ~0 before you set
+ * the seed.
+ */
+static int chksum_setkey(void *ctx, const u8 *key, unsigned int keylen,
+ u32 *flags)
+{
+ struct chksum_ctx *mctx = ctx;
+
+ if (keylen != sizeof(mctx->crc)) {
+ if (flags)
+ *flags = CRYPTO_TFM_RES_BAD_KEY_LEN;
+ return -EINVAL;
+ }
+ mctx->crc = __cpu_to_le32(*(u32 *)key);
+ return 0;
+}
+
+static void chksum_update(void *ctx, const u8 *data, size_t length)
+{
+ struct chksum_ctx *mctx = ctx;
+ u32 mcrc;
+
+ mcrc = crc32c(mctx->crc, data, length);
+
+ mctx->crc = mcrc;
+}
+
+static void chksum_final(void *ctx, u8 *out)
+{
+ struct chksum_ctx *mctx = ctx;
+ u32 mcrc = (mctx->crc ^ ~(u32)0);
+
+ *(u32 *)out = __le32_to_cpu(mcrc);
+}
+
+static struct crypto_alg alg = {
+ .cra_name = "crc32c",
+ .cra_flags = CRYPTO_ALG_TYPE_DIGEST,
+ .cra_blocksize = CHKSUM_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct chksum_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(alg.cra_list),
+ .cra_u = {
+ .digest = {
+ .dia_digestsize= CHKSUM_DIGEST_SIZE,
+ .dia_setkey = chksum_setkey,
+ .dia_init = chksum_init,
+ .dia_update = chksum_update,
+ .dia_final = chksum_final
+ }
+ }
+};
+
+static int __init init(void)
+{
+ return crypto_register_alg(&alg);
+}
+
+static void __exit fini(void)
+{
+ crypto_unregister_alg(&alg);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_AUTHOR("Clay Haapala <[email protected]>");
+MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations wrapper for lib/crc32c");
+MODULE_LICENSE("GPL");
diff -urN linux-2.6.4.orig/crypto/Kconfig linux/crypto/Kconfig
--- linux-2.6.4.orig/crypto/Kconfig 2004-03-17 15:23:06.000000000 -0600
+++ linux/crypto/Kconfig 2004-03-18 15:24:57.000000000 -0600
@@ -170,6 +170,16 @@
should not be used for other purposes because of the weakness
of the algorithm.

+config CRYPTO_CRC32C
+ tristate "CRC32c CRC algorithm"
+ depends on CRYPTO
+ select LIBCRC32C
+ help
+ Castagnoli, et al Cyclic Redundancy-Check Algorithm. Used
+ by iSCSI for header and data digests and by others.
+ See Castagnoli93. This implementation uses lib/libcrc32c.
+ Module will be crc32c.
+
config CRYPTO_TEST
tristate "Testing module"
depends on CRYPTO
diff -urN linux-2.6.4.orig/crypto/Makefile linux/crypto/Makefile
--- linux-2.6.4.orig/crypto/Makefile 2004-03-17 15:23:06.000000000 -0600
+++ linux/crypto/Makefile 2004-03-18 15:44:54.000000000 -0600
@@ -24,5 +24,6 @@
obj-$(CONFIG_CRYPTO_ARC4) += arc4.o
obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o
obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
+obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o

obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
diff -urN linux-2.6.4.orig/crypto/tcrypt.c linux/crypto/tcrypt.c
--- linux-2.6.4.orig/crypto/tcrypt.c 2004-03-17 15:23:06.000000000 -0600
+++ linux/crypto/tcrypt.c 2004-03-18 16:36:41.000000000 -0600
@@ -61,7 +61,7 @@
static char *check[] = {
"des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
"twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6",
- "arc4", "michael_mic", "deflate", NULL
+ "arc4", "michael_mic", "deflate", "crc32c", NULL
};

static void
@@ -496,6 +496,107 @@
}

static void
+test_crc32c(void)
+{
+#define NUMVEC 6
+#define VECSIZE 40
+
+ int i, j, pass;
+ u32 crc;
+ u8 b, test_vec[NUMVEC][VECSIZE];
+ static u32 vec_results[NUMVEC] = {
+ 0x0e2c157f, 0xe980ebf6, 0xde74bded,
+ 0xd579c862, 0xba979ad0, 0x2b29d913
+ };
+ static u32 tot_vec_results = 0x24c5d375;
+
+ struct scatterlist sg[NUMVEC];
+ struct crypto_tfm *tfm;
+ char *fmtdata = "testing crc32c initialized to %08x: %s\n";
+#define SEEDTESTVAL 0xedcba987
+ u32 seed;
+
+ printk("\ntesting crc32c\n");
+
+ tfm = crypto_alloc_tfm("crc32c", 0);
+ if (tfm == NULL) {
+ printk("failed to load transform for crc32c\n");
+ return;
+ }
+
+ crypto_digest_init(tfm);
+ crypto_digest_final(tfm, (u8*)&crc);
+ printk(fmtdata, crc, (crc == 0) ? "pass" : "ERROR");
+
+ /*
+ * stuff test_vec with known values, simple incrementing
+ * byte values.
+ */
+ b = 0;
+ for (i = 0; i < NUMVEC; i++) {
+ for (j = 0; j < VECSIZE; j++)
+ test_vec[i][j] = ++b;
+ sg[i].page = virt_to_page(test_vec[i]);
+ sg[i].offset = offset_in_page(test_vec[i]);
+ sg[i].length = VECSIZE;
+ }
+
+ seed = SEEDTESTVAL;
+ (void)crypto_digest_setkey(tfm, (const u8*)&seed, sizeof(u32));
+ crypto_digest_final(tfm, (u8*)&crc);
+ printk("testing crc32c setkey returns %08x : %s\n", crc, (crc == (SEEDTESTVAL ^ ~(u32)0)) ?
+ "pass" : "ERROR");
+
+ printk("testing crc32c using update/final:\n");
+
+ pass = 1; /* assume all is well */
+
+ for (i = 0; i < NUMVEC; i++) {
+ seed = ~(u32)0;
+ (void)crypto_digest_setkey(tfm, (const u8*)&seed, sizeof(u32));
+ crypto_digest_update(tfm, &sg[i], 1);
+ crypto_digest_final(tfm, (u8*)&crc);
+ if (crc == vec_results[i]) {
+ printk(" %08x:OK", crc);
+ } else {
+ printk(" %08x:BAD, wanted %08x\n", crc, vec_results[i]);
+ pass = 0;
+ }
+ }
+
+ printk("\ntesting crc32c using incremental accumulator:\n");
+ crc = 0;
+ for (i = 0; i < NUMVEC; i++) {
+ seed = (crc ^ ~(u32)0);
+ (void)crypto_digest_setkey(tfm, (const u8*)&seed, sizeof(u32));
+ crypto_digest_update(tfm, &sg[i], 1);
+ crypto_digest_final(tfm, (u8*)&crc);
+ }
+ if (crc == tot_vec_results) {
+ printk(" %08x:OK", crc);
+ } else {
+ printk(" %08x:BAD, wanted %08x\n", crc, tot_vec_results);
+ pass = 0;
+ }
+
+ printk("\ntesting crc32c using digest:\n");
+ seed = ~(u32)0;
+ (void)crypto_digest_setkey(tfm, (const u8*)&seed, sizeof(u32));
+ crypto_digest_digest(tfm, sg, NUMVEC, (u8*)&crc);
+ if (crc == tot_vec_results) {
+ printk(" %08x:OK", crc);
+ } else {
+ printk(" %08x:BAD, wanted %08x\n", crc, tot_vec_results);
+ pass = 0;
+ }
+
+ printk("\n%s\n", pass ? "pass" : "ERROR");
+
+ crypto_free_tfm(tfm);
+ printk("crc32c test complete\n");
+}
+
+static void
test_available(void)
{
char **name = check;
@@ -566,7 +667,8 @@

test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS);
test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS);
- test_deflate();
+ test_deflate();
+ test_crc32c();
#ifdef CONFIG_CRYPTO_HMAC
test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS);
test_hmac("sha1", hmac_sha1_tv_template, HMAC_SHA1_TEST_VECTORS);
@@ -657,6 +759,10 @@
test_hash("michael_mic", michael_mic_tv_template, MICHAEL_MIC_TEST_VECTORS);
break;

+ case 18:
+ test_crc32c();
+ break;
+
#ifdef CONFIG_CRYPTO_HMAC
case 100:
test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS);

2004-03-22 17:00:26

by Jeff Garzik

[permalink] [raw]
Subject: Re: [PATCH] lib/libcrc32c implementation

Clay Haapala wrote:
> This patch agains 2.6.4 kernel code implements the CRC32C algorithm.
> The routines are based on the same design as the existing CRC32 code.
> Licensing is intended to be identical (GPL).
>
> The immediate customer of this code is the wrapper code in
> crypto/crc32c, available in another patch.


Why not call it 'crc32c' like its cousin crc32, rather than the
less-similar 'libcrc32c'? Violates the Principle of Least Surprise ;-)

Jeff



2004-03-22 17:27:59

by Clay Haapala

[permalink] [raw]
Subject: Re: [PATCH] lib/libcrc32c implementation

On Mon, 22 Mar 2004, Jeff Garzik spake thusly:
> Clay Haapala wrote:
>> This patch agains 2.6.4 kernel code implements the CRC32C
>> algorithm. The routines are based on the same design as the
>> existing CRC32 code. Licensing is intended to be identical (GPL).
>> The immediate customer of this code is the wrapper code in
>> crypto/crc32c, available in another patch.
>
>
> Why not call it 'crc32c' like its cousin crc32, rather than the
> less-similar 'libcrc32c'? Violates the Principle of Least Surprise
> ;-)
>
> Jeff

The module under crypto is call "crc32c", which would conflict, UIASM.

I'd entertain any reasonable naming. For a bit, undercrypto, I was
calling that module "crc32c_wrap", but that looked ugly, too, but
probably is more PLS-compliant. :-)
--
Clay Haapala ([email protected]) Cisco Systems SRBU +1 763-398-1056
6450 Wedgwood Rd, Suite 130 Maple Grove MN 55311 PGP: C89240AD
Of course the drugs advertised in all those emails are safe.
Show me the dead spammers!
(Please!)

2004-03-22 17:37:01

by Jeff Garzik

[permalink] [raw]
Subject: Re: [PATCH] lib/libcrc32c implementation

Clay Haapala wrote:
> On Mon, 22 Mar 2004, Jeff Garzik spake thusly:
>
>>Clay Haapala wrote:
>>
>>>This patch agains 2.6.4 kernel code implements the CRC32C
>>>algorithm. The routines are based on the same design as the
>>>existing CRC32 code. Licensing is intended to be identical (GPL).
>>>The immediate customer of this code is the wrapper code in
>>>crypto/crc32c, available in another patch.
>>
>>
>>Why not call it 'crc32c' like its cousin crc32, rather than the
>>less-similar 'libcrc32c'? Violates the Principle of Least Surprise
>>;-)
>>
>> Jeff
>
>
> The module under crypto is call "crc32c", which would conflict, UIASM.

Fair enough...

Jeff




2004-03-26 16:36:35

by James Morris

[permalink] [raw]
Subject: Re: [PATCH] lib/libcrc32c implementation

On Mon, 22 Mar 2004, Clay Haapala wrote:

> This patch agains 2.6.4 kernel code implements the CRC32C algorithm.
> The routines are based on the same design as the existing CRC32 code.
> Licensing is intended to be identical (GPL).

These need to be rediffed against the latest Linus kernel.

It may be better to wait until 2.6.5 comes out, so we don't have too much
new stuff going into the -rc kernels.


- James
--
James Morris
<[email protected]>


2004-03-26 16:59:18

by Clay Haapala

[permalink] [raw]
Subject: Re: [PATCH] lib/libcrc32c implementation

On Fri, 26 Mar 2004, James Morris verbalised:
> On Mon, 22 Mar 2004, Clay Haapala wrote:
>
>> This patch agains 2.6.4 kernel code implements the CRC32C
>> algorithm. The routines are based on the same design as the
>> existing CRC32 code. Licensing is intended to be identical (GPL).
>
> These need to be rediffed against the latest Linus kernel.
>
> It may be better to wait until 2.6.5 comes out, so we don't have too
> much new stuff going into the -rc kernels.
>
All right, I'll wait for the 2.6.5 announcement and submit a diff
against that. I assume that the code looks OK.

Thanks!
--
Clay Haapala ([email protected]) Cisco Systems SRBU +1 763-398-1056
6450 Wedgwood Rd, Suite 130 Maple Grove MN 55311 PGP: C89240AD
"Microsoft bans gnus on these premises."

2004-03-26 18:17:06

by James Morris

[permalink] [raw]
Subject: Re: [PATCH] lib/libcrc32c implementation

On Fri, 26 Mar 2004, Clay Haapala wrote:

> All right, I'll wait for the 2.6.5 announcement and submit a diff
> against that. I assume that the code looks OK.

Yep, looks fine to me, glad we can finally get this resolved.


- James
--
James Morris
<[email protected]>


2004-03-30 17:33:32

by Clay Haapala

[permalink] [raw]
Subject: [PATCH] lib/libcrc32c

On Fri, 26 Mar 2004, James Morris outgrape:
> These need to be rediffed against the latest Linus kernel.
>
> It may be better to wait until 2.6.5 comes out, so we don't have too
> much new stuff going into the -rc kernels.
>
>
> - James

Rediffed they are! I see that the digest setkey() api is already part
of -rc3, so because this code is a simple "add" and I will be
on vacation next week when 2.6.5 might be cut, I am providing the
patch now.

This patch agains 2.6.5-rc3 kernel code implements the CRC32C
algorithm. The routines are based on the same design as the
existing CRC32 code. Licensing is intended to be identical (GPL).
--
Clay Haapala ([email protected]) Cisco Systems SRBU +1 763-398-1056
6450 Wedgwood Rd, Suite 130 Maple Grove MN 55311 PGP: C89240AD
Dyslexia meets Concealed Carry laws:
"Microsoft bans gnus on these premises"

diff -uNr --exclude BitKeeper --exclude SCCS linus-2.6.5-rc3/include/linux/crc32c.h linux/include/linux/crc32c.h
--- linus-2.6.5-rc3/include/linux/crc32c.h 1969-12-31 18:00:00.000000000 -0600
+++ linux/include/linux/crc32c.h 2004-03-29 16:36:24.000000000 -0600
@@ -0,0 +1,11 @@
+#ifndef _LINUX_CRC32C_H
+#define _LINUX_CRC32C_H
+
+#include <linux/types.h>
+
+extern u32 crc32c_le(u32 crc, unsigned char const *address, size_t length);
+extern u32 crc32c_be(u32 crc, unsigned char const *address, size_t length);
+
+#define crc32c(seed, data, length) crc32c_le(seed, (unsigned char const *)data, length)
+
+#endif /* _LINUX_CRC32C_H */
diff -uNr --exclude BitKeeper --exclude SCCS linus-2.6.5-rc3/lib/Kconfig linux/lib/Kconfig
--- linus-2.6.5-rc3/lib/Kconfig 2004-03-29 15:30:22.000000000 -0600
+++ linux/lib/Kconfig 2004-03-29 16:36:24.000000000 -0600
@@ -12,6 +12,15 @@
kernel tree does. Such modules that use library CRC32 functions
require M here.

+config LIBCRC32C
+ tristate "CRC32c (Castagnoli, et al) Cyclic Redundancy-Check"
+ help
+ This option is provided for the case where no in-kernel-tree
+ modules require CRC32c functions, but a module built outside the
+ kernel tree does. Such modules that use library CRC32c functions
+ require M here. See Castagnoli93.
+ Module will be libcrc32c.
+
#
# compression support is select'ed if needed
#
diff -uNr --exclude BitKeeper --exclude SCCS linus-2.6.5-rc3/lib/libcrc32c.c linux/lib/libcrc32c.c
--- linus-2.6.5-rc3/lib/libcrc32c.c 1969-12-31 18:00:00.000000000 -0600
+++ linux/lib/libcrc32c.c 2004-03-29 16:36:24.000000000 -0600
@@ -0,0 +1,205 @@
+/*
+ * CRC32C
+ *@Article{castagnoli-crc,
+ * author = { Guy Castagnoli and Stefan Braeuer and Martin Herrman},
+ * title = {{Optimization of Cyclic Redundancy-Check Codes with 24
+ * and 32 Parity Bits}},
+ * journal = IEEE Transactions on Communication,
+ * year = {1993},
+ * volume = {41},
+ * number = {6},
+ * pages = {},
+ * month = {June},
+ *}
+ * Used by the iSCSI driver, possibly others, and derived from the
+ * the iscsi-crc.c module of the linux-iscsi driver at
+ * http://linux-iscsi.sourceforge.net.
+ *
+ * Following the example of lib/crc32, this function is intended to be
+ * flexible and useful for all users. Modules that currently have their
+ * own crc32c, but hopefully may be able to use this one are:
+ * net/sctp (please add all your doco to here if you change to
+ * use this one!)
+ * <endoflist>
+ *
+ * Copyright (c) 2003 Cisco Systems, 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/crc32c.h>
+#include <linux/module.h>
+#include <asm/byteorder.h>
+
+MODULE_AUTHOR("Clay Haapala <[email protected]>");
+MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations");
+MODULE_LICENSE("GPL");
+
+#if __GNUC__ >= 3 /* 2.x has "attribute", but only 3.0 has "pure */
+#define attribute(x) __attribute__(x)
+#else
+#define attribute(x)
+#endif
+
+#define CRC32C_POLY_BE 0x1EDC6F41
+#define CRC32C_POLY_LE 0x82F63B78
+
+#ifndef CRC_LE_BITS
+# define CRC_LE_BITS 8
+#endif
+
+
+/*
+ * Haven't generated a big-endian table yet, but the bit-wise version
+ * should at least work.
+ */
+#if defined CRC_BE_BITS && CRC_BE_BITS != 1
+#undef CRC_BE_BITS
+#endif
+#ifndef CRC_BE_BITS
+# define CRC_BE_BITS 1
+#endif
+
+EXPORT_SYMBOL(crc32c_le);
+
+#if CRC_LE_BITS == 1
+/*
+ * Compute things bit-wise, as done in crc32.c. We could share the tight
+ * loop below with crc32 and vary the POLY if we don't find value in terms
+ * of space and maintainability in keeping the two modules separate.
+ */
+u32 attribute((pure))
+crc32c_le(u32 crc, unsigned char const *p, size_t len)
+{
+ int i;
+ while (len--) {
+ crc ^= *p++;
+ for (i = 0; i < 8; i++)
+ crc = (crc >> 1) ^ ((crc & 1) ? CRC32C_POLY_LE : 0);
+ }
+ return crc;
+}
+#else
+
+/*
+ * This is the CRC-32C table
+ * Generated with:
+ * width = 32 bits
+ * poly = 0x1EDC6F41
+ * reflect input bytes = true
+ * reflect output bytes = true
+ */
+
+static u32 crc32c_table[256] = {
+ 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
+ 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
+ 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
+ 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
+ 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
+ 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
+ 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
+ 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
+ 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
+ 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
+ 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
+ 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
+ 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
+ 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
+ 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
+ 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
+ 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
+ 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
+ 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
+ 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
+ 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
+ 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
+ 0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
+ 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
+ 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
+ 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
+ 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
+ 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
+ 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
+ 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
+ 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
+ 0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
+ 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
+ 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
+ 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
+ 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
+ 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
+ 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
+ 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
+ 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
+ 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
+ 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
+ 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
+ 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
+ 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
+ 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
+ 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
+ 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
+ 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
+ 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
+ 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
+ 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
+ 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
+ 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
+ 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
+ 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
+ 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
+ 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
+ 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
+ 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
+ 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
+ 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
+ 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
+ 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
+};
+
+/*
+ * Steps through buffer one byte at at time, calculates reflected
+ * crc using table.
+ */
+
+u32 attribute((pure))
+crc32c_le(u32 seed, unsigned char const *data, size_t length)
+{
+ u32 crc = __cpu_to_le32(seed);
+
+ while (length--)
+ crc =
+ crc32c_table[(crc ^ *data++) & 0xFFL] ^ (crc >> 8);
+
+ return __le32_to_cpu(crc);
+}
+
+#endif /* CRC_LE_BITS == 8 */
+
+/*EXPORT_SYMBOL(crc32c_be);*/
+
+#if CRC_BE_BITS == 1
+u32 attribute((pure))
+crc32_be(u32 crc, unsigned char const *p, size_t len)
+{
+ int i;
+ while (len--) {
+ crc ^= *p++ << 24;
+ for (i = 0; i < 8; i++)
+ crc =
+ (crc << 1) ^ ((crc & 0x80000000) ? CRC32C_POLY_BE :
+ 0);
+ }
+ return crc;
+}
+#endif
+
+/*
+ * Unit test
+ *
+ * A small unit test suite is implemented as part of the crypto suite.
+ * Select CRYPTO_CRC32C and use the tcrypt module to run the tests.
+ */
diff -uNr --exclude BitKeeper --exclude SCCS linus-2.6.5-rc3/lib/Makefile linux/lib/Makefile
--- linus-2.6.5-rc3/lib/Makefile 2004-03-29 15:30:22.000000000 -0600
+++ linux/lib/Makefile 2004-03-29 16:36:24.000000000 -0600
@@ -19,6 +19,7 @@
endif

obj-$(CONFIG_CRC32) += crc32.o
+obj-$(CONFIG_LIBCRC32C) += libcrc32c.o

obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/
obj-$(CONFIG_ZLIB_DEFLATE) += zlib_deflate/

2004-03-30 17:42:30

by Clay Haapala

[permalink] [raw]
Subject: [PATCH] crypto/crc32c implementation

This patch agains 2.6.5-rc3 implements the CRC32C algorithm as a type
of digest. It is implemented as a wrapper for libcrc32c, available in
a separate patch. The crypto CRC32C module will be used by the
iscsi-sfnet driver.

As I may be on vacation when 2.6.5 is cut, and this code is an "add",
I thought it best to provide the patch now.
--
Clay Haapala ([email protected]) Cisco Systems SRBU +1 763-398-1056
6450 Wedgwood Rd, Suite 130 Maple Grove MN 55311 PGP: C89240AD
Dyslexia meets Concealed Carry laws:
"Microsoft bans gnus on these premises"

diff -uNr --exclude BitKeeper --exclude SCCS linus-2.6.5-rc3/crypto/crc32c.c linux/crypto/crc32c.c
--- linus-2.6.5-rc3/crypto/crc32c.c 1969-12-31 18:00:00.000000000 -0600
+++ linux/crypto/crc32c.c 2004-03-29 16:36:04.000000000 -0600
@@ -0,0 +1,110 @@
+/*
+ * Cryptographic API.
+ *
+ * CRC32C chksum
+ *
+ * This module file is a wrapper to invoke the lib/crc32c routines.
+ *
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/crypto.h>
+#include <linux/crc32c.h>
+#include <asm/byteorder.h>
+
+#define CHKSUM_BLOCK_SIZE 32
+#define CHKSUM_DIGEST_SIZE 4
+
+struct chksum_ctx {
+ u32 crc;
+};
+
+/*
+ * Steps through buffer one byte at at time, calculates reflected
+ * crc using table.
+ */
+
+static void chksum_init(void *ctx)
+{
+ struct chksum_ctx *mctx = ctx;
+
+ mctx->crc = ~(u32)0; /* common usage */
+}
+
+/*
+ * Setting the seed allows arbitrary accumulators and flexible XOR policy
+ * If your algorithm starts with ~0, then XOR with ~0 before you set
+ * the seed.
+ */
+static int chksum_setkey(void *ctx, const u8 *key, unsigned int keylen,
+ u32 *flags)
+{
+ struct chksum_ctx *mctx = ctx;
+
+ if (keylen != sizeof(mctx->crc)) {
+ if (flags)
+ *flags = CRYPTO_TFM_RES_BAD_KEY_LEN;
+ return -EINVAL;
+ }
+ mctx->crc = __cpu_to_le32(*(u32 *)key);
+ return 0;
+}
+
+static void chksum_update(void *ctx, const u8 *data, size_t length)
+{
+ struct chksum_ctx *mctx = ctx;
+ u32 mcrc;
+
+ mcrc = crc32c(mctx->crc, data, length);
+
+ mctx->crc = mcrc;
+}
+
+static void chksum_final(void *ctx, u8 *out)
+{
+ struct chksum_ctx *mctx = ctx;
+ u32 mcrc = (mctx->crc ^ ~(u32)0);
+
+ *(u32 *)out = __le32_to_cpu(mcrc);
+}
+
+static struct crypto_alg alg = {
+ .cra_name = "crc32c",
+ .cra_flags = CRYPTO_ALG_TYPE_DIGEST,
+ .cra_blocksize = CHKSUM_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct chksum_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(alg.cra_list),
+ .cra_u = {
+ .digest = {
+ .dia_digestsize= CHKSUM_DIGEST_SIZE,
+ .dia_setkey = chksum_setkey,
+ .dia_init = chksum_init,
+ .dia_update = chksum_update,
+ .dia_final = chksum_final
+ }
+ }
+};
+
+static int __init init(void)
+{
+ return crypto_register_alg(&alg);
+}
+
+static void __exit fini(void)
+{
+ crypto_unregister_alg(&alg);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_AUTHOR("Clay Haapala <[email protected]>");
+MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations wrapper for lib/crc32c");
+MODULE_LICENSE("GPL");
diff -uNr --exclude BitKeeper --exclude SCCS linus-2.6.5-rc3/crypto/Kconfig linux/crypto/Kconfig
--- linus-2.6.5-rc3/crypto/Kconfig 2004-03-29 15:29:29.000000000 -0600
+++ linux/crypto/Kconfig 2004-03-29 16:36:04.000000000 -0600
@@ -170,6 +170,16 @@
should not be used for other purposes because of the weakness
of the algorithm.

+config CRYPTO_CRC32C
+ tristate "CRC32c CRC algorithm"
+ depends on CRYPTO
+ select LIBCRC32C
+ help
+ Castagnoli, et al Cyclic Redundancy-Check Algorithm. Used
+ by iSCSI for header and data digests and by others.
+ See Castagnoli93. This implementation uses lib/libcrc32c.
+ Module will be crc32c.
+
config CRYPTO_TEST
tristate "Testing module"
depends on CRYPTO
diff -uNr --exclude BitKeeper --exclude SCCS linus-2.6.5-rc3/crypto/Makefile linux/crypto/Makefile
--- linus-2.6.5-rc3/crypto/Makefile 2004-03-29 15:29:29.000000000 -0600
+++ linux/crypto/Makefile 2004-03-29 16:36:04.000000000 -0600
@@ -24,5 +24,6 @@
obj-$(CONFIG_CRYPTO_ARC4) += arc4.o
obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o
obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
+obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o

obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
diff -uNr --exclude BitKeeper --exclude SCCS linus-2.6.5-rc3/crypto/tcrypt.c linux/crypto/tcrypt.c
--- linus-2.6.5-rc3/crypto/tcrypt.c 2004-03-29 15:29:30.000000000 -0600
+++ linux/crypto/tcrypt.c 2004-03-29 16:36:04.000000000 -0600
@@ -61,7 +61,7 @@
static char *check[] = {
"des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
"twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6",
- "arc4", "michael_mic", "deflate", NULL
+ "arc4", "michael_mic", "deflate", "crc32c", NULL
};

static void
@@ -496,6 +496,107 @@
}

static void
+test_crc32c(void)
+{
+#define NUMVEC 6
+#define VECSIZE 40
+
+ int i, j, pass;
+ u32 crc;
+ u8 b, test_vec[NUMVEC][VECSIZE];
+ static u32 vec_results[NUMVEC] = {
+ 0x0e2c157f, 0xe980ebf6, 0xde74bded,
+ 0xd579c862, 0xba979ad0, 0x2b29d913
+ };
+ static u32 tot_vec_results = 0x24c5d375;
+
+ struct scatterlist sg[NUMVEC];
+ struct crypto_tfm *tfm;
+ char *fmtdata = "testing crc32c initialized to %08x: %s\n";
+#define SEEDTESTVAL 0xedcba987
+ u32 seed;
+
+ printk("\ntesting crc32c\n");
+
+ tfm = crypto_alloc_tfm("crc32c", 0);
+ if (tfm == NULL) {
+ printk("failed to load transform for crc32c\n");
+ return;
+ }
+
+ crypto_digest_init(tfm);
+ crypto_digest_final(tfm, (u8*)&crc);
+ printk(fmtdata, crc, (crc == 0) ? "pass" : "ERROR");
+
+ /*
+ * stuff test_vec with known values, simple incrementing
+ * byte values.
+ */
+ b = 0;
+ for (i = 0; i < NUMVEC; i++) {
+ for (j = 0; j < VECSIZE; j++)
+ test_vec[i][j] = ++b;
+ sg[i].page = virt_to_page(test_vec[i]);
+ sg[i].offset = offset_in_page(test_vec[i]);
+ sg[i].length = VECSIZE;
+ }
+
+ seed = SEEDTESTVAL;
+ (void)crypto_digest_setkey(tfm, (const u8*)&seed, sizeof(u32));
+ crypto_digest_final(tfm, (u8*)&crc);
+ printk("testing crc32c setkey returns %08x : %s\n", crc, (crc == (SEEDTESTVAL ^ ~(u32)0)) ?
+ "pass" : "ERROR");
+
+ printk("testing crc32c using update/final:\n");
+
+ pass = 1; /* assume all is well */
+
+ for (i = 0; i < NUMVEC; i++) {
+ seed = ~(u32)0;
+ (void)crypto_digest_setkey(tfm, (const u8*)&seed, sizeof(u32));
+ crypto_digest_update(tfm, &sg[i], 1);
+ crypto_digest_final(tfm, (u8*)&crc);
+ if (crc == vec_results[i]) {
+ printk(" %08x:OK", crc);
+ } else {
+ printk(" %08x:BAD, wanted %08x\n", crc, vec_results[i]);
+ pass = 0;
+ }
+ }
+
+ printk("\ntesting crc32c using incremental accumulator:\n");
+ crc = 0;
+ for (i = 0; i < NUMVEC; i++) {
+ seed = (crc ^ ~(u32)0);
+ (void)crypto_digest_setkey(tfm, (const u8*)&seed, sizeof(u32));
+ crypto_digest_update(tfm, &sg[i], 1);
+ crypto_digest_final(tfm, (u8*)&crc);
+ }
+ if (crc == tot_vec_results) {
+ printk(" %08x:OK", crc);
+ } else {
+ printk(" %08x:BAD, wanted %08x\n", crc, tot_vec_results);
+ pass = 0;
+ }
+
+ printk("\ntesting crc32c using digest:\n");
+ seed = ~(u32)0;
+ (void)crypto_digest_setkey(tfm, (const u8*)&seed, sizeof(u32));
+ crypto_digest_digest(tfm, sg, NUMVEC, (u8*)&crc);
+ if (crc == tot_vec_results) {
+ printk(" %08x:OK", crc);
+ } else {
+ printk(" %08x:BAD, wanted %08x\n", crc, tot_vec_results);
+ pass = 0;
+ }
+
+ printk("\n%s\n", pass ? "pass" : "ERROR");
+
+ crypto_free_tfm(tfm);
+ printk("crc32c test complete\n");
+}
+
+static void
test_available(void)
{
char **name = check;
@@ -566,7 +667,8 @@

test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS);
test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS);
- test_deflate();
+ test_deflate();
+ test_crc32c();
#ifdef CONFIG_CRYPTO_HMAC
test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS);
test_hmac("sha1", hmac_sha1_tv_template, HMAC_SHA1_TEST_VECTORS);
@@ -657,6 +759,10 @@
test_hash("michael_mic", michael_mic_tv_template, MICHAEL_MIC_TEST_VECTORS);
break;

+ case 18:
+ test_crc32c();
+ break;
+
#ifdef CONFIG_CRYPTO_HMAC
case 100:
test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS);

Subject: Re: [PATCH] lib/libcrc32c


Hi,

On Tuesday 30 of March 2004 19:32, Clay Haapala wrote:
> On Fri, 26 Mar 2004, James Morris outgrape:
> > These need to be rediffed against the latest Linus kernel.
> >
> > It may be better to wait until 2.6.5 comes out, so we don't have too
> > much new stuff going into the -rc kernels.
> >
> >
> > - James
>
> Rediffed they are! I see that the digest setkey() api is already part
> of -rc3, so because this code is a simple "add" and I will be
> on vacation next week when 2.6.5 might be cut, I am providing the
> patch now.
>
> This patch agains 2.6.5-rc3 kernel code implements the CRC32C
> algorithm. The routines are based on the same design as the
> existing CRC32 code. Licensing is intended to be identical (GPL).

+/*
+ * This is the CRC-32C table
+ * Generated with:
+ * width = 32 bits
+ * poly = 0x1EDC6F41
+ * reflect input bytes = true
+ * reflect output bytes = true
+ */
+
+static u32 crc32c_table[256] = {

Tables are build time generated in case of CRC32 (lib/gen_crc32table.c)
so you can trade some performance for smaller size of the table.

[ However I don't know how useful is this. ]

+/*EXPORT_SYMBOL(crc32c_be);*/
+
+#if CRC_BE_BITS == 1
+u32 attribute((pure))
+crc32_be(u32 crc, unsigned char const *p, size_t len)
+{
+ int i;
+ while (len--) {
+ crc ^= *p++ << 24;
+ for (i = 0; i < 8; i++)
+ crc =
+ (crc << 1) ^ ((crc & 0x80000000) ? CRC32C_POLY_BE :
+ 0);
+ }
+ return crc;
+}
+#endif

Is there any reason in adding crc32_be() until it is finished
(LE version) and/or needed?

Regards,
Bartlomiej

2004-03-30 19:16:28

by Clay Haapala

[permalink] [raw]
Subject: Re: [PATCH] lib/libcrc32c

On Tue, 30 Mar 2004, Bartlomiej Zolnierkiewicz outgrape:
> +
> +static u32 crc32c_table[256] = {
>
> Tables are build time generated in case of CRC32
> (lib/gen_crc32table.c) so you can trade some performance for smaller
> size of the table.
>
> [ However I don't know how useful is this. ]
>
As the table was statically in code in sctp and in the iSCSI driver
where it originally came from, I left it that way. Why would the
table be of a different size?

> +/*EXPORT_SYMBOL(crc32c_be);*/
> +
> +#if CRC_BE_BITS == 1 u32 attribute((pure)) crc32_be(u32 crc,
> +unsigned char const *p, size_t len) { int i; while (len--) { crc ^=
> +*p++ << 24; for (i = 0; i < 8; i++) crc = (crc << 1) ^ ((crc &
> +0x80000000) ? CRC32C_POLY_BE : 0);
> + }
> + return crc;
> +}
> +#endif
>
> Is there any reason in adding crc32_be() until it is finished
> (LE version) and/or needed?
>
> Regards,
> Bartlomiej

I judged the few lines of code needed to do the non-table version was
worth the bloat to include for completeness.
--
Clay Haapala ([email protected]) Cisco Systems SRBU +1 763-398-1056
6450 Wedgwood Rd, Suite 130 Maple Grove MN 55311 PGP: C89240AD
Dyslexia meets Concealed Carry laws:
"Microsoft bans gnus on these premises"

2004-03-30 19:25:12

by Matt Domsch

[permalink] [raw]
Subject: Re: [PATCH] lib/libcrc32c

On Tue, Mar 30, 2004 at 01:11:41PM -0600, Clay Haapala wrote:
> > +#if CRC_BE_BITS == 1
> > u32 attribute((pure)) crc32_be(u32 crc,

Shouldn't this be crc32c_bc() instead?

--
Matt Domsch
Sr. Software Engineer, Lead Engineer
Dell Linux Solutions linux.dell.com & http://www.dell.com/linux
Linux on Dell mailing lists @ http://lists.us.dell.com

2004-03-30 19:33:57

by Clay Haapala

[permalink] [raw]
Subject: Re: [PATCH] lib/libcrc32c

On Tue, 30 Mar 2004, Matt Domsch told this:
> On Tue, Mar 30, 2004 at 01:11:41PM -0600, Clay Haapala wrote:
>> > +#if CRC_BE_BITS == 1
>> > u32 attribute((pure)) crc32_be(u32 crc,
>
> Shouldn't this be crc32c_bc() instead?

Good catch! But rather crc32c_be(), I think.

Maybe I should just take the code out -- there are no current users.
--
Clay Haapala ([email protected]) Cisco Systems SRBU +1 763-398-1056
6450 Wedgwood Rd, Suite 130 Maple Grove MN 55311 PGP: C89240AD
Dyslexia meets Concealed Carry laws:
"Microsoft bans gnus on these premises"

Subject: Re: [PATCH] lib/libcrc32c

On Tuesday 30 of March 2004 21:11, Clay Haapala wrote:
> On Tue, 30 Mar 2004, Bartlomiej Zolnierkiewicz outgrape:
> > +
> > +static u32 crc32c_table[256] = {
> >
> > Tables are build time generated in case of CRC32
> > (lib/gen_crc32table.c) so you can trade some performance for smaller
> > size of the table.
> >
> > [ However I don't know how useful is this. ]
>
> As the table was statically in code in sctp and in the iSCSI driver
> where it originally came from, I left it that way. Why would the
> table be of a different size?

See lib/crc32defs.h and lib/gen_crc32table.c.

lib/crc32defs.h:

/* How many bits at a time to use. Requires a table of 4<<CRC_xx_BITS bytes. */
/* For less performance-sensitive, use 4 */
#ifndef CRC_LE_BITS
# define CRC_LE_BITS 8
#endif
#ifndef CRC_BE_BITS
# define CRC_BE_BITS 8
#endif

lib/gen_crc32table.c:

#define LE_TABLE_SIZE (1 << CRC_LE_BITS)
#define BE_TABLE_SIZE (1 << CRC_BE_BITS)

static u_int32_t crc32table_le[LE_TABLE_SIZE];
static u_int32_t crc32table_be[BE_TABLE_SIZE];


Regards,
Bartlomiej

2004-03-31 15:59:07

by Clay Haapala

[permalink] [raw]
Subject: Re: [PATCH] lib/libcrc32c

On Tue, 30 Mar 2004, Bartlomiej Zolnierkiewicz told this:

> On Tuesday 30 of March 2004 21:11, Clay Haapala wrote:
>> On Tue, 30 Mar 2004, Bartlomiej Zolnierkiewicz outgrape:
>> > +
>> > +static u32 crc32c_table[256] = {
>> >
>> > Tables are build time generated in case of CRC32
>> > (lib/gen_crc32table.c) so you can trade some performance for
>> > smaller size of the table.
>> >
>> > [ However I don't know how useful is this. ]
>>
>> As the table was statically in code in sctp and in the iSCSI driver
>> where it originally came from, I left it that way. Why would the
>> table be of a different size?
>
> See lib/crc32defs.h and lib/gen_crc32table.c.
>
> lib/crc32defs.h:
>
> /* How many bits at a time to use. Requires a table of
> 4<<CRC_xx_BITS bytes. */ /* For less performance-sensitive, use 4 */
> #ifndef CRC_LE_BITS # define CRC_LE_BITS 8 #endif #ifndef
> CRC_BE_BITS # define CRC_BE_BITS 8 #endif
>
> lib/gen_crc32table.c:
>
> #define LE_TABLE_SIZE (1 << CRC_LE_BITS)
> #define BE_TABLE_SIZE (1 << CRC_BE_BITS)
>
> static u_int32_t crc32table_le[LE_TABLE_SIZE];
> static u_int32_t crc32table_be[BE_TABLE_SIZE];
>
>
This is a legitimate question.

The immediate user of this crc32c is the iscsi-sfnet driver, and my
mind-set for that is always towards gigabit-ethernet wire-rate, so
that bias may prevent me from making the right choice here.

Regarding performance vs. size, we have the BITS == 8 table for "high"
performance and bigger size, and BITS == 1 bit-wise computation, for the
least size, albeit slower performance. Is that good enough?

The last time I wrote CRC lookup code for nibble-sized tables, it was
for an 8051 microcontroller. :-)
--
Clay Haapala ([email protected]) Cisco Systems SRBU +1 763-398-1056
6450 Wedgwood Rd, Suite 130 Maple Grove MN 55311 PGP: C89240AD
Dyslexia meets Concealed Carry laws:
"Microsoft bans gnus on these premises"

2004-03-31 21:04:30

by Clay Haapala

[permalink] [raw]
Subject: [PATCH] lib/libcrc32c, revised 040331

On Tue, 30 Mar 2004, Matt Domsch verbalised:
> On Tue, Mar 30, 2004 at 01:11:41PM -0600, Clay Haapala wrote:
>> > +#if CRC_BE_BITS == 1
>> > u32 attribute((pure)) crc32_be(u32 crc,
>
> Shouldn't this be crc32c_bc() instead?

Below is the corrected patch with crc32c_be() declared correctly.
We can still debate whether it should be included, but at least that's
right now.

--
Clay Haapala ([email protected]) Cisco Systems SRBU +1 763-398-1056
6450 Wedgwood Rd, Suite 130 Maple Grove MN 55311 PGP: C89240AD
Dyslexia meets Concealed Carry laws:
"Microsoft bans gnus on these premises"

--- linus-2.6.5-rc3/include/linux/crc32c.h 1969-12-31 18:00:00.000000000 -0600
+++ linux/include/linux/crc32c.h 2004-03-29 16:36:24.000000000 -0600
@@ -0,0 +1,11 @@
+#ifndef _LINUX_CRC32C_H
+#define _LINUX_CRC32C_H
+
+#include <linux/types.h>
+
+extern u32 crc32c_le(u32 crc, unsigned char const *address, size_t length);
+extern u32 crc32c_be(u32 crc, unsigned char const *address, size_t length);
+
+#define crc32c(seed, data, length) crc32c_le(seed, (unsigned char const *)data, length)
+
+#endif /* _LINUX_CRC32C_H */
--- linus-2.6.5-rc3/lib/Kconfig 2004-03-29 15:30:22.000000000 -0600
+++ linux/lib/Kconfig 2004-03-29 16:36:24.000000000 -0600
@@ -12,6 +12,15 @@
kernel tree does. Such modules that use library CRC32 functions
require M here.

+config LIBCRC32C
+ tristate "CRC32c (Castagnoli, et al) Cyclic Redundancy-Check"
+ help
+ This option is provided for the case where no in-kernel-tree
+ modules require CRC32c functions, but a module built outside the
+ kernel tree does. Such modules that use library CRC32c functions
+ require M here. See Castagnoli93.
+ Module will be libcrc32c.
+
#
# compression support is select'ed if needed
#
--- linus-2.6.5-rc3/lib/libcrc32c.c 1969-12-31 18:00:00.000000000 -0600
+++ linux/lib/libcrc32c.c 2004-03-31 14:52:05.000000000 -0600
@@ -0,0 +1,205 @@
+/*
+ * CRC32C
+ *@Article{castagnoli-crc,
+ * author = { Guy Castagnoli and Stefan Braeuer and Martin Herrman},
+ * title = {{Optimization of Cyclic Redundancy-Check Codes with 24
+ * and 32 Parity Bits}},
+ * journal = IEEE Transactions on Communication,
+ * year = {1993},
+ * volume = {41},
+ * number = {6},
+ * pages = {},
+ * month = {June},
+ *}
+ * Used by the iSCSI driver, possibly others, and derived from the
+ * the iscsi-crc.c module of the linux-iscsi driver at
+ * http://linux-iscsi.sourceforge.net.
+ *
+ * Following the example of lib/crc32, this function is intended to be
+ * flexible and useful for all users. Modules that currently have their
+ * own crc32c, but hopefully may be able to use this one are:
+ * net/sctp (please add all your doco to here if you change to
+ * use this one!)
+ * <endoflist>
+ *
+ * Copyright (c) 2004 Cisco Systems, 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/crc32c.h>
+#include <linux/module.h>
+#include <asm/byteorder.h>
+
+MODULE_AUTHOR("Clay Haapala <[email protected]>");
+MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations");
+MODULE_LICENSE("GPL");
+
+#if __GNUC__ >= 3 /* 2.x has "attribute", but only 3.0 has "pure */
+#define attribute(x) __attribute__(x)
+#else
+#define attribute(x)
+#endif
+
+#define CRC32C_POLY_BE 0x1EDC6F41
+#define CRC32C_POLY_LE 0x82F63B78
+
+#ifndef CRC_LE_BITS
+# define CRC_LE_BITS 8
+#endif
+
+
+/*
+ * Haven't generated a big-endian table yet, but the bit-wise version
+ * should at least work.
+ */
+#if defined CRC_BE_BITS && CRC_BE_BITS != 1
+#undef CRC_BE_BITS
+#endif
+#ifndef CRC_BE_BITS
+# define CRC_BE_BITS 1
+#endif
+
+EXPORT_SYMBOL(crc32c_le);
+
+#if CRC_LE_BITS == 1
+/*
+ * Compute things bit-wise, as done in crc32.c. We could share the tight
+ * loop below with crc32 and vary the POLY if we don't find value in terms
+ * of space and maintainability in keeping the two modules separate.
+ */
+u32 attribute((pure))
+crc32c_le(u32 crc, unsigned char const *p, size_t len)
+{
+ int i;
+ while (len--) {
+ crc ^= *p++;
+ for (i = 0; i < 8; i++)
+ crc = (crc >> 1) ^ ((crc & 1) ? CRC32C_POLY_LE : 0);
+ }
+ return crc;
+}
+#else
+
+/*
+ * This is the CRC-32C table
+ * Generated with:
+ * width = 32 bits
+ * poly = 0x1EDC6F41
+ * reflect input bytes = true
+ * reflect output bytes = true
+ */
+
+static u32 crc32c_table[256] = {
+ 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
+ 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
+ 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
+ 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
+ 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
+ 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
+ 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
+ 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
+ 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
+ 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
+ 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
+ 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
+ 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
+ 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
+ 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
+ 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
+ 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
+ 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
+ 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
+ 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
+ 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
+ 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
+ 0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
+ 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
+ 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
+ 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
+ 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
+ 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
+ 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
+ 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
+ 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
+ 0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
+ 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
+ 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
+ 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
+ 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
+ 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
+ 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
+ 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
+ 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
+ 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
+ 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
+ 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
+ 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
+ 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
+ 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
+ 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
+ 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
+ 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
+ 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
+ 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
+ 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
+ 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
+ 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
+ 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
+ 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
+ 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
+ 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
+ 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
+ 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
+ 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
+ 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
+ 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
+ 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
+};
+
+/*
+ * Steps through buffer one byte at at time, calculates reflected
+ * crc using table.
+ */
+
+u32 attribute((pure))
+crc32c_le(u32 seed, unsigned char const *data, size_t length)
+{
+ u32 crc = __cpu_to_le32(seed);
+
+ while (length--)
+ crc =
+ crc32c_table[(crc ^ *data++) & 0xFFL] ^ (crc >> 8);
+
+ return __le32_to_cpu(crc);
+}
+
+#endif /* CRC_LE_BITS == 8 */
+
+EXPORT_SYMBOL(crc32c_be);
+
+#if CRC_BE_BITS == 1
+u32 attribute((pure))
+crc32c_be(u32 crc, unsigned char const *p, size_t len)
+{
+ int i;
+ while (len--) {
+ crc ^= *p++ << 24;
+ for (i = 0; i < 8; i++)
+ crc =
+ (crc << 1) ^ ((crc & 0x80000000) ? CRC32C_POLY_BE :
+ 0);
+ }
+ return crc;
+}
+#endif
+
+/*
+ * Unit test
+ *
+ * A small unit test suite is implemented as part of the crypto suite.
+ * Select CRYPTO_CRC32C and use the tcrypt module to run the tests.
+ */
--- linus-2.6.5-rc3/lib/Makefile 2004-03-29 15:30:22.000000000 -0600
+++ linux/lib/Makefile 2004-03-29 16:36:24.000000000 -0600
@@ -19,6 +19,7 @@
endif

obj-$(CONFIG_CRC32) += crc32.o
+obj-$(CONFIG_LIBCRC32C) += libcrc32c.o

obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/
obj-$(CONFIG_ZLIB_DEFLATE) += zlib_deflate/

2004-04-19 21:32:23

by Clay Haapala

[permalink] [raw]
Subject: [PATCH] crypto/crc32c implementation, updated 040419

This patch agains 2.6.6-rc1-bk implements the CRC32C algorithm as a
type of digest. It is implemented as a wrapper for libcrc32c,
available in a separate patch. The crypto CRC32C module will be
used by the iscsi-sfnet driver.

--
Clay Haapala ([email protected]) Cisco Systems SRBU +1 763-398-1056
6450 Wedgwood Rd, Suite 130 Maple Grove MN 55311 PGP: C89240AD
If, for the sake of keeping Americans from dying, the
liberties for which Americans have fought and died are infringed,
who has won?

diff -ruN --exclude='*.orig' --exclude=SCCS --exclude=BitKeeper linux-2.6.6-rc1-bk.orig/crypto/crc32c.c linux-2.6.6-rc1/crypto/crc32c.c
--- linux-2.6.6-rc1-bk.orig/crypto/crc32c.c 1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.6-rc1/crypto/crc32c.c 2004-04-19 16:17:57.000000000 -0500
@@ -0,0 +1,110 @@
+/*
+ * Cryptographic API.
+ *
+ * CRC32C chksum
+ *
+ * This module file is a wrapper to invoke the lib/crc32c routines.
+ *
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/crypto.h>
+#include <linux/crc32c.h>
+#include <asm/byteorder.h>
+
+#define CHKSUM_BLOCK_SIZE 32
+#define CHKSUM_DIGEST_SIZE 4
+
+struct chksum_ctx {
+ u32 crc;
+};
+
+/*
+ * Steps through buffer one byte at at time, calculates reflected
+ * crc using table.
+ */
+
+static void chksum_init(void *ctx)
+{
+ struct chksum_ctx *mctx = ctx;
+
+ mctx->crc = ~(u32)0; /* common usage */
+}
+
+/*
+ * Setting the seed allows arbitrary accumulators and flexible XOR policy
+ * If your algorithm starts with ~0, then XOR with ~0 before you set
+ * the seed.
+ */
+static int chksum_setkey(void *ctx, const u8 *key, unsigned int keylen,
+ u32 *flags)
+{
+ struct chksum_ctx *mctx = ctx;
+
+ if (keylen != sizeof(mctx->crc)) {
+ if (flags)
+ *flags = CRYPTO_TFM_RES_BAD_KEY_LEN;
+ return -EINVAL;
+ }
+ mctx->crc = __cpu_to_le32(*(u32 *)key);
+ return 0;
+}
+
+static void chksum_update(void *ctx, const u8 *data, size_t length)
+{
+ struct chksum_ctx *mctx = ctx;
+ u32 mcrc;
+
+ mcrc = crc32c(mctx->crc, data, length);
+
+ mctx->crc = mcrc;
+}
+
+static void chksum_final(void *ctx, u8 *out)
+{
+ struct chksum_ctx *mctx = ctx;
+ u32 mcrc = (mctx->crc ^ ~(u32)0);
+
+ *(u32 *)out = __le32_to_cpu(mcrc);
+}
+
+static struct crypto_alg alg = {
+ .cra_name = "crc32c",
+ .cra_flags = CRYPTO_ALG_TYPE_DIGEST,
+ .cra_blocksize = CHKSUM_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct chksum_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(alg.cra_list),
+ .cra_u = {
+ .digest = {
+ .dia_digestsize= CHKSUM_DIGEST_SIZE,
+ .dia_setkey = chksum_setkey,
+ .dia_init = chksum_init,
+ .dia_update = chksum_update,
+ .dia_final = chksum_final
+ }
+ }
+};
+
+static int __init init(void)
+{
+ return crypto_register_alg(&alg);
+}
+
+static void __exit fini(void)
+{
+ crypto_unregister_alg(&alg);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_AUTHOR("Clay Haapala <[email protected]>");
+MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations wrapper for lib/crc32c");
+MODULE_LICENSE("GPL");
diff -ruN --exclude='*.orig' --exclude=SCCS --exclude=BitKeeper linux-2.6.6-rc1-bk.orig/crypto/Kconfig linux-2.6.6-rc1/crypto/Kconfig
--- linux-2.6.6-rc1-bk.orig/crypto/Kconfig 2004-04-19 15:04:01.000000000 -0500
+++ linux-2.6.6-rc1/crypto/Kconfig 2004-04-19 16:17:57.000000000 -0500
@@ -171,6 +171,16 @@
should not be used for other purposes because of the weakness
of the algorithm.

+config CRYPTO_CRC32C
+ tristate "CRC32c CRC algorithm"
+ depends on CRYPTO
+ select LIBCRC32C
+ help
+ Castagnoli, et al Cyclic Redundancy-Check Algorithm. Used
+ by iSCSI for header and data digests and by others.
+ See Castagnoli93. This implementation uses lib/libcrc32c.
+ Module will be crc32c.
+
config CRYPTO_TEST
tristate "Testing module"
depends on CRYPTO
diff -ruN --exclude='*.orig' --exclude=SCCS --exclude=BitKeeper linux-2.6.6-rc1-bk.orig/crypto/Makefile linux-2.6.6-rc1/crypto/Makefile
--- linux-2.6.6-rc1-bk.orig/crypto/Makefile 2004-03-29 15:29:29.000000000 -0600
+++ linux-2.6.6-rc1/crypto/Makefile 2004-04-19 16:17:57.000000000 -0500
@@ -24,5 +24,6 @@
obj-$(CONFIG_CRYPTO_ARC4) += arc4.o
obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o
obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
+obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o

obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
diff -ruN --exclude='*.orig' --exclude=SCCS --exclude=BitKeeper linux-2.6.6-rc1-bk.orig/crypto/tcrypt.c linux-2.6.6-rc1/crypto/tcrypt.c
--- linux-2.6.6-rc1-bk.orig/crypto/tcrypt.c 2004-03-29 15:29:30.000000000 -0600
+++ linux-2.6.6-rc1/crypto/tcrypt.c 2004-04-19 16:17:57.000000000 -0500
@@ -61,7 +61,7 @@
static char *check[] = {
"des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
"twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6",
- "arc4", "michael_mic", "deflate", NULL
+ "arc4", "michael_mic", "deflate", "crc32c", NULL
};

static void
@@ -496,6 +496,107 @@
}

static void
+test_crc32c(void)
+{
+#define NUMVEC 6
+#define VECSIZE 40
+
+ int i, j, pass;
+ u32 crc;
+ u8 b, test_vec[NUMVEC][VECSIZE];
+ static u32 vec_results[NUMVEC] = {
+ 0x0e2c157f, 0xe980ebf6, 0xde74bded,
+ 0xd579c862, 0xba979ad0, 0x2b29d913
+ };
+ static u32 tot_vec_results = 0x24c5d375;
+
+ struct scatterlist sg[NUMVEC];
+ struct crypto_tfm *tfm;
+ char *fmtdata = "testing crc32c initialized to %08x: %s\n";
+#define SEEDTESTVAL 0xedcba987
+ u32 seed;
+
+ printk("\ntesting crc32c\n");
+
+ tfm = crypto_alloc_tfm("crc32c", 0);
+ if (tfm == NULL) {
+ printk("failed to load transform for crc32c\n");
+ return;
+ }
+
+ crypto_digest_init(tfm);
+ crypto_digest_final(tfm, (u8*)&crc);
+ printk(fmtdata, crc, (crc == 0) ? "pass" : "ERROR");
+
+ /*
+ * stuff test_vec with known values, simple incrementing
+ * byte values.
+ */
+ b = 0;
+ for (i = 0; i < NUMVEC; i++) {
+ for (j = 0; j < VECSIZE; j++)
+ test_vec[i][j] = ++b;
+ sg[i].page = virt_to_page(test_vec[i]);
+ sg[i].offset = offset_in_page(test_vec[i]);
+ sg[i].length = VECSIZE;
+ }
+
+ seed = SEEDTESTVAL;
+ (void)crypto_digest_setkey(tfm, (const u8*)&seed, sizeof(u32));
+ crypto_digest_final(tfm, (u8*)&crc);
+ printk("testing crc32c setkey returns %08x : %s\n", crc, (crc == (SEEDTESTVAL ^ ~(u32)0)) ?
+ "pass" : "ERROR");
+
+ printk("testing crc32c using update/final:\n");
+
+ pass = 1; /* assume all is well */
+
+ for (i = 0; i < NUMVEC; i++) {
+ seed = ~(u32)0;
+ (void)crypto_digest_setkey(tfm, (const u8*)&seed, sizeof(u32));
+ crypto_digest_update(tfm, &sg[i], 1);
+ crypto_digest_final(tfm, (u8*)&crc);
+ if (crc == vec_results[i]) {
+ printk(" %08x:OK", crc);
+ } else {
+ printk(" %08x:BAD, wanted %08x\n", crc, vec_results[i]);
+ pass = 0;
+ }
+ }
+
+ printk("\ntesting crc32c using incremental accumulator:\n");
+ crc = 0;
+ for (i = 0; i < NUMVEC; i++) {
+ seed = (crc ^ ~(u32)0);
+ (void)crypto_digest_setkey(tfm, (const u8*)&seed, sizeof(u32));
+ crypto_digest_update(tfm, &sg[i], 1);
+ crypto_digest_final(tfm, (u8*)&crc);
+ }
+ if (crc == tot_vec_results) {
+ printk(" %08x:OK", crc);
+ } else {
+ printk(" %08x:BAD, wanted %08x\n", crc, tot_vec_results);
+ pass = 0;
+ }
+
+ printk("\ntesting crc32c using digest:\n");
+ seed = ~(u32)0;
+ (void)crypto_digest_setkey(tfm, (const u8*)&seed, sizeof(u32));
+ crypto_digest_digest(tfm, sg, NUMVEC, (u8*)&crc);
+ if (crc == tot_vec_results) {
+ printk(" %08x:OK", crc);
+ } else {
+ printk(" %08x:BAD, wanted %08x\n", crc, tot_vec_results);
+ pass = 0;
+ }
+
+ printk("\n%s\n", pass ? "pass" : "ERROR");
+
+ crypto_free_tfm(tfm);
+ printk("crc32c test complete\n");
+}
+
+static void
test_available(void)
{
char **name = check;
@@ -566,7 +667,8 @@

test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS);
test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS);
- test_deflate();
+ test_deflate();
+ test_crc32c();
#ifdef CONFIG_CRYPTO_HMAC
test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS);
test_hmac("sha1", hmac_sha1_tv_template, HMAC_SHA1_TEST_VECTORS);
@@ -657,6 +759,10 @@
test_hash("michael_mic", michael_mic_tv_template, MICHAEL_MIC_TEST_VECTORS);
break;

+ case 18:
+ test_crc32c();
+ break;
+
#ifdef CONFIG_CRYPTO_HMAC
case 100:
test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS);

2004-04-19 21:37:26

by Clay Haapala

[permalink] [raw]
Subject: [PATCH] lib/libcrc32c, revised 040419

On Wed, 31 Mar 2004, Clay Haapala spake thusly:
> On Tue, 30 Mar 2004, Matt Domsch verbalised:
>> On Tue, Mar 30, 2004 at 01:11:41PM -0600, Clay Haapala wrote:
>>> > +#if CRC_BE_BITS == 1
>>> > u32 attribute((pure)) crc32_be(u32 crc,
>>
>> Shouldn't this be crc32c_bc() instead?
>
> Below is the corrected patch with crc32c_be() declared correctly.
> We can still debate whether it should be included, but at least
> that's right now.

I re-diffed the lib directory against 2.6.6-rc1 fresh out of the BK
repo. There were no changes necessary, but here it is below.

The crc32c is used by the wrappers under crypto, which will be used by the
iscsi-sfnet driver presently.
--
Clay Haapala ([email protected]) Cisco Systems SRBU +1 763-398-1056
6450 Wedgwood Rd, Suite 130 Maple Grove MN 55311 PGP: C89240AD
If, for the sake of keeping Americans from dying, the
liberties for which Americans have fought and died are infringed,
who has won?

diff -ruN --exclude=SCCS --exclude=BitKeeper linux-2.6.6-rc1-bk.orig/lib/Kconfig linux-2.6.6-rc1/lib/Kconfig
--- linux-2.6.6-rc1-bk.orig/lib/Kconfig 2004-03-29 15:30:22.000000000 -0600
+++ linux-2.6.6-rc1/lib/Kconfig 2004-04-19 16:17:48.000000000 -0500
@@ -12,6 +12,15 @@
kernel tree does. Such modules that use library CRC32 functions
require M here.

+config LIBCRC32C
+ tristate "CRC32c (Castagnoli, et al) Cyclic Redundancy-Check"
+ help
+ This option is provided for the case where no in-kernel-tree
+ modules require CRC32c functions, but a module built outside the
+ kernel tree does. Such modules that use library CRC32c functions
+ require M here. See Castagnoli93.
+ Module will be libcrc32c.
+
#
# compression support is select'ed if needed
#
diff -ruN --exclude=SCCS --exclude=BitKeeper linux-2.6.6-rc1-bk.orig/lib/libcrc32c.c linux-2.6.6-rc1/lib/libcrc32c.c
--- linux-2.6.6-rc1-bk.orig/lib/libcrc32c.c 1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.6-rc1/lib/libcrc32c.c 2004-04-19 16:17:48.000000000 -0500
@@ -0,0 +1,205 @@
+/*
+ * CRC32C
+ *@Article{castagnoli-crc,
+ * author = { Guy Castagnoli and Stefan Braeuer and Martin Herrman},
+ * title = {{Optimization of Cyclic Redundancy-Check Codes with 24
+ * and 32 Parity Bits}},
+ * journal = IEEE Transactions on Communication,
+ * year = {1993},
+ * volume = {41},
+ * number = {6},
+ * pages = {},
+ * month = {June},
+ *}
+ * Used by the iSCSI driver, possibly others, and derived from the
+ * the iscsi-crc.c module of the linux-iscsi driver at
+ * http://linux-iscsi.sourceforge.net.
+ *
+ * Following the example of lib/crc32, this function is intended to be
+ * flexible and useful for all users. Modules that currently have their
+ * own crc32c, but hopefully may be able to use this one are:
+ * net/sctp (please add all your doco to here if you change to
+ * use this one!)
+ * <endoflist>
+ *
+ * Copyright (c) 2004 Cisco Systems, 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/crc32c.h>
+#include <linux/module.h>
+#include <asm/byteorder.h>
+
+MODULE_AUTHOR("Clay Haapala <[email protected]>");
+MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations");
+MODULE_LICENSE("GPL");
+
+#if __GNUC__ >= 3 /* 2.x has "attribute", but only 3.0 has "pure */
+#define attribute(x) __attribute__(x)
+#else
+#define attribute(x)
+#endif
+
+#define CRC32C_POLY_BE 0x1EDC6F41
+#define CRC32C_POLY_LE 0x82F63B78
+
+#ifndef CRC_LE_BITS
+# define CRC_LE_BITS 8
+#endif
+
+
+/*
+ * Haven't generated a big-endian table yet, but the bit-wise version
+ * should at least work.
+ */
+#if defined CRC_BE_BITS && CRC_BE_BITS != 1
+#undef CRC_BE_BITS
+#endif
+#ifndef CRC_BE_BITS
+# define CRC_BE_BITS 1
+#endif
+
+EXPORT_SYMBOL(crc32c_le);
+
+#if CRC_LE_BITS == 1
+/*
+ * Compute things bit-wise, as done in crc32.c. We could share the tight
+ * loop below with crc32 and vary the POLY if we don't find value in terms
+ * of space and maintainability in keeping the two modules separate.
+ */
+u32 attribute((pure))
+crc32c_le(u32 crc, unsigned char const *p, size_t len)
+{
+ int i;
+ while (len--) {
+ crc ^= *p++;
+ for (i = 0; i < 8; i++)
+ crc = (crc >> 1) ^ ((crc & 1) ? CRC32C_POLY_LE : 0);
+ }
+ return crc;
+}
+#else
+
+/*
+ * This is the CRC-32C table
+ * Generated with:
+ * width = 32 bits
+ * poly = 0x1EDC6F41
+ * reflect input bytes = true
+ * reflect output bytes = true
+ */
+
+static u32 crc32c_table[256] = {
+ 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
+ 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
+ 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
+ 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
+ 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
+ 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
+ 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
+ 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
+ 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
+ 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
+ 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
+ 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
+ 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
+ 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
+ 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
+ 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
+ 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
+ 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
+ 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
+ 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
+ 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
+ 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
+ 0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
+ 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
+ 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
+ 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
+ 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
+ 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
+ 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
+ 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
+ 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
+ 0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
+ 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
+ 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
+ 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
+ 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
+ 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
+ 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
+ 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
+ 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
+ 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
+ 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
+ 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
+ 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
+ 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
+ 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
+ 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
+ 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
+ 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
+ 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
+ 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
+ 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
+ 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
+ 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
+ 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
+ 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
+ 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
+ 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
+ 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
+ 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
+ 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
+ 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
+ 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
+ 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
+};
+
+/*
+ * Steps through buffer one byte at at time, calculates reflected
+ * crc using table.
+ */
+
+u32 attribute((pure))
+crc32c_le(u32 seed, unsigned char const *data, size_t length)
+{
+ u32 crc = __cpu_to_le32(seed);
+
+ while (length--)
+ crc =
+ crc32c_table[(crc ^ *data++) & 0xFFL] ^ (crc >> 8);
+
+ return __le32_to_cpu(crc);
+}
+
+#endif /* CRC_LE_BITS == 8 */
+
+EXPORT_SYMBOL(crc32c_be);
+
+#if CRC_BE_BITS == 1
+u32 attribute((pure))
+crc32c_be(u32 crc, unsigned char const *p, size_t len)
+{
+ int i;
+ while (len--) {
+ crc ^= *p++ << 24;
+ for (i = 0; i < 8; i++)
+ crc =
+ (crc << 1) ^ ((crc & 0x80000000) ? CRC32C_POLY_BE :
+ 0);
+ }
+ return crc;
+}
+#endif
+
+/*
+ * Unit test
+ *
+ * A small unit test suite is implemented as part of the crypto suite.
+ * Select CRYPTO_CRC32C and use the tcrypt module to run the tests.
+ */
diff -ruN --exclude=SCCS --exclude=BitKeeper linux-2.6.6-rc1-bk.orig/lib/Makefile linux-2.6.6-rc1/lib/Makefile
--- linux-2.6.6-rc1-bk.orig/lib/Makefile 2004-03-29 15:30:22.000000000 -0600
+++ linux-2.6.6-rc1/lib/Makefile 2004-04-19 16:17:48.000000000 -0500
@@ -19,6 +19,7 @@
endif

obj-$(CONFIG_CRC32) += crc32.o
+obj-$(CONFIG_LIBCRC32C) += libcrc32c.o

obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/
obj-$(CONFIG_ZLIB_DEFLATE) += zlib_deflate/
diff -ruN --exclude=SCCS --exclude=BitKeeper linux-2.6.6-rc1-bk.orig/include/linux/crc32c.h linux-2.6.6-rc1/include/linux/crc32c.h
--- linux-2.6.6-rc1-bk.orig/include/linux/crc32c.h 1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.6-rc1/include/linux/crc32c.h 2004-04-19 16:17:48.000000000 -0500
@@ -0,0 +1,11 @@
+#ifndef _LINUX_CRC32C_H
+#define _LINUX_CRC32C_H
+
+#include <linux/types.h>
+
+extern u32 crc32c_le(u32 crc, unsigned char const *address, size_t length);
+extern u32 crc32c_be(u32 crc, unsigned char const *address, size_t length);
+
+#define crc32c(seed, data, length) crc32c_le(seed, (unsigned char const *)data, length)
+
+#endif /* _LINUX_CRC32C_H */

2004-04-19 23:37:25

by David Miller

[permalink] [raw]
Subject: Re: [PATCH] crypto/crc32c implementation, updated 040419

On Mon, 19 Apr 2004 16:31:55 -0500
Clay Haapala <[email protected]> wrote:

> This patch agains 2.6.6-rc1-bk implements the CRC32C algorithm as a
> type of digest. It is implemented as a wrapper for libcrc32c,
> available in a separate patch. The crypto CRC32C module will be
> used by the iscsi-sfnet driver.

James, you got these two bits?

2004-04-20 13:20:59

by James Morris

[permalink] [raw]
Subject: Re: [PATCH] crypto/crc32c implementation, updated 040419

On Mon, 19 Apr 2004, David S. Miller wrote:

> On Mon, 19 Apr 2004 16:31:55 -0500
> Clay Haapala <[email protected]> wrote:
>
> > This patch agains 2.6.6-rc1-bk implements the CRC32C algorithm as a
> > type of digest. It is implemented as a wrapper for libcrc32c,
> > available in a separate patch. The crypto CRC32C module will be
> > used by the iscsi-sfnet driver.
>
> James, you got these two bits?
>

Yep, they look ok to me.


- James
--
James Morris
<[email protected]>


2004-04-23 23:43:05

by David Miller

[permalink] [raw]
Subject: Re: [PATCH] lib/libcrc32c, revised 040419

On Mon, 19 Apr 2004 16:37:01 -0500
Clay Haapala <[email protected]> wrote:

> +#if __GNUC__ >= 3 /* 2.x has "attribute", but only 3.0 has "pure */
> +#define attribute(x) __attribute__(x)
> +#else
> +#define attribute(x)
> +#endif

I was about to apply your two patches, but then I noticed this
thing. WHatever you may need this for exists in linux/compiler.h
and if it doesn't you should add the necessary macro interfaces
there.

Thanks.

2004-04-27 19:48:17

by Clay Haapala

[permalink] [raw]
Subject: [PATCH] lib/libcrc32c, revised 040427

On Fri, 23 Apr 2004, David S. Miller outgrape:
> On Mon, 19 Apr 2004 16:37:01 -0500
> Clay Haapala <[email protected]> wrote:
>
>> +#if __GNUC__ >= 3 /* 2.x has "attribute", but only 3.0 has "pure
>> +*/ #define attribute(x) __attribute__(x) #else #define
>> +attribute(x) #endif
>
> I was about to apply your two patches, but then I noticed this
> thing. WHatever you may need this for exists in linux/compiler.h
> and if it doesn't you should add the necessary macro interfaces
> there.
>
> Thanks.

Attribute(pure) was used, so I changed the patch to use the define in
compiler.h, as you suggest. I will also change crc32.c, and submit in
a second patch. This is a patch against 2.6.5 sources. I did not
change the crypto patch, as this construct was not used there.

Thanks!
--
Clay Haapala ([email protected]) Cisco Systems SRBU +1 763-398-1056
6450 Wedgwood Rd, Suite 130 Maple Grove MN 55311 PGP: C89240AD
"Oh, *that* Physics Prize. Well, I just substituted 'stupidity' for
'dark matter' in the equations, and it all came together."

diff -ruN linux-2.6.5.orig/lib/Kconfig linux-2.6.5/lib/Kconfig
--- linux-2.6.5.orig/lib/Kconfig Sat Apr 3 21:37:23 2004
+++ linux-2.6.5/lib/Kconfig Tue Apr 27 13:39:03 2004
@@ -12,6 +12,15 @@
kernel tree does. Such modules that use library CRC32 functions
require M here.

+config LIBCRC32C
+ tristate "CRC32c (Castagnoli, et al) Cyclic Redundancy-Check"
+ help
+ This option is provided for the case where no in-kernel-tree
+ modules require CRC32c functions, but a module built outside the
+ kernel tree does. Such modules that use library CRC32c functions
+ require M here. See Castagnoli93.
+ Module will be libcrc32c.
+
#
# compression support is select'ed if needed
#
diff -ruN linux-2.6.5.orig/lib/Makefile linux-2.6.5/lib/Makefile
--- linux-2.6.5.orig/lib/Makefile Sat Apr 3 21:36:16 2004
+++ linux-2.6.5/lib/Makefile Tue Apr 27 13:39:03 2004
@@ -19,6 +19,7 @@
endif

obj-$(CONFIG_CRC32) += crc32.o
+obj-$(CONFIG_LIBCRC32C) += libcrc32c.o

obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/
obj-$(CONFIG_ZLIB_DEFLATE) += zlib_deflate/
diff -ruN linux-2.6.5.orig/lib/libcrc32c.c linux-2.6.5/lib/libcrc32c.c
--- linux-2.6.5.orig/lib/libcrc32c.c Wed Dec 31 18:00:00 1969
+++ linux-2.6.5/lib/libcrc32c.c Tue Apr 27 14:34:10 2004
@@ -0,0 +1,199 @@
+/*
+ * CRC32C
+ *@Article{castagnoli-crc,
+ * author = { Guy Castagnoli and Stefan Braeuer and Martin Herrman},
+ * title = {{Optimization of Cyclic Redundancy-Check Codes with 24
+ * and 32 Parity Bits}},
+ * journal = IEEE Transactions on Communication,
+ * year = {1993},
+ * volume = {41},
+ * number = {6},
+ * pages = {},
+ * month = {June},
+ *}
+ * Used by the iSCSI driver, possibly others, and derived from the
+ * the iscsi-crc.c module of the linux-iscsi driver at
+ * http://linux-iscsi.sourceforge.net.
+ *
+ * Following the example of lib/crc32, this function is intended to be
+ * flexible and useful for all users. Modules that currently have their
+ * own crc32c, but hopefully may be able to use this one are:
+ * net/sctp (please add all your doco to here if you change to
+ * use this one!)
+ * <endoflist>
+ *
+ * Copyright (c) 2004 Cisco Systems, 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/crc32c.h>
+#include <linux/module.h>
+#include <asm/byteorder.h>
+
+MODULE_AUTHOR("Clay Haapala <[email protected]>");
+MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations");
+MODULE_LICENSE("GPL");
+
+#define CRC32C_POLY_BE 0x1EDC6F41
+#define CRC32C_POLY_LE 0x82F63B78
+
+#ifndef CRC_LE_BITS
+# define CRC_LE_BITS 8
+#endif
+
+
+/*
+ * Haven't generated a big-endian table yet, but the bit-wise version
+ * should at least work.
+ */
+#if defined CRC_BE_BITS && CRC_BE_BITS != 1
+#undef CRC_BE_BITS
+#endif
+#ifndef CRC_BE_BITS
+# define CRC_BE_BITS 1
+#endif
+
+EXPORT_SYMBOL(crc32c_le);
+
+#if CRC_LE_BITS == 1
+/*
+ * Compute things bit-wise, as done in crc32.c. We could share the tight
+ * loop below with crc32 and vary the POLY if we don't find value in terms
+ * of space and maintainability in keeping the two modules separate.
+ */
+u32 __attribute_pure__
+crc32c_le(u32 crc, unsigned char const *p, size_t len)
+{
+ int i;
+ while (len--) {
+ crc ^= *p++;
+ for (i = 0; i < 8; i++)
+ crc = (crc >> 1) ^ ((crc & 1) ? CRC32C_POLY_LE : 0);
+ }
+ return crc;
+}
+#else
+
+/*
+ * This is the CRC-32C table
+ * Generated with:
+ * width = 32 bits
+ * poly = 0x1EDC6F41
+ * reflect input bytes = true
+ * reflect output bytes = true
+ */
+
+static u32 crc32c_table[256] = {
+ 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
+ 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
+ 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
+ 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
+ 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
+ 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
+ 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
+ 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
+ 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
+ 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
+ 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
+ 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
+ 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
+ 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
+ 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
+ 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
+ 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
+ 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
+ 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
+ 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
+ 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
+ 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
+ 0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
+ 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
+ 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
+ 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
+ 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
+ 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
+ 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
+ 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
+ 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
+ 0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
+ 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
+ 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
+ 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
+ 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
+ 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
+ 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
+ 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
+ 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
+ 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
+ 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
+ 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
+ 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
+ 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
+ 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
+ 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
+ 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
+ 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
+ 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
+ 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
+ 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
+ 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
+ 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
+ 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
+ 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
+ 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
+ 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
+ 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
+ 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
+ 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
+ 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
+ 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
+ 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
+};
+
+/*
+ * Steps through buffer one byte at at time, calculates reflected
+ * crc using table.
+ */
+
+u32 __attribute_pure__
+crc32c_le(u32 seed, unsigned char const *data, size_t length)
+{
+ u32 crc = __cpu_to_le32(seed);
+
+ while (length--)
+ crc =
+ crc32c_table[(crc ^ *data++) & 0xFFL] ^ (crc >> 8);
+
+ return __le32_to_cpu(crc);
+}
+
+#endif /* CRC_LE_BITS == 8 */
+
+EXPORT_SYMBOL(crc32c_be);
+
+#if CRC_BE_BITS == 1
+u32 __attribute_pure__
+crc32c_be(u32 crc, unsigned char const *p, size_t len)
+{
+ int i;
+ while (len--) {
+ crc ^= *p++ << 24;
+ for (i = 0; i < 8; i++)
+ crc =
+ (crc << 1) ^ ((crc & 0x80000000) ? CRC32C_POLY_BE :
+ 0);
+ }
+ return crc;
+}
+#endif
+
+/*
+ * Unit test
+ *
+ * A small unit test suite is implemented as part of the crypto suite.
+ * Select CRYPTO_CRC32C and use the tcrypt module to run the tests.
+ */
diff -ruN linux-2.6.5.orig/include/linux/crc32c.h linux-2.6.5/include/linux/crc32c.h
--- linux-2.6.5.orig/include/linux/crc32c.h Wed Dec 31 18:00:00 1969
+++ linux-2.6.5/include/linux/crc32c.h Tue Apr 27 13:39:03 2004
@@ -0,0 +1,11 @@
+#ifndef _LINUX_CRC32C_H
+#define _LINUX_CRC32C_H
+
+#include <linux/types.h>
+
+extern u32 crc32c_le(u32 crc, unsigned char const *address, size_t length);
+extern u32 crc32c_be(u32 crc, unsigned char const *address, size_t length);
+
+#define crc32c(seed, data, length) crc32c_le(seed, (unsigned char const *)data, length)
+
+#endif /* _LINUX_CRC32C_H */

2004-04-27 19:52:12

by David Miller

[permalink] [raw]
Subject: Re: [PATCH] lib/libcrc32c, revised 040427

On Tue, 27 Apr 2004 14:46:35 -0500
Clay Haapala <[email protected]> wrote:

> Attribute(pure) was used, so I changed the patch to use the define in
> compiler.h, as you suggest. I will also change crc32.c, and submit in
> a second patch. This is a patch against 2.6.5 sources. I did not
> change the crypto patch, as this construct was not used there.

Please include linux/compiler.h if you're going to use it :-)

Once you fix that, send it again and resend the crypto part to
me as well and I'll apply everything for you.

Thanks a lot for following up on this.

2004-04-27 19:55:41

by Clay Haapala

[permalink] [raw]
Subject: [PATCH] lib/crc32.c: to use compiler.h defines

On Fri, 23 Apr 2004, David S. Miller told this:
> On Mon, 19 Apr 2004 16:37:01 -0500
> Clay Haapala <[email protected]> wrote:
>
>> +#if __GNUC__ >= 3 /* 2.x has "attribute", but only 3.0 has "pure
>> +*/ #define attribute(x) __attribute__(x) #else #define
>> +attribute(x) #endif
>
> I was about to apply your two patches, but then I noticed this
> thing. WHatever you may need this for exists in linux/compiler.h
> and if it doesn't you should add the necessary macro interfaces
> there.
>
> Thanks.

Below is a patch to lib/crc32.c to use the compiler.h define for
attribute((pure)).
--
Clay Haapala ([email protected]) Cisco Systems SRBU +1 763-398-1056
6450 Wedgwood Rd, Suite 130 Maple Grove MN 55311 PGP: C89240AD
"Oh, *that* Physics Prize. Well, I just substituted 'stupidity' for
'dark matter' in the equations, and it all came together."

--- linux-2.6.5.orig/lib/crc32.c Sat Apr 3 21:36:14 2004
+++ linux-2.6.5/lib/crc32.c Tue Apr 27 14:48:03 2004
@@ -37,13 +37,6 @@
#endif
#include "crc32table.h"

-#if __GNUC__ >= 3 /* 2.x has "attribute", but only 3.0 has "pure */
-#define attribute(x) __attribute__(x)
-#else
-#define attribute(x)
-#endif
-
-
MODULE_AUTHOR("Matt Domsch <[email protected]>");
MODULE_DESCRIPTION("Ethernet CRC32 calculations");
MODULE_LICENSE("GPL");
@@ -62,7 +55,7 @@
* @len - length of buffer @p
*
*/
-u32 attribute((pure)) crc32_le(u32 crc, unsigned char const *p, size_t len)
+u32 __attribute_pure__ crc32_le(u32 crc, unsigned char const *p, size_t len)
{
int i;
while (len--) {
@@ -82,7 +75,7 @@
* @len - length of buffer @p
*
*/
-u32 attribute((pure)) crc32_le(u32 crc, unsigned char const *p, size_t len)
+u32 __attribute_pure__ crc32_le(u32 crc, unsigned char const *p, size_t len)
{
# if CRC_LE_BITS == 8
const u32 *b =(u32 *)p;
@@ -165,7 +158,7 @@
* @len - length of buffer @p
*
*/
-u32 attribute((pure)) crc32_be(u32 crc, unsigned char const *p, size_t len)
+u32 __attribute_pure__ crc32_be(u32 crc, unsigned char const *p, size_t len)
{
int i;
while (len--) {
@@ -187,7 +180,7 @@
* @len -

2004-04-27 20:00:25

by Clay Haapala

[permalink] [raw]
Subject: Re: [PATCH] lib/libcrc32c, revised 040427

On Tue, 27 Apr 2004, David S. Miller spake thusly:
> On Tue, 27 Apr 2004 14:46:35 -0500
> Clay Haapala <[email protected]> wrote:
>
>> Attribute(pure) was used, so I changed the patch to use the define
>> in compiler.h, as you suggest. I will also change crc32.c, and
>> submit in a second patch. This is a patch against 2.6.5 sources.
>> I did not change the crypto patch, as this construct was not used
>> there.
>
> Please include linux/compiler.h if you're going to use it :-)
>
> Once you fix that, send it again and resend the crypto part to
> me as well and I'll apply everything for you.
>
> Thanks a lot for following up on this.

Uh .. I was prepared to terminally embarrassed by forgetting the
#include, but I *did* compile the files, with both GCC 3.3 and 2.96, so
compiler.h must be included by something else. Do you wish an
explicit include of compiler.h anyways? If so, no problem, let me know.
--
Clay Haapala ([email protected]) Cisco Systems SRBU +1 763-398-1056
6450 Wedgwood Rd, Suite 130 Maple Grove MN 55311 PGP: C89240AD
"Oh, *that* Physics Prize. Well, I just substituted 'stupidity' for
'dark matter' in the equations, and it all came together."

2004-04-27 21:50:10

by Clay Haapala

[permalink] [raw]
Subject: Re: [PATCH] lib/libcrc32c, revised 040427

On Tue, 27 Apr 2004, Clay Haapala stated:
> On Tue, 27 Apr 2004, David S. Miller spake thusly:
>> On Tue, 27 Apr 2004 14:46:35 -0500
>> Clay Haapala <[email protected]> wrote:
>>
>>> Attribute(pure) was used, so I changed the patch to use the define
>>> in compiler.h, as you suggest. I will also change crc32.c, and
>>> submit in a second patch. This is a patch against 2.6.5 sources.
>>> I did not change the crypto patch, as this construct was not used
>>> there.
>>
>> Please include linux/compiler.h if you're going to use it :-)
>>
>> Once you fix that, send it again and resend the crypto part to
>> me as well and I'll apply everything for you.
>>
>> Thanks a lot for following up on this.
>
> Uh .. I was prepared to terminally embarrassed by forgetting the
> #include, but I *did* compile the files, with both GCC 3.3 and 2.96,
> so compiler.h must be included by something else. Do you wish an
> explicit include of compiler.h anyways? If so, no problem, let me
> know.

The 'something else' in question that includes compiler.h is:
kernel.h:#include <linux/compiler.h>
module.h:#include <linux/compiler.h>
init.h:#include <linux/compiler.h>

so that is why it compiles.

Is it accepted form to add the include line even so?
--
Clay Haapala ([email protected]) Cisco Systems SRBU +1 763-398-1056
6450 Wedgwood Rd, Suite 130 Maple Grove MN 55311 PGP: C89240AD
"Oh, *that* Physics Prize. Well, I just substituted 'stupidity' for
'dark matter' in the equations, and it all came together."

2004-04-27 21:52:10

by David Miller

[permalink] [raw]
Subject: Re: [PATCH] lib/libcrc32c, revised 040427

On Tue, 27 Apr 2004 16:49:53 -0500
Clay Haapala <[email protected]> wrote:

> Is it accepted form to add the include line even so?

Yes, it only works today because those other headers include
it.

2004-04-28 15:14:57

by Clay Haapala

[permalink] [raw]
Subject: [PATCH] lib/libcrc32c, revised 040428, with compiler.h included

On Tue, 27 Apr 2004, David S. Miller stated:
> On Tue, 27 Apr 2004 16:49:53 -0500
> Clay Haapala <[email protected]> wrote:
>
>> Is it accepted form to add the include line even so?
>
> Yes, it only works today because those other headers include it.

OK, below is the patch with compiler.h included.
--
Clay Haapala ([email protected]) Cisco Systems SRBU +1 763-398-1056
6450 Wedgwood Rd, Suite 130 Maple Grove MN 55311 PGP: C89240AD
"Oh, *that* Physics Prize. Well, I just substituted 'stupidity' for
'dark matter' in the equations, and it all came together."

diff -ruN linux-2.6.5.orig/lib/Kconfig linux-2.6.5/lib/Kconfig
--- linux-2.6.5.orig/lib/Kconfig Sat Apr 3 21:37:23 2004
+++ linux-2.6.5/lib/Kconfig Tue Apr 27 13:39:03 2004
@@ -12,6 +12,15 @@
kernel tree does. Such modules that use library CRC32 functions
require M here.

+config LIBCRC32C
+ tristate "CRC32c (Castagnoli, et al) Cyclic Redundancy-Check"
+ help
+ This option is provided for the case where no in-kernel-tree
+ modules require CRC32c functions, but a module built outside the
+ kernel tree does. Such modules that use library CRC32c functions
+ require M here. See Castagnoli93.
+ Module will be libcrc32c.
+
#
# compression support is select'ed if needed
#
diff -ruN linux-2.6.5.orig/lib/Makefile linux-2.6.5/lib/Makefile
--- linux-2.6.5.orig/lib/Makefile Sat Apr 3 21:36:16 2004
+++ linux-2.6.5/lib/Makefile Tue Apr 27 13:39:03 2004
@@ -19,6 +19,7 @@
endif

obj-$(CONFIG_CRC32) += crc32.o
+obj-$(CONFIG_LIBCRC32C) += libcrc32c.o

obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/
obj-$(CONFIG_ZLIB_DEFLATE) += zlib_deflate/
diff -ruN linux-2.6.5.orig/lib/libcrc32c.c linux-2.6.5/lib/libcrc32c.c
--- linux-2.6.5.orig/lib/libcrc32c.c Wed Dec 31 18:00:00 1969
+++ linux-2.6.5/lib/libcrc32c.c Wed Apr 28 10:06:15 2004
@@ -0,0 +1,200 @@
+/*
+ * CRC32C
+ *@Article{castagnoli-crc,
+ * author = { Guy Castagnoli and Stefan Braeuer and Martin Herrman},
+ * title = {{Optimization of Cyclic Redundancy-Check Codes with 24
+ * and 32 Parity Bits}},
+ * journal = IEEE Transactions on Communication,
+ * year = {1993},
+ * volume = {41},
+ * number = {6},
+ * pages = {},
+ * month = {June},
+ *}
+ * Used by the iSCSI driver, possibly others, and derived from the
+ * the iscsi-crc.c module of the linux-iscsi driver at
+ * http://linux-iscsi.sourceforge.net.
+ *
+ * Following the example of lib/crc32, this function is intended to be
+ * flexible and useful for all users. Modules that currently have their
+ * own crc32c, but hopefully may be able to use this one are:
+ * net/sctp (please add all your doco to here if you change to
+ * use this one!)
+ * <endoflist>
+ *
+ * Copyright (c) 2004 Cisco Systems, 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/crc32c.h>
+#include <linux/compiler.h>
+#include <linux/module.h>
+#include <asm/byteorder.h>
+
+MODULE_AUTHOR("Clay Haapala <[email protected]>");
+MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations");
+MODULE_LICENSE("GPL");
+
+#define CRC32C_POLY_BE 0x1EDC6F41
+#define CRC32C_POLY_LE 0x82F63B78
+
+#ifndef CRC_LE_BITS
+# define CRC_LE_BITS 8
+#endif
+
+
+/*
+ * Haven't generated a big-endian table yet, but the bit-wise version
+ * should at least work.
+ */
+#if defined CRC_BE_BITS && CRC_BE_BITS != 1
+#undef CRC_BE_BITS
+#endif
+#ifndef CRC_BE_BITS
+# define CRC_BE_BITS 1
+#endif
+
+EXPORT_SYMBOL(crc32c_le);
+
+#if CRC_LE_BITS == 1
+/*
+ * Compute things bit-wise, as done in crc32.c. We could share the tight
+ * loop below with crc32 and vary the POLY if we don't find value in terms
+ * of space and maintainability in keeping the two modules separate.
+ */
+u32 __attribute_pure__
+crc32c_le(u32 crc, unsigned char const *p, size_t len)
+{
+ int i;
+ while (len--) {
+ crc ^= *p++;
+ for (i = 0; i < 8; i++)
+ crc = (crc >> 1) ^ ((crc & 1) ? CRC32C_POLY_LE : 0);
+ }
+ return crc;
+}
+#else
+
+/*
+ * This is the CRC-32C table
+ * Generated with:
+ * width = 32 bits
+ * poly = 0x1EDC6F41
+ * reflect input bytes = true
+ * reflect output bytes = true
+ */
+
+static u32 crc32c_table[256] = {
+ 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
+ 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
+ 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
+ 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
+ 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
+ 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
+ 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
+ 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
+ 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
+ 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
+ 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
+ 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
+ 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
+ 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
+ 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
+ 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
+ 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
+ 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
+ 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
+ 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
+ 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
+ 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
+ 0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
+ 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
+ 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
+ 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
+ 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
+ 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
+ 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
+ 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
+ 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
+ 0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
+ 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
+ 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
+ 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
+ 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
+ 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
+ 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
+ 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
+ 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
+ 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
+ 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
+ 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
+ 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
+ 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
+ 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
+ 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
+ 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
+ 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
+ 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
+ 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
+ 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
+ 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
+ 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
+ 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
+ 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
+ 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
+ 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
+ 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
+ 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
+ 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
+ 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
+ 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
+ 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
+};
+
+/*
+ * Steps through buffer one byte at at time, calculates reflected
+ * crc using table.
+ */
+
+u32 __attribute_pure__
+crc32c_le(u32 seed, unsigned char const *data, size_t length)
+{
+ u32 crc = __cpu_to_le32(seed);
+
+ while (length--)
+ crc =
+ crc32c_table[(crc ^ *data++) & 0xFFL] ^ (crc >> 8);
+
+ return __le32_to_cpu(crc);
+}
+
+#endif /* CRC_LE_BITS == 8 */
+
+EXPORT_SYMBOL(crc32c_be);
+
+#if CRC_BE_BITS == 1
+u32 __attribute_pure__
+crc32c_be(u32 crc, unsigned char const *p, size_t len)
+{
+ int i;
+ while (len--) {
+ crc ^= *p++ << 24;
+ for (i = 0; i < 8; i++)
+ crc =
+ (crc << 1) ^ ((crc & 0x80000000) ? CRC32C_POLY_BE :
+ 0);
+ }
+ return crc;
+}
+#endif
+
+/*
+ * Unit test
+ *
+ * A small unit test suite is implemented as part of the crypto suite.
+ * Select CRYPTO_CRC32C and use the tcrypt module to run the tests.
+ */
diff -ruN linux-2.6.5.orig/include/linux/crc32c.h linux-2.6.5/include/linux/crc32c.h
--- linux-2.6.5.orig/include/linux/crc32c.h Wed Dec 31 18:00:00 1969
+++ linux-2.6.5/include/linux/crc32c.h Tue Apr 27 13:39:03 2004
@@ -0,0 +1,11 @@
+#ifndef _LINUX_CRC32C_H
+#define _LINUX_CRC32C_H
+
+#include <linux/types.h>
+
+extern u32 crc32c_le(u32 crc, unsigned char const *address, size_t length);
+extern u32 crc32c_be(u32 crc, unsigned char const *address, size_t length);
+
+#define crc32c(seed, data, length) crc32c_le(seed, (unsigned char const *)data, length)
+
+#endif /* _LINUX_CRC32C_H */

2004-04-28 15:19:15

by Clay Haapala

[permalink] [raw]
Subject: [PATCH] lib/crc32.c: uses (and includes) compiler.h

Here is the crc32.c patch to remove attribute((pure)), with compiler.h
included.
--
Clay Haapala ([email protected]) Cisco Systems SRBU +1 763-398-1056
6450 Wedgwood Rd, Suite 130 Maple Grove MN 55311 PGP: C89240AD
"Oh, *that* Physics Prize. Well, I just substituted 'stupidity' for
'dark matter' in the equations, and it all came together."

--- linux-2.6.5.orig/lib/crc32.c Sat Apr 3 21:36:14 2004
+++ linux-2.6.5/lib/crc32.c Wed Apr 28 10:07:20 2004
@@ -23,6 +23,7 @@
#include <linux/crc32.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/compiler.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/init.h>
@@ -37,13 +38,6 @@
#endif
#include "crc32table.h"

-#if __GNUC__ >= 3 /* 2.x has "attribute", but only 3.0 has "pure */
-#define attribute(x) __attribute__(x)
-#else
-#define attribute(x)
-#endif
-
-
MODULE_AUTHOR("Matt Domsch <[email protected]>");
MODULE_DESCRIPTION("Ethernet CRC32 calculations");
MODULE_LICENSE("GPL");
@@ -62,7 +56,7 @@
* @len - length of buffer @p
*
*/
-u32 attribute((pure)) crc32_le(u32 crc, unsigned char const *p, size_t len)
+u32 __attribute_pure__ crc32_le(u32 crc, unsigned char const *p, size_t len)
{
int i;
while (len--) {
@@ -82,7 +76,7 @@
* @len - length of buffer @p
*
*/
-u32 attribute((pure)) crc32_le(u32 crc, unsigned char const *p, size_t len)
+u32 __attribute_pure__ crc32_le(u32 crc, unsigned char const *p, size_t len)
{
# if CRC_LE_BITS == 8
const u32 *b =(u32 *)p;
@@ -165,7 +159,7 @@
* @len - length of buffer @p
*
*/
-u32 attribute((pure)) crc32_be(u32 crc, unsigned char const *p, size_t len)
+u32 __attribute_pure__ crc32_be(u32 crc, unsigned char const *p, size_t len)
{
int i;
while (len--) {
@@ -187,7 +181,7 @@
* @len - length of buffer @p
*
*/
-u32 attribute((pure)) crc32_be(u32 crc, unsigned char const *p, size_t len)
+u32 __attribute_pure__ crc32_be(u32 crc, unsigned char const *p, size_t len)
{
# if CRC_BE_BITS == 8
const u32 *b =(u32 *)p;

2004-04-28 20:26:05

by David Miller

[permalink] [raw]
Subject: Re: [PATCH] lib/crc32.c: uses (and includes) compiler.h

On Wed, 28 Apr 2004 10:19:02 -0500
Clay Haapala <[email protected]> wrote:

> Here is the crc32.c patch to remove attribute((pure)), with compiler.h
> included.

Applied, thanks!

2004-04-28 20:26:06

by David Miller

[permalink] [raw]
Subject: Re: [PATCH] lib/libcrc32c, revised 040428, with compiler.h included

On Wed, 28 Apr 2004 10:14:32 -0500
Clay Haapala <[email protected]> wrote:

> On Tue, 27 Apr 2004, David S. Miller stated:
> > On Tue, 27 Apr 2004 16:49:53 -0500
> > Clay Haapala <[email protected]> wrote:
> >
> >> Is it accepted form to add the include line even so?
> >
> > Yes, it only works today because those other headers include it.
>
> OK, below is the patch with compiler.h included.

Looks great, patch applied.

Thanks.