Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6: (125 commits)
[CRYPTO] twofish: Merge common glue code
[CRYPTO] hifn_795x: Fixup container_of() usage
[CRYPTO] cast6: inline bloat--
[CRYPTO] api: Set default CRYPTO_MINALIGN to unsigned long long
[CRYPTO] tcrypt: Make xcbc available as a standalone test
[CRYPTO] xcbc: Remove bogus hash/cipher test
[CRYPTO] xcbc: Fix algorithm leak when block size check fails
[CRYPTO] tcrypt: Zero axbuf in the right function
[CRYPTO] padlock: Only reset the key once for each CBC and ECB operation
[CRYPTO] api: Include sched.h for cond_resched in scatterwalk.h
[CRYPTO] salsa20-asm: Remove unnecessary dependency on CRYPTO_SALSA20
[CRYPTO] tcrypt: Add select of AEAD
[CRYPTO] salsa20: Add x86-64 assembly version
[CRYPTO] salsa20_i586: Salsa20 stream cipher algorithm (i586 version)
[CRYPTO] gcm: Introduce rfc4106
[CRYPTO] api: Show async type
[CRYPTO] chainiv: Avoid lock spinning where possible
[CRYPTO] seqiv: Add select AEAD in Kconfig
[CRYPTO] scatterwalk: Handle zero nbytes in scatterwalk_map_and_copy
[CRYPTO] null: Allow setkey on digest_null
...
diff --git a/Documentation/crypto/api-intro.txt b/Documentation/crypto/api-intro.txt
index a2ac6d2..8b49302 100644
--- a/Documentation/crypto/api-intro.txt
+++ b/Documentation/crypto/api-intro.txt
@@ -33,9 +33,16 @@
very simple, while hiding the core logic from both. Many good ideas
from existing APIs such as Cryptoapi and Nettle have been adapted for this.
-The API currently supports three types of transforms: Ciphers, Digests and
-Compressors. The compression algorithms especially seem to be performing
-very well so far.
+The API currently supports five main types of transforms: AEAD (Authenticated
+Encryption with Associated Data), Block Ciphers, Ciphers, Compressors and
+Hashes.
+
+Please note that Block Ciphers is somewhat of a misnomer. It is in fact
+meant to support all ciphers including stream ciphers. The difference
+between Block Ciphers and Ciphers is that the latter operates on exactly
+one block while the former can operate on an arbitrary amount of data,
+subject to block size requirements (i.e., non-stream ciphers can only
+process multiples of blocks).
Support for hardware crypto devices via an asynchronous interface is
under development.
@@ -69,29 +76,12 @@
Many real examples are available in the regression test module (tcrypt.c).
-CONFIGURATION NOTES
-
-As Triple DES is part of the DES module, for those using modular builds,
-add the following line to /etc/modprobe.conf:
-
- alias des3_ede des
-
-The Null algorithms reside in the crypto_null module, so these lines
-should also be added:
-
- alias cipher_null crypto_null
- alias digest_null crypto_null
- alias compress_null crypto_null
-
-The SHA384 algorithm shares code within the SHA512 module, so you'll
-also need:
- alias sha384 sha512
-
-
DEVELOPER NOTES
Transforms may only be allocated in user context, and cryptographic
-methods may only be called from softirq and user contexts.
+methods may only be called from softirq and user contexts. For
+transforms with a setkey method it too should only be called from
+user context.
When using the API for ciphers, performance will be optimal if each
scatterlist contains data which is a multiple of the cipher's block
@@ -130,8 +120,9 @@
BUGS
Send bug reports to:
-Herbert Xu <herbert@gondor.apana.org.au>
-Cc: David S. Miller <davem@redhat.com>
+linux-crypto@vger.kernel.org
+Cc: Herbert Xu <herbert@gondor.apana.org.au>,
+ David S. Miller <davem@redhat.com>
FURTHER INFORMATION
diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c
index 5126696..46c97058 100644
--- a/arch/s390/crypto/aes_s390.c
+++ b/arch/s390/crypto/aes_s390.c
@@ -6,6 +6,7 @@
* s390 Version:
* Copyright IBM Corp. 2005,2007
* Author(s): Jan Glauber (jang@de.ibm.com)
+ * Sebastian Siewior (sebastian@breakpoint.cc> SW-Fallback
*
* Derived from "crypto/aes_generic.c"
*
@@ -16,17 +17,13 @@
*
*/
+#include <crypto/aes.h>
#include <crypto/algapi.h>
+#include <linux/err.h>
#include <linux/module.h>
#include <linux/init.h>
#include "crypt_s390.h"
-#define AES_MIN_KEY_SIZE 16
-#define AES_MAX_KEY_SIZE 32
-
-/* data block size for all key lengths */
-#define AES_BLOCK_SIZE 16
-
#define AES_KEYLEN_128 1
#define AES_KEYLEN_192 2
#define AES_KEYLEN_256 4
@@ -39,45 +36,89 @@
long enc;
long dec;
int key_len;
+ union {
+ struct crypto_blkcipher *blk;
+ struct crypto_cipher *cip;
+ } fallback;
};
+/*
+ * Check if the key_len is supported by the HW.
+ * Returns 0 if it is, a positive number if it is not and software fallback is
+ * required or a negative number in case the key size is not valid
+ */
+static int need_fallback(unsigned int key_len)
+{
+ switch (key_len) {
+ case 16:
+ if (!(keylen_flag & AES_KEYLEN_128))
+ return 1;
+ break;
+ case 24:
+ if (!(keylen_flag & AES_KEYLEN_192))
+ return 1;
+ break;
+ case 32:
+ if (!(keylen_flag & AES_KEYLEN_256))
+ return 1;
+ break;
+ default:
+ return -1;
+ break;
+ }
+ return 0;
+}
+
+static int setkey_fallback_cip(struct crypto_tfm *tfm, const u8 *in_key,
+ unsigned int key_len)
+{
+ struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
+ int ret;
+
+ sctx->fallback.blk->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
+ sctx->fallback.blk->base.crt_flags |= (tfm->crt_flags &
+ CRYPTO_TFM_REQ_MASK);
+
+ ret = crypto_cipher_setkey(sctx->fallback.cip, in_key, key_len);
+ if (ret) {
+ tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK;
+ tfm->crt_flags |= (sctx->fallback.blk->base.crt_flags &
+ CRYPTO_TFM_RES_MASK);
+ }
+ return ret;
+}
+
static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
unsigned int key_len)
{
struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
u32 *flags = &tfm->crt_flags;
+ int ret;
- switch (key_len) {
- case 16:
- if (!(keylen_flag & AES_KEYLEN_128))
- goto fail;
- break;
- case 24:
- if (!(keylen_flag & AES_KEYLEN_192))
- goto fail;
-
- break;
- case 32:
- if (!(keylen_flag & AES_KEYLEN_256))
- goto fail;
- break;
- default:
- goto fail;
- break;
+ ret = need_fallback(key_len);
+ if (ret < 0) {
+ *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+ return -EINVAL;
}
sctx->key_len = key_len;
- memcpy(sctx->key, in_key, key_len);
- return 0;
-fail:
- *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
- return -EINVAL;
+ if (!ret) {
+ memcpy(sctx->key, in_key, key_len);
+ return 0;
+ }
+
+ return setkey_fallback_cip(tfm, in_key, key_len);
}
static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
{
const struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
+ if (unlikely(need_fallback(sctx->key_len))) {
+ crypto_cipher_encrypt_one(sctx->fallback.cip, out, in);
+ return;
+ }
+
switch (sctx->key_len) {
case 16:
crypt_s390_km(KM_AES_128_ENCRYPT, &sctx->key, out, in,
@@ -98,6 +139,11 @@
{
const struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
+ if (unlikely(need_fallback(sctx->key_len))) {
+ crypto_cipher_decrypt_one(sctx->fallback.cip, out, in);
+ return;
+ }
+
switch (sctx->key_len) {
case 16:
crypt_s390_km(KM_AES_128_DECRYPT, &sctx->key, out, in,
@@ -114,6 +160,29 @@
}
}
+static int fallback_init_cip(struct crypto_tfm *tfm)
+{
+ const char *name = tfm->__crt_alg->cra_name;
+ struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
+
+ sctx->fallback.cip = crypto_alloc_cipher(name, 0,
+ CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK);
+
+ if (IS_ERR(sctx->fallback.cip)) {
+ printk(KERN_ERR "Error allocating fallback algo %s\n", name);
+ return PTR_ERR(sctx->fallback.blk);
+ }
+
+ return 0;
+}
+
+static void fallback_exit_cip(struct crypto_tfm *tfm)
+{
+ struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
+
+ crypto_free_cipher(sctx->fallback.cip);
+ sctx->fallback.cip = NULL;
+}
static struct crypto_alg aes_alg = {
.cra_name = "aes",
@@ -125,6 +194,8 @@
.cra_ctxsize = sizeof(struct s390_aes_ctx),
.cra_module = THIS_MODULE,
.cra_list = LIST_HEAD_INIT(aes_alg.cra_list),
+ .cra_init = fallback_init_cip,
+ .cra_exit = fallback_exit_cip,
.cra_u = {
.cipher = {
.cia_min_keysize = AES_MIN_KEY_SIZE,
@@ -136,10 +207,70 @@
}
};
+static int setkey_fallback_blk(struct crypto_tfm *tfm, const u8 *key,
+ unsigned int len)
+{
+ struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
+ unsigned int ret;
+
+ sctx->fallback.blk->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
+ sctx->fallback.blk->base.crt_flags |= (tfm->crt_flags &
+ CRYPTO_TFM_REQ_MASK);
+
+ ret = crypto_blkcipher_setkey(sctx->fallback.blk, key, len);
+ if (ret) {
+ tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK;
+ tfm->crt_flags |= (sctx->fallback.blk->base.crt_flags &
+ CRYPTO_TFM_RES_MASK);
+ }
+ return ret;
+}
+
+static int fallback_blk_dec(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ unsigned int ret;
+ struct crypto_blkcipher *tfm;
+ struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
+
+ tfm = desc->tfm;
+ desc->tfm = sctx->fallback.blk;
+
+ ret = crypto_blkcipher_decrypt_iv(desc, dst, src, nbytes);
+
+ desc->tfm = tfm;
+ return ret;
+}
+
+static int fallback_blk_enc(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ unsigned int ret;
+ struct crypto_blkcipher *tfm;
+ struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
+
+ tfm = desc->tfm;
+ desc->tfm = sctx->fallback.blk;
+
+ ret = crypto_blkcipher_encrypt_iv(desc, dst, src, nbytes);
+
+ desc->tfm = tfm;
+ return ret;
+}
+
static int ecb_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
unsigned int key_len)
{
struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
+ int ret;
+
+ ret = need_fallback(key_len);
+ if (ret > 0) {
+ sctx->key_len = key_len;
+ return setkey_fallback_blk(tfm, in_key, key_len);
+ }
switch (key_len) {
case 16:
@@ -188,6 +319,9 @@
struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
struct blkcipher_walk walk;
+ if (unlikely(need_fallback(sctx->key_len)))
+ return fallback_blk_enc(desc, dst, src, nbytes);
+
blkcipher_walk_init(&walk, dst, src, nbytes);
return ecb_aes_crypt(desc, sctx->enc, sctx->key, &walk);
}
@@ -199,10 +333,37 @@
struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
struct blkcipher_walk walk;
+ if (unlikely(need_fallback(sctx->key_len)))
+ return fallback_blk_dec(desc, dst, src, nbytes);
+
blkcipher_walk_init(&walk, dst, src, nbytes);
return ecb_aes_crypt(desc, sctx->dec, sctx->key, &walk);
}
+static int fallback_init_blk(struct crypto_tfm *tfm)
+{
+ const char *name = tfm->__crt_alg->cra_name;
+ struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
+
+ sctx->fallback.blk = crypto_alloc_blkcipher(name, 0,
+ CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK);
+
+ if (IS_ERR(sctx->fallback.blk)) {
+ printk(KERN_ERR "Error allocating fallback algo %s\n", name);
+ return PTR_ERR(sctx->fallback.blk);
+ }
+
+ return 0;
+}
+
+static void fallback_exit_blk(struct crypto_tfm *tfm)
+{
+ struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
+
+ crypto_free_blkcipher(sctx->fallback.blk);
+ sctx->fallback.blk = NULL;
+}
+
static struct crypto_alg ecb_aes_alg = {
.cra_name = "ecb(aes)",
.cra_driver_name = "ecb-aes-s390",
@@ -214,6 +375,8 @@
.cra_type = &crypto_blkcipher_type,
.cra_module = THIS_MODULE,
.cra_list = LIST_HEAD_INIT(ecb_aes_alg.cra_list),
+ .cra_init = fallback_init_blk,
+ .cra_exit = fallback_exit_blk,
.cra_u = {
.blkcipher = {
.min_keysize = AES_MIN_KEY_SIZE,
@@ -229,6 +392,13 @@
unsigned int key_len)
{
struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
+ int ret;
+
+ ret = need_fallback(key_len);
+ if (ret > 0) {
+ sctx->key_len = key_len;
+ return setkey_fallback_blk(tfm, in_key, key_len);
+ }
switch (key_len) {
case 16:
@@ -283,6 +453,9 @@
struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
struct blkcipher_walk walk;
+ if (unlikely(need_fallback(sctx->key_len)))
+ return fallback_blk_enc(desc, dst, src, nbytes);
+
blkcipher_walk_init(&walk, dst, src, nbytes);
return cbc_aes_crypt(desc, sctx->enc, sctx->iv, &walk);
}
@@ -294,6 +467,9 @@
struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
struct blkcipher_walk walk;
+ if (unlikely(need_fallback(sctx->key_len)))
+ return fallback_blk_dec(desc, dst, src, nbytes);
+
blkcipher_walk_init(&walk, dst, src, nbytes);
return cbc_aes_crypt(desc, sctx->dec, sctx->iv, &walk);
}
@@ -309,6 +485,8 @@
.cra_type = &crypto_blkcipher_type,
.cra_module = THIS_MODULE,
.cra_list = LIST_HEAD_INIT(cbc_aes_alg.cra_list),
+ .cra_init = fallback_init_blk,
+ .cra_exit = fallback_exit_blk,
.cra_u = {
.blkcipher = {
.min_keysize = AES_MIN_KEY_SIZE,
@@ -336,14 +514,10 @@
return -EOPNOTSUPP;
/* z9 109 and z9 BC/EC only support 128 bit key length */
- if (keylen_flag == AES_KEYLEN_128) {
- aes_alg.cra_u.cipher.cia_max_keysize = AES_MIN_KEY_SIZE;
- ecb_aes_alg.cra_u.blkcipher.max_keysize = AES_MIN_KEY_SIZE;
- cbc_aes_alg.cra_u.blkcipher.max_keysize = AES_MIN_KEY_SIZE;
+ if (keylen_flag == AES_KEYLEN_128)
printk(KERN_INFO
"aes_s390: hardware acceleration only available for"
"128 bit keys\n");
- }
ret = crypto_register_alg(&aes_alg);
if (ret)
@@ -382,4 +556,3 @@
MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm");
MODULE_LICENSE("GPL");
-
diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile
index 46bb609..3874c2d 100644
--- a/arch/x86/crypto/Makefile
+++ b/arch/x86/crypto/Makefile
@@ -4,12 +4,16 @@
obj-$(CONFIG_CRYPTO_AES_586) += aes-i586.o
obj-$(CONFIG_CRYPTO_TWOFISH_586) += twofish-i586.o
+obj-$(CONFIG_CRYPTO_SALSA20_586) += salsa20-i586.o
obj-$(CONFIG_CRYPTO_AES_X86_64) += aes-x86_64.o
obj-$(CONFIG_CRYPTO_TWOFISH_X86_64) += twofish-x86_64.o
+obj-$(CONFIG_CRYPTO_SALSA20_X86_64) += salsa20-x86_64.o
-aes-i586-y := aes-i586-asm_32.o aes_32.o
-twofish-i586-y := twofish-i586-asm_32.o twofish_32.o
+aes-i586-y := aes-i586-asm_32.o aes_glue.o
+twofish-i586-y := twofish-i586-asm_32.o twofish_glue.o
+salsa20-i586-y := salsa20-i586-asm_32.o salsa20_glue.o
-aes-x86_64-y := aes-x86_64-asm_64.o aes_64.o
-twofish-x86_64-y := twofish-x86_64-asm_64.o twofish_64.o
+aes-x86_64-y := aes-x86_64-asm_64.o aes_glue.o
+twofish-x86_64-y := twofish-x86_64-asm_64.o twofish_glue.o
+salsa20-x86_64-y := salsa20-x86_64-asm_64.o salsa20_glue.o
diff --git a/arch/x86/crypto/aes-i586-asm_32.S b/arch/x86/crypto/aes-i586-asm_32.S
index f942f0c..1093bed 100644
--- a/arch/x86/crypto/aes-i586-asm_32.S
+++ b/arch/x86/crypto/aes-i586-asm_32.S
@@ -46,9 +46,9 @@
#define in_blk 16
/* offsets in crypto_tfm structure */
-#define ekey (crypto_tfm_ctx_offset + 0)
-#define nrnd (crypto_tfm_ctx_offset + 256)
-#define dkey (crypto_tfm_ctx_offset + 260)
+#define klen (crypto_tfm_ctx_offset + 0)
+#define ekey (crypto_tfm_ctx_offset + 4)
+#define dkey (crypto_tfm_ctx_offset + 244)
// register mapping for encrypt and decrypt subroutines
@@ -221,8 +221,8 @@
.global aes_enc_blk
-.extern ft_tab
-.extern fl_tab
+.extern crypto_ft_tab
+.extern crypto_fl_tab
.align 4
@@ -236,7 +236,7 @@
1: push %ebx
mov in_blk+4(%esp),%r2
push %esi
- mov nrnd(%ebp),%r3 // number of rounds
+ mov klen(%ebp),%r3 // key size
push %edi
#if ekey != 0
lea ekey(%ebp),%ebp // key pointer
@@ -255,26 +255,26 @@
sub $8,%esp // space for register saves on stack
add $16,%ebp // increment to next round key
- cmp $12,%r3
+ cmp $24,%r3
jb 4f // 10 rounds for 128-bit key
lea 32(%ebp),%ebp
je 3f // 12 rounds for 192-bit key
lea 32(%ebp),%ebp
-2: fwd_rnd1( -64(%ebp) ,ft_tab) // 14 rounds for 256-bit key
- fwd_rnd2( -48(%ebp) ,ft_tab)
-3: fwd_rnd1( -32(%ebp) ,ft_tab) // 12 rounds for 192-bit key
- fwd_rnd2( -16(%ebp) ,ft_tab)
-4: fwd_rnd1( (%ebp) ,ft_tab) // 10 rounds for 128-bit key
- fwd_rnd2( +16(%ebp) ,ft_tab)
- fwd_rnd1( +32(%ebp) ,ft_tab)
- fwd_rnd2( +48(%ebp) ,ft_tab)
- fwd_rnd1( +64(%ebp) ,ft_tab)
- fwd_rnd2( +80(%ebp) ,ft_tab)
- fwd_rnd1( +96(%ebp) ,ft_tab)
- fwd_rnd2(+112(%ebp) ,ft_tab)
- fwd_rnd1(+128(%ebp) ,ft_tab)
- fwd_rnd2(+144(%ebp) ,fl_tab) // last round uses a different table
+2: fwd_rnd1( -64(%ebp), crypto_ft_tab) // 14 rounds for 256-bit key
+ fwd_rnd2( -48(%ebp), crypto_ft_tab)
+3: fwd_rnd1( -32(%ebp), crypto_ft_tab) // 12 rounds for 192-bit key
+ fwd_rnd2( -16(%ebp), crypto_ft_tab)
+4: fwd_rnd1( (%ebp), crypto_ft_tab) // 10 rounds for 128-bit key
+ fwd_rnd2( +16(%ebp), crypto_ft_tab)
+ fwd_rnd1( +32(%ebp), crypto_ft_tab)
+ fwd_rnd2( +48(%ebp), crypto_ft_tab)
+ fwd_rnd1( +64(%ebp), crypto_ft_tab)
+ fwd_rnd2( +80(%ebp), crypto_ft_tab)
+ fwd_rnd1( +96(%ebp), crypto_ft_tab)
+ fwd_rnd2(+112(%ebp), crypto_ft_tab)
+ fwd_rnd1(+128(%ebp), crypto_ft_tab)
+ fwd_rnd2(+144(%ebp), crypto_fl_tab) // last round uses a different table
// move final values to the output array. CAUTION: the
// order of these assigns rely on the register mappings
@@ -297,8 +297,8 @@
.global aes_dec_blk
-.extern it_tab
-.extern il_tab
+.extern crypto_it_tab
+.extern crypto_il_tab
.align 4
@@ -312,14 +312,11 @@
1: push %ebx
mov in_blk+4(%esp),%r2
push %esi
- mov nrnd(%ebp),%r3 // number of rounds
+ mov klen(%ebp),%r3 // key size
push %edi
#if dkey != 0
lea dkey(%ebp),%ebp // key pointer
#endif
- mov %r3,%r0
- shl $4,%r0
- add %r0,%ebp
// input four columns and xor in first round key
@@ -333,27 +330,27 @@
xor 12(%ebp),%r5
sub $8,%esp // space for register saves on stack
- sub $16,%ebp // increment to next round key
- cmp $12,%r3
+ add $16,%ebp // increment to next round key
+ cmp $24,%r3
jb 4f // 10 rounds for 128-bit key
- lea -32(%ebp),%ebp
+ lea 32(%ebp),%ebp
je 3f // 12 rounds for 192-bit key
- lea -32(%ebp),%ebp
+ lea 32(%ebp),%ebp
-2: inv_rnd1( +64(%ebp), it_tab) // 14 rounds for 256-bit key
- inv_rnd2( +48(%ebp), it_tab)
-3: inv_rnd1( +32(%ebp), it_tab) // 12 rounds for 192-bit key
- inv_rnd2( +16(%ebp), it_tab)
-4: inv_rnd1( (%ebp), it_tab) // 10 rounds for 128-bit key
- inv_rnd2( -16(%ebp), it_tab)
- inv_rnd1( -32(%ebp), it_tab)
- inv_rnd2( -48(%ebp), it_tab)
- inv_rnd1( -64(%ebp), it_tab)
- inv_rnd2( -80(%ebp), it_tab)
- inv_rnd1( -96(%ebp), it_tab)
- inv_rnd2(-112(%ebp), it_tab)
- inv_rnd1(-128(%ebp), it_tab)
- inv_rnd2(-144(%ebp), il_tab) // last round uses a different table
+2: inv_rnd1( -64(%ebp), crypto_it_tab) // 14 rounds for 256-bit key
+ inv_rnd2( -48(%ebp), crypto_it_tab)
+3: inv_rnd1( -32(%ebp), crypto_it_tab) // 12 rounds for 192-bit key
+ inv_rnd2( -16(%ebp), crypto_it_tab)
+4: inv_rnd1( (%ebp), crypto_it_tab) // 10 rounds for 128-bit key
+ inv_rnd2( +16(%ebp), crypto_it_tab)
+ inv_rnd1( +32(%ebp), crypto_it_tab)
+ inv_rnd2( +48(%ebp), crypto_it_tab)
+ inv_rnd1( +64(%ebp), crypto_it_tab)
+ inv_rnd2( +80(%ebp), crypto_it_tab)
+ inv_rnd1( +96(%ebp), crypto_it_tab)
+ inv_rnd2(+112(%ebp), crypto_it_tab)
+ inv_rnd1(+128(%ebp), crypto_it_tab)
+ inv_rnd2(+144(%ebp), crypto_il_tab) // last round uses a different table
// move final values to the output array. CAUTION: the
// order of these assigns rely on the register mappings
diff --git a/arch/x86/crypto/aes-x86_64-asm_64.S b/arch/x86/crypto/aes-x86_64-asm_64.S
index 26b40de4..a120f52 100644
--- a/arch/x86/crypto/aes-x86_64-asm_64.S
+++ b/arch/x86/crypto/aes-x86_64-asm_64.S
@@ -8,10 +8,10 @@
* including this sentence is retained in full.
*/
-.extern aes_ft_tab
-.extern aes_it_tab
-.extern aes_fl_tab
-.extern aes_il_tab
+.extern crypto_ft_tab
+.extern crypto_it_tab
+.extern crypto_fl_tab
+.extern crypto_il_tab
.text
@@ -56,13 +56,13 @@
.align 8; \
FUNC: movq r1,r2; \
movq r3,r4; \
- leaq BASE+KEY+52(r8),r9; \
+ leaq BASE+KEY+48+4(r8),r9; \
movq r10,r11; \
movl (r7),r5 ## E; \
movl 4(r7),r1 ## E; \
movl 8(r7),r6 ## E; \
movl 12(r7),r7 ## E; \
- movl BASE(r8),r10 ## E; \
+ movl BASE+0(r8),r10 ## E; \
xorl -48(r9),r5 ## E; \
xorl -44(r9),r1 ## E; \
xorl -40(r9),r6 ## E; \
@@ -154,37 +154,37 @@
/* void aes_enc_blk(stuct crypto_tfm *tfm, u8 *out, const u8 *in) */
entry(aes_enc_blk,0,enc128,enc192)
- encrypt_round(aes_ft_tab,-96)
- encrypt_round(aes_ft_tab,-80)
-enc192: encrypt_round(aes_ft_tab,-64)
- encrypt_round(aes_ft_tab,-48)
-enc128: encrypt_round(aes_ft_tab,-32)
- encrypt_round(aes_ft_tab,-16)
- encrypt_round(aes_ft_tab, 0)
- encrypt_round(aes_ft_tab, 16)
- encrypt_round(aes_ft_tab, 32)
- encrypt_round(aes_ft_tab, 48)
- encrypt_round(aes_ft_tab, 64)
- encrypt_round(aes_ft_tab, 80)
- encrypt_round(aes_ft_tab, 96)
- encrypt_final(aes_fl_tab,112)
+ encrypt_round(crypto_ft_tab,-96)
+ encrypt_round(crypto_ft_tab,-80)
+enc192: encrypt_round(crypto_ft_tab,-64)
+ encrypt_round(crypto_ft_tab,-48)
+enc128: encrypt_round(crypto_ft_tab,-32)
+ encrypt_round(crypto_ft_tab,-16)
+ encrypt_round(crypto_ft_tab, 0)
+ encrypt_round(crypto_ft_tab, 16)
+ encrypt_round(crypto_ft_tab, 32)
+ encrypt_round(crypto_ft_tab, 48)
+ encrypt_round(crypto_ft_tab, 64)
+ encrypt_round(crypto_ft_tab, 80)
+ encrypt_round(crypto_ft_tab, 96)
+ encrypt_final(crypto_fl_tab,112)
return
/* void aes_dec_blk(struct crypto_tfm *tfm, u8 *out, const u8 *in) */
entry(aes_dec_blk,240,dec128,dec192)
- decrypt_round(aes_it_tab,-96)
- decrypt_round(aes_it_tab,-80)
-dec192: decrypt_round(aes_it_tab,-64)
- decrypt_round(aes_it_tab,-48)
-dec128: decrypt_round(aes_it_tab,-32)
- decrypt_round(aes_it_tab,-16)
- decrypt_round(aes_it_tab, 0)
- decrypt_round(aes_it_tab, 16)
- decrypt_round(aes_it_tab, 32)
- decrypt_round(aes_it_tab, 48)
- decrypt_round(aes_it_tab, 64)
- decrypt_round(aes_it_tab, 80)
- decrypt_round(aes_it_tab, 96)
- decrypt_final(aes_il_tab,112)
+ decrypt_round(crypto_it_tab,-96)
+ decrypt_round(crypto_it_tab,-80)
+dec192: decrypt_round(crypto_it_tab,-64)
+ decrypt_round(crypto_it_tab,-48)
+dec128: decrypt_round(crypto_it_tab,-32)
+ decrypt_round(crypto_it_tab,-16)
+ decrypt_round(crypto_it_tab, 0)
+ decrypt_round(crypto_it_tab, 16)
+ decrypt_round(crypto_it_tab, 32)
+ decrypt_round(crypto_it_tab, 48)
+ decrypt_round(crypto_it_tab, 64)
+ decrypt_round(crypto_it_tab, 80)
+ decrypt_round(crypto_it_tab, 96)
+ decrypt_final(crypto_il_tab,112)
return
diff --git a/arch/x86/crypto/aes_32.c b/arch/x86/crypto/aes_32.c
deleted file mode 100644
index 49aad93..0000000
--- a/arch/x86/crypto/aes_32.c
+++ /dev/null
@@ -1,515 +0,0 @@
-/*
- *
- * Glue Code for optimized 586 assembler version of AES
- *
- * Copyright (c) 2002, Dr Brian Gladman <>, Worcester, UK.
- * All rights reserved.
- *
- * LICENSE TERMS
- *
- * The free distribution and use of this software in both source and binary
- * form is allowed (with or without changes) provided that:
- *
- * 1. distributions of this source code include the above copyright
- * notice, this list of conditions and the following disclaimer;
- *
- * 2. distributions in binary form include the above copyright
- * notice, this list of conditions and the following disclaimer
- * in the documentation and/or other associated materials;
- *
- * 3. the copyright holder's name is not used to endorse products
- * built using this software without specific written permission.
- *
- * ALTERNATIVELY, provided that this notice is retained in full, this product
- * may be distributed under the terms of the GNU General Public License (GPL),
- * in which case the provisions of the GPL apply INSTEAD OF those given above.
- *
- * DISCLAIMER
- *
- * This software is provided 'as is' with no explicit or implied warranties
- * in respect of its properties, including, but not limited to, correctness
- * and/or fitness for purpose.
- *
- * Copyright (c) 2003, Adam J. Richter <adam@yggdrasil.com> (conversion to
- * 2.5 API).
- * Copyright (c) 2003, 2004 Fruhwirth Clemens <clemens@endorphin.org>
- * Copyright (c) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com>
- *
- */
-
-#include <asm/byteorder.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/crypto.h>
-#include <linux/linkage.h>
-
-asmlinkage void aes_enc_blk(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
-asmlinkage void aes_dec_blk(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
-
-#define AES_MIN_KEY_SIZE 16
-#define AES_MAX_KEY_SIZE 32
-#define AES_BLOCK_SIZE 16
-#define AES_KS_LENGTH 4 * AES_BLOCK_SIZE
-#define RC_LENGTH 29
-
-struct aes_ctx {
- u32 ekey[AES_KS_LENGTH];
- u32 rounds;
- u32 dkey[AES_KS_LENGTH];
-};
-
-#define WPOLY 0x011b
-#define bytes2word(b0, b1, b2, b3) \
- (((u32)(b3) << 24) | ((u32)(b2) << 16) | ((u32)(b1) << 8) | (b0))
-
-/* define the finite field multiplies required for Rijndael */
-#define f2(x) ((x) ? pow[log[x] + 0x19] : 0)
-#define f3(x) ((x) ? pow[log[x] + 0x01] : 0)
-#define f9(x) ((x) ? pow[log[x] + 0xc7] : 0)
-#define fb(x) ((x) ? pow[log[x] + 0x68] : 0)
-#define fd(x) ((x) ? pow[log[x] + 0xee] : 0)
-#define fe(x) ((x) ? pow[log[x] + 0xdf] : 0)
-#define fi(x) ((x) ? pow[255 - log[x]]: 0)
-
-static inline u32 upr(u32 x, int n)
-{
- return (x << 8 * n) | (x >> (32 - 8 * n));
-}
-
-static inline u8 bval(u32 x, int n)
-{
- return x >> 8 * n;
-}
-
-/* The forward and inverse affine transformations used in the S-box */
-#define fwd_affine(x) \
- (w = (u32)x, w ^= (w<<1)^(w<<2)^(w<<3)^(w<<4), 0x63^(u8)(w^(w>>8)))
-
-#define inv_affine(x) \
- (w = (u32)x, w = (w<<1)^(w<<3)^(w<<6), 0x05^(u8)(w^(w>>8)))
-
-static u32 rcon_tab[RC_LENGTH];
-
-u32 ft_tab[4][256];
-u32 fl_tab[4][256];
-static u32 im_tab[4][256];
-u32 il_tab[4][256];
-u32 it_tab[4][256];
-
-static void gen_tabs(void)
-{
- u32 i, w;
- u8 pow[512], log[256];
-
- /*
- * log and power tables for GF(2^8) finite field with
- * WPOLY as modular polynomial - the simplest primitive
- * root is 0x03, used here to generate the tables.
- */
- i = 0; w = 1;
-
- do {
- pow[i] = (u8)w;
- pow[i + 255] = (u8)w;
- log[w] = (u8)i++;
- w ^= (w << 1) ^ (w & 0x80 ? WPOLY : 0);
- } while (w != 1);
-
- for(i = 0, w = 1; i < RC_LENGTH; ++i) {
- rcon_tab[i] = bytes2word(w, 0, 0, 0);
- w = f2(w);
- }
-
- for(i = 0; i < 256; ++i) {
- u8 b;
-
- b = fwd_affine(fi((u8)i));
- w = bytes2word(f2(b), b, b, f3(b));
-
- /* tables for a normal encryption round */
- ft_tab[0][i] = w;
- ft_tab[1][i] = upr(w, 1);
- ft_tab[2][i] = upr(w, 2);
- ft_tab[3][i] = upr(w, 3);
- w = bytes2word(b, 0, 0, 0);
-
- /*
- * tables for last encryption round
- * (may also be used in the key schedule)
- */
- fl_tab[0][i] = w;
- fl_tab[1][i] = upr(w, 1);
- fl_tab[2][i] = upr(w, 2);
- fl_tab[3][i] = upr(w, 3);
-
- b = fi(inv_affine((u8)i));
- w = bytes2word(fe(b), f9(b), fd(b), fb(b));
-
- /* tables for the inverse mix column operation */
- im_tab[0][b] = w;
- im_tab[1][b] = upr(w, 1);
- im_tab[2][b] = upr(w, 2);
- im_tab[3][b] = upr(w, 3);
-
- /* tables for a normal decryption round */
- it_tab[0][i] = w;
- it_tab[1][i] = upr(w,1);
- it_tab[2][i] = upr(w,2);
- it_tab[3][i] = upr(w,3);
-
- w = bytes2word(b, 0, 0, 0);
-
- /* tables for last decryption round */
- il_tab[0][i] = w;
- il_tab[1][i] = upr(w,1);
- il_tab[2][i] = upr(w,2);
- il_tab[3][i] = upr(w,3);
- }
-}
-
-#define four_tables(x,tab,vf,rf,c) \
-( tab[0][bval(vf(x,0,c),rf(0,c))] ^ \
- tab[1][bval(vf(x,1,c),rf(1,c))] ^ \
- tab[2][bval(vf(x,2,c),rf(2,c))] ^ \
- tab[3][bval(vf(x,3,c),rf(3,c))] \
-)
-
-#define vf1(x,r,c) (x)
-#define rf1(r,c) (r)
-#define rf2(r,c) ((r-c)&3)
-
-#define inv_mcol(x) four_tables(x,im_tab,vf1,rf1,0)
-#define ls_box(x,c) four_tables(x,fl_tab,vf1,rf2,c)
-
-#define ff(x) inv_mcol(x)
-
-#define ke4(k,i) \
-{ \
- k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ rcon_tab[i]; \
- k[4*(i)+5] = ss[1] ^= ss[0]; \
- k[4*(i)+6] = ss[2] ^= ss[1]; \
- k[4*(i)+7] = ss[3] ^= ss[2]; \
-}
-
-#define kel4(k,i) \
-{ \
- k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ rcon_tab[i]; \
- k[4*(i)+5] = ss[1] ^= ss[0]; \
- k[4*(i)+6] = ss[2] ^= ss[1]; k[4*(i)+7] = ss[3] ^= ss[2]; \
-}
-
-#define ke6(k,i) \
-{ \
- k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ rcon_tab[i]; \
- k[6*(i)+ 7] = ss[1] ^= ss[0]; \
- k[6*(i)+ 8] = ss[2] ^= ss[1]; \
- k[6*(i)+ 9] = ss[3] ^= ss[2]; \
- k[6*(i)+10] = ss[4] ^= ss[3]; \
- k[6*(i)+11] = ss[5] ^= ss[4]; \
-}
-
-#define kel6(k,i) \
-{ \
- k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ rcon_tab[i]; \
- k[6*(i)+ 7] = ss[1] ^= ss[0]; \
- k[6*(i)+ 8] = ss[2] ^= ss[1]; \
- k[6*(i)+ 9] = ss[3] ^= ss[2]; \
-}
-
-#define ke8(k,i) \
-{ \
- k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ rcon_tab[i]; \
- k[8*(i)+ 9] = ss[1] ^= ss[0]; \
- k[8*(i)+10] = ss[2] ^= ss[1]; \
- k[8*(i)+11] = ss[3] ^= ss[2]; \
- k[8*(i)+12] = ss[4] ^= ls_box(ss[3],0); \
- k[8*(i)+13] = ss[5] ^= ss[4]; \
- k[8*(i)+14] = ss[6] ^= ss[5]; \
- k[8*(i)+15] = ss[7] ^= ss[6]; \
-}
-
-#define kel8(k,i) \
-{ \
- k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ rcon_tab[i]; \
- k[8*(i)+ 9] = ss[1] ^= ss[0]; \
- k[8*(i)+10] = ss[2] ^= ss[1]; \
- k[8*(i)+11] = ss[3] ^= ss[2]; \
-}
-
-#define kdf4(k,i) \
-{ \
- ss[0] = ss[0] ^ ss[2] ^ ss[1] ^ ss[3]; \
- ss[1] = ss[1] ^ ss[3]; \
- ss[2] = ss[2] ^ ss[3]; \
- ss[3] = ss[3]; \
- ss[4] = ls_box(ss[(i+3) % 4], 3) ^ rcon_tab[i]; \
- ss[i % 4] ^= ss[4]; \
- ss[4] ^= k[4*(i)]; \
- k[4*(i)+4] = ff(ss[4]); \
- ss[4] ^= k[4*(i)+1]; \
- k[4*(i)+5] = ff(ss[4]); \
- ss[4] ^= k[4*(i)+2]; \
- k[4*(i)+6] = ff(ss[4]); \
- ss[4] ^= k[4*(i)+3]; \
- k[4*(i)+7] = ff(ss[4]); \
-}
-
-#define kd4(k,i) \
-{ \
- ss[4] = ls_box(ss[(i+3) % 4], 3) ^ rcon_tab[i]; \
- ss[i % 4] ^= ss[4]; \
- ss[4] = ff(ss[4]); \
- k[4*(i)+4] = ss[4] ^= k[4*(i)]; \
- k[4*(i)+5] = ss[4] ^= k[4*(i)+1]; \
- k[4*(i)+6] = ss[4] ^= k[4*(i)+2]; \
- k[4*(i)+7] = ss[4] ^= k[4*(i)+3]; \
-}
-
-#define kdl4(k,i) \
-{ \
- ss[4] = ls_box(ss[(i+3) % 4], 3) ^ rcon_tab[i]; \
- ss[i % 4] ^= ss[4]; \
- k[4*(i)+4] = (ss[0] ^= ss[1]) ^ ss[2] ^ ss[3]; \
- k[4*(i)+5] = ss[1] ^ ss[3]; \
- k[4*(i)+6] = ss[0]; \
- k[4*(i)+7] = ss[1]; \
-}
-
-#define kdf6(k,i) \
-{ \
- ss[0] ^= ls_box(ss[5],3) ^ rcon_tab[i]; \
- k[6*(i)+ 6] = ff(ss[0]); \
- ss[1] ^= ss[0]; \
- k[6*(i)+ 7] = ff(ss[1]); \
- ss[2] ^= ss[1]; \
- k[6*(i)+ 8] = ff(ss[2]); \
- ss[3] ^= ss[2]; \
- k[6*(i)+ 9] = ff(ss[3]); \
- ss[4] ^= ss[3]; \
- k[6*(i)+10] = ff(ss[4]); \
- ss[5] ^= ss[4]; \
- k[6*(i)+11] = ff(ss[5]); \
-}
-
-#define kd6(k,i) \
-{ \
- ss[6] = ls_box(ss[5],3) ^ rcon_tab[i]; \
- ss[0] ^= ss[6]; ss[6] = ff(ss[6]); \
- k[6*(i)+ 6] = ss[6] ^= k[6*(i)]; \
- ss[1] ^= ss[0]; \
- k[6*(i)+ 7] = ss[6] ^= k[6*(i)+ 1]; \
- ss[2] ^= ss[1]; \
- k[6*(i)+ 8] = ss[6] ^= k[6*(i)+ 2]; \
- ss[3] ^= ss[2]; \
- k[6*(i)+ 9] = ss[6] ^= k[6*(i)+ 3]; \
- ss[4] ^= ss[3]; \
- k[6*(i)+10] = ss[6] ^= k[6*(i)+ 4]; \
- ss[5] ^= ss[4]; \
- k[6*(i)+11] = ss[6] ^= k[6*(i)+ 5]; \
-}
-
-#define kdl6(k,i) \
-{ \
- ss[0] ^= ls_box(ss[5],3) ^ rcon_tab[i]; \
- k[6*(i)+ 6] = ss[0]; \
- ss[1] ^= ss[0]; \
- k[6*(i)+ 7] = ss[1]; \
- ss[2] ^= ss[1]; \
- k[6*(i)+ 8] = ss[2]; \
- ss[3] ^= ss[2]; \
- k[6*(i)+ 9] = ss[3]; \
-}
-
-#define kdf8(k,i) \
-{ \
- ss[0] ^= ls_box(ss[7],3) ^ rcon_tab[i]; \
- k[8*(i)+ 8] = ff(ss[0]); \
- ss[1] ^= ss[0]; \
- k[8*(i)+ 9] = ff(ss[1]); \
- ss[2] ^= ss[1]; \
- k[8*(i)+10] = ff(ss[2]); \
- ss[3] ^= ss[2]; \
- k[8*(i)+11] = ff(ss[3]); \
- ss[4] ^= ls_box(ss[3],0); \
- k[8*(i)+12] = ff(ss[4]); \
- ss[5] ^= ss[4]; \
- k[8*(i)+13] = ff(ss[5]); \
- ss[6] ^= ss[5]; \
- k[8*(i)+14] = ff(ss[6]); \
- ss[7] ^= ss[6]; \
- k[8*(i)+15] = ff(ss[7]); \
-}
-
-#define kd8(k,i) \
-{ \
- u32 __g = ls_box(ss[7],3) ^ rcon_tab[i]; \
- ss[0] ^= __g; \
- __g = ff(__g); \
- k[8*(i)+ 8] = __g ^= k[8*(i)]; \
- ss[1] ^= ss[0]; \
- k[8*(i)+ 9] = __g ^= k[8*(i)+ 1]; \
- ss[2] ^= ss[1]; \
- k[8*(i)+10] = __g ^= k[8*(i)+ 2]; \
- ss[3] ^= ss[2]; \
- k[8*(i)+11] = __g ^= k[8*(i)+ 3]; \
- __g = ls_box(ss[3],0); \
- ss[4] ^= __g; \
- __g = ff(__g); \
- k[8*(i)+12] = __g ^= k[8*(i)+ 4]; \
- ss[5] ^= ss[4]; \
- k[8*(i)+13] = __g ^= k[8*(i)+ 5]; \
- ss[6] ^= ss[5]; \
- k[8*(i)+14] = __g ^= k[8*(i)+ 6]; \
- ss[7] ^= ss[6]; \
- k[8*(i)+15] = __g ^= k[8*(i)+ 7]; \
-}
-
-#define kdl8(k,i) \
-{ \
- ss[0] ^= ls_box(ss[7],3) ^ rcon_tab[i]; \
- k[8*(i)+ 8] = ss[0]; \
- ss[1] ^= ss[0]; \
- k[8*(i)+ 9] = ss[1]; \
- ss[2] ^= ss[1]; \
- k[8*(i)+10] = ss[2]; \
- ss[3] ^= ss[2]; \
- k[8*(i)+11] = ss[3]; \
-}
-
-static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
- unsigned int key_len)
-{
- int i;
- u32 ss[8];
- struct aes_ctx *ctx = crypto_tfm_ctx(tfm);
- const __le32 *key = (const __le32 *)in_key;
- u32 *flags = &tfm->crt_flags;
-
- /* encryption schedule */
-
- ctx->ekey[0] = ss[0] = le32_to_cpu(key[0]);
- ctx->ekey[1] = ss[1] = le32_to_cpu(key[1]);
- ctx->ekey[2] = ss[2] = le32_to_cpu(key[2]);
- ctx->ekey[3] = ss[3] = le32_to_cpu(key[3]);
-
- switch(key_len) {
- case 16:
- for (i = 0; i < 9; i++)
- ke4(ctx->ekey, i);
- kel4(ctx->ekey, 9);
- ctx->rounds = 10;
- break;
-
- case 24:
- ctx->ekey[4] = ss[4] = le32_to_cpu(key[4]);
- ctx->ekey[5] = ss[5] = le32_to_cpu(key[5]);
- for (i = 0; i < 7; i++)
- ke6(ctx->ekey, i);
- kel6(ctx->ekey, 7);
- ctx->rounds = 12;
- break;
-
- case 32:
- ctx->ekey[4] = ss[4] = le32_to_cpu(key[4]);
- ctx->ekey[5] = ss[5] = le32_to_cpu(key[5]);
- ctx->ekey[6] = ss[6] = le32_to_cpu(key[6]);
- ctx->ekey[7] = ss[7] = le32_to_cpu(key[7]);
- for (i = 0; i < 6; i++)
- ke8(ctx->ekey, i);
- kel8(ctx->ekey, 6);
- ctx->rounds = 14;
- break;
-
- default:
- *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
- return -EINVAL;
- }
-
- /* decryption schedule */
-
- ctx->dkey[0] = ss[0] = le32_to_cpu(key[0]);
- ctx->dkey[1] = ss[1] = le32_to_cpu(key[1]);
- ctx->dkey[2] = ss[2] = le32_to_cpu(key[2]);
- ctx->dkey[3] = ss[3] = le32_to_cpu(key[3]);
-
- switch (key_len) {
- case 16:
- kdf4(ctx->dkey, 0);
- for (i = 1; i < 9; i++)
- kd4(ctx->dkey, i);
- kdl4(ctx->dkey, 9);
- break;
-
- case 24:
- ctx->dkey[4] = ff(ss[4] = le32_to_cpu(key[4]));
- ctx->dkey[5] = ff(ss[5] = le32_to_cpu(key[5]));
- kdf6(ctx->dkey, 0);
- for (i = 1; i < 7; i++)
- kd6(ctx->dkey, i);
- kdl6(ctx->dkey, 7);
- break;
-
- case 32:
- ctx->dkey[4] = ff(ss[4] = le32_to_cpu(key[4]));
- ctx->dkey[5] = ff(ss[5] = le32_to_cpu(key[5]));
- ctx->dkey[6] = ff(ss[6] = le32_to_cpu(key[6]));
- ctx->dkey[7] = ff(ss[7] = le32_to_cpu(key[7]));
- kdf8(ctx->dkey, 0);
- for (i = 1; i < 6; i++)
- kd8(ctx->dkey, i);
- kdl8(ctx->dkey, 6);
- break;
- }
- return 0;
-}
-
-static void aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
-{
- aes_enc_blk(tfm, dst, src);
-}
-
-static void aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
-{
- aes_dec_blk(tfm, dst, src);
-}
-
-static struct crypto_alg aes_alg = {
- .cra_name = "aes",
- .cra_driver_name = "aes-i586",
- .cra_priority = 200,
- .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
- .cra_blocksize = AES_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct aes_ctx),
- .cra_module = THIS_MODULE,
- .cra_list = LIST_HEAD_INIT(aes_alg.cra_list),
- .cra_u = {
- .cipher = {
- .cia_min_keysize = AES_MIN_KEY_SIZE,
- .cia_max_keysize = AES_MAX_KEY_SIZE,
- .cia_setkey = aes_set_key,
- .cia_encrypt = aes_encrypt,
- .cia_decrypt = aes_decrypt
- }
- }
-};
-
-static int __init aes_init(void)
-{
- gen_tabs();
- return crypto_register_alg(&aes_alg);
-}
-
-static void __exit aes_fini(void)
-{
- crypto_unregister_alg(&aes_alg);
-}
-
-module_init(aes_init);
-module_exit(aes_fini);
-
-MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm, i586 asm optimized");
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_AUTHOR("Fruhwirth Clemens, James Morris, Brian Gladman, Adam Richter");
-MODULE_ALIAS("aes");
diff --git a/arch/x86/crypto/aes_64.c b/arch/x86/crypto/aes_64.c
deleted file mode 100644
index 5cdb13e..0000000
--- a/arch/x86/crypto/aes_64.c
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- * Cryptographic API.
- *
- * AES Cipher Algorithm.
- *
- * Based on Brian Gladman's code.
- *
- * Linux developers:
- * Alexander Kjeldaas <astor@fast.no>
- * Herbert Valerio Riedel <hvr@hvrlab.org>
- * Kyle McMartin <kyle@debian.org>
- * Adam J. Richter <adam@yggdrasil.com> (conversion to 2.5 API).
- * Andreas Steinmetz <ast@domdv.de> (adapted to x86_64 assembler)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * ---------------------------------------------------------------------------
- * Copyright (c) 2002, Dr Brian Gladman <brg@gladman.me.uk>, Worcester, UK.
- * All rights reserved.
- *
- * LICENSE TERMS
- *
- * The free distribution and use of this software in both source and binary
- * form is allowed (with or without changes) provided that:
- *
- * 1. distributions of this source code include the above copyright
- * notice, this list of conditions and the following disclaimer;
- *
- * 2. distributions in binary form include the above copyright
- * notice, this list of conditions and the following disclaimer
- * in the documentation and/or other associated materials;
- *
- * 3. the copyright holder's name is not used to endorse products
- * built using this software without specific written permission.
- *
- * ALTERNATIVELY, provided that this notice is retained in full, this product
- * may be distributed under the terms of the GNU General Public License (GPL),
- * in which case the provisions of the GPL apply INSTEAD OF those given above.
- *
- * DISCLAIMER
- *
- * This software is provided 'as is' with no explicit or implied warranties
- * in respect of its properties, including, but not limited to, correctness
- * and/or fitness for purpose.
- * ---------------------------------------------------------------------------
- */
-
-/* Some changes from the Gladman version:
- s/RIJNDAEL(e_key)/E_KEY/g
- s/RIJNDAEL(d_key)/D_KEY/g
-*/
-
-#include <asm/byteorder.h>
-#include <linux/bitops.h>
-#include <linux/crypto.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/types.h>
-
-#define AES_MIN_KEY_SIZE 16
-#define AES_MAX_KEY_SIZE 32
-
-#define AES_BLOCK_SIZE 16
-
-/*
- * #define byte(x, nr) ((unsigned char)((x) >> (nr*8)))
- */
-static inline u8 byte(const u32 x, const unsigned n)
-{
- return x >> (n << 3);
-}
-
-struct aes_ctx
-{
- u32 key_length;
- u32 buf[120];
-};
-
-#define E_KEY (&ctx->buf[0])
-#define D_KEY (&ctx->buf[60])
-
-static u8 pow_tab[256] __initdata;
-static u8 log_tab[256] __initdata;
-static u8 sbx_tab[256] __initdata;
-static u8 isb_tab[256] __initdata;
-static u32 rco_tab[10];
-u32 aes_ft_tab[4][256];
-u32 aes_it_tab[4][256];
-
-u32 aes_fl_tab[4][256];
-u32 aes_il_tab[4][256];
-
-static inline u8 f_mult(u8 a, u8 b)
-{
- u8 aa = log_tab[a], cc = aa + log_tab[b];
-
- return pow_tab[cc + (cc < aa ? 1 : 0)];
-}
-
-#define ff_mult(a, b) (a && b ? f_mult(a, b) : 0)
-
-#define ls_box(x) \
- (aes_fl_tab[0][byte(x, 0)] ^ \
- aes_fl_tab[1][byte(x, 1)] ^ \
- aes_fl_tab[2][byte(x, 2)] ^ \
- aes_fl_tab[3][byte(x, 3)])
-
-static void __init gen_tabs(void)
-{
- u32 i, t;
- u8 p, q;
-
- /* log and power tables for GF(2**8) finite field with
- 0x011b as modular polynomial - the simplest primitive
- root is 0x03, used here to generate the tables */
-
- for (i = 0, p = 1; i < 256; ++i) {
- pow_tab[i] = (u8)p;
- log_tab[p] = (u8)i;
-
- p ^= (p << 1) ^ (p & 0x80 ? 0x01b : 0);
- }
-
- log_tab[1] = 0;
-
- for (i = 0, p = 1; i < 10; ++i) {
- rco_tab[i] = p;
-
- p = (p << 1) ^ (p & 0x80 ? 0x01b : 0);
- }
-
- for (i = 0; i < 256; ++i) {
- p = (i ? pow_tab[255 - log_tab[i]] : 0);
- q = ((p >> 7) | (p << 1)) ^ ((p >> 6) | (p << 2));
- p ^= 0x63 ^ q ^ ((q >> 6) | (q << 2));
- sbx_tab[i] = p;
- isb_tab[p] = (u8)i;
- }
-
- for (i = 0; i < 256; ++i) {
- p = sbx_tab[i];
-
- t = p;
- aes_fl_tab[0][i] = t;
- aes_fl_tab[1][i] = rol32(t, 8);
- aes_fl_tab[2][i] = rol32(t, 16);
- aes_fl_tab[3][i] = rol32(t, 24);
-
- t = ((u32)ff_mult(2, p)) |
- ((u32)p << 8) |
- ((u32)p << 16) | ((u32)ff_mult(3, p) << 24);
-
- aes_ft_tab[0][i] = t;
- aes_ft_tab[1][i] = rol32(t, 8);
- aes_ft_tab[2][i] = rol32(t, 16);
- aes_ft_tab[3][i] = rol32(t, 24);
-
- p = isb_tab[i];
-
- t = p;
- aes_il_tab[0][i] = t;
- aes_il_tab[1][i] = rol32(t, 8);
- aes_il_tab[2][i] = rol32(t, 16);
- aes_il_tab[3][i] = rol32(t, 24);
-
- t = ((u32)ff_mult(14, p)) |
- ((u32)ff_mult(9, p) << 8) |
- ((u32)ff_mult(13, p) << 16) |
- ((u32)ff_mult(11, p) << 24);
-
- aes_it_tab[0][i] = t;
- aes_it_tab[1][i] = rol32(t, 8);
- aes_it_tab[2][i] = rol32(t, 16);
- aes_it_tab[3][i] = rol32(t, 24);
- }
-}
-
-#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b)
-
-#define imix_col(y, x) \
- u = star_x(x); \
- v = star_x(u); \
- w = star_x(v); \
- t = w ^ (x); \
- (y) = u ^ v ^ w; \
- (y) ^= ror32(u ^ t, 8) ^ \
- ror32(v ^ t, 16) ^ \
- ror32(t, 24)
-
-/* initialise the key schedule from the user supplied key */
-
-#define loop4(i) \
-{ \
- t = ror32(t, 8); t = ls_box(t) ^ rco_tab[i]; \
- t ^= E_KEY[4 * i]; E_KEY[4 * i + 4] = t; \
- t ^= E_KEY[4 * i + 1]; E_KEY[4 * i + 5] = t; \
- t ^= E_KEY[4 * i + 2]; E_KEY[4 * i + 6] = t; \
- t ^= E_KEY[4 * i + 3]; E_KEY[4 * i + 7] = t; \
-}
-
-#define loop6(i) \
-{ \
- t = ror32(t, 8); t = ls_box(t) ^ rco_tab[i]; \
- t ^= E_KEY[6 * i]; E_KEY[6 * i + 6] = t; \
- t ^= E_KEY[6 * i + 1]; E_KEY[6 * i + 7] = t; \
- t ^= E_KEY[6 * i + 2]; E_KEY[6 * i + 8] = t; \
- t ^= E_KEY[6 * i + 3]; E_KEY[6 * i + 9] = t; \
- t ^= E_KEY[6 * i + 4]; E_KEY[6 * i + 10] = t; \
- t ^= E_KEY[6 * i + 5]; E_KEY[6 * i + 11] = t; \
-}
-
-#define loop8(i) \
-{ \
- t = ror32(t, 8); ; t = ls_box(t) ^ rco_tab[i]; \
- t ^= E_KEY[8 * i]; E_KEY[8 * i + 8] = t; \
- t ^= E_KEY[8 * i + 1]; E_KEY[8 * i + 9] = t; \
- t ^= E_KEY[8 * i + 2]; E_KEY[8 * i + 10] = t; \
- t ^= E_KEY[8 * i + 3]; E_KEY[8 * i + 11] = t; \
- t = E_KEY[8 * i + 4] ^ ls_box(t); \
- E_KEY[8 * i + 12] = t; \
- t ^= E_KEY[8 * i + 5]; E_KEY[8 * i + 13] = t; \
- t ^= E_KEY[8 * i + 6]; E_KEY[8 * i + 14] = t; \
- t ^= E_KEY[8 * i + 7]; E_KEY[8 * i + 15] = t; \
-}
-
-static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
- unsigned int key_len)
-{
- struct aes_ctx *ctx = crypto_tfm_ctx(tfm);
- const __le32 *key = (const __le32 *)in_key;
- u32 *flags = &tfm->crt_flags;
- u32 i, j, t, u, v, w;
-
- if (key_len % 8) {
- *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
- return -EINVAL;
- }
-
- ctx->key_length = key_len;
-
- D_KEY[key_len + 24] = E_KEY[0] = le32_to_cpu(key[0]);
- D_KEY[key_len + 25] = E_KEY[1] = le32_to_cpu(key[1]);
- D_KEY[key_len + 26] = E_KEY[2] = le32_to_cpu(key[2]);
- D_KEY[key_len + 27] = E_KEY[3] = le32_to_cpu(key[3]);
-
- switch (key_len) {
- case 16:
- t = E_KEY[3];
- for (i = 0; i < 10; ++i)
- loop4(i);
- break;
-
- case 24:
- E_KEY[4] = le32_to_cpu(key[4]);
- t = E_KEY[5] = le32_to_cpu(key[5]);
- for (i = 0; i < 8; ++i)
- loop6 (i);
- break;
-
- case 32:
- E_KEY[4] = le32_to_cpu(key[4]);
- E_KEY[5] = le32_to_cpu(key[5]);
- E_KEY[6] = le32_to_cpu(key[6]);
- t = E_KEY[7] = le32_to_cpu(key[7]);
- for (i = 0; i < 7; ++i)
- loop8(i);
- break;
- }
-
- D_KEY[0] = E_KEY[key_len + 24];
- D_KEY[1] = E_KEY[key_len + 25];
- D_KEY[2] = E_KEY[key_len + 26];
- D_KEY[3] = E_KEY[key_len + 27];
-
- for (i = 4; i < key_len + 24; ++i) {
- j = key_len + 24 - (i & ~3) + (i & 3);
- imix_col(D_KEY[j], E_KEY[i]);
- }
-
- return 0;
-}
-
-asmlinkage void aes_enc_blk(struct crypto_tfm *tfm, u8 *out, const u8 *in);
-asmlinkage void aes_dec_blk(struct crypto_tfm *tfm, u8 *out, const u8 *in);
-
-static void aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
-{
- aes_enc_blk(tfm, dst, src);
-}
-
-static void aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
-{
- aes_dec_blk(tfm, dst, src);
-}
-
-static struct crypto_alg aes_alg = {
- .cra_name = "aes",
- .cra_driver_name = "aes-x86_64",
- .cra_priority = 200,
- .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
- .cra_blocksize = AES_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct aes_ctx),
- .cra_module = THIS_MODULE,
- .cra_list = LIST_HEAD_INIT(aes_alg.cra_list),
- .cra_u = {
- .cipher = {
- .cia_min_keysize = AES_MIN_KEY_SIZE,
- .cia_max_keysize = AES_MAX_KEY_SIZE,
- .cia_setkey = aes_set_key,
- .cia_encrypt = aes_encrypt,
- .cia_decrypt = aes_decrypt
- }
- }
-};
-
-static int __init aes_init(void)
-{
- gen_tabs();
- return crypto_register_alg(&aes_alg);
-}
-
-static void __exit aes_fini(void)
-{
- crypto_unregister_alg(&aes_alg);
-}
-
-module_init(aes_init);
-module_exit(aes_fini);
-
-MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("aes");
diff --git a/arch/x86/crypto/aes_glue.c b/arch/x86/crypto/aes_glue.c
new file mode 100644
index 0000000..71f4578
--- /dev/null
+++ b/arch/x86/crypto/aes_glue.c
@@ -0,0 +1,57 @@
+/*
+ * Glue Code for the asm optimized version of the AES Cipher Algorithm
+ *
+ */
+
+#include <crypto/aes.h>
+
+asmlinkage void aes_enc_blk(struct crypto_tfm *tfm, u8 *out, const u8 *in);
+asmlinkage void aes_dec_blk(struct crypto_tfm *tfm, u8 *out, const u8 *in);
+
+static void aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+ aes_enc_blk(tfm, dst, src);
+}
+
+static void aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+ aes_dec_blk(tfm, dst, src);
+}
+
+static struct crypto_alg aes_alg = {
+ .cra_name = "aes",
+ .cra_driver_name = "aes-asm",
+ .cra_priority = 200,
+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct crypto_aes_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(aes_alg.cra_list),
+ .cra_u = {
+ .cipher = {
+ .cia_min_keysize = AES_MIN_KEY_SIZE,
+ .cia_max_keysize = AES_MAX_KEY_SIZE,
+ .cia_setkey = crypto_aes_set_key,
+ .cia_encrypt = aes_encrypt,
+ .cia_decrypt = aes_decrypt
+ }
+ }
+};
+
+static int __init aes_init(void)
+{
+ return crypto_register_alg(&aes_alg);
+}
+
+static void __exit aes_fini(void)
+{
+ crypto_unregister_alg(&aes_alg);
+}
+
+module_init(aes_init);
+module_exit(aes_fini);
+
+MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm, asm optimized");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("aes");
+MODULE_ALIAS("aes-asm");
diff --git a/arch/x86/crypto/salsa20-i586-asm_32.S b/arch/x86/crypto/salsa20-i586-asm_32.S
new file mode 100644
index 0000000..72eb306
--- /dev/null
+++ b/arch/x86/crypto/salsa20-i586-asm_32.S
@@ -0,0 +1,1114 @@
+# salsa20_pm.s version 20051229
+# D. J. Bernstein
+# Public domain.
+
+# enter ECRYPT_encrypt_bytes
+.text
+.p2align 5
+.globl ECRYPT_encrypt_bytes
+ECRYPT_encrypt_bytes:
+ mov %esp,%eax
+ and $31,%eax
+ add $256,%eax
+ sub %eax,%esp
+ # eax_stack = eax
+ movl %eax,80(%esp)
+ # ebx_stack = ebx
+ movl %ebx,84(%esp)
+ # esi_stack = esi
+ movl %esi,88(%esp)
+ # edi_stack = edi
+ movl %edi,92(%esp)
+ # ebp_stack = ebp
+ movl %ebp,96(%esp)
+ # x = arg1
+ movl 4(%esp,%eax),%edx
+ # m = arg2
+ movl 8(%esp,%eax),%esi
+ # out = arg3
+ movl 12(%esp,%eax),%edi
+ # bytes = arg4
+ movl 16(%esp,%eax),%ebx
+ # bytes -= 0
+ sub $0,%ebx
+ # goto done if unsigned<=
+ jbe ._done
+._start:
+ # in0 = *(uint32 *) (x + 0)
+ movl 0(%edx),%eax
+ # in1 = *(uint32 *) (x + 4)
+ movl 4(%edx),%ecx
+ # in2 = *(uint32 *) (x + 8)
+ movl 8(%edx),%ebp
+ # j0 = in0
+ movl %eax,164(%esp)
+ # in3 = *(uint32 *) (x + 12)
+ movl 12(%edx),%eax
+ # j1 = in1
+ movl %ecx,168(%esp)
+ # in4 = *(uint32 *) (x + 16)
+ movl 16(%edx),%ecx
+ # j2 = in2
+ movl %ebp,172(%esp)
+ # in5 = *(uint32 *) (x + 20)
+ movl 20(%edx),%ebp
+ # j3 = in3
+ movl %eax,176(%esp)
+ # in6 = *(uint32 *) (x + 24)
+ movl 24(%edx),%eax
+ # j4 = in4
+ movl %ecx,180(%esp)
+ # in7 = *(uint32 *) (x + 28)
+ movl 28(%edx),%ecx
+ # j5 = in5
+ movl %ebp,184(%esp)
+ # in8 = *(uint32 *) (x + 32)
+ movl 32(%edx),%ebp
+ # j6 = in6
+ movl %eax,188(%esp)
+ # in9 = *(uint32 *) (x + 36)
+ movl 36(%edx),%eax
+ # j7 = in7
+ movl %ecx,192(%esp)
+ # in10 = *(uint32 *) (x + 40)
+ movl 40(%edx),%ecx
+ # j8 = in8
+ movl %ebp,196(%esp)
+ # in11 = *(uint32 *) (x + 44)
+ movl 44(%edx),%ebp
+ # j9 = in9
+ movl %eax,200(%esp)
+ # in12 = *(uint32 *) (x + 48)
+ movl 48(%edx),%eax
+ # j10 = in10
+ movl %ecx,204(%esp)
+ # in13 = *(uint32 *) (x + 52)
+ movl 52(%edx),%ecx
+ # j11 = in11
+ movl %ebp,208(%esp)
+ # in14 = *(uint32 *) (x + 56)
+ movl 56(%edx),%ebp
+ # j12 = in12
+ movl %eax,212(%esp)
+ # in15 = *(uint32 *) (x + 60)
+ movl 60(%edx),%eax
+ # j13 = in13
+ movl %ecx,216(%esp)
+ # j14 = in14
+ movl %ebp,220(%esp)
+ # j15 = in15
+ movl %eax,224(%esp)
+ # x_backup = x
+ movl %edx,64(%esp)
+._bytesatleast1:
+ # bytes - 64
+ cmp $64,%ebx
+ # goto nocopy if unsigned>=
+ jae ._nocopy
+ # ctarget = out
+ movl %edi,228(%esp)
+ # out = &tmp
+ leal 0(%esp),%edi
+ # i = bytes
+ mov %ebx,%ecx
+ # while (i) { *out++ = *m++; --i }
+ rep movsb
+ # out = &tmp
+ leal 0(%esp),%edi
+ # m = &tmp
+ leal 0(%esp),%esi
+._nocopy:
+ # out_backup = out
+ movl %edi,72(%esp)
+ # m_backup = m
+ movl %esi,68(%esp)
+ # bytes_backup = bytes
+ movl %ebx,76(%esp)
+ # in0 = j0
+ movl 164(%esp),%eax
+ # in1 = j1
+ movl 168(%esp),%ecx
+ # in2 = j2
+ movl 172(%esp),%edx
+ # in3 = j3
+ movl 176(%esp),%ebx
+ # x0 = in0
+ movl %eax,100(%esp)
+ # x1 = in1
+ movl %ecx,104(%esp)
+ # x2 = in2
+ movl %edx,108(%esp)
+ # x3 = in3
+ movl %ebx,112(%esp)
+ # in4 = j4
+ movl 180(%esp),%eax
+ # in5 = j5
+ movl 184(%esp),%ecx
+ # in6 = j6
+ movl 188(%esp),%edx
+ # in7 = j7
+ movl 192(%esp),%ebx
+ # x4 = in4
+ movl %eax,116(%esp)
+ # x5 = in5
+ movl %ecx,120(%esp)
+ # x6 = in6
+ movl %edx,124(%esp)
+ # x7 = in7
+ movl %ebx,128(%esp)
+ # in8 = j8
+ movl 196(%esp),%eax
+ # in9 = j9
+ movl 200(%esp),%ecx
+ # in10 = j10
+ movl 204(%esp),%edx
+ # in11 = j11
+ movl 208(%esp),%ebx
+ # x8 = in8
+ movl %eax,132(%esp)
+ # x9 = in9
+ movl %ecx,136(%esp)
+ # x10 = in10
+ movl %edx,140(%esp)
+ # x11 = in11
+ movl %ebx,144(%esp)
+ # in12 = j12
+ movl 212(%esp),%eax
+ # in13 = j13
+ movl 216(%esp),%ecx
+ # in14 = j14
+ movl 220(%esp),%edx
+ # in15 = j15
+ movl 224(%esp),%ebx
+ # x12 = in12
+ movl %eax,148(%esp)
+ # x13 = in13
+ movl %ecx,152(%esp)
+ # x14 = in14
+ movl %edx,156(%esp)
+ # x15 = in15
+ movl %ebx,160(%esp)
+ # i = 20
+ mov $20,%ebp
+ # p = x0
+ movl 100(%esp),%eax
+ # s = x5
+ movl 120(%esp),%ecx
+ # t = x10
+ movl 140(%esp),%edx
+ # w = x15
+ movl 160(%esp),%ebx
+._mainloop:
+ # x0 = p
+ movl %eax,100(%esp)
+ # x10 = t
+ movl %edx,140(%esp)
+ # p += x12
+ addl 148(%esp),%eax
+ # x5 = s
+ movl %ecx,120(%esp)
+ # t += x6
+ addl 124(%esp),%edx
+ # x15 = w
+ movl %ebx,160(%esp)
+ # r = x1
+ movl 104(%esp),%esi
+ # r += s
+ add %ecx,%esi
+ # v = x11
+ movl 144(%esp),%edi
+ # v += w
+ add %ebx,%edi
+ # p <<<= 7
+ rol $7,%eax
+ # p ^= x4
+ xorl 116(%esp),%eax
+ # t <<<= 7
+ rol $7,%edx
+ # t ^= x14
+ xorl 156(%esp),%edx
+ # r <<<= 7
+ rol $7,%esi
+ # r ^= x9
+ xorl 136(%esp),%esi
+ # v <<<= 7
+ rol $7,%edi
+ # v ^= x3
+ xorl 112(%esp),%edi
+ # x4 = p
+ movl %eax,116(%esp)
+ # x14 = t
+ movl %edx,156(%esp)
+ # p += x0
+ addl 100(%esp),%eax
+ # x9 = r
+ movl %esi,136(%esp)
+ # t += x10
+ addl 140(%esp),%edx
+ # x3 = v
+ movl %edi,112(%esp)
+ # p <<<= 9
+ rol $9,%eax
+ # p ^= x8
+ xorl 132(%esp),%eax
+ # t <<<= 9
+ rol $9,%edx
+ # t ^= x2
+ xorl 108(%esp),%edx
+ # s += r
+ add %esi,%ecx
+ # s <<<= 9
+ rol $9,%ecx
+ # s ^= x13
+ xorl 152(%esp),%ecx
+ # w += v
+ add %edi,%ebx
+ # w <<<= 9
+ rol $9,%ebx
+ # w ^= x7
+ xorl 128(%esp),%ebx
+ # x8 = p
+ movl %eax,132(%esp)
+ # x2 = t
+ movl %edx,108(%esp)
+ # p += x4
+ addl 116(%esp),%eax
+ # x13 = s
+ movl %ecx,152(%esp)
+ # t += x14
+ addl 156(%esp),%edx
+ # x7 = w
+ movl %ebx,128(%esp)
+ # p <<<= 13
+ rol $13,%eax
+ # p ^= x12
+ xorl 148(%esp),%eax
+ # t <<<= 13
+ rol $13,%edx
+ # t ^= x6
+ xorl 124(%esp),%edx
+ # r += s
+ add %ecx,%esi
+ # r <<<= 13
+ rol $13,%esi
+ # r ^= x1
+ xorl 104(%esp),%esi
+ # v += w
+ add %ebx,%edi
+ # v <<<= 13
+ rol $13,%edi
+ # v ^= x11
+ xorl 144(%esp),%edi
+ # x12 = p
+ movl %eax,148(%esp)
+ # x6 = t
+ movl %edx,124(%esp)
+ # p += x8
+ addl 132(%esp),%eax
+ # x1 = r
+ movl %esi,104(%esp)
+ # t += x2
+ addl 108(%esp),%edx
+ # x11 = v
+ movl %edi,144(%esp)
+ # p <<<= 18
+ rol $18,%eax
+ # p ^= x0
+ xorl 100(%esp),%eax
+ # t <<<= 18
+ rol $18,%edx
+ # t ^= x10
+ xorl 140(%esp),%edx
+ # s += r
+ add %esi,%ecx
+ # s <<<= 18
+ rol $18,%ecx
+ # s ^= x5
+ xorl 120(%esp),%ecx
+ # w += v
+ add %edi,%ebx
+ # w <<<= 18
+ rol $18,%ebx
+ # w ^= x15
+ xorl 160(%esp),%ebx
+ # x0 = p
+ movl %eax,100(%esp)
+ # x10 = t
+ movl %edx,140(%esp)
+ # p += x3
+ addl 112(%esp),%eax
+ # p <<<= 7
+ rol $7,%eax
+ # x5 = s
+ movl %ecx,120(%esp)
+ # t += x9
+ addl 136(%esp),%edx
+ # x15 = w
+ movl %ebx,160(%esp)
+ # r = x4
+ movl 116(%esp),%esi
+ # r += s
+ add %ecx,%esi
+ # v = x14
+ movl 156(%esp),%edi
+ # v += w
+ add %ebx,%edi
+ # p ^= x1
+ xorl 104(%esp),%eax
+ # t <<<= 7
+ rol $7,%edx
+ # t ^= x11
+ xorl 144(%esp),%edx
+ # r <<<= 7
+ rol $7,%esi
+ # r ^= x6
+ xorl 124(%esp),%esi
+ # v <<<= 7
+ rol $7,%edi
+ # v ^= x12
+ xorl 148(%esp),%edi
+ # x1 = p
+ movl %eax,104(%esp)
+ # x11 = t
+ movl %edx,144(%esp)
+ # p += x0
+ addl 100(%esp),%eax
+ # x6 = r
+ movl %esi,124(%esp)
+ # t += x10
+ addl 140(%esp),%edx
+ # x12 = v
+ movl %edi,148(%esp)
+ # p <<<= 9
+ rol $9,%eax
+ # p ^= x2
+ xorl 108(%esp),%eax
+ # t <<<= 9
+ rol $9,%edx
+ # t ^= x8
+ xorl 132(%esp),%edx
+ # s += r
+ add %esi,%ecx
+ # s <<<= 9
+ rol $9,%ecx
+ # s ^= x7
+ xorl 128(%esp),%ecx
+ # w += v
+ add %edi,%ebx
+ # w <<<= 9
+ rol $9,%ebx
+ # w ^= x13
+ xorl 152(%esp),%ebx
+ # x2 = p
+ movl %eax,108(%esp)
+ # x8 = t
+ movl %edx,132(%esp)
+ # p += x1
+ addl 104(%esp),%eax
+ # x7 = s
+ movl %ecx,128(%esp)
+ # t += x11
+ addl 144(%esp),%edx
+ # x13 = w
+ movl %ebx,152(%esp)
+ # p <<<= 13
+ rol $13,%eax
+ # p ^= x3
+ xorl 112(%esp),%eax
+ # t <<<= 13
+ rol $13,%edx
+ # t ^= x9
+ xorl 136(%esp),%edx
+ # r += s
+ add %ecx,%esi
+ # r <<<= 13
+ rol $13,%esi
+ # r ^= x4
+ xorl 116(%esp),%esi
+ # v += w
+ add %ebx,%edi
+ # v <<<= 13
+ rol $13,%edi
+ # v ^= x14
+ xorl 156(%esp),%edi
+ # x3 = p
+ movl %eax,112(%esp)
+ # x9 = t
+ movl %edx,136(%esp)
+ # p += x2
+ addl 108(%esp),%eax
+ # x4 = r
+ movl %esi,116(%esp)
+ # t += x8
+ addl 132(%esp),%edx
+ # x14 = v
+ movl %edi,156(%esp)
+ # p <<<= 18
+ rol $18,%eax
+ # p ^= x0
+ xorl 100(%esp),%eax
+ # t <<<= 18
+ rol $18,%edx
+ # t ^= x10
+ xorl 140(%esp),%edx
+ # s += r
+ add %esi,%ecx
+ # s <<<= 18
+ rol $18,%ecx
+ # s ^= x5
+ xorl 120(%esp),%ecx
+ # w += v
+ add %edi,%ebx
+ # w <<<= 18
+ rol $18,%ebx
+ # w ^= x15
+ xorl 160(%esp),%ebx
+ # x0 = p
+ movl %eax,100(%esp)
+ # x10 = t
+ movl %edx,140(%esp)
+ # p += x12
+ addl 148(%esp),%eax
+ # x5 = s
+ movl %ecx,120(%esp)
+ # t += x6
+ addl 124(%esp),%edx
+ # x15 = w
+ movl %ebx,160(%esp)
+ # r = x1
+ movl 104(%esp),%esi
+ # r += s
+ add %ecx,%esi
+ # v = x11
+ movl 144(%esp),%edi
+ # v += w
+ add %ebx,%edi
+ # p <<<= 7
+ rol $7,%eax
+ # p ^= x4
+ xorl 116(%esp),%eax
+ # t <<<= 7
+ rol $7,%edx
+ # t ^= x14
+ xorl 156(%esp),%edx
+ # r <<<= 7
+ rol $7,%esi
+ # r ^= x9
+ xorl 136(%esp),%esi
+ # v <<<= 7
+ rol $7,%edi
+ # v ^= x3
+ xorl 112(%esp),%edi
+ # x4 = p
+ movl %eax,116(%esp)
+ # x14 = t
+ movl %edx,156(%esp)
+ # p += x0
+ addl 100(%esp),%eax
+ # x9 = r
+ movl %esi,136(%esp)
+ # t += x10
+ addl 140(%esp),%edx
+ # x3 = v
+ movl %edi,112(%esp)
+ # p <<<= 9
+ rol $9,%eax
+ # p ^= x8
+ xorl 132(%esp),%eax
+ # t <<<= 9
+ rol $9,%edx
+ # t ^= x2
+ xorl 108(%esp),%edx
+ # s += r
+ add %esi,%ecx
+ # s <<<= 9
+ rol $9,%ecx
+ # s ^= x13
+ xorl 152(%esp),%ecx
+ # w += v
+ add %edi,%ebx
+ # w <<<= 9
+ rol $9,%ebx
+ # w ^= x7
+ xorl 128(%esp),%ebx
+ # x8 = p
+ movl %eax,132(%esp)
+ # x2 = t
+ movl %edx,108(%esp)
+ # p += x4
+ addl 116(%esp),%eax
+ # x13 = s
+ movl %ecx,152(%esp)
+ # t += x14
+ addl 156(%esp),%edx
+ # x7 = w
+ movl %ebx,128(%esp)
+ # p <<<= 13
+ rol $13,%eax
+ # p ^= x12
+ xorl 148(%esp),%eax
+ # t <<<= 13
+ rol $13,%edx
+ # t ^= x6
+ xorl 124(%esp),%edx
+ # r += s
+ add %ecx,%esi
+ # r <<<= 13
+ rol $13,%esi
+ # r ^= x1
+ xorl 104(%esp),%esi
+ # v += w
+ add %ebx,%edi
+ # v <<<= 13
+ rol $13,%edi
+ # v ^= x11
+ xorl 144(%esp),%edi
+ # x12 = p
+ movl %eax,148(%esp)
+ # x6 = t
+ movl %edx,124(%esp)
+ # p += x8
+ addl 132(%esp),%eax
+ # x1 = r
+ movl %esi,104(%esp)
+ # t += x2
+ addl 108(%esp),%edx
+ # x11 = v
+ movl %edi,144(%esp)
+ # p <<<= 18
+ rol $18,%eax
+ # p ^= x0
+ xorl 100(%esp),%eax
+ # t <<<= 18
+ rol $18,%edx
+ # t ^= x10
+ xorl 140(%esp),%edx
+ # s += r
+ add %esi,%ecx
+ # s <<<= 18
+ rol $18,%ecx
+ # s ^= x5
+ xorl 120(%esp),%ecx
+ # w += v
+ add %edi,%ebx
+ # w <<<= 18
+ rol $18,%ebx
+ # w ^= x15
+ xorl 160(%esp),%ebx
+ # x0 = p
+ movl %eax,100(%esp)
+ # x10 = t
+ movl %edx,140(%esp)
+ # p += x3
+ addl 112(%esp),%eax
+ # p <<<= 7
+ rol $7,%eax
+ # x5 = s
+ movl %ecx,120(%esp)
+ # t += x9
+ addl 136(%esp),%edx
+ # x15 = w
+ movl %ebx,160(%esp)
+ # r = x4
+ movl 116(%esp),%esi
+ # r += s
+ add %ecx,%esi
+ # v = x14
+ movl 156(%esp),%edi
+ # v += w
+ add %ebx,%edi
+ # p ^= x1
+ xorl 104(%esp),%eax
+ # t <<<= 7
+ rol $7,%edx
+ # t ^= x11
+ xorl 144(%esp),%edx
+ # r <<<= 7
+ rol $7,%esi
+ # r ^= x6
+ xorl 124(%esp),%esi
+ # v <<<= 7
+ rol $7,%edi
+ # v ^= x12
+ xorl 148(%esp),%edi
+ # x1 = p
+ movl %eax,104(%esp)
+ # x11 = t
+ movl %edx,144(%esp)
+ # p += x0
+ addl 100(%esp),%eax
+ # x6 = r
+ movl %esi,124(%esp)
+ # t += x10
+ addl 140(%esp),%edx
+ # x12 = v
+ movl %edi,148(%esp)
+ # p <<<= 9
+ rol $9,%eax
+ # p ^= x2
+ xorl 108(%esp),%eax
+ # t <<<= 9
+ rol $9,%edx
+ # t ^= x8
+ xorl 132(%esp),%edx
+ # s += r
+ add %esi,%ecx
+ # s <<<= 9
+ rol $9,%ecx
+ # s ^= x7
+ xorl 128(%esp),%ecx
+ # w += v
+ add %edi,%ebx
+ # w <<<= 9
+ rol $9,%ebx
+ # w ^= x13
+ xorl 152(%esp),%ebx
+ # x2 = p
+ movl %eax,108(%esp)
+ # x8 = t
+ movl %edx,132(%esp)
+ # p += x1
+ addl 104(%esp),%eax
+ # x7 = s
+ movl %ecx,128(%esp)
+ # t += x11
+ addl 144(%esp),%edx
+ # x13 = w
+ movl %ebx,152(%esp)
+ # p <<<= 13
+ rol $13,%eax
+ # p ^= x3
+ xorl 112(%esp),%eax
+ # t <<<= 13
+ rol $13,%edx
+ # t ^= x9
+ xorl 136(%esp),%edx
+ # r += s
+ add %ecx,%esi
+ # r <<<= 13
+ rol $13,%esi
+ # r ^= x4
+ xorl 116(%esp),%esi
+ # v += w
+ add %ebx,%edi
+ # v <<<= 13
+ rol $13,%edi
+ # v ^= x14
+ xorl 156(%esp),%edi
+ # x3 = p
+ movl %eax,112(%esp)
+ # x9 = t
+ movl %edx,136(%esp)
+ # p += x2
+ addl 108(%esp),%eax
+ # x4 = r
+ movl %esi,116(%esp)
+ # t += x8
+ addl 132(%esp),%edx
+ # x14 = v
+ movl %edi,156(%esp)
+ # p <<<= 18
+ rol $18,%eax
+ # p ^= x0
+ xorl 100(%esp),%eax
+ # t <<<= 18
+ rol $18,%edx
+ # t ^= x10
+ xorl 140(%esp),%edx
+ # s += r
+ add %esi,%ecx
+ # s <<<= 18
+ rol $18,%ecx
+ # s ^= x5
+ xorl 120(%esp),%ecx
+ # w += v
+ add %edi,%ebx
+ # w <<<= 18
+ rol $18,%ebx
+ # w ^= x15
+ xorl 160(%esp),%ebx
+ # i -= 4
+ sub $4,%ebp
+ # goto mainloop if unsigned >
+ ja ._mainloop
+ # x0 = p
+ movl %eax,100(%esp)
+ # x5 = s
+ movl %ecx,120(%esp)
+ # x10 = t
+ movl %edx,140(%esp)
+ # x15 = w
+ movl %ebx,160(%esp)
+ # out = out_backup
+ movl 72(%esp),%edi
+ # m = m_backup
+ movl 68(%esp),%esi
+ # in0 = x0
+ movl 100(%esp),%eax
+ # in1 = x1
+ movl 104(%esp),%ecx
+ # in0 += j0
+ addl 164(%esp),%eax
+ # in1 += j1
+ addl 168(%esp),%ecx
+ # in0 ^= *(uint32 *) (m + 0)
+ xorl 0(%esi),%eax
+ # in1 ^= *(uint32 *) (m + 4)
+ xorl 4(%esi),%ecx
+ # *(uint32 *) (out + 0) = in0
+ movl %eax,0(%edi)
+ # *(uint32 *) (out + 4) = in1
+ movl %ecx,4(%edi)
+ # in2 = x2
+ movl 108(%esp),%eax
+ # in3 = x3
+ movl 112(%esp),%ecx
+ # in2 += j2
+ addl 172(%esp),%eax
+ # in3 += j3
+ addl 176(%esp),%ecx
+ # in2 ^= *(uint32 *) (m + 8)
+ xorl 8(%esi),%eax
+ # in3 ^= *(uint32 *) (m + 12)
+ xorl 12(%esi),%ecx
+ # *(uint32 *) (out + 8) = in2
+ movl %eax,8(%edi)
+ # *(uint32 *) (out + 12) = in3
+ movl %ecx,12(%edi)
+ # in4 = x4
+ movl 116(%esp),%eax
+ # in5 = x5
+ movl 120(%esp),%ecx
+ # in4 += j4
+ addl 180(%esp),%eax
+ # in5 += j5
+ addl 184(%esp),%ecx
+ # in4 ^= *(uint32 *) (m + 16)
+ xorl 16(%esi),%eax
+ # in5 ^= *(uint32 *) (m + 20)
+ xorl 20(%esi),%ecx
+ # *(uint32 *) (out + 16) = in4
+ movl %eax,16(%edi)
+ # *(uint32 *) (out + 20) = in5
+ movl %ecx,20(%edi)
+ # in6 = x6
+ movl 124(%esp),%eax
+ # in7 = x7
+ movl 128(%esp),%ecx
+ # in6 += j6
+ addl 188(%esp),%eax
+ # in7 += j7
+ addl 192(%esp),%ecx
+ # in6 ^= *(uint32 *) (m + 24)
+ xorl 24(%esi),%eax
+ # in7 ^= *(uint32 *) (m + 28)
+ xorl 28(%esi),%ecx
+ # *(uint32 *) (out + 24) = in6
+ movl %eax,24(%edi)
+ # *(uint32 *) (out + 28) = in7
+ movl %ecx,28(%edi)
+ # in8 = x8
+ movl 132(%esp),%eax
+ # in9 = x9
+ movl 136(%esp),%ecx
+ # in8 += j8
+ addl 196(%esp),%eax
+ # in9 += j9
+ addl 200(%esp),%ecx
+ # in8 ^= *(uint32 *) (m + 32)
+ xorl 32(%esi),%eax
+ # in9 ^= *(uint32 *) (m + 36)
+ xorl 36(%esi),%ecx
+ # *(uint32 *) (out + 32) = in8
+ movl %eax,32(%edi)
+ # *(uint32 *) (out + 36) = in9
+ movl %ecx,36(%edi)
+ # in10 = x10
+ movl 140(%esp),%eax
+ # in11 = x11
+ movl 144(%esp),%ecx
+ # in10 += j10
+ addl 204(%esp),%eax
+ # in11 += j11
+ addl 208(%esp),%ecx
+ # in10 ^= *(uint32 *) (m + 40)
+ xorl 40(%esi),%eax
+ # in11 ^= *(uint32 *) (m + 44)
+ xorl 44(%esi),%ecx
+ # *(uint32 *) (out + 40) = in10
+ movl %eax,40(%edi)
+ # *(uint32 *) (out + 44) = in11
+ movl %ecx,44(%edi)
+ # in12 = x12
+ movl 148(%esp),%eax
+ # in13 = x13
+ movl 152(%esp),%ecx
+ # in12 += j12
+ addl 212(%esp),%eax
+ # in13 += j13
+ addl 216(%esp),%ecx
+ # in12 ^= *(uint32 *) (m + 48)
+ xorl 48(%esi),%eax
+ # in13 ^= *(uint32 *) (m + 52)
+ xorl 52(%esi),%ecx
+ # *(uint32 *) (out + 48) = in12
+ movl %eax,48(%edi)
+ # *(uint32 *) (out + 52) = in13
+ movl %ecx,52(%edi)
+ # in14 = x14
+ movl 156(%esp),%eax
+ # in15 = x15
+ movl 160(%esp),%ecx
+ # in14 += j14
+ addl 220(%esp),%eax
+ # in15 += j15
+ addl 224(%esp),%ecx
+ # in14 ^= *(uint32 *) (m + 56)
+ xorl 56(%esi),%eax
+ # in15 ^= *(uint32 *) (m + 60)
+ xorl 60(%esi),%ecx
+ # *(uint32 *) (out + 56) = in14
+ movl %eax,56(%edi)
+ # *(uint32 *) (out + 60) = in15
+ movl %ecx,60(%edi)
+ # bytes = bytes_backup
+ movl 76(%esp),%ebx
+ # in8 = j8
+ movl 196(%esp),%eax
+ # in9 = j9
+ movl 200(%esp),%ecx
+ # in8 += 1
+ add $1,%eax
+ # in9 += 0 + carry
+ adc $0,%ecx
+ # j8 = in8
+ movl %eax,196(%esp)
+ # j9 = in9
+ movl %ecx,200(%esp)
+ # bytes - 64
+ cmp $64,%ebx
+ # goto bytesatleast65 if unsigned>
+ ja ._bytesatleast65
+ # goto bytesatleast64 if unsigned>=
+ jae ._bytesatleast64
+ # m = out
+ mov %edi,%esi
+ # out = ctarget
+ movl 228(%esp),%edi
+ # i = bytes
+ mov %ebx,%ecx
+ # while (i) { *out++ = *m++; --i }
+ rep movsb
+._bytesatleast64:
+ # x = x_backup
+ movl 64(%esp),%eax
+ # in8 = j8
+ movl 196(%esp),%ecx
+ # in9 = j9
+ movl 200(%esp),%edx
+ # *(uint32 *) (x + 32) = in8
+ movl %ecx,32(%eax)
+ # *(uint32 *) (x + 36) = in9
+ movl %edx,36(%eax)
+._done:
+ # eax = eax_stack
+ movl 80(%esp),%eax
+ # ebx = ebx_stack
+ movl 84(%esp),%ebx
+ # esi = esi_stack
+ movl 88(%esp),%esi
+ # edi = edi_stack
+ movl 92(%esp),%edi
+ # ebp = ebp_stack
+ movl 96(%esp),%ebp
+ # leave
+ add %eax,%esp
+ ret
+._bytesatleast65:
+ # bytes -= 64
+ sub $64,%ebx
+ # out += 64
+ add $64,%edi
+ # m += 64
+ add $64,%esi
+ # goto bytesatleast1
+ jmp ._bytesatleast1
+# enter ECRYPT_keysetup
+.text
+.p2align 5
+.globl ECRYPT_keysetup
+ECRYPT_keysetup:
+ mov %esp,%eax
+ and $31,%eax
+ add $256,%eax
+ sub %eax,%esp
+ # eax_stack = eax
+ movl %eax,64(%esp)
+ # ebx_stack = ebx
+ movl %ebx,68(%esp)
+ # esi_stack = esi
+ movl %esi,72(%esp)
+ # edi_stack = edi
+ movl %edi,76(%esp)
+ # ebp_stack = ebp
+ movl %ebp,80(%esp)
+ # k = arg2
+ movl 8(%esp,%eax),%ecx
+ # kbits = arg3
+ movl 12(%esp,%eax),%edx
+ # x = arg1
+ movl 4(%esp,%eax),%eax
+ # in1 = *(uint32 *) (k + 0)
+ movl 0(%ecx),%ebx
+ # in2 = *(uint32 *) (k + 4)
+ movl 4(%ecx),%esi
+ # in3 = *(uint32 *) (k + 8)
+ movl 8(%ecx),%edi
+ # in4 = *(uint32 *) (k + 12)
+ movl 12(%ecx),%ebp
+ # *(uint32 *) (x + 4) = in1
+ movl %ebx,4(%eax)
+ # *(uint32 *) (x + 8) = in2
+ movl %esi,8(%eax)
+ # *(uint32 *) (x + 12) = in3
+ movl %edi,12(%eax)
+ # *(uint32 *) (x + 16) = in4
+ movl %ebp,16(%eax)
+ # kbits - 256
+ cmp $256,%edx
+ # goto kbits128 if unsigned<
+ jb ._kbits128
+._kbits256:
+ # in11 = *(uint32 *) (k + 16)
+ movl 16(%ecx),%edx
+ # in12 = *(uint32 *) (k + 20)
+ movl 20(%ecx),%ebx
+ # in13 = *(uint32 *) (k + 24)
+ movl 24(%ecx),%esi
+ # in14 = *(uint32 *) (k + 28)
+ movl 28(%ecx),%ecx
+ # *(uint32 *) (x + 44) = in11
+ movl %edx,44(%eax)
+ # *(uint32 *) (x + 48) = in12
+ movl %ebx,48(%eax)
+ # *(uint32 *) (x + 52) = in13
+ movl %esi,52(%eax)
+ # *(uint32 *) (x + 56) = in14
+ movl %ecx,56(%eax)
+ # in0 = 1634760805
+ mov $1634760805,%ecx
+ # in5 = 857760878
+ mov $857760878,%edx
+ # in10 = 2036477234
+ mov $2036477234,%ebx
+ # in15 = 1797285236
+ mov $1797285236,%esi
+ # *(uint32 *) (x + 0) = in0
+ movl %ecx,0(%eax)
+ # *(uint32 *) (x + 20) = in5
+ movl %edx,20(%eax)
+ # *(uint32 *) (x + 40) = in10
+ movl %ebx,40(%eax)
+ # *(uint32 *) (x + 60) = in15
+ movl %esi,60(%eax)
+ # goto keysetupdone
+ jmp ._keysetupdone
+._kbits128:
+ # in11 = *(uint32 *) (k + 0)
+ movl 0(%ecx),%edx
+ # in12 = *(uint32 *) (k + 4)
+ movl 4(%ecx),%ebx
+ # in13 = *(uint32 *) (k + 8)
+ movl 8(%ecx),%esi
+ # in14 = *(uint32 *) (k + 12)
+ movl 12(%ecx),%ecx
+ # *(uint32 *) (x + 44) = in11
+ movl %edx,44(%eax)
+ # *(uint32 *) (x + 48) = in12
+ movl %ebx,48(%eax)
+ # *(uint32 *) (x + 52) = in13
+ movl %esi,52(%eax)
+ # *(uint32 *) (x + 56) = in14
+ movl %ecx,56(%eax)
+ # in0 = 1634760805
+ mov $1634760805,%ecx
+ # in5 = 824206446
+ mov $824206446,%edx
+ # in10 = 2036477238
+ mov $2036477238,%ebx
+ # in15 = 1797285236
+ mov $1797285236,%esi
+ # *(uint32 *) (x + 0) = in0
+ movl %ecx,0(%eax)
+ # *(uint32 *) (x + 20) = in5
+ movl %edx,20(%eax)
+ # *(uint32 *) (x + 40) = in10
+ movl %ebx,40(%eax)
+ # *(uint32 *) (x + 60) = in15
+ movl %esi,60(%eax)
+._keysetupdone:
+ # eax = eax_stack
+ movl 64(%esp),%eax
+ # ebx = ebx_stack
+ movl 68(%esp),%ebx
+ # esi = esi_stack
+ movl 72(%esp),%esi
+ # edi = edi_stack
+ movl 76(%esp),%edi
+ # ebp = ebp_stack
+ movl 80(%esp),%ebp
+ # leave
+ add %eax,%esp
+ ret
+# enter ECRYPT_ivsetup
+.text
+.p2align 5
+.globl ECRYPT_ivsetup
+ECRYPT_ivsetup:
+ mov %esp,%eax
+ and $31,%eax
+ add $256,%eax
+ sub %eax,%esp
+ # eax_stack = eax
+ movl %eax,64(%esp)
+ # ebx_stack = ebx
+ movl %ebx,68(%esp)
+ # esi_stack = esi
+ movl %esi,72(%esp)
+ # edi_stack = edi
+ movl %edi,76(%esp)
+ # ebp_stack = ebp
+ movl %ebp,80(%esp)
+ # iv = arg2
+ movl 8(%esp,%eax),%ecx
+ # x = arg1
+ movl 4(%esp,%eax),%eax
+ # in6 = *(uint32 *) (iv + 0)
+ movl 0(%ecx),%edx
+ # in7 = *(uint32 *) (iv + 4)
+ movl 4(%ecx),%ecx
+ # in8 = 0
+ mov $0,%ebx
+ # in9 = 0
+ mov $0,%esi
+ # *(uint32 *) (x + 24) = in6
+ movl %edx,24(%eax)
+ # *(uint32 *) (x + 28) = in7
+ movl %ecx,28(%eax)
+ # *(uint32 *) (x + 32) = in8
+ movl %ebx,32(%eax)
+ # *(uint32 *) (x + 36) = in9
+ movl %esi,36(%eax)
+ # eax = eax_stack
+ movl 64(%esp),%eax
+ # ebx = ebx_stack
+ movl 68(%esp),%ebx
+ # esi = esi_stack
+ movl 72(%esp),%esi
+ # edi = edi_stack
+ movl 76(%esp),%edi
+ # ebp = ebp_stack
+ movl 80(%esp),%ebp
+ # leave
+ add %eax,%esp
+ ret
diff --git a/arch/x86/crypto/salsa20-x86_64-asm_64.S b/arch/x86/crypto/salsa20-x86_64-asm_64.S
new file mode 100644
index 0000000..6214a9b
--- /dev/null
+++ b/arch/x86/crypto/salsa20-x86_64-asm_64.S
@@ -0,0 +1,920 @@
+# enter ECRYPT_encrypt_bytes
+.text
+.p2align 5
+.globl ECRYPT_encrypt_bytes
+ECRYPT_encrypt_bytes:
+ mov %rsp,%r11
+ and $31,%r11
+ add $256,%r11
+ sub %r11,%rsp
+ # x = arg1
+ mov %rdi,%r8
+ # m = arg2
+ mov %rsi,%rsi
+ # out = arg3
+ mov %rdx,%rdi
+ # bytes = arg4
+ mov %rcx,%rdx
+ # unsigned>? bytes - 0
+ cmp $0,%rdx
+ # comment:fp stack unchanged by jump
+ # goto done if !unsigned>
+ jbe ._done
+ # comment:fp stack unchanged by fallthrough
+# start:
+._start:
+ # r11_stack = r11
+ movq %r11,0(%rsp)
+ # r12_stack = r12
+ movq %r12,8(%rsp)
+ # r13_stack = r13
+ movq %r13,16(%rsp)
+ # r14_stack = r14
+ movq %r14,24(%rsp)
+ # r15_stack = r15
+ movq %r15,32(%rsp)
+ # rbx_stack = rbx
+ movq %rbx,40(%rsp)
+ # rbp_stack = rbp
+ movq %rbp,48(%rsp)
+ # in0 = *(uint64 *) (x + 0)
+ movq 0(%r8),%rcx
+ # in2 = *(uint64 *) (x + 8)
+ movq 8(%r8),%r9
+ # in4 = *(uint64 *) (x + 16)
+ movq 16(%r8),%rax
+ # in6 = *(uint64 *) (x + 24)
+ movq 24(%r8),%r10
+ # in8 = *(uint64 *) (x + 32)
+ movq 32(%r8),%r11
+ # in10 = *(uint64 *) (x + 40)
+ movq 40(%r8),%r12
+ # in12 = *(uint64 *) (x + 48)
+ movq 48(%r8),%r13
+ # in14 = *(uint64 *) (x + 56)
+ movq 56(%r8),%r14
+ # j0 = in0
+ movq %rcx,56(%rsp)
+ # j2 = in2
+ movq %r9,64(%rsp)
+ # j4 = in4
+ movq %rax,72(%rsp)
+ # j6 = in6
+ movq %r10,80(%rsp)
+ # j8 = in8
+ movq %r11,88(%rsp)
+ # j10 = in10
+ movq %r12,96(%rsp)
+ # j12 = in12
+ movq %r13,104(%rsp)
+ # j14 = in14
+ movq %r14,112(%rsp)
+ # x_backup = x
+ movq %r8,120(%rsp)
+# bytesatleast1:
+._bytesatleast1:
+ # unsigned<? bytes - 64
+ cmp $64,%rdx
+ # comment:fp stack unchanged by jump
+ # goto nocopy if !unsigned<
+ jae ._nocopy
+ # ctarget = out
+ movq %rdi,128(%rsp)
+ # out = &tmp
+ leaq 192(%rsp),%rdi
+ # i = bytes
+ mov %rdx,%rcx
+ # while (i) { *out++ = *m++; --i }
+ rep movsb
+ # out = &tmp
+ leaq 192(%rsp),%rdi
+ # m = &tmp
+ leaq 192(%rsp),%rsi
+ # comment:fp stack unchanged by fallthrough
+# nocopy:
+._nocopy:
+ # out_backup = out
+ movq %rdi,136(%rsp)
+ # m_backup = m
+ movq %rsi,144(%rsp)
+ # bytes_backup = bytes
+ movq %rdx,152(%rsp)
+ # x1 = j0
+ movq 56(%rsp),%rdi
+ # x0 = x1
+ mov %rdi,%rdx
+ # (uint64) x1 >>= 32
+ shr $32,%rdi
+ # x3 = j2
+ movq 64(%rsp),%rsi
+ # x2 = x3
+ mov %rsi,%rcx
+ # (uint64) x3 >>= 32
+ shr $32,%rsi
+ # x5 = j4
+ movq 72(%rsp),%r8
+ # x4 = x5
+ mov %r8,%r9
+ # (uint64) x5 >>= 32
+ shr $32,%r8
+ # x5_stack = x5
+ movq %r8,160(%rsp)
+ # x7 = j6
+ movq 80(%rsp),%r8
+ # x6 = x7
+ mov %r8,%rax
+ # (uint64) x7 >>= 32
+ shr $32,%r8
+ # x9 = j8
+ movq 88(%rsp),%r10
+ # x8 = x9
+ mov %r10,%r11
+ # (uint64) x9 >>= 32
+ shr $32,%r10
+ # x11 = j10
+ movq 96(%rsp),%r12
+ # x10 = x11
+ mov %r12,%r13
+ # x10_stack = x10
+ movq %r13,168(%rsp)
+ # (uint64) x11 >>= 32
+ shr $32,%r12
+ # x13 = j12
+ movq 104(%rsp),%r13
+ # x12 = x13
+ mov %r13,%r14
+ # (uint64) x13 >>= 32
+ shr $32,%r13
+ # x15 = j14
+ movq 112(%rsp),%r15
+ # x14 = x15
+ mov %r15,%rbx
+ # (uint64) x15 >>= 32
+ shr $32,%r15
+ # x15_stack = x15
+ movq %r15,176(%rsp)
+ # i = 20
+ mov $20,%r15
+# mainloop:
+._mainloop:
+ # i_backup = i
+ movq %r15,184(%rsp)
+ # x5 = x5_stack
+ movq 160(%rsp),%r15
+ # a = x12 + x0
+ lea (%r14,%rdx),%rbp
+ # (uint32) a <<<= 7
+ rol $7,%ebp
+ # x4 ^= a
+ xor %rbp,%r9
+ # b = x1 + x5
+ lea (%rdi,%r15),%rbp
+ # (uint32) b <<<= 7
+ rol $7,%ebp
+ # x9 ^= b
+ xor %rbp,%r10
+ # a = x0 + x4
+ lea (%rdx,%r9),%rbp
+ # (uint32) a <<<= 9
+ rol $9,%ebp
+ # x8 ^= a
+ xor %rbp,%r11
+ # b = x5 + x9
+ lea (%r15,%r10),%rbp
+ # (uint32) b <<<= 9
+ rol $9,%ebp
+ # x13 ^= b
+ xor %rbp,%r13
+ # a = x4 + x8
+ lea (%r9,%r11),%rbp
+ # (uint32) a <<<= 13
+ rol $13,%ebp
+ # x12 ^= a
+ xor %rbp,%r14
+ # b = x9 + x13
+ lea (%r10,%r13),%rbp
+ # (uint32) b <<<= 13
+ rol $13,%ebp
+ # x1 ^= b
+ xor %rbp,%rdi
+ # a = x8 + x12
+ lea (%r11,%r14),%rbp
+ # (uint32) a <<<= 18
+ rol $18,%ebp
+ # x0 ^= a
+ xor %rbp,%rdx
+ # b = x13 + x1
+ lea (%r13,%rdi),%rbp
+ # (uint32) b <<<= 18
+ rol $18,%ebp
+ # x5 ^= b
+ xor %rbp,%r15
+ # x10 = x10_stack
+ movq 168(%rsp),%rbp
+ # x5_stack = x5
+ movq %r15,160(%rsp)
+ # c = x6 + x10
+ lea (%rax,%rbp),%r15
+ # (uint32) c <<<= 7
+ rol $7,%r15d
+ # x14 ^= c
+ xor %r15,%rbx
+ # c = x10 + x14
+ lea (%rbp,%rbx),%r15
+ # (uint32) c <<<= 9
+ rol $9,%r15d
+ # x2 ^= c
+ xor %r15,%rcx
+ # c = x14 + x2
+ lea (%rbx,%rcx),%r15
+ # (uint32) c <<<= 13
+ rol $13,%r15d
+ # x6 ^= c
+ xor %r15,%rax
+ # c = x2 + x6
+ lea (%rcx,%rax),%r15
+ # (uint32) c <<<= 18
+ rol $18,%r15d
+ # x10 ^= c
+ xor %r15,%rbp
+ # x15 = x15_stack
+ movq 176(%rsp),%r15
+ # x10_stack = x10
+ movq %rbp,168(%rsp)
+ # d = x11 + x15
+ lea (%r12,%r15),%rbp
+ # (uint32) d <<<= 7
+ rol $7,%ebp
+ # x3 ^= d
+ xor %rbp,%rsi
+ # d = x15 + x3
+ lea (%r15,%rsi),%rbp
+ # (uint32) d <<<= 9
+ rol $9,%ebp
+ # x7 ^= d
+ xor %rbp,%r8
+ # d = x3 + x7
+ lea (%rsi,%r8),%rbp
+ # (uint32) d <<<= 13
+ rol $13,%ebp
+ # x11 ^= d
+ xor %rbp,%r12
+ # d = x7 + x11
+ lea (%r8,%r12),%rbp
+ # (uint32) d <<<= 18
+ rol $18,%ebp
+ # x15 ^= d
+ xor %rbp,%r15
+ # x15_stack = x15
+ movq %r15,176(%rsp)
+ # x5 = x5_stack
+ movq 160(%rsp),%r15
+ # a = x3 + x0
+ lea (%rsi,%rdx),%rbp
+ # (uint32) a <<<= 7
+ rol $7,%ebp
+ # x1 ^= a
+ xor %rbp,%rdi
+ # b = x4 + x5
+ lea (%r9,%r15),%rbp
+ # (uint32) b <<<= 7
+ rol $7,%ebp
+ # x6 ^= b
+ xor %rbp,%rax
+ # a = x0 + x1
+ lea (%rdx,%rdi),%rbp
+ # (uint32) a <<<= 9
+ rol $9,%ebp
+ # x2 ^= a
+ xor %rbp,%rcx
+ # b = x5 + x6
+ lea (%r15,%rax),%rbp
+ # (uint32) b <<<= 9
+ rol $9,%ebp
+ # x7 ^= b
+ xor %rbp,%r8
+ # a = x1 + x2
+ lea (%rdi,%rcx),%rbp
+ # (uint32) a <<<= 13
+ rol $13,%ebp
+ # x3 ^= a
+ xor %rbp,%rsi
+ # b = x6 + x7
+ lea (%rax,%r8),%rbp
+ # (uint32) b <<<= 13
+ rol $13,%ebp
+ # x4 ^= b
+ xor %rbp,%r9
+ # a = x2 + x3
+ lea (%rcx,%rsi),%rbp
+ # (uint32) a <<<= 18
+ rol $18,%ebp
+ # x0 ^= a
+ xor %rbp,%rdx
+ # b = x7 + x4
+ lea (%r8,%r9),%rbp
+ # (uint32) b <<<= 18
+ rol $18,%ebp
+ # x5 ^= b
+ xor %rbp,%r15
+ # x10 = x10_stack
+ movq 168(%rsp),%rbp
+ # x5_stack = x5
+ movq %r15,160(%rsp)
+ # c = x9 + x10
+ lea (%r10,%rbp),%r15
+ # (uint32) c <<<= 7
+ rol $7,%r15d
+ # x11 ^= c
+ xor %r15,%r12
+ # c = x10 + x11
+ lea (%rbp,%r12),%r15
+ # (uint32) c <<<= 9
+ rol $9,%r15d
+ # x8 ^= c
+ xor %r15,%r11
+ # c = x11 + x8
+ lea (%r12,%r11),%r15
+ # (uint32) c <<<= 13
+ rol $13,%r15d
+ # x9 ^= c
+ xor %r15,%r10
+ # c = x8 + x9
+ lea (%r11,%r10),%r15
+ # (uint32) c <<<= 18
+ rol $18,%r15d
+ # x10 ^= c
+ xor %r15,%rbp
+ # x15 = x15_stack
+ movq 176(%rsp),%r15
+ # x10_stack = x10
+ movq %rbp,168(%rsp)
+ # d = x14 + x15
+ lea (%rbx,%r15),%rbp
+ # (uint32) d <<<= 7
+ rol $7,%ebp
+ # x12 ^= d
+ xor %rbp,%r14
+ # d = x15 + x12
+ lea (%r15,%r14),%rbp
+ # (uint32) d <<<= 9
+ rol $9,%ebp
+ # x13 ^= d
+ xor %rbp,%r13
+ # d = x12 + x13
+ lea (%r14,%r13),%rbp
+ # (uint32) d <<<= 13
+ rol $13,%ebp
+ # x14 ^= d
+ xor %rbp,%rbx
+ # d = x13 + x14
+ lea (%r13,%rbx),%rbp
+ # (uint32) d <<<= 18
+ rol $18,%ebp
+ # x15 ^= d
+ xor %rbp,%r15
+ # x15_stack = x15
+ movq %r15,176(%rsp)
+ # x5 = x5_stack
+ movq 160(%rsp),%r15
+ # a = x12 + x0
+ lea (%r14,%rdx),%rbp
+ # (uint32) a <<<= 7
+ rol $7,%ebp
+ # x4 ^= a
+ xor %rbp,%r9
+ # b = x1 + x5
+ lea (%rdi,%r15),%rbp
+ # (uint32) b <<<= 7
+ rol $7,%ebp
+ # x9 ^= b
+ xor %rbp,%r10
+ # a = x0 + x4
+ lea (%rdx,%r9),%rbp
+ # (uint32) a <<<= 9
+ rol $9,%ebp
+ # x8 ^= a
+ xor %rbp,%r11
+ # b = x5 + x9
+ lea (%r15,%r10),%rbp
+ # (uint32) b <<<= 9
+ rol $9,%ebp
+ # x13 ^= b
+ xor %rbp,%r13
+ # a = x4 + x8
+ lea (%r9,%r11),%rbp
+ # (uint32) a <<<= 13
+ rol $13,%ebp
+ # x12 ^= a
+ xor %rbp,%r14
+ # b = x9 + x13
+ lea (%r10,%r13),%rbp
+ # (uint32) b <<<= 13
+ rol $13,%ebp
+ # x1 ^= b
+ xor %rbp,%rdi
+ # a = x8 + x12
+ lea (%r11,%r14),%rbp
+ # (uint32) a <<<= 18
+ rol $18,%ebp
+ # x0 ^= a
+ xor %rbp,%rdx
+ # b = x13 + x1
+ lea (%r13,%rdi),%rbp
+ # (uint32) b <<<= 18
+ rol $18,%ebp
+ # x5 ^= b
+ xor %rbp,%r15
+ # x10 = x10_stack
+ movq 168(%rsp),%rbp
+ # x5_stack = x5
+ movq %r15,160(%rsp)
+ # c = x6 + x10
+ lea (%rax,%rbp),%r15
+ # (uint32) c <<<= 7
+ rol $7,%r15d
+ # x14 ^= c
+ xor %r15,%rbx
+ # c = x10 + x14
+ lea (%rbp,%rbx),%r15
+ # (uint32) c <<<= 9
+ rol $9,%r15d
+ # x2 ^= c
+ xor %r15,%rcx
+ # c = x14 + x2
+ lea (%rbx,%rcx),%r15
+ # (uint32) c <<<= 13
+ rol $13,%r15d
+ # x6 ^= c
+ xor %r15,%rax
+ # c = x2 + x6
+ lea (%rcx,%rax),%r15
+ # (uint32) c <<<= 18
+ rol $18,%r15d
+ # x10 ^= c
+ xor %r15,%rbp
+ # x15 = x15_stack
+ movq 176(%rsp),%r15
+ # x10_stack = x10
+ movq %rbp,168(%rsp)
+ # d = x11 + x15
+ lea (%r12,%r15),%rbp
+ # (uint32) d <<<= 7
+ rol $7,%ebp
+ # x3 ^= d
+ xor %rbp,%rsi
+ # d = x15 + x3
+ lea (%r15,%rsi),%rbp
+ # (uint32) d <<<= 9
+ rol $9,%ebp
+ # x7 ^= d
+ xor %rbp,%r8
+ # d = x3 + x7
+ lea (%rsi,%r8),%rbp
+ # (uint32) d <<<= 13
+ rol $13,%ebp
+ # x11 ^= d
+ xor %rbp,%r12
+ # d = x7 + x11
+ lea (%r8,%r12),%rbp
+ # (uint32) d <<<= 18
+ rol $18,%ebp
+ # x15 ^= d
+ xor %rbp,%r15
+ # x15_stack = x15
+ movq %r15,176(%rsp)
+ # x5 = x5_stack
+ movq 160(%rsp),%r15
+ # a = x3 + x0
+ lea (%rsi,%rdx),%rbp
+ # (uint32) a <<<= 7
+ rol $7,%ebp
+ # x1 ^= a
+ xor %rbp,%rdi
+ # b = x4 + x5
+ lea (%r9,%r15),%rbp
+ # (uint32) b <<<= 7
+ rol $7,%ebp
+ # x6 ^= b
+ xor %rbp,%rax
+ # a = x0 + x1
+ lea (%rdx,%rdi),%rbp
+ # (uint32) a <<<= 9
+ rol $9,%ebp
+ # x2 ^= a
+ xor %rbp,%rcx
+ # b = x5 + x6
+ lea (%r15,%rax),%rbp
+ # (uint32) b <<<= 9
+ rol $9,%ebp
+ # x7 ^= b
+ xor %rbp,%r8
+ # a = x1 + x2
+ lea (%rdi,%rcx),%rbp
+ # (uint32) a <<<= 13
+ rol $13,%ebp
+ # x3 ^= a
+ xor %rbp,%rsi
+ # b = x6 + x7
+ lea (%rax,%r8),%rbp
+ # (uint32) b <<<= 13
+ rol $13,%ebp
+ # x4 ^= b
+ xor %rbp,%r9
+ # a = x2 + x3
+ lea (%rcx,%rsi),%rbp
+ # (uint32) a <<<= 18
+ rol $18,%ebp
+ # x0 ^= a
+ xor %rbp,%rdx
+ # b = x7 + x4
+ lea (%r8,%r9),%rbp
+ # (uint32) b <<<= 18
+ rol $18,%ebp
+ # x5 ^= b
+ xor %rbp,%r15
+ # x10 = x10_stack
+ movq 168(%rsp),%rbp
+ # x5_stack = x5
+ movq %r15,160(%rsp)
+ # c = x9 + x10
+ lea (%r10,%rbp),%r15
+ # (uint32) c <<<= 7
+ rol $7,%r15d
+ # x11 ^= c
+ xor %r15,%r12
+ # c = x10 + x11
+ lea (%rbp,%r12),%r15
+ # (uint32) c <<<= 9
+ rol $9,%r15d
+ # x8 ^= c
+ xor %r15,%r11
+ # c = x11 + x8
+ lea (%r12,%r11),%r15
+ # (uint32) c <<<= 13
+ rol $13,%r15d
+ # x9 ^= c
+ xor %r15,%r10
+ # c = x8 + x9
+ lea (%r11,%r10),%r15
+ # (uint32) c <<<= 18
+ rol $18,%r15d
+ # x10 ^= c
+ xor %r15,%rbp
+ # x15 = x15_stack
+ movq 176(%rsp),%r15
+ # x10_stack = x10
+ movq %rbp,168(%rsp)
+ # d = x14 + x15
+ lea (%rbx,%r15),%rbp
+ # (uint32) d <<<= 7
+ rol $7,%ebp
+ # x12 ^= d
+ xor %rbp,%r14
+ # d = x15 + x12
+ lea (%r15,%r14),%rbp
+ # (uint32) d <<<= 9
+ rol $9,%ebp
+ # x13 ^= d
+ xor %rbp,%r13
+ # d = x12 + x13
+ lea (%r14,%r13),%rbp
+ # (uint32) d <<<= 13
+ rol $13,%ebp
+ # x14 ^= d
+ xor %rbp,%rbx
+ # d = x13 + x14
+ lea (%r13,%rbx),%rbp
+ # (uint32) d <<<= 18
+ rol $18,%ebp
+ # x15 ^= d
+ xor %rbp,%r15
+ # x15_stack = x15
+ movq %r15,176(%rsp)
+ # i = i_backup
+ movq 184(%rsp),%r15
+ # unsigned>? i -= 4
+ sub $4,%r15
+ # comment:fp stack unchanged by jump
+ # goto mainloop if unsigned>
+ ja ._mainloop
+ # (uint32) x2 += j2
+ addl 64(%rsp),%ecx
+ # x3 <<= 32
+ shl $32,%rsi
+ # x3 += j2
+ addq 64(%rsp),%rsi
+ # (uint64) x3 >>= 32
+ shr $32,%rsi
+ # x3 <<= 32
+ shl $32,%rsi
+ # x2 += x3
+ add %rsi,%rcx
+ # (uint32) x6 += j6
+ addl 80(%rsp),%eax
+ # x7 <<= 32
+ shl $32,%r8
+ # x7 += j6
+ addq 80(%rsp),%r8
+ # (uint64) x7 >>= 32
+ shr $32,%r8
+ # x7 <<= 32
+ shl $32,%r8
+ # x6 += x7
+ add %r8,%rax
+ # (uint32) x8 += j8
+ addl 88(%rsp),%r11d
+ # x9 <<= 32
+ shl $32,%r10
+ # x9 += j8
+ addq 88(%rsp),%r10
+ # (uint64) x9 >>= 32
+ shr $32,%r10
+ # x9 <<= 32
+ shl $32,%r10
+ # x8 += x9
+ add %r10,%r11
+ # (uint32) x12 += j12
+ addl 104(%rsp),%r14d
+ # x13 <<= 32
+ shl $32,%r13
+ # x13 += j12
+ addq 104(%rsp),%r13
+ # (uint64) x13 >>= 32
+ shr $32,%r13
+ # x13 <<= 32
+ shl $32,%r13
+ # x12 += x13
+ add %r13,%r14
+ # (uint32) x0 += j0
+ addl 56(%rsp),%edx
+ # x1 <<= 32
+ shl $32,%rdi
+ # x1 += j0
+ addq 56(%rsp),%rdi
+ # (uint64) x1 >>= 32
+ shr $32,%rdi
+ # x1 <<= 32
+ shl $32,%rdi
+ # x0 += x1
+ add %rdi,%rdx
+ # x5 = x5_stack
+ movq 160(%rsp),%rdi
+ # (uint32) x4 += j4
+ addl 72(%rsp),%r9d
+ # x5 <<= 32
+ shl $32,%rdi
+ # x5 += j4
+ addq 72(%rsp),%rdi
+ # (uint64) x5 >>= 32
+ shr $32,%rdi
+ # x5 <<= 32
+ shl $32,%rdi
+ # x4 += x5
+ add %rdi,%r9
+ # x10 = x10_stack
+ movq 168(%rsp),%r8
+ # (uint32) x10 += j10
+ addl 96(%rsp),%r8d
+ # x11 <<= 32
+ shl $32,%r12
+ # x11 += j10
+ addq 96(%rsp),%r12
+ # (uint64) x11 >>= 32
+ shr $32,%r12
+ # x11 <<= 32
+ shl $32,%r12
+ # x10 += x11
+ add %r12,%r8
+ # x15 = x15_stack
+ movq 176(%rsp),%rdi
+ # (uint32) x14 += j14
+ addl 112(%rsp),%ebx
+ # x15 <<= 32
+ shl $32,%rdi
+ # x15 += j14
+ addq 112(%rsp),%rdi
+ # (uint64) x15 >>= 32
+ shr $32,%rdi
+ # x15 <<= 32
+ shl $32,%rdi
+ # x14 += x15
+ add %rdi,%rbx
+ # out = out_backup
+ movq 136(%rsp),%rdi
+ # m = m_backup
+ movq 144(%rsp),%rsi
+ # x0 ^= *(uint64 *) (m + 0)
+ xorq 0(%rsi),%rdx
+ # *(uint64 *) (out + 0) = x0
+ movq %rdx,0(%rdi)
+ # x2 ^= *(uint64 *) (m + 8)
+ xorq 8(%rsi),%rcx
+ # *(uint64 *) (out + 8) = x2
+ movq %rcx,8(%rdi)
+ # x4 ^= *(uint64 *) (m + 16)
+ xorq 16(%rsi),%r9
+ # *(uint64 *) (out + 16) = x4
+ movq %r9,16(%rdi)
+ # x6 ^= *(uint64 *) (m + 24)
+ xorq 24(%rsi),%rax
+ # *(uint64 *) (out + 24) = x6
+ movq %rax,24(%rdi)
+ # x8 ^= *(uint64 *) (m + 32)
+ xorq 32(%rsi),%r11
+ # *(uint64 *) (out + 32) = x8
+ movq %r11,32(%rdi)
+ # x10 ^= *(uint64 *) (m + 40)
+ xorq 40(%rsi),%r8
+ # *(uint64 *) (out + 40) = x10
+ movq %r8,40(%rdi)
+ # x12 ^= *(uint64 *) (m + 48)
+ xorq 48(%rsi),%r14
+ # *(uint64 *) (out + 48) = x12
+ movq %r14,48(%rdi)
+ # x14 ^= *(uint64 *) (m + 56)
+ xorq 56(%rsi),%rbx
+ # *(uint64 *) (out + 56) = x14
+ movq %rbx,56(%rdi)
+ # bytes = bytes_backup
+ movq 152(%rsp),%rdx
+ # in8 = j8
+ movq 88(%rsp),%rcx
+ # in8 += 1
+ add $1,%rcx
+ # j8 = in8
+ movq %rcx,88(%rsp)
+ # unsigned>? unsigned<? bytes - 64
+ cmp $64,%rdx
+ # comment:fp stack unchanged by jump
+ # goto bytesatleast65 if unsigned>
+ ja ._bytesatleast65
+ # comment:fp stack unchanged by jump
+ # goto bytesatleast64 if !unsigned<
+ jae ._bytesatleast64
+ # m = out
+ mov %rdi,%rsi
+ # out = ctarget
+ movq 128(%rsp),%rdi
+ # i = bytes
+ mov %rdx,%rcx
+ # while (i) { *out++ = *m++; --i }
+ rep movsb
+ # comment:fp stack unchanged by fallthrough
+# bytesatleast64:
+._bytesatleast64:
+ # x = x_backup
+ movq 120(%rsp),%rdi
+ # in8 = j8
+ movq 88(%rsp),%rsi
+ # *(uint64 *) (x + 32) = in8
+ movq %rsi,32(%rdi)
+ # r11 = r11_stack
+ movq 0(%rsp),%r11
+ # r12 = r12_stack
+ movq 8(%rsp),%r12
+ # r13 = r13_stack
+ movq 16(%rsp),%r13
+ # r14 = r14_stack
+ movq 24(%rsp),%r14
+ # r15 = r15_stack
+ movq 32(%rsp),%r15
+ # rbx = rbx_stack
+ movq 40(%rsp),%rbx
+ # rbp = rbp_stack
+ movq 48(%rsp),%rbp
+ # comment:fp stack unchanged by fallthrough
+# done:
+._done:
+ # leave
+ add %r11,%rsp
+ mov %rdi,%rax
+ mov %rsi,%rdx
+ ret
+# bytesatleast65:
+._bytesatleast65:
+ # bytes -= 64
+ sub $64,%rdx
+ # out += 64
+ add $64,%rdi
+ # m += 64
+ add $64,%rsi
+ # comment:fp stack unchanged by jump
+ # goto bytesatleast1
+ jmp ._bytesatleast1
+# enter ECRYPT_keysetup
+.text
+.p2align 5
+.globl ECRYPT_keysetup
+ECRYPT_keysetup:
+ mov %rsp,%r11
+ and $31,%r11
+ add $256,%r11
+ sub %r11,%rsp
+ # k = arg2
+ mov %rsi,%rsi
+ # kbits = arg3
+ mov %rdx,%rdx
+ # x = arg1
+ mov %rdi,%rdi
+ # in0 = *(uint64 *) (k + 0)
+ movq 0(%rsi),%r8
+ # in2 = *(uint64 *) (k + 8)
+ movq 8(%rsi),%r9
+ # *(uint64 *) (x + 4) = in0
+ movq %r8,4(%rdi)
+ # *(uint64 *) (x + 12) = in2
+ movq %r9,12(%rdi)
+ # unsigned<? kbits - 256
+ cmp $256,%rdx
+ # comment:fp stack unchanged by jump
+ # goto kbits128 if unsigned<
+ jb ._kbits128
+# kbits256:
+._kbits256:
+ # in10 = *(uint64 *) (k + 16)
+ movq 16(%rsi),%rdx
+ # in12 = *(uint64 *) (k + 24)
+ movq 24(%rsi),%rsi
+ # *(uint64 *) (x + 44) = in10
+ movq %rdx,44(%rdi)
+ # *(uint64 *) (x + 52) = in12
+ movq %rsi,52(%rdi)
+ # in0 = 1634760805
+ mov $1634760805,%rsi
+ # in4 = 857760878
+ mov $857760878,%rdx
+ # in10 = 2036477234
+ mov $2036477234,%rcx
+ # in14 = 1797285236
+ mov $1797285236,%r8
+ # *(uint32 *) (x + 0) = in0
+ movl %esi,0(%rdi)
+ # *(uint32 *) (x + 20) = in4
+ movl %edx,20(%rdi)
+ # *(uint32 *) (x + 40) = in10
+ movl %ecx,40(%rdi)
+ # *(uint32 *) (x + 60) = in14
+ movl %r8d,60(%rdi)
+ # comment:fp stack unchanged by jump
+ # goto keysetupdone
+ jmp ._keysetupdone
+# kbits128:
+._kbits128:
+ # in10 = *(uint64 *) (k + 0)
+ movq 0(%rsi),%rdx
+ # in12 = *(uint64 *) (k + 8)
+ movq 8(%rsi),%rsi
+ # *(uint64 *) (x + 44) = in10
+ movq %rdx,44(%rdi)
+ # *(uint64 *) (x + 52) = in12
+ movq %rsi,52(%rdi)
+ # in0 = 1634760805
+ mov $1634760805,%rsi
+ # in4 = 824206446
+ mov $824206446,%rdx
+ # in10 = 2036477238
+ mov $2036477238,%rcx
+ # in14 = 1797285236
+ mov $1797285236,%r8
+ # *(uint32 *) (x + 0) = in0
+ movl %esi,0(%rdi)
+ # *(uint32 *) (x + 20) = in4
+ movl %edx,20(%rdi)
+ # *(uint32 *) (x + 40) = in10
+ movl %ecx,40(%rdi)
+ # *(uint32 *) (x + 60) = in14
+ movl %r8d,60(%rdi)
+# keysetupdone:
+._keysetupdone:
+ # leave
+ add %r11,%rsp
+ mov %rdi,%rax
+ mov %rsi,%rdx
+ ret
+# enter ECRYPT_ivsetup
+.text
+.p2align 5
+.globl ECRYPT_ivsetup
+ECRYPT_ivsetup:
+ mov %rsp,%r11
+ and $31,%r11
+ add $256,%r11
+ sub %r11,%rsp
+ # iv = arg2
+ mov %rsi,%rsi
+ # x = arg1
+ mov %rdi,%rdi
+ # in6 = *(uint64 *) (iv + 0)
+ movq 0(%rsi),%rsi
+ # in8 = 0
+ mov $0,%r8
+ # *(uint64 *) (x + 24) = in6
+ movq %rsi,24(%rdi)
+ # *(uint64 *) (x + 32) = in8
+ movq %r8,32(%rdi)
+ # leave
+ add %r11,%rsp
+ mov %rdi,%rax
+ mov %rsi,%rdx
+ ret
diff --git a/arch/x86/crypto/salsa20_glue.c b/arch/x86/crypto/salsa20_glue.c
new file mode 100644
index 0000000..bccb76d
--- /dev/null
+++ b/arch/x86/crypto/salsa20_glue.c
@@ -0,0 +1,129 @@
+/*
+ * Glue code for optimized assembly version of Salsa20.
+ *
+ * Copyright (c) 2007 Tan Swee Heng <thesweeheng@gmail.com>
+ *
+ * The assembly codes are public domain assembly codes written by Daniel. J.
+ * Bernstein <djb@cr.yp.to>. The codes are modified to include indentation
+ * and to remove extraneous comments and functions that are not needed.
+ * - i586 version, renamed as salsa20-i586-asm_32.S
+ * available from <http://cr.yp.to/snuffle/salsa20/x86-pm/salsa20.s>
+ * - x86-64 version, renamed as salsa20-x86_64-asm_64.S
+ * available from <http://cr.yp.to/snuffle/salsa20/amd64-3/salsa20.s>
+ *
+ * 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 <crypto/algapi.h>
+#include <linux/module.h>
+#include <linux/crypto.h>
+
+#define SALSA20_IV_SIZE 8U
+#define SALSA20_MIN_KEY_SIZE 16U
+#define SALSA20_MAX_KEY_SIZE 32U
+
+// use the ECRYPT_* function names
+#define salsa20_keysetup ECRYPT_keysetup
+#define salsa20_ivsetup ECRYPT_ivsetup
+#define salsa20_encrypt_bytes ECRYPT_encrypt_bytes
+
+struct salsa20_ctx
+{
+ u32 input[16];
+};
+
+asmlinkage void salsa20_keysetup(struct salsa20_ctx *ctx, const u8 *k,
+ u32 keysize, u32 ivsize);
+asmlinkage void salsa20_ivsetup(struct salsa20_ctx *ctx, const u8 *iv);
+asmlinkage void salsa20_encrypt_bytes(struct salsa20_ctx *ctx,
+ const u8 *src, u8 *dst, u32 bytes);
+
+static int setkey(struct crypto_tfm *tfm, const u8 *key,
+ unsigned int keysize)
+{
+ struct salsa20_ctx *ctx = crypto_tfm_ctx(tfm);
+ salsa20_keysetup(ctx, key, keysize*8, SALSA20_IV_SIZE*8);
+ return 0;
+}
+
+static int encrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ struct blkcipher_walk walk;
+ struct crypto_blkcipher *tfm = desc->tfm;
+ struct salsa20_ctx *ctx = crypto_blkcipher_ctx(tfm);
+ int err;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ err = blkcipher_walk_virt_block(desc, &walk, 64);
+
+ salsa20_ivsetup(ctx, walk.iv);
+
+ if (likely(walk.nbytes == nbytes))
+ {
+ salsa20_encrypt_bytes(ctx, walk.src.virt.addr,
+ walk.dst.virt.addr, nbytes);
+ return blkcipher_walk_done(desc, &walk, 0);
+ }
+
+ while (walk.nbytes >= 64) {
+ salsa20_encrypt_bytes(ctx, walk.src.virt.addr,
+ walk.dst.virt.addr,
+ walk.nbytes - (walk.nbytes % 64));
+ err = blkcipher_walk_done(desc, &walk, walk.nbytes % 64);
+ }
+
+ if (walk.nbytes) {
+ salsa20_encrypt_bytes(ctx, walk.src.virt.addr,
+ walk.dst.virt.addr, walk.nbytes);
+ err = blkcipher_walk_done(desc, &walk, 0);
+ }
+
+ return err;
+}
+
+static struct crypto_alg alg = {
+ .cra_name = "salsa20",
+ .cra_driver_name = "salsa20-asm",
+ .cra_priority = 200,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_type = &crypto_blkcipher_type,
+ .cra_blocksize = 1,
+ .cra_ctxsize = sizeof(struct salsa20_ctx),
+ .cra_alignmask = 3,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(alg.cra_list),
+ .cra_u = {
+ .blkcipher = {
+ .setkey = setkey,
+ .encrypt = encrypt,
+ .decrypt = encrypt,
+ .min_keysize = SALSA20_MIN_KEY_SIZE,
+ .max_keysize = SALSA20_MAX_KEY_SIZE,
+ .ivsize = SALSA20_IV_SIZE,
+ }
+ }
+};
+
+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_LICENSE("GPL");
+MODULE_DESCRIPTION ("Salsa20 stream cipher algorithm (optimized assembly version)");
+MODULE_ALIAS("salsa20");
+MODULE_ALIAS("salsa20-asm");
diff --git a/arch/x86/crypto/twofish_32.c b/arch/x86/crypto/twofish_32.c
deleted file mode 100644
index e3004df..0000000
--- a/arch/x86/crypto/twofish_32.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Glue Code for optimized 586 assembler version of TWOFISH
- *
- * Originally Twofish for GPG
- * By Matthew Skala <mskala@ansuz.sooke.bc.ca>, July 26, 1998
- * 256-bit key length added March 20, 1999
- * Some modifications to reduce the text size by Werner Koch, April, 1998
- * Ported to the kerneli patch by Marc Mutz <Marc@Mutz.com>
- * Ported to CryptoAPI by Colin Slater <hoho@tacomeat.net>
- *
- * The original author has disclaimed all copyright interest in this
- * code and thus put it in the public domain. The subsequent authors
- * have put this under the GNU General Public License.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
- *
- * This code is a "clean room" implementation, written from the paper
- * _Twofish: A 128-Bit Block Cipher_ by Bruce Schneier, John Kelsey,
- * Doug Whiting, David Wagner, Chris Hall, and Niels Ferguson, available
- * through http://www.counterpane.com/twofish.html
- *
- * For background information on multiplication in finite fields, used for
- * the matrix operations in the key schedule, see the book _Contemporary
- * Abstract Algebra_ by Joseph A. Gallian, especially chapter 22 in the
- * Third Edition.
- */
-
-#include <crypto/twofish.h>
-#include <linux/crypto.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/types.h>
-
-
-asmlinkage void twofish_enc_blk(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
-asmlinkage void twofish_dec_blk(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
-
-static void twofish_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
-{
- twofish_enc_blk(tfm, dst, src);
-}
-
-static void twofish_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
-{
- twofish_dec_blk(tfm, dst, src);
-}
-
-static struct crypto_alg alg = {
- .cra_name = "twofish",
- .cra_driver_name = "twofish-i586",
- .cra_priority = 200,
- .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
- .cra_blocksize = TF_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct twofish_ctx),
- .cra_alignmask = 3,
- .cra_module = THIS_MODULE,
- .cra_list = LIST_HEAD_INIT(alg.cra_list),
- .cra_u = {
- .cipher = {
- .cia_min_keysize = TF_MIN_KEY_SIZE,
- .cia_max_keysize = TF_MAX_KEY_SIZE,
- .cia_setkey = twofish_setkey,
- .cia_encrypt = twofish_encrypt,
- .cia_decrypt = twofish_decrypt
- }
- }
-};
-
-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_LICENSE("GPL");
-MODULE_DESCRIPTION ("Twofish Cipher Algorithm, i586 asm optimized");
-MODULE_ALIAS("twofish");
diff --git a/arch/x86/crypto/twofish_64.c b/arch/x86/crypto/twofish_glue.c
similarity index 93%
rename from arch/x86/crypto/twofish_64.c
rename to arch/x86/crypto/twofish_glue.c
index 182d91d..cefaf8b 100644
--- a/arch/x86/crypto/twofish_64.c
+++ b/arch/x86/crypto/twofish_glue.c
@@ -1,5 +1,5 @@
/*
- * Glue Code for optimized x86_64 assembler version of TWOFISH
+ * Glue Code for assembler optimized version of TWOFISH
*
* Originally Twofish for GPG
* By Matthew Skala <mskala@ansuz.sooke.bc.ca>, July 26, 1998
@@ -41,7 +41,6 @@
#include <crypto/twofish.h>
#include <linux/crypto.h>
#include <linux/init.h>
-#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
@@ -60,7 +59,7 @@
static struct crypto_alg alg = {
.cra_name = "twofish",
- .cra_driver_name = "twofish-x86_64",
+ .cra_driver_name = "twofish-asm",
.cra_priority = 200,
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = TF_BLOCK_SIZE,
@@ -93,5 +92,6 @@
module_exit(fini);
MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION ("Twofish Cipher Algorithm, x86_64 asm optimized");
+MODULE_DESCRIPTION ("Twofish Cipher Algorithm, asm optimized");
MODULE_ALIAS("twofish");
+MODULE_ALIAS("twofish-asm");
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 083d2e1..c3166a1 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -24,10 +24,6 @@
help
This option provides the API for cryptographic algorithms.
-config CRYPTO_ABLKCIPHER
- tristate
- select CRYPTO_BLKCIPHER
-
config CRYPTO_AEAD
tristate
select CRYPTO_ALGAPI
@@ -36,6 +32,15 @@
tristate
select CRYPTO_ALGAPI
+config CRYPTO_SEQIV
+ tristate "Sequence Number IV Generator"
+ select CRYPTO_AEAD
+ select CRYPTO_BLKCIPHER
+ help
+ This IV generator generates an IV based on a sequence number by
+ xoring it with a salt. This algorithm is mainly useful for CTR
+ and similar modes.
+
config CRYPTO_HASH
tristate
select CRYPTO_ALGAPI
@@ -91,7 +96,7 @@
SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
config CRYPTO_SHA256
- tristate "SHA256 digest algorithm"
+ tristate "SHA224 and SHA256 digest algorithm"
select CRYPTO_ALGAPI
help
SHA256 secure hash standard (DFIPS 180-2).
@@ -99,6 +104,9 @@
This version of SHA implements a 256 bit hash with 128 bits of
security against collision attacks.
+ This code also includes SHA-224, a 224 bit hash with 112 bits
+ of security against collision attacks.
+
config CRYPTO_SHA512
tristate "SHA384 and SHA512 digest algorithms"
select CRYPTO_ALGAPI
@@ -195,9 +203,34 @@
key size 256, 384 or 512 bits. This implementation currently
can't handle a sectorsize which is not a multiple of 16 bytes.
+config CRYPTO_CTR
+ tristate "CTR support"
+ select CRYPTO_BLKCIPHER
+ select CRYPTO_SEQIV
+ select CRYPTO_MANAGER
+ help
+ CTR: Counter mode
+ This block cipher algorithm is required for IPSec.
+
+config CRYPTO_GCM
+ tristate "GCM/GMAC support"
+ select CRYPTO_CTR
+ select CRYPTO_AEAD
+ select CRYPTO_GF128MUL
+ help
+ Support for Galois/Counter Mode (GCM) and Galois Message
+ Authentication Code (GMAC). Required for IPSec.
+
+config CRYPTO_CCM
+ tristate "CCM support"
+ select CRYPTO_CTR
+ select CRYPTO_AEAD
+ help
+ Support for Counter with CBC MAC. Required for IPsec.
+
config CRYPTO_CRYPTD
tristate "Software async crypto daemon"
- select CRYPTO_ABLKCIPHER
+ select CRYPTO_BLKCIPHER
select CRYPTO_MANAGER
help
This is a generic software asynchronous crypto daemon that
@@ -320,6 +353,7 @@
tristate "AES cipher algorithms (i586)"
depends on (X86 || UML_X86) && !64BIT
select CRYPTO_ALGAPI
+ select CRYPTO_AES
help
AES cipher algorithms (FIPS-197). AES uses the Rijndael
algorithm.
@@ -341,6 +375,7 @@
tristate "AES cipher algorithms (x86_64)"
depends on (X86 || UML_X86) && 64BIT
select CRYPTO_ALGAPI
+ select CRYPTO_AES
help
AES cipher algorithms (FIPS-197). AES uses the Rijndael
algorithm.
@@ -441,6 +476,46 @@
See also:
<http://www.kisa.or.kr/kisa/seed/jsp/seed_eng.jsp>
+config CRYPTO_SALSA20
+ tristate "Salsa20 stream cipher algorithm (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ select CRYPTO_BLKCIPHER
+ help
+ Salsa20 stream cipher algorithm.
+
+ Salsa20 is a stream cipher submitted to eSTREAM, the ECRYPT
+ Stream Cipher Project. See <http://www.ecrypt.eu.org/stream/>
+
+ The Salsa20 stream cipher algorithm is designed by Daniel J.
+ Bernstein <djb@cr.yp.to>. See <http://cr.yp.to/snuffle.html>
+
+config CRYPTO_SALSA20_586
+ tristate "Salsa20 stream cipher algorithm (i586) (EXPERIMENTAL)"
+ depends on (X86 || UML_X86) && !64BIT
+ depends on EXPERIMENTAL
+ select CRYPTO_BLKCIPHER
+ help
+ Salsa20 stream cipher algorithm.
+
+ Salsa20 is a stream cipher submitted to eSTREAM, the ECRYPT
+ Stream Cipher Project. See <http://www.ecrypt.eu.org/stream/>
+
+ The Salsa20 stream cipher algorithm is designed by Daniel J.
+ Bernstein <djb@cr.yp.to>. See <http://cr.yp.to/snuffle.html>
+
+config CRYPTO_SALSA20_X86_64
+ tristate "Salsa20 stream cipher algorithm (x86_64) (EXPERIMENTAL)"
+ depends on (X86 || UML_X86) && 64BIT
+ depends on EXPERIMENTAL
+ select CRYPTO_BLKCIPHER
+ help
+ Salsa20 stream cipher algorithm.
+
+ Salsa20 is a stream cipher submitted to eSTREAM, the ECRYPT
+ Stream Cipher Project. See <http://www.ecrypt.eu.org/stream/>
+
+ The Salsa20 stream cipher algorithm is designed by Daniel J.
+ Bernstein <djb@cr.yp.to>. See <http://cr.yp.to/snuffle.html>
config CRYPTO_DEFLATE
tristate "Deflate compression algorithm"
@@ -491,6 +566,7 @@
tristate "Testing module"
depends on m
select CRYPTO_ALGAPI
+ select CRYPTO_AEAD
help
Quick & dirty crypto test module.
@@ -498,10 +574,19 @@
tristate "Authenc support"
select CRYPTO_AEAD
select CRYPTO_MANAGER
+ select CRYPTO_HASH
help
Authenc: Combined mode wrapper for IPsec.
This is required for IPSec.
+config CRYPTO_LZO
+ tristate "LZO compression algorithm"
+ select CRYPTO_ALGAPI
+ select LZO_COMPRESS
+ select LZO_DECOMPRESS
+ help
+ This is the LZO algorithm.
+
source "drivers/crypto/Kconfig"
endif # if CRYPTO
diff --git a/crypto/Makefile b/crypto/Makefile
index 43c2a0d..48c7583 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -8,9 +8,14 @@
crypto_algapi-objs := algapi.o scatterwalk.o $(crypto_algapi-y)
obj-$(CONFIG_CRYPTO_ALGAPI) += crypto_algapi.o
-obj-$(CONFIG_CRYPTO_ABLKCIPHER) += ablkcipher.o
obj-$(CONFIG_CRYPTO_AEAD) += aead.o
-obj-$(CONFIG_CRYPTO_BLKCIPHER) += blkcipher.o
+
+crypto_blkcipher-objs := ablkcipher.o
+crypto_blkcipher-objs += blkcipher.o
+obj-$(CONFIG_CRYPTO_BLKCIPHER) += crypto_blkcipher.o
+obj-$(CONFIG_CRYPTO_BLKCIPHER) += chainiv.o
+obj-$(CONFIG_CRYPTO_BLKCIPHER) += eseqiv.o
+obj-$(CONFIG_CRYPTO_SEQIV) += seqiv.o
crypto_hash-objs := hash.o
obj-$(CONFIG_CRYPTO_HASH) += crypto_hash.o
@@ -32,6 +37,9 @@
obj-$(CONFIG_CRYPTO_PCBC) += pcbc.o
obj-$(CONFIG_CRYPTO_LRW) += lrw.o
obj-$(CONFIG_CRYPTO_XTS) += xts.o
+obj-$(CONFIG_CRYPTO_CTR) += ctr.o
+obj-$(CONFIG_CRYPTO_GCM) += gcm.o
+obj-$(CONFIG_CRYPTO_CCM) += ccm.o
obj-$(CONFIG_CRYPTO_CRYPTD) += cryptd.o
obj-$(CONFIG_CRYPTO_DES) += des_generic.o
obj-$(CONFIG_CRYPTO_FCRYPT) += fcrypt.o
@@ -48,10 +56,12 @@
obj-$(CONFIG_CRYPTO_KHAZAD) += khazad.o
obj-$(CONFIG_CRYPTO_ANUBIS) += anubis.o
obj-$(CONFIG_CRYPTO_SEED) += seed.o
+obj-$(CONFIG_CRYPTO_SALSA20) += salsa20_generic.o
obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o
obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o
obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o
+obj-$(CONFIG_CRYPTO_LZO) += lzo.o
obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c
index 2731acb..3bcb099 100644
--- a/crypto/ablkcipher.c
+++ b/crypto/ablkcipher.c
@@ -13,14 +13,18 @@
*
*/
-#include <crypto/algapi.h>
-#include <linux/errno.h>
+#include <crypto/internal/skcipher.h>
+#include <linux/err.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/rtnetlink.h>
+#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/seq_file.h>
+#include "internal.h"
+
static int setkey_unaligned(struct crypto_ablkcipher *tfm, const u8 *key,
unsigned int keylen)
{
@@ -66,6 +70,16 @@
return alg->cra_ctxsize;
}
+int skcipher_null_givencrypt(struct skcipher_givcrypt_request *req)
+{
+ return crypto_ablkcipher_encrypt(&req->creq);
+}
+
+int skcipher_null_givdecrypt(struct skcipher_givcrypt_request *req)
+{
+ return crypto_ablkcipher_decrypt(&req->creq);
+}
+
static int crypto_init_ablkcipher_ops(struct crypto_tfm *tfm, u32 type,
u32 mask)
{
@@ -78,6 +92,11 @@
crt->setkey = setkey;
crt->encrypt = alg->encrypt;
crt->decrypt = alg->decrypt;
+ if (!alg->ivsize) {
+ crt->givencrypt = skcipher_null_givencrypt;
+ crt->givdecrypt = skcipher_null_givdecrypt;
+ }
+ crt->base = __crypto_ablkcipher_cast(tfm);
crt->ivsize = alg->ivsize;
return 0;
@@ -90,10 +109,13 @@
struct ablkcipher_alg *ablkcipher = &alg->cra_ablkcipher;
seq_printf(m, "type : ablkcipher\n");
+ seq_printf(m, "async : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ?
+ "yes" : "no");
seq_printf(m, "blocksize : %u\n", alg->cra_blocksize);
seq_printf(m, "min keysize : %u\n", ablkcipher->min_keysize);
seq_printf(m, "max keysize : %u\n", ablkcipher->max_keysize);
seq_printf(m, "ivsize : %u\n", ablkcipher->ivsize);
+ seq_printf(m, "geniv : %s\n", ablkcipher->geniv ?: "<default>");
}
const struct crypto_type crypto_ablkcipher_type = {
@@ -105,5 +127,220 @@
};
EXPORT_SYMBOL_GPL(crypto_ablkcipher_type);
+static int no_givdecrypt(struct skcipher_givcrypt_request *req)
+{
+ return -ENOSYS;
+}
+
+static int crypto_init_givcipher_ops(struct crypto_tfm *tfm, u32 type,
+ u32 mask)
+{
+ struct ablkcipher_alg *alg = &tfm->__crt_alg->cra_ablkcipher;
+ struct ablkcipher_tfm *crt = &tfm->crt_ablkcipher;
+
+ if (alg->ivsize > PAGE_SIZE / 8)
+ return -EINVAL;
+
+ crt->setkey = tfm->__crt_alg->cra_flags & CRYPTO_ALG_GENIV ?
+ alg->setkey : setkey;
+ crt->encrypt = alg->encrypt;
+ crt->decrypt = alg->decrypt;
+ crt->givencrypt = alg->givencrypt;
+ crt->givdecrypt = alg->givdecrypt ?: no_givdecrypt;
+ crt->base = __crypto_ablkcipher_cast(tfm);
+ crt->ivsize = alg->ivsize;
+
+ return 0;
+}
+
+static void crypto_givcipher_show(struct seq_file *m, struct crypto_alg *alg)
+ __attribute__ ((unused));
+static void crypto_givcipher_show(struct seq_file *m, struct crypto_alg *alg)
+{
+ struct ablkcipher_alg *ablkcipher = &alg->cra_ablkcipher;
+
+ seq_printf(m, "type : givcipher\n");
+ seq_printf(m, "async : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ?
+ "yes" : "no");
+ seq_printf(m, "blocksize : %u\n", alg->cra_blocksize);
+ seq_printf(m, "min keysize : %u\n", ablkcipher->min_keysize);
+ seq_printf(m, "max keysize : %u\n", ablkcipher->max_keysize);
+ seq_printf(m, "ivsize : %u\n", ablkcipher->ivsize);
+ seq_printf(m, "geniv : %s\n", ablkcipher->geniv ?: "<built-in>");
+}
+
+const struct crypto_type crypto_givcipher_type = {
+ .ctxsize = crypto_ablkcipher_ctxsize,
+ .init = crypto_init_givcipher_ops,
+#ifdef CONFIG_PROC_FS
+ .show = crypto_givcipher_show,
+#endif
+};
+EXPORT_SYMBOL_GPL(crypto_givcipher_type);
+
+const char *crypto_default_geniv(const struct crypto_alg *alg)
+{
+ return alg->cra_flags & CRYPTO_ALG_ASYNC ? "eseqiv" : "chainiv";
+}
+
+static int crypto_givcipher_default(struct crypto_alg *alg, u32 type, u32 mask)
+{
+ struct rtattr *tb[3];
+ struct {
+ struct rtattr attr;
+ struct crypto_attr_type data;
+ } ptype;
+ struct {
+ struct rtattr attr;
+ struct crypto_attr_alg data;
+ } palg;
+ struct crypto_template *tmpl;
+ struct crypto_instance *inst;
+ struct crypto_alg *larval;
+ const char *geniv;
+ int err;
+
+ larval = crypto_larval_lookup(alg->cra_driver_name,
+ CRYPTO_ALG_TYPE_GIVCIPHER,
+ CRYPTO_ALG_TYPE_MASK);
+ err = PTR_ERR(larval);
+ if (IS_ERR(larval))
+ goto out;
+
+ err = -EAGAIN;
+ if (!crypto_is_larval(larval))
+ goto drop_larval;
+
+ ptype.attr.rta_len = sizeof(ptype);
+ ptype.attr.rta_type = CRYPTOA_TYPE;
+ ptype.data.type = type | CRYPTO_ALG_GENIV;
+ /* GENIV tells the template that we're making a default geniv. */
+ ptype.data.mask = mask | CRYPTO_ALG_GENIV;
+ tb[0] = &ptype.attr;
+
+ palg.attr.rta_len = sizeof(palg);
+ palg.attr.rta_type = CRYPTOA_ALG;
+ /* Must use the exact name to locate ourselves. */
+ memcpy(palg.data.name, alg->cra_driver_name, CRYPTO_MAX_ALG_NAME);
+ tb[1] = &palg.attr;
+
+ tb[2] = NULL;
+
+ if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
+ CRYPTO_ALG_TYPE_BLKCIPHER)
+ geniv = alg->cra_blkcipher.geniv;
+ else
+ geniv = alg->cra_ablkcipher.geniv;
+
+ if (!geniv)
+ geniv = crypto_default_geniv(alg);
+
+ tmpl = crypto_lookup_template(geniv);
+ err = -ENOENT;
+ if (!tmpl)
+ goto kill_larval;
+
+ inst = tmpl->alloc(tb);
+ err = PTR_ERR(inst);
+ if (IS_ERR(inst))
+ goto put_tmpl;
+
+ if ((err = crypto_register_instance(tmpl, inst))) {
+ tmpl->free(inst);
+ goto put_tmpl;
+ }
+
+ /* Redo the lookup to use the instance we just registered. */
+ err = -EAGAIN;
+
+put_tmpl:
+ crypto_tmpl_put(tmpl);
+kill_larval:
+ crypto_larval_kill(larval);
+drop_larval:
+ crypto_mod_put(larval);
+out:
+ crypto_mod_put(alg);
+ return err;
+}
+
+static struct crypto_alg *crypto_lookup_skcipher(const char *name, u32 type,
+ u32 mask)
+{
+ struct crypto_alg *alg;
+
+ alg = crypto_alg_mod_lookup(name, type, mask);
+ if (IS_ERR(alg))
+ return alg;
+
+ if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
+ CRYPTO_ALG_TYPE_GIVCIPHER)
+ return alg;
+
+ if (!((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
+ CRYPTO_ALG_TYPE_BLKCIPHER ? alg->cra_blkcipher.ivsize :
+ alg->cra_ablkcipher.ivsize))
+ return alg;
+
+ return ERR_PTR(crypto_givcipher_default(alg, type, mask));
+}
+
+int crypto_grab_skcipher(struct crypto_skcipher_spawn *spawn, const char *name,
+ u32 type, u32 mask)
+{
+ struct crypto_alg *alg;
+ int err;
+
+ type = crypto_skcipher_type(type);
+ mask = crypto_skcipher_mask(mask);
+
+ alg = crypto_lookup_skcipher(name, type, mask);
+ if (IS_ERR(alg))
+ return PTR_ERR(alg);
+
+ err = crypto_init_spawn(&spawn->base, alg, spawn->base.inst, mask);
+ crypto_mod_put(alg);
+ return err;
+}
+EXPORT_SYMBOL_GPL(crypto_grab_skcipher);
+
+struct crypto_ablkcipher *crypto_alloc_ablkcipher(const char *alg_name,
+ u32 type, u32 mask)
+{
+ struct crypto_tfm *tfm;
+ int err;
+
+ type = crypto_skcipher_type(type);
+ mask = crypto_skcipher_mask(mask);
+
+ for (;;) {
+ struct crypto_alg *alg;
+
+ alg = crypto_lookup_skcipher(alg_name, type, mask);
+ if (IS_ERR(alg)) {
+ err = PTR_ERR(alg);
+ goto err;
+ }
+
+ tfm = __crypto_alloc_tfm(alg, type, mask);
+ if (!IS_ERR(tfm))
+ return __crypto_ablkcipher_cast(tfm);
+
+ crypto_mod_put(alg);
+ err = PTR_ERR(tfm);
+
+err:
+ if (err != -EAGAIN)
+ break;
+ if (signal_pending(current)) {
+ err = -EINTR;
+ break;
+ }
+ }
+
+ return ERR_PTR(err);
+}
+EXPORT_SYMBOL_GPL(crypto_alloc_ablkcipher);
+
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Asynchronous block chaining cipher type");
diff --git a/crypto/aead.c b/crypto/aead.c
index 84a3501..3a6f3f5 100644
--- a/crypto/aead.c
+++ b/crypto/aead.c
@@ -12,14 +12,17 @@
*
*/
-#include <crypto/algapi.h>
-#include <linux/errno.h>
+#include <crypto/internal/aead.h>
+#include <linux/err.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/rtnetlink.h>
#include <linux/slab.h>
#include <linux/seq_file.h>
+#include "internal.h"
+
static int setkey_unaligned(struct crypto_aead *tfm, const u8 *key,
unsigned int keylen)
{
@@ -53,25 +56,54 @@
return aead->setkey(tfm, key, keylen);
}
+int crypto_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize)
+{
+ struct aead_tfm *crt = crypto_aead_crt(tfm);
+ int err;
+
+ if (authsize > crypto_aead_alg(tfm)->maxauthsize)
+ return -EINVAL;
+
+ if (crypto_aead_alg(tfm)->setauthsize) {
+ err = crypto_aead_alg(tfm)->setauthsize(crt->base, authsize);
+ if (err)
+ return err;
+ }
+
+ crypto_aead_crt(crt->base)->authsize = authsize;
+ crt->authsize = authsize;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(crypto_aead_setauthsize);
+
static unsigned int crypto_aead_ctxsize(struct crypto_alg *alg, u32 type,
u32 mask)
{
return alg->cra_ctxsize;
}
+static int no_givcrypt(struct aead_givcrypt_request *req)
+{
+ return -ENOSYS;
+}
+
static int crypto_init_aead_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
{
struct aead_alg *alg = &tfm->__crt_alg->cra_aead;
struct aead_tfm *crt = &tfm->crt_aead;
- if (max(alg->authsize, alg->ivsize) > PAGE_SIZE / 8)
+ if (max(alg->maxauthsize, alg->ivsize) > PAGE_SIZE / 8)
return -EINVAL;
- crt->setkey = setkey;
+ crt->setkey = tfm->__crt_alg->cra_flags & CRYPTO_ALG_GENIV ?
+ alg->setkey : setkey;
crt->encrypt = alg->encrypt;
crt->decrypt = alg->decrypt;
+ crt->givencrypt = alg->givencrypt ?: no_givcrypt;
+ crt->givdecrypt = alg->givdecrypt ?: no_givcrypt;
+ crt->base = __crypto_aead_cast(tfm);
crt->ivsize = alg->ivsize;
- crt->authsize = alg->authsize;
+ crt->authsize = alg->maxauthsize;
return 0;
}
@@ -83,9 +115,12 @@
struct aead_alg *aead = &alg->cra_aead;
seq_printf(m, "type : aead\n");
+ seq_printf(m, "async : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ?
+ "yes" : "no");
seq_printf(m, "blocksize : %u\n", alg->cra_blocksize);
seq_printf(m, "ivsize : %u\n", aead->ivsize);
- seq_printf(m, "authsize : %u\n", aead->authsize);
+ seq_printf(m, "maxauthsize : %u\n", aead->maxauthsize);
+ seq_printf(m, "geniv : %s\n", aead->geniv ?: "<built-in>");
}
const struct crypto_type crypto_aead_type = {
@@ -97,5 +132,358 @@
};
EXPORT_SYMBOL_GPL(crypto_aead_type);
+static int aead_null_givencrypt(struct aead_givcrypt_request *req)
+{
+ return crypto_aead_encrypt(&req->areq);
+}
+
+static int aead_null_givdecrypt(struct aead_givcrypt_request *req)
+{
+ return crypto_aead_decrypt(&req->areq);
+}
+
+static int crypto_init_nivaead_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
+{
+ struct aead_alg *alg = &tfm->__crt_alg->cra_aead;
+ struct aead_tfm *crt = &tfm->crt_aead;
+
+ if (max(alg->maxauthsize, alg->ivsize) > PAGE_SIZE / 8)
+ return -EINVAL;
+
+ crt->setkey = setkey;
+ crt->encrypt = alg->encrypt;
+ crt->decrypt = alg->decrypt;
+ if (!alg->ivsize) {
+ crt->givencrypt = aead_null_givencrypt;
+ crt->givdecrypt = aead_null_givdecrypt;
+ }
+ crt->base = __crypto_aead_cast(tfm);
+ crt->ivsize = alg->ivsize;
+ crt->authsize = alg->maxauthsize;
+
+ return 0;
+}
+
+static void crypto_nivaead_show(struct seq_file *m, struct crypto_alg *alg)
+ __attribute__ ((unused));
+static void crypto_nivaead_show(struct seq_file *m, struct crypto_alg *alg)
+{
+ struct aead_alg *aead = &alg->cra_aead;
+
+ seq_printf(m, "type : nivaead\n");
+ seq_printf(m, "async : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ?
+ "yes" : "no");
+ seq_printf(m, "blocksize : %u\n", alg->cra_blocksize);
+ seq_printf(m, "ivsize : %u\n", aead->ivsize);
+ seq_printf(m, "maxauthsize : %u\n", aead->maxauthsize);
+ seq_printf(m, "geniv : %s\n", aead->geniv);
+}
+
+const struct crypto_type crypto_nivaead_type = {
+ .ctxsize = crypto_aead_ctxsize,
+ .init = crypto_init_nivaead_ops,
+#ifdef CONFIG_PROC_FS
+ .show = crypto_nivaead_show,
+#endif
+};
+EXPORT_SYMBOL_GPL(crypto_nivaead_type);
+
+static int crypto_grab_nivaead(struct crypto_aead_spawn *spawn,
+ const char *name, u32 type, u32 mask)
+{
+ struct crypto_alg *alg;
+ int err;
+
+ type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
+ type |= CRYPTO_ALG_TYPE_AEAD;
+ mask |= CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV;
+
+ alg = crypto_alg_mod_lookup(name, type, mask);
+ if (IS_ERR(alg))
+ return PTR_ERR(alg);
+
+ err = crypto_init_spawn(&spawn->base, alg, spawn->base.inst, mask);
+ crypto_mod_put(alg);
+ return err;
+}
+
+struct crypto_instance *aead_geniv_alloc(struct crypto_template *tmpl,
+ struct rtattr **tb, u32 type,
+ u32 mask)
+{
+ const char *name;
+ struct crypto_aead_spawn *spawn;
+ struct crypto_attr_type *algt;
+ struct crypto_instance *inst;
+ struct crypto_alg *alg;
+ int err;
+
+ algt = crypto_get_attr_type(tb);
+ err = PTR_ERR(algt);
+ if (IS_ERR(algt))
+ return ERR_PTR(err);
+
+ if ((algt->type ^ (CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV)) &
+ algt->mask)
+ return ERR_PTR(-EINVAL);
+
+ name = crypto_attr_alg_name(tb[1]);
+ err = PTR_ERR(name);
+ if (IS_ERR(name))
+ return ERR_PTR(err);
+
+ inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
+ if (!inst)
+ return ERR_PTR(-ENOMEM);
+
+ spawn = crypto_instance_ctx(inst);
+
+ /* Ignore async algorithms if necessary. */
+ mask |= crypto_requires_sync(algt->type, algt->mask);
+
+ crypto_set_aead_spawn(spawn, inst);
+ err = crypto_grab_nivaead(spawn, name, type, mask);
+ if (err)
+ goto err_free_inst;
+
+ alg = crypto_aead_spawn_alg(spawn);
+
+ err = -EINVAL;
+ if (!alg->cra_aead.ivsize)
+ goto err_drop_alg;
+
+ /*
+ * This is only true if we're constructing an algorithm with its
+ * default IV generator. For the default generator we elide the
+ * template name and double-check the IV generator.
+ */
+ if (algt->mask & CRYPTO_ALG_GENIV) {
+ if (strcmp(tmpl->name, alg->cra_aead.geniv))
+ goto err_drop_alg;
+
+ memcpy(inst->alg.cra_name, alg->cra_name, CRYPTO_MAX_ALG_NAME);
+ memcpy(inst->alg.cra_driver_name, alg->cra_driver_name,
+ CRYPTO_MAX_ALG_NAME);
+ } else {
+ err = -ENAMETOOLONG;
+ if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
+ "%s(%s)", tmpl->name, alg->cra_name) >=
+ CRYPTO_MAX_ALG_NAME)
+ goto err_drop_alg;
+ if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
+ "%s(%s)", tmpl->name, alg->cra_driver_name) >=
+ CRYPTO_MAX_ALG_NAME)
+ goto err_drop_alg;
+ }
+
+ inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV;
+ inst->alg.cra_flags |= alg->cra_flags & CRYPTO_ALG_ASYNC;
+ inst->alg.cra_priority = alg->cra_priority;
+ inst->alg.cra_blocksize = alg->cra_blocksize;
+ inst->alg.cra_alignmask = alg->cra_alignmask;
+ inst->alg.cra_type = &crypto_aead_type;
+
+ inst->alg.cra_aead.ivsize = alg->cra_aead.ivsize;
+ inst->alg.cra_aead.maxauthsize = alg->cra_aead.maxauthsize;
+ inst->alg.cra_aead.geniv = alg->cra_aead.geniv;
+
+ inst->alg.cra_aead.setkey = alg->cra_aead.setkey;
+ inst->alg.cra_aead.setauthsize = alg->cra_aead.setauthsize;
+ inst->alg.cra_aead.encrypt = alg->cra_aead.encrypt;
+ inst->alg.cra_aead.decrypt = alg->cra_aead.decrypt;
+
+out:
+ return inst;
+
+err_drop_alg:
+ crypto_drop_aead(spawn);
+err_free_inst:
+ kfree(inst);
+ inst = ERR_PTR(err);
+ goto out;
+}
+EXPORT_SYMBOL_GPL(aead_geniv_alloc);
+
+void aead_geniv_free(struct crypto_instance *inst)
+{
+ crypto_drop_aead(crypto_instance_ctx(inst));
+ kfree(inst);
+}
+EXPORT_SYMBOL_GPL(aead_geniv_free);
+
+int aead_geniv_init(struct crypto_tfm *tfm)
+{
+ struct crypto_instance *inst = (void *)tfm->__crt_alg;
+ struct crypto_aead *aead;
+
+ aead = crypto_spawn_aead(crypto_instance_ctx(inst));
+ if (IS_ERR(aead))
+ return PTR_ERR(aead);
+
+ tfm->crt_aead.base = aead;
+ tfm->crt_aead.reqsize += crypto_aead_reqsize(aead);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(aead_geniv_init);
+
+void aead_geniv_exit(struct crypto_tfm *tfm)
+{
+ crypto_free_aead(tfm->crt_aead.base);
+}
+EXPORT_SYMBOL_GPL(aead_geniv_exit);
+
+static int crypto_nivaead_default(struct crypto_alg *alg, u32 type, u32 mask)
+{
+ struct rtattr *tb[3];
+ struct {
+ struct rtattr attr;
+ struct crypto_attr_type data;
+ } ptype;
+ struct {
+ struct rtattr attr;
+ struct crypto_attr_alg data;
+ } palg;
+ struct crypto_template *tmpl;
+ struct crypto_instance *inst;
+ struct crypto_alg *larval;
+ const char *geniv;
+ int err;
+
+ larval = crypto_larval_lookup(alg->cra_driver_name,
+ CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV,
+ CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
+ err = PTR_ERR(larval);
+ if (IS_ERR(larval))
+ goto out;
+
+ err = -EAGAIN;
+ if (!crypto_is_larval(larval))
+ goto drop_larval;
+
+ ptype.attr.rta_len = sizeof(ptype);
+ ptype.attr.rta_type = CRYPTOA_TYPE;
+ ptype.data.type = type | CRYPTO_ALG_GENIV;
+ /* GENIV tells the template that we're making a default geniv. */
+ ptype.data.mask = mask | CRYPTO_ALG_GENIV;
+ tb[0] = &ptype.attr;
+
+ palg.attr.rta_len = sizeof(palg);
+ palg.attr.rta_type = CRYPTOA_ALG;
+ /* Must use the exact name to locate ourselves. */
+ memcpy(palg.data.name, alg->cra_driver_name, CRYPTO_MAX_ALG_NAME);
+ tb[1] = &palg.attr;
+
+ tb[2] = NULL;
+
+ geniv = alg->cra_aead.geniv;
+
+ tmpl = crypto_lookup_template(geniv);
+ err = -ENOENT;
+ if (!tmpl)
+ goto kill_larval;
+
+ inst = tmpl->alloc(tb);
+ err = PTR_ERR(inst);
+ if (IS_ERR(inst))
+ goto put_tmpl;
+
+ if ((err = crypto_register_instance(tmpl, inst))) {
+ tmpl->free(inst);
+ goto put_tmpl;
+ }
+
+ /* Redo the lookup to use the instance we just registered. */
+ err = -EAGAIN;
+
+put_tmpl:
+ crypto_tmpl_put(tmpl);
+kill_larval:
+ crypto_larval_kill(larval);
+drop_larval:
+ crypto_mod_put(larval);
+out:
+ crypto_mod_put(alg);
+ return err;
+}
+
+static struct crypto_alg *crypto_lookup_aead(const char *name, u32 type,
+ u32 mask)
+{
+ struct crypto_alg *alg;
+
+ alg = crypto_alg_mod_lookup(name, type, mask);
+ if (IS_ERR(alg))
+ return alg;
+
+ if (alg->cra_type == &crypto_aead_type)
+ return alg;
+
+ if (!alg->cra_aead.ivsize)
+ return alg;
+
+ return ERR_PTR(crypto_nivaead_default(alg, type, mask));
+}
+
+int crypto_grab_aead(struct crypto_aead_spawn *spawn, const char *name,
+ u32 type, u32 mask)
+{
+ struct crypto_alg *alg;
+ int err;
+
+ type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
+ type |= CRYPTO_ALG_TYPE_AEAD;
+ mask &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
+ mask |= CRYPTO_ALG_TYPE_MASK;
+
+ alg = crypto_lookup_aead(name, type, mask);
+ if (IS_ERR(alg))
+ return PTR_ERR(alg);
+
+ err = crypto_init_spawn(&spawn->base, alg, spawn->base.inst, mask);
+ crypto_mod_put(alg);
+ return err;
+}
+EXPORT_SYMBOL_GPL(crypto_grab_aead);
+
+struct crypto_aead *crypto_alloc_aead(const char *alg_name, u32 type, u32 mask)
+{
+ struct crypto_tfm *tfm;
+ int err;
+
+ type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
+ type |= CRYPTO_ALG_TYPE_AEAD;
+ mask &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
+ mask |= CRYPTO_ALG_TYPE_MASK;
+
+ for (;;) {
+ struct crypto_alg *alg;
+
+ alg = crypto_lookup_aead(alg_name, type, mask);
+ if (IS_ERR(alg)) {
+ err = PTR_ERR(alg);
+ goto err;
+ }
+
+ tfm = __crypto_alloc_tfm(alg, type, mask);
+ if (!IS_ERR(tfm))
+ return __crypto_aead_cast(tfm);
+
+ crypto_mod_put(alg);
+ err = PTR_ERR(tfm);
+
+err:
+ if (err != -EAGAIN)
+ break;
+ if (signal_pending(current)) {
+ err = -EINTR;
+ break;
+ }
+ }
+
+ return ERR_PTR(err);
+}
+EXPORT_SYMBOL_GPL(crypto_alloc_aead);
+
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Authenticated Encryption with Associated Data (AEAD)");
diff --git a/crypto/aes_generic.c b/crypto/aes_generic.c
index 9401dca..cf30af74 100644
--- a/crypto/aes_generic.c
+++ b/crypto/aes_generic.c
@@ -47,11 +47,7 @@
* ---------------------------------------------------------------------------
*/
-/* Some changes from the Gladman version:
- s/RIJNDAEL(e_key)/E_KEY/g
- s/RIJNDAEL(d_key)/D_KEY/g
-*/
-
+#include <crypto/aes.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
@@ -59,88 +55,46 @@
#include <linux/crypto.h>
#include <asm/byteorder.h>
-#define AES_MIN_KEY_SIZE 16
-#define AES_MAX_KEY_SIZE 32
-
-#define AES_BLOCK_SIZE 16
-
-/*
- * #define byte(x, nr) ((unsigned char)((x) >> (nr*8)))
- */
-static inline u8
-byte(const u32 x, const unsigned n)
+static inline u8 byte(const u32 x, const unsigned n)
{
return x >> (n << 3);
}
-struct aes_ctx {
- int key_length;
- u32 buf[120];
-};
-
-#define E_KEY (&ctx->buf[0])
-#define D_KEY (&ctx->buf[60])
-
static u8 pow_tab[256] __initdata;
static u8 log_tab[256] __initdata;
static u8 sbx_tab[256] __initdata;
static u8 isb_tab[256] __initdata;
static u32 rco_tab[10];
-static u32 ft_tab[4][256];
-static u32 it_tab[4][256];
-static u32 fl_tab[4][256];
-static u32 il_tab[4][256];
+u32 crypto_ft_tab[4][256];
+u32 crypto_fl_tab[4][256];
+u32 crypto_it_tab[4][256];
+u32 crypto_il_tab[4][256];
-static inline u8 __init
-f_mult (u8 a, u8 b)
+EXPORT_SYMBOL_GPL(crypto_ft_tab);
+EXPORT_SYMBOL_GPL(crypto_fl_tab);
+EXPORT_SYMBOL_GPL(crypto_it_tab);
+EXPORT_SYMBOL_GPL(crypto_il_tab);
+
+static inline u8 __init f_mult(u8 a, u8 b)
{
u8 aa = log_tab[a], cc = aa + log_tab[b];
return pow_tab[cc + (cc < aa ? 1 : 0)];
}
-#define ff_mult(a,b) (a && b ? f_mult(a, b) : 0)
+#define ff_mult(a, b) (a && b ? f_mult(a, b) : 0)
-#define f_rn(bo, bi, n, k) \
- bo[n] = ft_tab[0][byte(bi[n],0)] ^ \
- ft_tab[1][byte(bi[(n + 1) & 3],1)] ^ \
- ft_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
- ft_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)
-
-#define i_rn(bo, bi, n, k) \
- bo[n] = it_tab[0][byte(bi[n],0)] ^ \
- it_tab[1][byte(bi[(n + 3) & 3],1)] ^ \
- it_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
- it_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
-
-#define ls_box(x) \
- ( fl_tab[0][byte(x, 0)] ^ \
- fl_tab[1][byte(x, 1)] ^ \
- fl_tab[2][byte(x, 2)] ^ \
- fl_tab[3][byte(x, 3)] )
-
-#define f_rl(bo, bi, n, k) \
- bo[n] = fl_tab[0][byte(bi[n],0)] ^ \
- fl_tab[1][byte(bi[(n + 1) & 3],1)] ^ \
- fl_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
- fl_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)
-
-#define i_rl(bo, bi, n, k) \
- bo[n] = il_tab[0][byte(bi[n],0)] ^ \
- il_tab[1][byte(bi[(n + 3) & 3],1)] ^ \
- il_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
- il_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
-
-static void __init
-gen_tabs (void)
+static void __init gen_tabs(void)
{
u32 i, t;
u8 p, q;
- /* log and power tables for GF(2**8) finite field with
- 0x011b as modular polynomial - the simplest primitive
- root is 0x03, used here to generate the tables */
+ /*
+ * log and power tables for GF(2**8) finite field with
+ * 0x011b as modular polynomial - the simplest primitive
+ * root is 0x03, used here to generate the tables
+ */
for (i = 0, p = 1; i < 256; ++i) {
pow_tab[i] = (u8) p;
@@ -169,92 +123,119 @@
p = sbx_tab[i];
t = p;
- fl_tab[0][i] = t;
- fl_tab[1][i] = rol32(t, 8);
- fl_tab[2][i] = rol32(t, 16);
- fl_tab[3][i] = rol32(t, 24);
+ crypto_fl_tab[0][i] = t;
+ crypto_fl_tab[1][i] = rol32(t, 8);
+ crypto_fl_tab[2][i] = rol32(t, 16);
+ crypto_fl_tab[3][i] = rol32(t, 24);
- t = ((u32) ff_mult (2, p)) |
+ t = ((u32) ff_mult(2, p)) |
((u32) p << 8) |
- ((u32) p << 16) | ((u32) ff_mult (3, p) << 24);
+ ((u32) p << 16) | ((u32) ff_mult(3, p) << 24);
- ft_tab[0][i] = t;
- ft_tab[1][i] = rol32(t, 8);
- ft_tab[2][i] = rol32(t, 16);
- ft_tab[3][i] = rol32(t, 24);
+ crypto_ft_tab[0][i] = t;
+ crypto_ft_tab[1][i] = rol32(t, 8);
+ crypto_ft_tab[2][i] = rol32(t, 16);
+ crypto_ft_tab[3][i] = rol32(t, 24);
p = isb_tab[i];
t = p;
- il_tab[0][i] = t;
- il_tab[1][i] = rol32(t, 8);
- il_tab[2][i] = rol32(t, 16);
- il_tab[3][i] = rol32(t, 24);
+ crypto_il_tab[0][i] = t;
+ crypto_il_tab[1][i] = rol32(t, 8);
+ crypto_il_tab[2][i] = rol32(t, 16);
+ crypto_il_tab[3][i] = rol32(t, 24);
- t = ((u32) ff_mult (14, p)) |
- ((u32) ff_mult (9, p) << 8) |
- ((u32) ff_mult (13, p) << 16) |
- ((u32) ff_mult (11, p) << 24);
+ t = ((u32) ff_mult(14, p)) |
+ ((u32) ff_mult(9, p) << 8) |
+ ((u32) ff_mult(13, p) << 16) |
+ ((u32) ff_mult(11, p) << 24);
- it_tab[0][i] = t;
- it_tab[1][i] = rol32(t, 8);
- it_tab[2][i] = rol32(t, 16);
- it_tab[3][i] = rol32(t, 24);
+ crypto_it_tab[0][i] = t;
+ crypto_it_tab[1][i] = rol32(t, 8);
+ crypto_it_tab[2][i] = rol32(t, 16);
+ crypto_it_tab[3][i] = rol32(t, 24);
}
}
-#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b)
-
-#define imix_col(y,x) \
- u = star_x(x); \
- v = star_x(u); \
- w = star_x(v); \
- t = w ^ (x); \
- (y) = u ^ v ^ w; \
- (y) ^= ror32(u ^ t, 8) ^ \
- ror32(v ^ t, 16) ^ \
- ror32(t,24)
-
/* initialise the key schedule from the user supplied key */
-#define loop4(i) \
-{ t = ror32(t, 8); t = ls_box(t) ^ rco_tab[i]; \
- t ^= E_KEY[4 * i]; E_KEY[4 * i + 4] = t; \
- t ^= E_KEY[4 * i + 1]; E_KEY[4 * i + 5] = t; \
- t ^= E_KEY[4 * i + 2]; E_KEY[4 * i + 6] = t; \
- t ^= E_KEY[4 * i + 3]; E_KEY[4 * i + 7] = t; \
-}
+#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b)
-#define loop6(i) \
-{ t = ror32(t, 8); t = ls_box(t) ^ rco_tab[i]; \
- t ^= E_KEY[6 * i]; E_KEY[6 * i + 6] = t; \
- t ^= E_KEY[6 * i + 1]; E_KEY[6 * i + 7] = t; \
- t ^= E_KEY[6 * i + 2]; E_KEY[6 * i + 8] = t; \
- t ^= E_KEY[6 * i + 3]; E_KEY[6 * i + 9] = t; \
- t ^= E_KEY[6 * i + 4]; E_KEY[6 * i + 10] = t; \
- t ^= E_KEY[6 * i + 5]; E_KEY[6 * i + 11] = t; \
-}
+#define imix_col(y,x) do { \
+ u = star_x(x); \
+ v = star_x(u); \
+ w = star_x(v); \
+ t = w ^ (x); \
+ (y) = u ^ v ^ w; \
+ (y) ^= ror32(u ^ t, 8) ^ \
+ ror32(v ^ t, 16) ^ \
+ ror32(t, 24); \
+} while (0)
-#define loop8(i) \
-{ t = ror32(t, 8); ; t = ls_box(t) ^ rco_tab[i]; \
- t ^= E_KEY[8 * i]; E_KEY[8 * i + 8] = t; \
- t ^= E_KEY[8 * i + 1]; E_KEY[8 * i + 9] = t; \
- t ^= E_KEY[8 * i + 2]; E_KEY[8 * i + 10] = t; \
- t ^= E_KEY[8 * i + 3]; E_KEY[8 * i + 11] = t; \
- t = E_KEY[8 * i + 4] ^ ls_box(t); \
- E_KEY[8 * i + 12] = t; \
- t ^= E_KEY[8 * i + 5]; E_KEY[8 * i + 13] = t; \
- t ^= E_KEY[8 * i + 6]; E_KEY[8 * i + 14] = t; \
- t ^= E_KEY[8 * i + 7]; E_KEY[8 * i + 15] = t; \
-}
+#define ls_box(x) \
+ crypto_fl_tab[0][byte(x, 0)] ^ \
+ crypto_fl_tab[1][byte(x, 1)] ^ \
+ crypto_fl_tab[2][byte(x, 2)] ^ \
+ crypto_fl_tab[3][byte(x, 3)]
-static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
- unsigned int key_len)
+#define loop4(i) do { \
+ t = ror32(t, 8); \
+ t = ls_box(t) ^ rco_tab[i]; \
+ t ^= ctx->key_enc[4 * i]; \
+ ctx->key_enc[4 * i + 4] = t; \
+ t ^= ctx->key_enc[4 * i + 1]; \
+ ctx->key_enc[4 * i + 5] = t; \
+ t ^= ctx->key_enc[4 * i + 2]; \
+ ctx->key_enc[4 * i + 6] = t; \
+ t ^= ctx->key_enc[4 * i + 3]; \
+ ctx->key_enc[4 * i + 7] = t; \
+} while (0)
+
+#define loop6(i) do { \
+ t = ror32(t, 8); \
+ t = ls_box(t) ^ rco_tab[i]; \
+ t ^= ctx->key_enc[6 * i]; \
+ ctx->key_enc[6 * i + 6] = t; \
+ t ^= ctx->key_enc[6 * i + 1]; \
+ ctx->key_enc[6 * i + 7] = t; \
+ t ^= ctx->key_enc[6 * i + 2]; \
+ ctx->key_enc[6 * i + 8] = t; \
+ t ^= ctx->key_enc[6 * i + 3]; \
+ ctx->key_enc[6 * i + 9] = t; \
+ t ^= ctx->key_enc[6 * i + 4]; \
+ ctx->key_enc[6 * i + 10] = t; \
+ t ^= ctx->key_enc[6 * i + 5]; \
+ ctx->key_enc[6 * i + 11] = t; \
+} while (0)
+
+#define loop8(i) do { \
+ t = ror32(t, 8); \
+ t = ls_box(t) ^ rco_tab[i]; \
+ t ^= ctx->key_enc[8 * i]; \
+ ctx->key_enc[8 * i + 8] = t; \
+ t ^= ctx->key_enc[8 * i + 1]; \
+ ctx->key_enc[8 * i + 9] = t; \
+ t ^= ctx->key_enc[8 * i + 2]; \
+ ctx->key_enc[8 * i + 10] = t; \
+ t ^= ctx->key_enc[8 * i + 3]; \
+ ctx->key_enc[8 * i + 11] = t; \
+ t = ctx->key_enc[8 * i + 4] ^ ls_box(t); \
+ ctx->key_enc[8 * i + 12] = t; \
+ t ^= ctx->key_enc[8 * i + 5]; \
+ ctx->key_enc[8 * i + 13] = t; \
+ t ^= ctx->key_enc[8 * i + 6]; \
+ ctx->key_enc[8 * i + 14] = t; \
+ t ^= ctx->key_enc[8 * i + 7]; \
+ ctx->key_enc[8 * i + 15] = t; \
+} while (0)
+
+int crypto_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+ unsigned int key_len)
{
- struct aes_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
const __le32 *key = (const __le32 *)in_key;
u32 *flags = &tfm->crt_flags;
- u32 i, t, u, v, w;
+ u32 i, t, u, v, w, j;
if (key_len % 8) {
*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
@@ -263,95 +244,113 @@
ctx->key_length = key_len;
- E_KEY[0] = le32_to_cpu(key[0]);
- E_KEY[1] = le32_to_cpu(key[1]);
- E_KEY[2] = le32_to_cpu(key[2]);
- E_KEY[3] = le32_to_cpu(key[3]);
+ ctx->key_dec[key_len + 24] = ctx->key_enc[0] = le32_to_cpu(key[0]);
+ ctx->key_dec[key_len + 25] = ctx->key_enc[1] = le32_to_cpu(key[1]);
+ ctx->key_dec[key_len + 26] = ctx->key_enc[2] = le32_to_cpu(key[2]);
+ ctx->key_dec[key_len + 27] = ctx->key_enc[3] = le32_to_cpu(key[3]);
switch (key_len) {
case 16:
- t = E_KEY[3];
+ t = ctx->key_enc[3];
for (i = 0; i < 10; ++i)
- loop4 (i);
+ loop4(i);
break;
case 24:
- E_KEY[4] = le32_to_cpu(key[4]);
- t = E_KEY[5] = le32_to_cpu(key[5]);
+ ctx->key_enc[4] = le32_to_cpu(key[4]);
+ t = ctx->key_enc[5] = le32_to_cpu(key[5]);
for (i = 0; i < 8; ++i)
- loop6 (i);
+ loop6(i);
break;
case 32:
- E_KEY[4] = le32_to_cpu(key[4]);
- E_KEY[5] = le32_to_cpu(key[5]);
- E_KEY[6] = le32_to_cpu(key[6]);
- t = E_KEY[7] = le32_to_cpu(key[7]);
+ ctx->key_enc[4] = le32_to_cpu(key[4]);
+ ctx->key_enc[5] = le32_to_cpu(key[5]);
+ ctx->key_enc[6] = le32_to_cpu(key[6]);
+ t = ctx->key_enc[7] = le32_to_cpu(key[7]);
for (i = 0; i < 7; ++i)
- loop8 (i);
+ loop8(i);
break;
}
- D_KEY[0] = E_KEY[0];
- D_KEY[1] = E_KEY[1];
- D_KEY[2] = E_KEY[2];
- D_KEY[3] = E_KEY[3];
+ ctx->key_dec[0] = ctx->key_enc[key_len + 24];
+ ctx->key_dec[1] = ctx->key_enc[key_len + 25];
+ ctx->key_dec[2] = ctx->key_enc[key_len + 26];
+ ctx->key_dec[3] = ctx->key_enc[key_len + 27];
for (i = 4; i < key_len + 24; ++i) {
- imix_col (D_KEY[i], E_KEY[i]);
+ j = key_len + 24 - (i & ~3) + (i & 3);
+ imix_col(ctx->key_dec[j], ctx->key_enc[i]);
}
-
return 0;
}
+EXPORT_SYMBOL_GPL(crypto_aes_set_key);
/* encrypt a block of text */
-#define f_nround(bo, bi, k) \
- f_rn(bo, bi, 0, k); \
- f_rn(bo, bi, 1, k); \
- f_rn(bo, bi, 2, k); \
- f_rn(bo, bi, 3, k); \
- k += 4
+#define f_rn(bo, bi, n, k) do { \
+ bo[n] = crypto_ft_tab[0][byte(bi[n], 0)] ^ \
+ crypto_ft_tab[1][byte(bi[(n + 1) & 3], 1)] ^ \
+ crypto_ft_tab[2][byte(bi[(n + 2) & 3], 2)] ^ \
+ crypto_ft_tab[3][byte(bi[(n + 3) & 3], 3)] ^ *(k + n); \
+} while (0)
-#define f_lround(bo, bi, k) \
- f_rl(bo, bi, 0, k); \
- f_rl(bo, bi, 1, k); \
- f_rl(bo, bi, 2, k); \
- f_rl(bo, bi, 3, k)
+#define f_nround(bo, bi, k) do {\
+ f_rn(bo, bi, 0, k); \
+ f_rn(bo, bi, 1, k); \
+ f_rn(bo, bi, 2, k); \
+ f_rn(bo, bi, 3, k); \
+ k += 4; \
+} while (0)
+
+#define f_rl(bo, bi, n, k) do { \
+ bo[n] = crypto_fl_tab[0][byte(bi[n], 0)] ^ \
+ crypto_fl_tab[1][byte(bi[(n + 1) & 3], 1)] ^ \
+ crypto_fl_tab[2][byte(bi[(n + 2) & 3], 2)] ^ \
+ crypto_fl_tab[3][byte(bi[(n + 3) & 3], 3)] ^ *(k + n); \
+} while (0)
+
+#define f_lround(bo, bi, k) do {\
+ f_rl(bo, bi, 0, k); \
+ f_rl(bo, bi, 1, k); \
+ f_rl(bo, bi, 2, k); \
+ f_rl(bo, bi, 3, k); \
+} while (0)
static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
{
- const struct aes_ctx *ctx = crypto_tfm_ctx(tfm);
+ const struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
const __le32 *src = (const __le32 *)in;
__le32 *dst = (__le32 *)out;
u32 b0[4], b1[4];
- const u32 *kp = E_KEY + 4;
+ const u32 *kp = ctx->key_enc + 4;
+ const int key_len = ctx->key_length;
- b0[0] = le32_to_cpu(src[0]) ^ E_KEY[0];
- b0[1] = le32_to_cpu(src[1]) ^ E_KEY[1];
- b0[2] = le32_to_cpu(src[2]) ^ E_KEY[2];
- b0[3] = le32_to_cpu(src[3]) ^ E_KEY[3];
+ b0[0] = le32_to_cpu(src[0]) ^ ctx->key_enc[0];
+ b0[1] = le32_to_cpu(src[1]) ^ ctx->key_enc[1];
+ b0[2] = le32_to_cpu(src[2]) ^ ctx->key_enc[2];
+ b0[3] = le32_to_cpu(src[3]) ^ ctx->key_enc[3];
- if (ctx->key_length > 24) {
- f_nround (b1, b0, kp);
- f_nround (b0, b1, kp);
+ if (key_len > 24) {
+ f_nround(b1, b0, kp);
+ f_nround(b0, b1, kp);
}
- if (ctx->key_length > 16) {
- f_nround (b1, b0, kp);
- f_nround (b0, b1, kp);
+ if (key_len > 16) {
+ f_nround(b1, b0, kp);
+ f_nround(b0, b1, kp);
}
- f_nround (b1, b0, kp);
- f_nround (b0, b1, kp);
- f_nround (b1, b0, kp);
- f_nround (b0, b1, kp);
- f_nround (b1, b0, kp);
- f_nround (b0, b1, kp);
- f_nround (b1, b0, kp);
- f_nround (b0, b1, kp);
- f_nround (b1, b0, kp);
- f_lround (b0, b1, kp);
+ f_nround(b1, b0, kp);
+ f_nround(b0, b1, kp);
+ f_nround(b1, b0, kp);
+ f_nround(b0, b1, kp);
+ f_nround(b1, b0, kp);
+ f_nround(b0, b1, kp);
+ f_nround(b1, b0, kp);
+ f_nround(b0, b1, kp);
+ f_nround(b1, b0, kp);
+ f_lround(b0, b1, kp);
dst[0] = cpu_to_le32(b0[0]);
dst[1] = cpu_to_le32(b0[1]);
@@ -361,53 +360,69 @@
/* decrypt a block of text */
-#define i_nround(bo, bi, k) \
- i_rn(bo, bi, 0, k); \
- i_rn(bo, bi, 1, k); \
- i_rn(bo, bi, 2, k); \
- i_rn(bo, bi, 3, k); \
- k -= 4
+#define i_rn(bo, bi, n, k) do { \
+ bo[n] = crypto_it_tab[0][byte(bi[n], 0)] ^ \
+ crypto_it_tab[1][byte(bi[(n + 3) & 3], 1)] ^ \
+ crypto_it_tab[2][byte(bi[(n + 2) & 3], 2)] ^ \
+ crypto_it_tab[3][byte(bi[(n + 1) & 3], 3)] ^ *(k + n); \
+} while (0)
-#define i_lround(bo, bi, k) \
- i_rl(bo, bi, 0, k); \
- i_rl(bo, bi, 1, k); \
- i_rl(bo, bi, 2, k); \
- i_rl(bo, bi, 3, k)
+#define i_nround(bo, bi, k) do {\
+ i_rn(bo, bi, 0, k); \
+ i_rn(bo, bi, 1, k); \
+ i_rn(bo, bi, 2, k); \
+ i_rn(bo, bi, 3, k); \
+ k += 4; \
+} while (0)
+
+#define i_rl(bo, bi, n, k) do { \
+ bo[n] = crypto_il_tab[0][byte(bi[n], 0)] ^ \
+ crypto_il_tab[1][byte(bi[(n + 3) & 3], 1)] ^ \
+ crypto_il_tab[2][byte(bi[(n + 2) & 3], 2)] ^ \
+ crypto_il_tab[3][byte(bi[(n + 1) & 3], 3)] ^ *(k + n); \
+} while (0)
+
+#define i_lround(bo, bi, k) do {\
+ i_rl(bo, bi, 0, k); \
+ i_rl(bo, bi, 1, k); \
+ i_rl(bo, bi, 2, k); \
+ i_rl(bo, bi, 3, k); \
+} while (0)
static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
{
- const struct aes_ctx *ctx = crypto_tfm_ctx(tfm);
+ const struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
const __le32 *src = (const __le32 *)in;
__le32 *dst = (__le32 *)out;
u32 b0[4], b1[4];
const int key_len = ctx->key_length;
- const u32 *kp = D_KEY + key_len + 20;
+ const u32 *kp = ctx->key_dec + 4;
- b0[0] = le32_to_cpu(src[0]) ^ E_KEY[key_len + 24];
- b0[1] = le32_to_cpu(src[1]) ^ E_KEY[key_len + 25];
- b0[2] = le32_to_cpu(src[2]) ^ E_KEY[key_len + 26];
- b0[3] = le32_to_cpu(src[3]) ^ E_KEY[key_len + 27];
+ b0[0] = le32_to_cpu(src[0]) ^ ctx->key_dec[0];
+ b0[1] = le32_to_cpu(src[1]) ^ ctx->key_dec[1];
+ b0[2] = le32_to_cpu(src[2]) ^ ctx->key_dec[2];
+ b0[3] = le32_to_cpu(src[3]) ^ ctx->key_dec[3];
if (key_len > 24) {
- i_nround (b1, b0, kp);
- i_nround (b0, b1, kp);
+ i_nround(b1, b0, kp);
+ i_nround(b0, b1, kp);
}
if (key_len > 16) {
- i_nround (b1, b0, kp);
- i_nround (b0, b1, kp);
+ i_nround(b1, b0, kp);
+ i_nround(b0, b1, kp);
}
- i_nround (b1, b0, kp);
- i_nround (b0, b1, kp);
- i_nround (b1, b0, kp);
- i_nround (b0, b1, kp);
- i_nround (b1, b0, kp);
- i_nround (b0, b1, kp);
- i_nround (b1, b0, kp);
- i_nround (b0, b1, kp);
- i_nround (b1, b0, kp);
- i_lround (b0, b1, kp);
+ i_nround(b1, b0, kp);
+ i_nround(b0, b1, kp);
+ i_nround(b1, b0, kp);
+ i_nround(b0, b1, kp);
+ i_nround(b1, b0, kp);
+ i_nround(b0, b1, kp);
+ i_nround(b1, b0, kp);
+ i_nround(b0, b1, kp);
+ i_nround(b1, b0, kp);
+ i_lround(b0, b1, kp);
dst[0] = cpu_to_le32(b0[0]);
dst[1] = cpu_to_le32(b0[1]);
@@ -415,14 +430,13 @@
dst[3] = cpu_to_le32(b0[3]);
}
-
static struct crypto_alg aes_alg = {
.cra_name = "aes",
.cra_driver_name = "aes-generic",
.cra_priority = 100,
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = AES_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct aes_ctx),
+ .cra_ctxsize = sizeof(struct crypto_aes_ctx),
.cra_alignmask = 3,
.cra_module = THIS_MODULE,
.cra_list = LIST_HEAD_INIT(aes_alg.cra_list),
@@ -430,9 +444,9 @@
.cipher = {
.cia_min_keysize = AES_MIN_KEY_SIZE,
.cia_max_keysize = AES_MAX_KEY_SIZE,
- .cia_setkey = aes_set_key,
- .cia_encrypt = aes_encrypt,
- .cia_decrypt = aes_decrypt
+ .cia_setkey = crypto_aes_set_key,
+ .cia_encrypt = aes_encrypt,
+ .cia_decrypt = aes_decrypt
}
}
};
diff --git a/crypto/algapi.c b/crypto/algapi.c
index 8383282..e65cb50 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -472,7 +472,7 @@
}
EXPORT_SYMBOL_GPL(crypto_check_attr_type);
-struct crypto_alg *crypto_attr_alg(struct rtattr *rta, u32 type, u32 mask)
+const char *crypto_attr_alg_name(struct rtattr *rta)
{
struct crypto_attr_alg *alga;
@@ -486,7 +486,21 @@
alga = RTA_DATA(rta);
alga->name[CRYPTO_MAX_ALG_NAME - 1] = 0;
- return crypto_alg_mod_lookup(alga->name, type, mask);
+ return alga->name;
+}
+EXPORT_SYMBOL_GPL(crypto_attr_alg_name);
+
+struct crypto_alg *crypto_attr_alg(struct rtattr *rta, u32 type, u32 mask)
+{
+ const char *name;
+ int err;
+
+ name = crypto_attr_alg_name(rta);
+ err = PTR_ERR(name);
+ if (IS_ERR(name))
+ return ERR_PTR(err);
+
+ return crypto_alg_mod_lookup(name, type, mask);
}
EXPORT_SYMBOL_GPL(crypto_attr_alg);
@@ -605,6 +619,53 @@
}
EXPORT_SYMBOL_GPL(crypto_tfm_in_queue);
+static inline void crypto_inc_byte(u8 *a, unsigned int size)
+{
+ u8 *b = (a + size);
+ u8 c;
+
+ for (; size; size--) {
+ c = *--b + 1;
+ *b = c;
+ if (c)
+ break;
+ }
+}
+
+void crypto_inc(u8 *a, unsigned int size)
+{
+ __be32 *b = (__be32 *)(a + size);
+ u32 c;
+
+ for (; size >= 4; size -= 4) {
+ c = be32_to_cpu(*--b) + 1;
+ *b = cpu_to_be32(c);
+ if (c)
+ return;
+ }
+
+ crypto_inc_byte(a, size);
+}
+EXPORT_SYMBOL_GPL(crypto_inc);
+
+static inline void crypto_xor_byte(u8 *a, const u8 *b, unsigned int size)
+{
+ for (; size; size--)
+ *a++ ^= *b++;
+}
+
+void crypto_xor(u8 *dst, const u8 *src, unsigned int size)
+{
+ u32 *a = (u32 *)dst;
+ u32 *b = (u32 *)src;
+
+ for (; size >= 4; size -= 4)
+ *a++ ^= *b++;
+
+ crypto_xor_byte((u8 *)a, (u8 *)b, size);
+}
+EXPORT_SYMBOL_GPL(crypto_xor);
+
static int __init crypto_algapi_init(void)
{
crypto_init_proc();
diff --git a/crypto/api.c b/crypto/api.c
index 1f5c724..a2496d1 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -137,7 +137,7 @@
return alg;
}
-static void crypto_larval_kill(struct crypto_alg *alg)
+void crypto_larval_kill(struct crypto_alg *alg)
{
struct crypto_larval *larval = (void *)alg;
@@ -147,6 +147,7 @@
complete_all(&larval->completion);
crypto_alg_put(alg);
}
+EXPORT_SYMBOL_GPL(crypto_larval_kill);
static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg)
{
@@ -176,11 +177,9 @@
return alg;
}
-struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask)
+struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask)
{
struct crypto_alg *alg;
- struct crypto_alg *larval;
- int ok;
if (!name)
return ERR_PTR(-ENOENT);
@@ -193,7 +192,17 @@
if (alg)
return crypto_is_larval(alg) ? crypto_larval_wait(alg) : alg;
- larval = crypto_larval_alloc(name, type, mask);
+ return crypto_larval_alloc(name, type, mask);
+}
+EXPORT_SYMBOL_GPL(crypto_larval_lookup);
+
+struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask)
+{
+ struct crypto_alg *alg;
+ struct crypto_alg *larval;
+ int ok;
+
+ larval = crypto_larval_lookup(name, type, mask);
if (IS_ERR(larval) || !crypto_is_larval(larval))
return larval;
diff --git a/crypto/authenc.c b/crypto/authenc.c
index 126a529b..ed8ac5a 100644
--- a/crypto/authenc.c
+++ b/crypto/authenc.c
@@ -10,22 +10,21 @@
*
*/
-#include <crypto/algapi.h>
+#include <crypto/aead.h>
+#include <crypto/internal/skcipher.h>
+#include <crypto/authenc.h>
+#include <crypto/scatterwalk.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/rtnetlink.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
-#include "scatterwalk.h"
-
struct authenc_instance_ctx {
struct crypto_spawn auth;
- struct crypto_spawn enc;
-
- unsigned int authsize;
- unsigned int enckeylen;
+ struct crypto_skcipher_spawn enc;
};
struct crypto_authenc_ctx {
@@ -37,19 +36,31 @@
static int crypto_authenc_setkey(struct crypto_aead *authenc, const u8 *key,
unsigned int keylen)
{
- struct authenc_instance_ctx *ictx =
- crypto_instance_ctx(crypto_aead_alg_instance(authenc));
- unsigned int enckeylen = ictx->enckeylen;
unsigned int authkeylen;
+ unsigned int enckeylen;
struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
struct crypto_hash *auth = ctx->auth;
struct crypto_ablkcipher *enc = ctx->enc;
+ struct rtattr *rta = (void *)key;
+ struct crypto_authenc_key_param *param;
int err = -EINVAL;
- if (keylen < enckeylen) {
- crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN);
- goto out;
- }
+ if (!RTA_OK(rta, keylen))
+ goto badkey;
+ if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
+ goto badkey;
+ if (RTA_PAYLOAD(rta) < sizeof(*param))
+ goto badkey;
+
+ param = RTA_DATA(rta);
+ enckeylen = be32_to_cpu(param->enckeylen);
+
+ key += RTA_ALIGN(rta->rta_len);
+ keylen -= RTA_ALIGN(rta->rta_len);
+
+ if (keylen < enckeylen)
+ goto badkey;
+
authkeylen = keylen - enckeylen;
crypto_hash_clear_flags(auth, CRYPTO_TFM_REQ_MASK);
@@ -71,21 +82,38 @@
out:
return err;
+
+badkey:
+ crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN);
+ goto out;
}
-static int crypto_authenc_hash(struct aead_request *req)
+static void authenc_chain(struct scatterlist *head, struct scatterlist *sg,
+ int chain)
+{
+ if (chain) {
+ head->length += sg->length;
+ sg = scatterwalk_sg_next(sg);
+ }
+
+ if (sg)
+ scatterwalk_sg_chain(head, 2, sg);
+ else
+ sg_mark_end(head);
+}
+
+static u8 *crypto_authenc_hash(struct aead_request *req, unsigned int flags,
+ struct scatterlist *cipher,
+ unsigned int cryptlen)
{
struct crypto_aead *authenc = crypto_aead_reqtfm(req);
- struct authenc_instance_ctx *ictx =
- crypto_instance_ctx(crypto_aead_alg_instance(authenc));
struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
struct crypto_hash *auth = ctx->auth;
struct hash_desc desc = {
.tfm = auth,
+ .flags = aead_request_flags(req) & flags,
};
u8 *hash = aead_request_ctx(req);
- struct scatterlist *dst = req->dst;
- unsigned int cryptlen = req->cryptlen;
int err;
hash = (u8 *)ALIGN((unsigned long)hash + crypto_hash_alignmask(auth),
@@ -100,7 +128,7 @@
if (err)
goto auth_unlock;
- err = crypto_hash_update(&desc, dst, cryptlen);
+ err = crypto_hash_update(&desc, cipher, cryptlen);
if (err)
goto auth_unlock;
@@ -109,17 +137,53 @@
spin_unlock_bh(&ctx->auth_lock);
if (err)
- return err;
+ return ERR_PTR(err);
- scatterwalk_map_and_copy(hash, dst, cryptlen, ictx->authsize, 1);
+ return hash;
+}
+
+static int crypto_authenc_genicv(struct aead_request *req, u8 *iv,
+ unsigned int flags)
+{
+ struct crypto_aead *authenc = crypto_aead_reqtfm(req);
+ struct scatterlist *dst = req->dst;
+ struct scatterlist cipher[2];
+ struct page *dstp;
+ unsigned int ivsize = crypto_aead_ivsize(authenc);
+ unsigned int cryptlen;
+ u8 *vdst;
+ u8 *hash;
+
+ dstp = sg_page(dst);
+ vdst = PageHighMem(dstp) ? NULL : page_address(dstp) + dst->offset;
+
+ sg_init_table(cipher, 2);
+ sg_set_buf(cipher, iv, ivsize);
+ authenc_chain(cipher, dst, vdst == iv + ivsize);
+
+ cryptlen = req->cryptlen + ivsize;
+ hash = crypto_authenc_hash(req, flags, cipher, cryptlen);
+ if (IS_ERR(hash))
+ return PTR_ERR(hash);
+
+ scatterwalk_map_and_copy(hash, cipher, cryptlen,
+ crypto_aead_authsize(authenc), 1);
return 0;
}
static void crypto_authenc_encrypt_done(struct crypto_async_request *req,
int err)
{
- if (!err)
- err = crypto_authenc_hash(req->data);
+ if (!err) {
+ struct aead_request *areq = req->data;
+ struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
+ struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
+ struct ablkcipher_request *abreq = aead_request_ctx(areq);
+ u8 *iv = (u8 *)(abreq + 1) +
+ crypto_ablkcipher_reqsize(ctx->enc);
+
+ err = crypto_authenc_genicv(areq, iv, 0);
+ }
aead_request_complete(req->data, err);
}
@@ -129,72 +193,99 @@
struct crypto_aead *authenc = crypto_aead_reqtfm(req);
struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
struct ablkcipher_request *abreq = aead_request_ctx(req);
+ struct crypto_ablkcipher *enc = ctx->enc;
+ struct scatterlist *dst = req->dst;
+ unsigned int cryptlen = req->cryptlen;
+ u8 *iv = (u8 *)(abreq + 1) + crypto_ablkcipher_reqsize(enc);
int err;
- ablkcipher_request_set_tfm(abreq, ctx->enc);
+ ablkcipher_request_set_tfm(abreq, enc);
ablkcipher_request_set_callback(abreq, aead_request_flags(req),
crypto_authenc_encrypt_done, req);
- ablkcipher_request_set_crypt(abreq, req->src, req->dst, req->cryptlen,
- req->iv);
+ ablkcipher_request_set_crypt(abreq, req->src, dst, cryptlen, req->iv);
+
+ memcpy(iv, req->iv, crypto_aead_ivsize(authenc));
err = crypto_ablkcipher_encrypt(abreq);
if (err)
return err;
- return crypto_authenc_hash(req);
+ return crypto_authenc_genicv(req, iv, CRYPTO_TFM_REQ_MAY_SLEEP);
}
-static int crypto_authenc_verify(struct aead_request *req)
+static void crypto_authenc_givencrypt_done(struct crypto_async_request *req,
+ int err)
{
- struct crypto_aead *authenc = crypto_aead_reqtfm(req);
- struct authenc_instance_ctx *ictx =
- crypto_instance_ctx(crypto_aead_alg_instance(authenc));
+ if (!err) {
+ struct aead_givcrypt_request *greq = req->data;
+
+ err = crypto_authenc_genicv(&greq->areq, greq->giv, 0);
+ }
+
+ aead_request_complete(req->data, err);
+}
+
+static int crypto_authenc_givencrypt(struct aead_givcrypt_request *req)
+{
+ struct crypto_aead *authenc = aead_givcrypt_reqtfm(req);
struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
- struct crypto_hash *auth = ctx->auth;
- struct hash_desc desc = {
- .tfm = auth,
- .flags = aead_request_flags(req),
- };
- u8 *ohash = aead_request_ctx(req);
- u8 *ihash;
- struct scatterlist *src = req->src;
- unsigned int cryptlen = req->cryptlen;
- unsigned int authsize;
+ struct aead_request *areq = &req->areq;
+ struct skcipher_givcrypt_request *greq = aead_request_ctx(areq);
+ u8 *iv = req->giv;
int err;
- ohash = (u8 *)ALIGN((unsigned long)ohash + crypto_hash_alignmask(auth),
- crypto_hash_alignmask(auth) + 1);
- ihash = ohash + crypto_hash_digestsize(auth);
+ skcipher_givcrypt_set_tfm(greq, ctx->enc);
+ skcipher_givcrypt_set_callback(greq, aead_request_flags(areq),
+ crypto_authenc_givencrypt_done, areq);
+ skcipher_givcrypt_set_crypt(greq, areq->src, areq->dst, areq->cryptlen,
+ areq->iv);
+ skcipher_givcrypt_set_giv(greq, iv, req->seq);
- spin_lock_bh(&ctx->auth_lock);
- err = crypto_hash_init(&desc);
- if (err)
- goto auth_unlock;
-
- err = crypto_hash_update(&desc, req->assoc, req->assoclen);
- if (err)
- goto auth_unlock;
-
- err = crypto_hash_update(&desc, src, cryptlen);
- if (err)
- goto auth_unlock;
-
- err = crypto_hash_final(&desc, ohash);
-auth_unlock:
- spin_unlock_bh(&ctx->auth_lock);
-
+ err = crypto_skcipher_givencrypt(greq);
if (err)
return err;
- authsize = ictx->authsize;
- scatterwalk_map_and_copy(ihash, src, cryptlen, authsize, 0);
- return memcmp(ihash, ohash, authsize) ? -EINVAL : 0;
+ return crypto_authenc_genicv(areq, iv, CRYPTO_TFM_REQ_MAY_SLEEP);
}
-static void crypto_authenc_decrypt_done(struct crypto_async_request *req,
- int err)
+static int crypto_authenc_verify(struct aead_request *req,
+ struct scatterlist *cipher,
+ unsigned int cryptlen)
{
- aead_request_complete(req->data, err);
+ struct crypto_aead *authenc = crypto_aead_reqtfm(req);
+ u8 *ohash;
+ u8 *ihash;
+ unsigned int authsize;
+
+ ohash = crypto_authenc_hash(req, CRYPTO_TFM_REQ_MAY_SLEEP, cipher,
+ cryptlen);
+ if (IS_ERR(ohash))
+ return PTR_ERR(ohash);
+
+ authsize = crypto_aead_authsize(authenc);
+ ihash = ohash + authsize;
+ scatterwalk_map_and_copy(ihash, cipher, cryptlen, authsize, 0);
+ return memcmp(ihash, ohash, authsize) ? -EBADMSG: 0;
+}
+
+static int crypto_authenc_iverify(struct aead_request *req, u8 *iv,
+ unsigned int cryptlen)
+{
+ struct crypto_aead *authenc = crypto_aead_reqtfm(req);
+ struct scatterlist *src = req->src;
+ struct scatterlist cipher[2];
+ struct page *srcp;
+ unsigned int ivsize = crypto_aead_ivsize(authenc);
+ u8 *vsrc;
+
+ srcp = sg_page(src);
+ vsrc = PageHighMem(srcp) ? NULL : page_address(srcp) + src->offset;
+
+ sg_init_table(cipher, 2);
+ sg_set_buf(cipher, iv, ivsize);
+ authenc_chain(cipher, src, vsrc == iv + ivsize);
+
+ return crypto_authenc_verify(req, cipher, cryptlen + ivsize);
}
static int crypto_authenc_decrypt(struct aead_request *req)
@@ -202,17 +293,23 @@
struct crypto_aead *authenc = crypto_aead_reqtfm(req);
struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
struct ablkcipher_request *abreq = aead_request_ctx(req);
+ unsigned int cryptlen = req->cryptlen;
+ unsigned int authsize = crypto_aead_authsize(authenc);
+ u8 *iv = req->iv;
int err;
- err = crypto_authenc_verify(req);
+ if (cryptlen < authsize)
+ return -EINVAL;
+ cryptlen -= authsize;
+
+ err = crypto_authenc_iverify(req, iv, cryptlen);
if (err)
return err;
ablkcipher_request_set_tfm(abreq, ctx->enc);
ablkcipher_request_set_callback(abreq, aead_request_flags(req),
- crypto_authenc_decrypt_done, req);
- ablkcipher_request_set_crypt(abreq, req->src, req->dst, req->cryptlen,
- req->iv);
+ req->base.complete, req->base.data);
+ ablkcipher_request_set_crypt(abreq, req->src, req->dst, cryptlen, iv);
return crypto_ablkcipher_decrypt(abreq);
}
@@ -224,19 +321,13 @@
struct crypto_authenc_ctx *ctx = crypto_tfm_ctx(tfm);
struct crypto_hash *auth;
struct crypto_ablkcipher *enc;
- unsigned int digestsize;
int err;
auth = crypto_spawn_hash(&ictx->auth);
if (IS_ERR(auth))
return PTR_ERR(auth);
- err = -EINVAL;
- digestsize = crypto_hash_digestsize(auth);
- if (ictx->authsize > digestsize)
- goto err_free_hash;
-
- enc = crypto_spawn_ablkcipher(&ictx->enc);
+ enc = crypto_spawn_skcipher(&ictx->enc);
err = PTR_ERR(enc);
if (IS_ERR(enc))
goto err_free_hash;
@@ -246,9 +337,10 @@
tfm->crt_aead.reqsize = max_t(unsigned int,
(crypto_hash_alignmask(auth) &
~(crypto_tfm_ctx_alignment() - 1)) +
- digestsize * 2,
- sizeof(struct ablkcipher_request) +
- crypto_ablkcipher_reqsize(enc));
+ crypto_hash_digestsize(auth) * 2,
+ sizeof(struct skcipher_givcrypt_request) +
+ crypto_ablkcipher_reqsize(enc) +
+ crypto_ablkcipher_ivsize(enc));
spin_lock_init(&ctx->auth_lock);
@@ -269,75 +361,74 @@
static struct crypto_instance *crypto_authenc_alloc(struct rtattr **tb)
{
+ struct crypto_attr_type *algt;
struct crypto_instance *inst;
struct crypto_alg *auth;
struct crypto_alg *enc;
struct authenc_instance_ctx *ctx;
- unsigned int authsize;
- unsigned int enckeylen;
+ const char *enc_name;
int err;
- err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD);
- if (err)
+ algt = crypto_get_attr_type(tb);
+ err = PTR_ERR(algt);
+ if (IS_ERR(algt))
return ERR_PTR(err);
+ if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
+ return ERR_PTR(-EINVAL);
+
auth = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_HASH,
CRYPTO_ALG_TYPE_HASH_MASK);
if (IS_ERR(auth))
return ERR_PTR(PTR_ERR(auth));
- err = crypto_attr_u32(tb[2], &authsize);
- inst = ERR_PTR(err);
- if (err)
+ enc_name = crypto_attr_alg_name(tb[2]);
+ err = PTR_ERR(enc_name);
+ if (IS_ERR(enc_name))
goto out_put_auth;
- enc = crypto_attr_alg(tb[3], CRYPTO_ALG_TYPE_BLKCIPHER,
- CRYPTO_ALG_TYPE_MASK);
- inst = ERR_PTR(PTR_ERR(enc));
- if (IS_ERR(enc))
- goto out_put_auth;
-
- err = crypto_attr_u32(tb[4], &enckeylen);
- if (err)
- goto out_put_enc;
-
inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
err = -ENOMEM;
if (!inst)
- goto out_put_enc;
-
- err = -ENAMETOOLONG;
- if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
- "authenc(%s,%u,%s,%u)", auth->cra_name, authsize,
- enc->cra_name, enckeylen) >= CRYPTO_MAX_ALG_NAME)
- goto err_free_inst;
-
- if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
- "authenc(%s,%u,%s,%u)", auth->cra_driver_name,
- authsize, enc->cra_driver_name, enckeylen) >=
- CRYPTO_MAX_ALG_NAME)
- goto err_free_inst;
+ goto out_put_auth;
ctx = crypto_instance_ctx(inst);
- ctx->authsize = authsize;
- ctx->enckeylen = enckeylen;
err = crypto_init_spawn(&ctx->auth, auth, inst, CRYPTO_ALG_TYPE_MASK);
if (err)
goto err_free_inst;
- err = crypto_init_spawn(&ctx->enc, enc, inst, CRYPTO_ALG_TYPE_MASK);
+ crypto_set_skcipher_spawn(&ctx->enc, inst);
+ err = crypto_grab_skcipher(&ctx->enc, enc_name, 0,
+ crypto_requires_sync(algt->type,
+ algt->mask));
if (err)
goto err_drop_auth;
- inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC;
+ enc = crypto_skcipher_spawn_alg(&ctx->enc);
+
+ err = -ENAMETOOLONG;
+ if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
+ "authenc(%s,%s)", auth->cra_name, enc->cra_name) >=
+ CRYPTO_MAX_ALG_NAME)
+ goto err_drop_enc;
+
+ if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
+ "authenc(%s,%s)", auth->cra_driver_name,
+ enc->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
+ goto err_drop_enc;
+
+ inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD;
+ inst->alg.cra_flags |= enc->cra_flags & CRYPTO_ALG_ASYNC;
inst->alg.cra_priority = enc->cra_priority * 10 + auth->cra_priority;
inst->alg.cra_blocksize = enc->cra_blocksize;
- inst->alg.cra_alignmask = max(auth->cra_alignmask, enc->cra_alignmask);
+ inst->alg.cra_alignmask = auth->cra_alignmask | enc->cra_alignmask;
inst->alg.cra_type = &crypto_aead_type;
- inst->alg.cra_aead.ivsize = enc->cra_blkcipher.ivsize;
- inst->alg.cra_aead.authsize = authsize;
+ inst->alg.cra_aead.ivsize = enc->cra_ablkcipher.ivsize;
+ inst->alg.cra_aead.maxauthsize = auth->cra_type == &crypto_hash_type ?
+ auth->cra_hash.digestsize :
+ auth->cra_digest.dia_digestsize;
inst->alg.cra_ctxsize = sizeof(struct crypto_authenc_ctx);
@@ -347,18 +438,19 @@
inst->alg.cra_aead.setkey = crypto_authenc_setkey;
inst->alg.cra_aead.encrypt = crypto_authenc_encrypt;
inst->alg.cra_aead.decrypt = crypto_authenc_decrypt;
+ inst->alg.cra_aead.givencrypt = crypto_authenc_givencrypt;
out:
- crypto_mod_put(enc);
-out_put_auth:
crypto_mod_put(auth);
return inst;
+err_drop_enc:
+ crypto_drop_skcipher(&ctx->enc);
err_drop_auth:
crypto_drop_spawn(&ctx->auth);
err_free_inst:
kfree(inst);
-out_put_enc:
+out_put_auth:
inst = ERR_PTR(err);
goto out;
}
@@ -367,7 +459,7 @@
{
struct authenc_instance_ctx *ctx = crypto_instance_ctx(inst);
- crypto_drop_spawn(&ctx->enc);
+ crypto_drop_skcipher(&ctx->enc);
crypto_drop_spawn(&ctx->auth);
kfree(inst);
}
diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c
index f6c67f9..4a7e65c 100644
--- a/crypto/blkcipher.c
+++ b/crypto/blkcipher.c
@@ -14,7 +14,8 @@
*
*/
-#include <linux/crypto.h>
+#include <crypto/internal/skcipher.h>
+#include <crypto/scatterwalk.h>
#include <linux/errno.h>
#include <linux/hardirq.h>
#include <linux/kernel.h>
@@ -25,7 +26,6 @@
#include <linux/string.h>
#include "internal.h"
-#include "scatterwalk.h"
enum {
BLKCIPHER_WALK_PHYS = 1 << 0,
@@ -433,9 +433,8 @@
struct blkcipher_alg *cipher = &alg->cra_blkcipher;
unsigned int len = alg->cra_ctxsize;
- type ^= CRYPTO_ALG_ASYNC;
- mask &= CRYPTO_ALG_ASYNC;
- if ((type & mask) && cipher->ivsize) {
+ if ((mask & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_MASK &&
+ cipher->ivsize) {
len = ALIGN(len, (unsigned long)alg->cra_alignmask + 1);
len += cipher->ivsize;
}
@@ -451,6 +450,11 @@
crt->setkey = async_setkey;
crt->encrypt = async_encrypt;
crt->decrypt = async_decrypt;
+ if (!alg->ivsize) {
+ crt->givencrypt = skcipher_null_givencrypt;
+ crt->givdecrypt = skcipher_null_givdecrypt;
+ }
+ crt->base = __crypto_ablkcipher_cast(tfm);
crt->ivsize = alg->ivsize;
return 0;
@@ -482,9 +486,7 @@
if (alg->ivsize > PAGE_SIZE / 8)
return -EINVAL;
- type ^= CRYPTO_ALG_ASYNC;
- mask &= CRYPTO_ALG_ASYNC;
- if (type & mask)
+ if ((mask & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_MASK)
return crypto_init_blkcipher_ops_sync(tfm);
else
return crypto_init_blkcipher_ops_async(tfm);
@@ -499,6 +501,8 @@
seq_printf(m, "min keysize : %u\n", alg->cra_blkcipher.min_keysize);
seq_printf(m, "max keysize : %u\n", alg->cra_blkcipher.max_keysize);
seq_printf(m, "ivsize : %u\n", alg->cra_blkcipher.ivsize);
+ seq_printf(m, "geniv : %s\n", alg->cra_blkcipher.geniv ?:
+ "<default>");
}
const struct crypto_type crypto_blkcipher_type = {
@@ -510,5 +514,187 @@
};
EXPORT_SYMBOL_GPL(crypto_blkcipher_type);
+static int crypto_grab_nivcipher(struct crypto_skcipher_spawn *spawn,
+ const char *name, u32 type, u32 mask)
+{
+ struct crypto_alg *alg;
+ int err;
+
+ type = crypto_skcipher_type(type);
+ mask = crypto_skcipher_mask(mask) | CRYPTO_ALG_GENIV;
+
+ alg = crypto_alg_mod_lookup(name, type, mask);
+ if (IS_ERR(alg))
+ return PTR_ERR(alg);
+
+ err = crypto_init_spawn(&spawn->base, alg, spawn->base.inst, mask);
+ crypto_mod_put(alg);
+ return err;
+}
+
+struct crypto_instance *skcipher_geniv_alloc(struct crypto_template *tmpl,
+ struct rtattr **tb, u32 type,
+ u32 mask)
+{
+ struct {
+ int (*setkey)(struct crypto_ablkcipher *tfm, const u8 *key,
+ unsigned int keylen);
+ int (*encrypt)(struct ablkcipher_request *req);
+ int (*decrypt)(struct ablkcipher_request *req);
+
+ unsigned int min_keysize;
+ unsigned int max_keysize;
+ unsigned int ivsize;
+
+ const char *geniv;
+ } balg;
+ const char *name;
+ struct crypto_skcipher_spawn *spawn;
+ struct crypto_attr_type *algt;
+ struct crypto_instance *inst;
+ struct crypto_alg *alg;
+ int err;
+
+ algt = crypto_get_attr_type(tb);
+ err = PTR_ERR(algt);
+ if (IS_ERR(algt))
+ return ERR_PTR(err);
+
+ if ((algt->type ^ (CRYPTO_ALG_TYPE_GIVCIPHER | CRYPTO_ALG_GENIV)) &
+ algt->mask)
+ return ERR_PTR(-EINVAL);
+
+ name = crypto_attr_alg_name(tb[1]);
+ err = PTR_ERR(name);
+ if (IS_ERR(name))
+ return ERR_PTR(err);
+
+ inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
+ if (!inst)
+ return ERR_PTR(-ENOMEM);
+
+ spawn = crypto_instance_ctx(inst);
+
+ /* Ignore async algorithms if necessary. */
+ mask |= crypto_requires_sync(algt->type, algt->mask);
+
+ crypto_set_skcipher_spawn(spawn, inst);
+ err = crypto_grab_nivcipher(spawn, name, type, mask);
+ if (err)
+ goto err_free_inst;
+
+ alg = crypto_skcipher_spawn_alg(spawn);
+
+ if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
+ CRYPTO_ALG_TYPE_BLKCIPHER) {
+ balg.ivsize = alg->cra_blkcipher.ivsize;
+ balg.min_keysize = alg->cra_blkcipher.min_keysize;
+ balg.max_keysize = alg->cra_blkcipher.max_keysize;
+
+ balg.setkey = async_setkey;
+ balg.encrypt = async_encrypt;
+ balg.decrypt = async_decrypt;
+
+ balg.geniv = alg->cra_blkcipher.geniv;
+ } else {
+ balg.ivsize = alg->cra_ablkcipher.ivsize;
+ balg.min_keysize = alg->cra_ablkcipher.min_keysize;
+ balg.max_keysize = alg->cra_ablkcipher.max_keysize;
+
+ balg.setkey = alg->cra_ablkcipher.setkey;
+ balg.encrypt = alg->cra_ablkcipher.encrypt;
+ balg.decrypt = alg->cra_ablkcipher.decrypt;
+
+ balg.geniv = alg->cra_ablkcipher.geniv;
+ }
+
+ err = -EINVAL;
+ if (!balg.ivsize)
+ goto err_drop_alg;
+
+ /*
+ * This is only true if we're constructing an algorithm with its
+ * default IV generator. For the default generator we elide the
+ * template name and double-check the IV generator.
+ */
+ if (algt->mask & CRYPTO_ALG_GENIV) {
+ if (!balg.geniv)
+ balg.geniv = crypto_default_geniv(alg);
+ err = -EAGAIN;
+ if (strcmp(tmpl->name, balg.geniv))
+ goto err_drop_alg;
+
+ memcpy(inst->alg.cra_name, alg->cra_name, CRYPTO_MAX_ALG_NAME);
+ memcpy(inst->alg.cra_driver_name, alg->cra_driver_name,
+ CRYPTO_MAX_ALG_NAME);
+ } else {
+ err = -ENAMETOOLONG;
+ if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
+ "%s(%s)", tmpl->name, alg->cra_name) >=
+ CRYPTO_MAX_ALG_NAME)
+ goto err_drop_alg;
+ if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
+ "%s(%s)", tmpl->name, alg->cra_driver_name) >=
+ CRYPTO_MAX_ALG_NAME)
+ goto err_drop_alg;
+ }
+
+ inst->alg.cra_flags = CRYPTO_ALG_TYPE_GIVCIPHER | CRYPTO_ALG_GENIV;
+ inst->alg.cra_flags |= alg->cra_flags & CRYPTO_ALG_ASYNC;
+ inst->alg.cra_priority = alg->cra_priority;
+ inst->alg.cra_blocksize = alg->cra_blocksize;
+ inst->alg.cra_alignmask = alg->cra_alignmask;
+ inst->alg.cra_type = &crypto_givcipher_type;
+
+ inst->alg.cra_ablkcipher.ivsize = balg.ivsize;
+ inst->alg.cra_ablkcipher.min_keysize = balg.min_keysize;
+ inst->alg.cra_ablkcipher.max_keysize = balg.max_keysize;
+ inst->alg.cra_ablkcipher.geniv = balg.geniv;
+
+ inst->alg.cra_ablkcipher.setkey = balg.setkey;
+ inst->alg.cra_ablkcipher.encrypt = balg.encrypt;
+ inst->alg.cra_ablkcipher.decrypt = balg.decrypt;
+
+out:
+ return inst;
+
+err_drop_alg:
+ crypto_drop_skcipher(spawn);
+err_free_inst:
+ kfree(inst);
+ inst = ERR_PTR(err);
+ goto out;
+}
+EXPORT_SYMBOL_GPL(skcipher_geniv_alloc);
+
+void skcipher_geniv_free(struct crypto_instance *inst)
+{
+ crypto_drop_skcipher(crypto_instance_ctx(inst));
+ kfree(inst);
+}
+EXPORT_SYMBOL_GPL(skcipher_geniv_free);
+
+int skcipher_geniv_init(struct crypto_tfm *tfm)
+{
+ struct crypto_instance *inst = (void *)tfm->__crt_alg;
+ struct crypto_ablkcipher *cipher;
+
+ cipher = crypto_spawn_skcipher(crypto_instance_ctx(inst));
+ if (IS_ERR(cipher))
+ return PTR_ERR(cipher);
+
+ tfm->crt_ablkcipher.base = cipher;
+ tfm->crt_ablkcipher.reqsize += crypto_ablkcipher_reqsize(cipher);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(skcipher_geniv_init);
+
+void skcipher_geniv_exit(struct crypto_tfm *tfm)
+{
+ crypto_free_ablkcipher(tfm->crt_ablkcipher.base);
+}
+EXPORT_SYMBOL_GPL(skcipher_geniv_exit);
+
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Generic block chaining cipher type");
diff --git a/crypto/camellia.c b/crypto/camellia.c
index 6877ecf..493fee7 100644
--- a/crypto/camellia.c
+++ b/crypto/camellia.c
@@ -36,176 +36,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
-
-#define CAMELLIA_MIN_KEY_SIZE 16
-#define CAMELLIA_MAX_KEY_SIZE 32
-#define CAMELLIA_BLOCK_SIZE 16
-#define CAMELLIA_TABLE_BYTE_LEN 272
-#define CAMELLIA_TABLE_WORD_LEN (CAMELLIA_TABLE_BYTE_LEN / 4)
-
-typedef u32 KEY_TABLE_TYPE[CAMELLIA_TABLE_WORD_LEN];
-
-
-/* key constants */
-
-#define CAMELLIA_SIGMA1L (0xA09E667FL)
-#define CAMELLIA_SIGMA1R (0x3BCC908BL)
-#define CAMELLIA_SIGMA2L (0xB67AE858L)
-#define CAMELLIA_SIGMA2R (0x4CAA73B2L)
-#define CAMELLIA_SIGMA3L (0xC6EF372FL)
-#define CAMELLIA_SIGMA3R (0xE94F82BEL)
-#define CAMELLIA_SIGMA4L (0x54FF53A5L)
-#define CAMELLIA_SIGMA4R (0xF1D36F1CL)
-#define CAMELLIA_SIGMA5L (0x10E527FAL)
-#define CAMELLIA_SIGMA5R (0xDE682D1DL)
-#define CAMELLIA_SIGMA6L (0xB05688C2L)
-#define CAMELLIA_SIGMA6R (0xB3E6C1FDL)
-
-struct camellia_ctx {
- int key_length;
- KEY_TABLE_TYPE key_table;
-};
-
-
-/*
- * macros
- */
-
-
-# define GETU32(pt) (((u32)(pt)[0] << 24) \
- ^ ((u32)(pt)[1] << 16) \
- ^ ((u32)(pt)[2] << 8) \
- ^ ((u32)(pt)[3]))
-
-#define COPY4WORD(dst, src) \
- do { \
- (dst)[0]=(src)[0]; \
- (dst)[1]=(src)[1]; \
- (dst)[2]=(src)[2]; \
- (dst)[3]=(src)[3]; \
- }while(0)
-
-#define SWAP4WORD(word) \
- do { \
- CAMELLIA_SWAP4((word)[0]); \
- CAMELLIA_SWAP4((word)[1]); \
- CAMELLIA_SWAP4((word)[2]); \
- CAMELLIA_SWAP4((word)[3]); \
- }while(0)
-
-#define XOR4WORD(a, b)/* a = a ^ b */ \
- do { \
- (a)[0]^=(b)[0]; \
- (a)[1]^=(b)[1]; \
- (a)[2]^=(b)[2]; \
- (a)[3]^=(b)[3]; \
- }while(0)
-
-#define XOR4WORD2(a, b, c)/* a = b ^ c */ \
- do { \
- (a)[0]=(b)[0]^(c)[0]; \
- (a)[1]=(b)[1]^(c)[1]; \
- (a)[2]=(b)[2]^(c)[2]; \
- (a)[3]=(b)[3]^(c)[3]; \
- }while(0)
-
-#define CAMELLIA_SUBKEY_L(INDEX) (subkey[(INDEX)*2])
-#define CAMELLIA_SUBKEY_R(INDEX) (subkey[(INDEX)*2 + 1])
-
-/* rotation right shift 1byte */
-#define CAMELLIA_RR8(x) (((x) >> 8) + ((x) << 24))
-/* rotation left shift 1bit */
-#define CAMELLIA_RL1(x) (((x) << 1) + ((x) >> 31))
-/* rotation left shift 1byte */
-#define CAMELLIA_RL8(x) (((x) << 8) + ((x) >> 24))
-
-#define CAMELLIA_ROLDQ(ll, lr, rl, rr, w0, w1, bits) \
- do { \
- w0 = ll; \
- ll = (ll << bits) + (lr >> (32 - bits)); \
- lr = (lr << bits) + (rl >> (32 - bits)); \
- rl = (rl << bits) + (rr >> (32 - bits)); \
- rr = (rr << bits) + (w0 >> (32 - bits)); \
- } while(0)
-
-#define CAMELLIA_ROLDQo32(ll, lr, rl, rr, w0, w1, bits) \
- do { \
- w0 = ll; \
- w1 = lr; \
- ll = (lr << (bits - 32)) + (rl >> (64 - bits)); \
- lr = (rl << (bits - 32)) + (rr >> (64 - bits)); \
- rl = (rr << (bits - 32)) + (w0 >> (64 - bits)); \
- rr = (w0 << (bits - 32)) + (w1 >> (64 - bits)); \
- } while(0)
-
-#define CAMELLIA_SP1110(INDEX) (camellia_sp1110[(INDEX)])
-#define CAMELLIA_SP0222(INDEX) (camellia_sp0222[(INDEX)])
-#define CAMELLIA_SP3033(INDEX) (camellia_sp3033[(INDEX)])
-#define CAMELLIA_SP4404(INDEX) (camellia_sp4404[(INDEX)])
-
-#define CAMELLIA_F(xl, xr, kl, kr, yl, yr, il, ir, t0, t1) \
- do { \
- il = xl ^ kl; \
- ir = xr ^ kr; \
- t0 = il >> 16; \
- t1 = ir >> 16; \
- yl = CAMELLIA_SP1110(ir & 0xff) \
- ^ CAMELLIA_SP0222((t1 >> 8) & 0xff) \
- ^ CAMELLIA_SP3033(t1 & 0xff) \
- ^ CAMELLIA_SP4404((ir >> 8) & 0xff); \
- yr = CAMELLIA_SP1110((t0 >> 8) & 0xff) \
- ^ CAMELLIA_SP0222(t0 & 0xff) \
- ^ CAMELLIA_SP3033((il >> 8) & 0xff) \
- ^ CAMELLIA_SP4404(il & 0xff); \
- yl ^= yr; \
- yr = CAMELLIA_RR8(yr); \
- yr ^= yl; \
- } while(0)
-
-
-/*
- * for speed up
- *
- */
-#define CAMELLIA_FLS(ll, lr, rl, rr, kll, klr, krl, krr, t0, t1, t2, t3) \
- do { \
- t0 = kll; \
- t2 = krr; \
- t0 &= ll; \
- t2 |= rr; \
- rl ^= t2; \
- lr ^= CAMELLIA_RL1(t0); \
- t3 = krl; \
- t1 = klr; \
- t3 &= rl; \
- t1 |= lr; \
- ll ^= t1; \
- rr ^= CAMELLIA_RL1(t3); \
- } while(0)
-
-#define CAMELLIA_ROUNDSM(xl, xr, kl, kr, yl, yr, il, ir, t0, t1) \
- do { \
- ir = CAMELLIA_SP1110(xr & 0xff); \
- il = CAMELLIA_SP1110((xl>>24) & 0xff); \
- ir ^= CAMELLIA_SP0222((xr>>24) & 0xff); \
- il ^= CAMELLIA_SP0222((xl>>16) & 0xff); \
- ir ^= CAMELLIA_SP3033((xr>>16) & 0xff); \
- il ^= CAMELLIA_SP3033((xl>>8) & 0xff); \
- ir ^= CAMELLIA_SP4404((xr>>8) & 0xff); \
- il ^= CAMELLIA_SP4404(xl & 0xff); \
- il ^= kl; \
- ir ^= il ^ kr; \
- yl ^= ir; \
- yr ^= CAMELLIA_RR8(il) ^ ir; \
- } while(0)
-
-/**
- * Stuff related to the Camellia key schedule
- */
-#define SUBL(x) subL[(x)]
-#define SUBR(x) subR[(x)]
-
-
static const u32 camellia_sp1110[256] = {
0x70707000,0x82828200,0x2c2c2c00,0xececec00,
0xb3b3b300,0x27272700,0xc0c0c000,0xe5e5e500,
@@ -475,67 +305,348 @@
};
+#define CAMELLIA_MIN_KEY_SIZE 16
+#define CAMELLIA_MAX_KEY_SIZE 32
+#define CAMELLIA_BLOCK_SIZE 16
+#define CAMELLIA_TABLE_BYTE_LEN 272
+
+/*
+ * NB: L and R below stand for 'left' and 'right' as in written numbers.
+ * That is, in (xxxL,xxxR) pair xxxL holds most significant digits,
+ * _not_ least significant ones!
+ */
+
+
+/* key constants */
+
+#define CAMELLIA_SIGMA1L (0xA09E667FL)
+#define CAMELLIA_SIGMA1R (0x3BCC908BL)
+#define CAMELLIA_SIGMA2L (0xB67AE858L)
+#define CAMELLIA_SIGMA2R (0x4CAA73B2L)
+#define CAMELLIA_SIGMA3L (0xC6EF372FL)
+#define CAMELLIA_SIGMA3R (0xE94F82BEL)
+#define CAMELLIA_SIGMA4L (0x54FF53A5L)
+#define CAMELLIA_SIGMA4R (0xF1D36F1CL)
+#define CAMELLIA_SIGMA5L (0x10E527FAL)
+#define CAMELLIA_SIGMA5R (0xDE682D1DL)
+#define CAMELLIA_SIGMA6L (0xB05688C2L)
+#define CAMELLIA_SIGMA6R (0xB3E6C1FDL)
+
+/*
+ * macros
+ */
+#define GETU32(v, pt) \
+ do { \
+ /* latest breed of gcc is clever enough to use move */ \
+ memcpy(&(v), (pt), 4); \
+ (v) = be32_to_cpu(v); \
+ } while(0)
+
+/* rotation right shift 1byte */
+#define ROR8(x) (((x) >> 8) + ((x) << 24))
+/* rotation left shift 1bit */
+#define ROL1(x) (((x) << 1) + ((x) >> 31))
+/* rotation left shift 1byte */
+#define ROL8(x) (((x) << 8) + ((x) >> 24))
+
+#define ROLDQ(ll, lr, rl, rr, w0, w1, bits) \
+ do { \
+ w0 = ll; \
+ ll = (ll << bits) + (lr >> (32 - bits)); \
+ lr = (lr << bits) + (rl >> (32 - bits)); \
+ rl = (rl << bits) + (rr >> (32 - bits)); \
+ rr = (rr << bits) + (w0 >> (32 - bits)); \
+ } while(0)
+
+#define ROLDQo32(ll, lr, rl, rr, w0, w1, bits) \
+ do { \
+ w0 = ll; \
+ w1 = lr; \
+ ll = (lr << (bits - 32)) + (rl >> (64 - bits)); \
+ lr = (rl << (bits - 32)) + (rr >> (64 - bits)); \
+ rl = (rr << (bits - 32)) + (w0 >> (64 - bits)); \
+ rr = (w0 << (bits - 32)) + (w1 >> (64 - bits)); \
+ } while(0)
+
+#define CAMELLIA_F(xl, xr, kl, kr, yl, yr, il, ir, t0, t1) \
+ do { \
+ il = xl ^ kl; \
+ ir = xr ^ kr; \
+ t0 = il >> 16; \
+ t1 = ir >> 16; \
+ yl = camellia_sp1110[(u8)(ir )] \
+ ^ camellia_sp0222[ (t1 >> 8)] \
+ ^ camellia_sp3033[(u8)(t1 )] \
+ ^ camellia_sp4404[(u8)(ir >> 8)]; \
+ yr = camellia_sp1110[ (t0 >> 8)] \
+ ^ camellia_sp0222[(u8)(t0 )] \
+ ^ camellia_sp3033[(u8)(il >> 8)] \
+ ^ camellia_sp4404[(u8)(il )]; \
+ yl ^= yr; \
+ yr = ROR8(yr); \
+ yr ^= yl; \
+ } while(0)
+
+#define SUBKEY_L(INDEX) (subkey[(INDEX)*2])
+#define SUBKEY_R(INDEX) (subkey[(INDEX)*2 + 1])
+
+static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
+{
+ u32 dw, tl, tr;
+ u32 kw4l, kw4r;
+ int i;
+
+ /* absorb kw2 to other subkeys */
+ /* round 2 */
+ subL[3] ^= subL[1]; subR[3] ^= subR[1];
+ /* round 4 */
+ subL[5] ^= subL[1]; subR[5] ^= subR[1];
+ /* round 6 */
+ subL[7] ^= subL[1]; subR[7] ^= subR[1];
+ subL[1] ^= subR[1] & ~subR[9];
+ dw = subL[1] & subL[9],
+ subR[1] ^= ROL1(dw); /* modified for FLinv(kl2) */
+ /* round 8 */
+ subL[11] ^= subL[1]; subR[11] ^= subR[1];
+ /* round 10 */
+ subL[13] ^= subL[1]; subR[13] ^= subR[1];
+ /* round 12 */
+ subL[15] ^= subL[1]; subR[15] ^= subR[1];
+ subL[1] ^= subR[1] & ~subR[17];
+ dw = subL[1] & subL[17],
+ subR[1] ^= ROL1(dw); /* modified for FLinv(kl4) */
+ /* round 14 */
+ subL[19] ^= subL[1]; subR[19] ^= subR[1];
+ /* round 16 */
+ subL[21] ^= subL[1]; subR[21] ^= subR[1];
+ /* round 18 */
+ subL[23] ^= subL[1]; subR[23] ^= subR[1];
+ if (max == 24) {
+ /* kw3 */
+ subL[24] ^= subL[1]; subR[24] ^= subR[1];
+
+ /* absorb kw4 to other subkeys */
+ kw4l = subL[25]; kw4r = subR[25];
+ } else {
+ subL[1] ^= subR[1] & ~subR[25];
+ dw = subL[1] & subL[25],
+ subR[1] ^= ROL1(dw); /* modified for FLinv(kl6) */
+ /* round 20 */
+ subL[27] ^= subL[1]; subR[27] ^= subR[1];
+ /* round 22 */
+ subL[29] ^= subL[1]; subR[29] ^= subR[1];
+ /* round 24 */
+ subL[31] ^= subL[1]; subR[31] ^= subR[1];
+ /* kw3 */
+ subL[32] ^= subL[1]; subR[32] ^= subR[1];
+
+ /* absorb kw4 to other subkeys */
+ kw4l = subL[33]; kw4r = subR[33];
+ /* round 23 */
+ subL[30] ^= kw4l; subR[30] ^= kw4r;
+ /* round 21 */
+ subL[28] ^= kw4l; subR[28] ^= kw4r;
+ /* round 19 */
+ subL[26] ^= kw4l; subR[26] ^= kw4r;
+ kw4l ^= kw4r & ~subR[24];
+ dw = kw4l & subL[24],
+ kw4r ^= ROL1(dw); /* modified for FL(kl5) */
+ }
+ /* round 17 */
+ subL[22] ^= kw4l; subR[22] ^= kw4r;
+ /* round 15 */
+ subL[20] ^= kw4l; subR[20] ^= kw4r;
+ /* round 13 */
+ subL[18] ^= kw4l; subR[18] ^= kw4r;
+ kw4l ^= kw4r & ~subR[16];
+ dw = kw4l & subL[16],
+ kw4r ^= ROL1(dw); /* modified for FL(kl3) */
+ /* round 11 */
+ subL[14] ^= kw4l; subR[14] ^= kw4r;
+ /* round 9 */
+ subL[12] ^= kw4l; subR[12] ^= kw4r;
+ /* round 7 */
+ subL[10] ^= kw4l; subR[10] ^= kw4r;
+ kw4l ^= kw4r & ~subR[8];
+ dw = kw4l & subL[8],
+ kw4r ^= ROL1(dw); /* modified for FL(kl1) */
+ /* round 5 */
+ subL[6] ^= kw4l; subR[6] ^= kw4r;
+ /* round 3 */
+ subL[4] ^= kw4l; subR[4] ^= kw4r;
+ /* round 1 */
+ subL[2] ^= kw4l; subR[2] ^= kw4r;
+ /* kw1 */
+ subL[0] ^= kw4l; subR[0] ^= kw4r;
+
+ /* key XOR is end of F-function */
+ SUBKEY_L(0) = subL[0] ^ subL[2];/* kw1 */
+ SUBKEY_R(0) = subR[0] ^ subR[2];
+ SUBKEY_L(2) = subL[3]; /* round 1 */
+ SUBKEY_R(2) = subR[3];
+ SUBKEY_L(3) = subL[2] ^ subL[4]; /* round 2 */
+ SUBKEY_R(3) = subR[2] ^ subR[4];
+ SUBKEY_L(4) = subL[3] ^ subL[5]; /* round 3 */
+ SUBKEY_R(4) = subR[3] ^ subR[5];
+ SUBKEY_L(5) = subL[4] ^ subL[6]; /* round 4 */
+ SUBKEY_R(5) = subR[4] ^ subR[6];
+ SUBKEY_L(6) = subL[5] ^ subL[7]; /* round 5 */
+ SUBKEY_R(6) = subR[5] ^ subR[7];
+ tl = subL[10] ^ (subR[10] & ~subR[8]);
+ dw = tl & subL[8], /* FL(kl1) */
+ tr = subR[10] ^ ROL1(dw);
+ SUBKEY_L(7) = subL[6] ^ tl; /* round 6 */
+ SUBKEY_R(7) = subR[6] ^ tr;
+ SUBKEY_L(8) = subL[8]; /* FL(kl1) */
+ SUBKEY_R(8) = subR[8];
+ SUBKEY_L(9) = subL[9]; /* FLinv(kl2) */
+ SUBKEY_R(9) = subR[9];
+ tl = subL[7] ^ (subR[7] & ~subR[9]);
+ dw = tl & subL[9], /* FLinv(kl2) */
+ tr = subR[7] ^ ROL1(dw);
+ SUBKEY_L(10) = tl ^ subL[11]; /* round 7 */
+ SUBKEY_R(10) = tr ^ subR[11];
+ SUBKEY_L(11) = subL[10] ^ subL[12]; /* round 8 */
+ SUBKEY_R(11) = subR[10] ^ subR[12];
+ SUBKEY_L(12) = subL[11] ^ subL[13]; /* round 9 */
+ SUBKEY_R(12) = subR[11] ^ subR[13];
+ SUBKEY_L(13) = subL[12] ^ subL[14]; /* round 10 */
+ SUBKEY_R(13) = subR[12] ^ subR[14];
+ SUBKEY_L(14) = subL[13] ^ subL[15]; /* round 11 */
+ SUBKEY_R(14) = subR[13] ^ subR[15];
+ tl = subL[18] ^ (subR[18] & ~subR[16]);
+ dw = tl & subL[16], /* FL(kl3) */
+ tr = subR[18] ^ ROL1(dw);
+ SUBKEY_L(15) = subL[14] ^ tl; /* round 12 */
+ SUBKEY_R(15) = subR[14] ^ tr;
+ SUBKEY_L(16) = subL[16]; /* FL(kl3) */
+ SUBKEY_R(16) = subR[16];
+ SUBKEY_L(17) = subL[17]; /* FLinv(kl4) */
+ SUBKEY_R(17) = subR[17];
+ tl = subL[15] ^ (subR[15] & ~subR[17]);
+ dw = tl & subL[17], /* FLinv(kl4) */
+ tr = subR[15] ^ ROL1(dw);
+ SUBKEY_L(18) = tl ^ subL[19]; /* round 13 */
+ SUBKEY_R(18) = tr ^ subR[19];
+ SUBKEY_L(19) = subL[18] ^ subL[20]; /* round 14 */
+ SUBKEY_R(19) = subR[18] ^ subR[20];
+ SUBKEY_L(20) = subL[19] ^ subL[21]; /* round 15 */
+ SUBKEY_R(20) = subR[19] ^ subR[21];
+ SUBKEY_L(21) = subL[20] ^ subL[22]; /* round 16 */
+ SUBKEY_R(21) = subR[20] ^ subR[22];
+ SUBKEY_L(22) = subL[21] ^ subL[23]; /* round 17 */
+ SUBKEY_R(22) = subR[21] ^ subR[23];
+ if (max == 24) {
+ SUBKEY_L(23) = subL[22]; /* round 18 */
+ SUBKEY_R(23) = subR[22];
+ SUBKEY_L(24) = subL[24] ^ subL[23]; /* kw3 */
+ SUBKEY_R(24) = subR[24] ^ subR[23];
+ } else {
+ tl = subL[26] ^ (subR[26] & ~subR[24]);
+ dw = tl & subL[24], /* FL(kl5) */
+ tr = subR[26] ^ ROL1(dw);
+ SUBKEY_L(23) = subL[22] ^ tl; /* round 18 */
+ SUBKEY_R(23) = subR[22] ^ tr;
+ SUBKEY_L(24) = subL[24]; /* FL(kl5) */
+ SUBKEY_R(24) = subR[24];
+ SUBKEY_L(25) = subL[25]; /* FLinv(kl6) */
+ SUBKEY_R(25) = subR[25];
+ tl = subL[23] ^ (subR[23] & ~subR[25]);
+ dw = tl & subL[25], /* FLinv(kl6) */
+ tr = subR[23] ^ ROL1(dw);
+ SUBKEY_L(26) = tl ^ subL[27]; /* round 19 */
+ SUBKEY_R(26) = tr ^ subR[27];
+ SUBKEY_L(27) = subL[26] ^ subL[28]; /* round 20 */
+ SUBKEY_R(27) = subR[26] ^ subR[28];
+ SUBKEY_L(28) = subL[27] ^ subL[29]; /* round 21 */
+ SUBKEY_R(28) = subR[27] ^ subR[29];
+ SUBKEY_L(29) = subL[28] ^ subL[30]; /* round 22 */
+ SUBKEY_R(29) = subR[28] ^ subR[30];
+ SUBKEY_L(30) = subL[29] ^ subL[31]; /* round 23 */
+ SUBKEY_R(30) = subR[29] ^ subR[31];
+ SUBKEY_L(31) = subL[30]; /* round 24 */
+ SUBKEY_R(31) = subR[30];
+ SUBKEY_L(32) = subL[32] ^ subL[31]; /* kw3 */
+ SUBKEY_R(32) = subR[32] ^ subR[31];
+ }
+
+ /* apply the inverse of the last half of P-function */
+ i = 2;
+ do {
+ dw = SUBKEY_L(i + 0) ^ SUBKEY_R(i + 0); dw = ROL8(dw);/* round 1 */
+ SUBKEY_R(i + 0) = SUBKEY_L(i + 0) ^ dw; SUBKEY_L(i + 0) = dw;
+ dw = SUBKEY_L(i + 1) ^ SUBKEY_R(i + 1); dw = ROL8(dw);/* round 2 */
+ SUBKEY_R(i + 1) = SUBKEY_L(i + 1) ^ dw; SUBKEY_L(i + 1) = dw;
+ dw = SUBKEY_L(i + 2) ^ SUBKEY_R(i + 2); dw = ROL8(dw);/* round 3 */
+ SUBKEY_R(i + 2) = SUBKEY_L(i + 2) ^ dw; SUBKEY_L(i + 2) = dw;
+ dw = SUBKEY_L(i + 3) ^ SUBKEY_R(i + 3); dw = ROL8(dw);/* round 4 */
+ SUBKEY_R(i + 3) = SUBKEY_L(i + 3) ^ dw; SUBKEY_L(i + 3) = dw;
+ dw = SUBKEY_L(i + 4) ^ SUBKEY_R(i + 4); dw = ROL8(dw);/* round 5 */
+ SUBKEY_R(i + 4) = SUBKEY_L(i + 4) ^ dw; SUBKEY_L(i + 4) = dw;
+ dw = SUBKEY_L(i + 5) ^ SUBKEY_R(i + 5); dw = ROL8(dw);/* round 6 */
+ SUBKEY_R(i + 5) = SUBKEY_L(i + 5) ^ dw; SUBKEY_L(i + 5) = dw;
+ i += 8;
+ } while (i < max);
+}
static void camellia_setup128(const unsigned char *key, u32 *subkey)
{
u32 kll, klr, krl, krr;
u32 il, ir, t0, t1, w0, w1;
- u32 kw4l, kw4r, dw, tl, tr;
u32 subL[26];
u32 subR[26];
/**
- * k == kll || klr || krl || krr (|| is concatination)
+ * k == kll || klr || krl || krr (|| is concatenation)
*/
- kll = GETU32(key );
- klr = GETU32(key + 4);
- krl = GETU32(key + 8);
- krr = GETU32(key + 12);
- /**
- * generate KL dependent subkeys
- */
+ GETU32(kll, key );
+ GETU32(klr, key + 4);
+ GETU32(krl, key + 8);
+ GETU32(krr, key + 12);
+
+ /* generate KL dependent subkeys */
/* kw1 */
- SUBL(0) = kll; SUBR(0) = klr;
+ subL[0] = kll; subR[0] = klr;
/* kw2 */
- SUBL(1) = krl; SUBR(1) = krr;
+ subL[1] = krl; subR[1] = krr;
/* rotation left shift 15bit */
- CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+ ROLDQ(kll, klr, krl, krr, w0, w1, 15);
/* k3 */
- SUBL(4) = kll; SUBR(4) = klr;
+ subL[4] = kll; subR[4] = klr;
/* k4 */
- SUBL(5) = krl; SUBR(5) = krr;
+ subL[5] = krl; subR[5] = krr;
/* rotation left shift 15+30bit */
- CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 30);
+ ROLDQ(kll, klr, krl, krr, w0, w1, 30);
/* k7 */
- SUBL(10) = kll; SUBR(10) = klr;
+ subL[10] = kll; subR[10] = klr;
/* k8 */
- SUBL(11) = krl; SUBR(11) = krr;
+ subL[11] = krl; subR[11] = krr;
/* rotation left shift 15+30+15bit */
- CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+ ROLDQ(kll, klr, krl, krr, w0, w1, 15);
/* k10 */
- SUBL(13) = krl; SUBR(13) = krr;
+ subL[13] = krl; subR[13] = krr;
/* rotation left shift 15+30+15+17 bit */
- CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
+ ROLDQ(kll, klr, krl, krr, w0, w1, 17);
/* kl3 */
- SUBL(16) = kll; SUBR(16) = klr;
+ subL[16] = kll; subR[16] = klr;
/* kl4 */
- SUBL(17) = krl; SUBR(17) = krr;
+ subL[17] = krl; subR[17] = krr;
/* rotation left shift 15+30+15+17+17 bit */
- CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
+ ROLDQ(kll, klr, krl, krr, w0, w1, 17);
/* k13 */
- SUBL(18) = kll; SUBR(18) = klr;
+ subL[18] = kll; subR[18] = klr;
/* k14 */
- SUBL(19) = krl; SUBR(19) = krr;
+ subL[19] = krl; subR[19] = krr;
/* rotation left shift 15+30+15+17+17+17 bit */
- CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
+ ROLDQ(kll, klr, krl, krr, w0, w1, 17);
/* k17 */
- SUBL(22) = kll; SUBR(22) = klr;
+ subL[22] = kll; subR[22] = klr;
/* k18 */
- SUBL(23) = krl; SUBR(23) = krr;
+ subL[23] = krl; subR[23] = krr;
/* generate KA */
- kll = SUBL(0); klr = SUBR(0);
- krl = SUBL(1); krr = SUBR(1);
+ kll = subL[0]; klr = subR[0];
+ krl = subL[1]; krr = subR[1];
CAMELLIA_F(kll, klr,
CAMELLIA_SIGMA1L, CAMELLIA_SIGMA1R,
w0, w1, il, ir, t0, t1);
@@ -555,306 +666,108 @@
/* generate KA dependent subkeys */
/* k1, k2 */
- SUBL(2) = kll; SUBR(2) = klr;
- SUBL(3) = krl; SUBR(3) = krr;
- CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+ subL[2] = kll; subR[2] = klr;
+ subL[3] = krl; subR[3] = krr;
+ ROLDQ(kll, klr, krl, krr, w0, w1, 15);
/* k5,k6 */
- SUBL(6) = kll; SUBR(6) = klr;
- SUBL(7) = krl; SUBR(7) = krr;
- CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+ subL[6] = kll; subR[6] = klr;
+ subL[7] = krl; subR[7] = krr;
+ ROLDQ(kll, klr, krl, krr, w0, w1, 15);
/* kl1, kl2 */
- SUBL(8) = kll; SUBR(8) = klr;
- SUBL(9) = krl; SUBR(9) = krr;
- CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+ subL[8] = kll; subR[8] = klr;
+ subL[9] = krl; subR[9] = krr;
+ ROLDQ(kll, klr, krl, krr, w0, w1, 15);
/* k9 */
- SUBL(12) = kll; SUBR(12) = klr;
- CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+ subL[12] = kll; subR[12] = klr;
+ ROLDQ(kll, klr, krl, krr, w0, w1, 15);
/* k11, k12 */
- SUBL(14) = kll; SUBR(14) = klr;
- SUBL(15) = krl; SUBR(15) = krr;
- CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 34);
+ subL[14] = kll; subR[14] = klr;
+ subL[15] = krl; subR[15] = krr;
+ ROLDQo32(kll, klr, krl, krr, w0, w1, 34);
/* k15, k16 */
- SUBL(20) = kll; SUBR(20) = klr;
- SUBL(21) = krl; SUBR(21) = krr;
- CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
+ subL[20] = kll; subR[20] = klr;
+ subL[21] = krl; subR[21] = krr;
+ ROLDQ(kll, klr, krl, krr, w0, w1, 17);
/* kw3, kw4 */
- SUBL(24) = kll; SUBR(24) = klr;
- SUBL(25) = krl; SUBR(25) = krr;
+ subL[24] = kll; subR[24] = klr;
+ subL[25] = krl; subR[25] = krr;
-
- /* absorb kw2 to other subkeys */
- /* round 2 */
- SUBL(3) ^= SUBL(1); SUBR(3) ^= SUBR(1);
- /* round 4 */
- SUBL(5) ^= SUBL(1); SUBR(5) ^= SUBR(1);
- /* round 6 */
- SUBL(7) ^= SUBL(1); SUBR(7) ^= SUBR(1);
- SUBL(1) ^= SUBR(1) & ~SUBR(9);
- dw = SUBL(1) & SUBL(9),
- SUBR(1) ^= CAMELLIA_RL1(dw); /* modified for FLinv(kl2) */
- /* round 8 */
- SUBL(11) ^= SUBL(1); SUBR(11) ^= SUBR(1);
- /* round 10 */
- SUBL(13) ^= SUBL(1); SUBR(13) ^= SUBR(1);
- /* round 12 */
- SUBL(15) ^= SUBL(1); SUBR(15) ^= SUBR(1);
- SUBL(1) ^= SUBR(1) & ~SUBR(17);
- dw = SUBL(1) & SUBL(17),
- SUBR(1) ^= CAMELLIA_RL1(dw); /* modified for FLinv(kl4) */
- /* round 14 */
- SUBL(19) ^= SUBL(1); SUBR(19) ^= SUBR(1);
- /* round 16 */
- SUBL(21) ^= SUBL(1); SUBR(21) ^= SUBR(1);
- /* round 18 */
- SUBL(23) ^= SUBL(1); SUBR(23) ^= SUBR(1);
- /* kw3 */
- SUBL(24) ^= SUBL(1); SUBR(24) ^= SUBR(1);
-
- /* absorb kw4 to other subkeys */
- kw4l = SUBL(25); kw4r = SUBR(25);
- /* round 17 */
- SUBL(22) ^= kw4l; SUBR(22) ^= kw4r;
- /* round 15 */
- SUBL(20) ^= kw4l; SUBR(20) ^= kw4r;
- /* round 13 */
- SUBL(18) ^= kw4l; SUBR(18) ^= kw4r;
- kw4l ^= kw4r & ~SUBR(16);
- dw = kw4l & SUBL(16),
- kw4r ^= CAMELLIA_RL1(dw); /* modified for FL(kl3) */
- /* round 11 */
- SUBL(14) ^= kw4l; SUBR(14) ^= kw4r;
- /* round 9 */
- SUBL(12) ^= kw4l; SUBR(12) ^= kw4r;
- /* round 7 */
- SUBL(10) ^= kw4l; SUBR(10) ^= kw4r;
- kw4l ^= kw4r & ~SUBR(8);
- dw = kw4l & SUBL(8),
- kw4r ^= CAMELLIA_RL1(dw); /* modified for FL(kl1) */
- /* round 5 */
- SUBL(6) ^= kw4l; SUBR(6) ^= kw4r;
- /* round 3 */
- SUBL(4) ^= kw4l; SUBR(4) ^= kw4r;
- /* round 1 */
- SUBL(2) ^= kw4l; SUBR(2) ^= kw4r;
- /* kw1 */
- SUBL(0) ^= kw4l; SUBR(0) ^= kw4r;
-
-
- /* key XOR is end of F-function */
- CAMELLIA_SUBKEY_L(0) = SUBL(0) ^ SUBL(2);/* kw1 */
- CAMELLIA_SUBKEY_R(0) = SUBR(0) ^ SUBR(2);
- CAMELLIA_SUBKEY_L(2) = SUBL(3); /* round 1 */
- CAMELLIA_SUBKEY_R(2) = SUBR(3);
- CAMELLIA_SUBKEY_L(3) = SUBL(2) ^ SUBL(4); /* round 2 */
- CAMELLIA_SUBKEY_R(3) = SUBR(2) ^ SUBR(4);
- CAMELLIA_SUBKEY_L(4) = SUBL(3) ^ SUBL(5); /* round 3 */
- CAMELLIA_SUBKEY_R(4) = SUBR(3) ^ SUBR(5);
- CAMELLIA_SUBKEY_L(5) = SUBL(4) ^ SUBL(6); /* round 4 */
- CAMELLIA_SUBKEY_R(5) = SUBR(4) ^ SUBR(6);
- CAMELLIA_SUBKEY_L(6) = SUBL(5) ^ SUBL(7); /* round 5 */
- CAMELLIA_SUBKEY_R(6) = SUBR(5) ^ SUBR(7);
- tl = SUBL(10) ^ (SUBR(10) & ~SUBR(8));
- dw = tl & SUBL(8), /* FL(kl1) */
- tr = SUBR(10) ^ CAMELLIA_RL1(dw);
- CAMELLIA_SUBKEY_L(7) = SUBL(6) ^ tl; /* round 6 */
- CAMELLIA_SUBKEY_R(7) = SUBR(6) ^ tr;
- CAMELLIA_SUBKEY_L(8) = SUBL(8); /* FL(kl1) */
- CAMELLIA_SUBKEY_R(8) = SUBR(8);
- CAMELLIA_SUBKEY_L(9) = SUBL(9); /* FLinv(kl2) */
- CAMELLIA_SUBKEY_R(9) = SUBR(9);
- tl = SUBL(7) ^ (SUBR(7) & ~SUBR(9));
- dw = tl & SUBL(9), /* FLinv(kl2) */
- tr = SUBR(7) ^ CAMELLIA_RL1(dw);
- CAMELLIA_SUBKEY_L(10) = tl ^ SUBL(11); /* round 7 */
- CAMELLIA_SUBKEY_R(10) = tr ^ SUBR(11);
- CAMELLIA_SUBKEY_L(11) = SUBL(10) ^ SUBL(12); /* round 8 */
- CAMELLIA_SUBKEY_R(11) = SUBR(10) ^ SUBR(12);
- CAMELLIA_SUBKEY_L(12) = SUBL(11) ^ SUBL(13); /* round 9 */
- CAMELLIA_SUBKEY_R(12) = SUBR(11) ^ SUBR(13);
- CAMELLIA_SUBKEY_L(13) = SUBL(12) ^ SUBL(14); /* round 10 */
- CAMELLIA_SUBKEY_R(13) = SUBR(12) ^ SUBR(14);
- CAMELLIA_SUBKEY_L(14) = SUBL(13) ^ SUBL(15); /* round 11 */
- CAMELLIA_SUBKEY_R(14) = SUBR(13) ^ SUBR(15);
- tl = SUBL(18) ^ (SUBR(18) & ~SUBR(16));
- dw = tl & SUBL(16), /* FL(kl3) */
- tr = SUBR(18) ^ CAMELLIA_RL1(dw);
- CAMELLIA_SUBKEY_L(15) = SUBL(14) ^ tl; /* round 12 */
- CAMELLIA_SUBKEY_R(15) = SUBR(14) ^ tr;
- CAMELLIA_SUBKEY_L(16) = SUBL(16); /* FL(kl3) */
- CAMELLIA_SUBKEY_R(16) = SUBR(16);
- CAMELLIA_SUBKEY_L(17) = SUBL(17); /* FLinv(kl4) */
- CAMELLIA_SUBKEY_R(17) = SUBR(17);
- tl = SUBL(15) ^ (SUBR(15) & ~SUBR(17));
- dw = tl & SUBL(17), /* FLinv(kl4) */
- tr = SUBR(15) ^ CAMELLIA_RL1(dw);
- CAMELLIA_SUBKEY_L(18) = tl ^ SUBL(19); /* round 13 */
- CAMELLIA_SUBKEY_R(18) = tr ^ SUBR(19);
- CAMELLIA_SUBKEY_L(19) = SUBL(18) ^ SUBL(20); /* round 14 */
- CAMELLIA_SUBKEY_R(19) = SUBR(18) ^ SUBR(20);
- CAMELLIA_SUBKEY_L(20) = SUBL(19) ^ SUBL(21); /* round 15 */
- CAMELLIA_SUBKEY_R(20) = SUBR(19) ^ SUBR(21);
- CAMELLIA_SUBKEY_L(21) = SUBL(20) ^ SUBL(22); /* round 16 */
- CAMELLIA_SUBKEY_R(21) = SUBR(20) ^ SUBR(22);
- CAMELLIA_SUBKEY_L(22) = SUBL(21) ^ SUBL(23); /* round 17 */
- CAMELLIA_SUBKEY_R(22) = SUBR(21) ^ SUBR(23);
- CAMELLIA_SUBKEY_L(23) = SUBL(22); /* round 18 */
- CAMELLIA_SUBKEY_R(23) = SUBR(22);
- CAMELLIA_SUBKEY_L(24) = SUBL(24) ^ SUBL(23); /* kw3 */
- CAMELLIA_SUBKEY_R(24) = SUBR(24) ^ SUBR(23);
-
- /* apply the inverse of the last half of P-function */
- dw = CAMELLIA_SUBKEY_L(2) ^ CAMELLIA_SUBKEY_R(2),
- dw = CAMELLIA_RL8(dw);/* round 1 */
- CAMELLIA_SUBKEY_R(2) = CAMELLIA_SUBKEY_L(2) ^ dw,
- CAMELLIA_SUBKEY_L(2) = dw;
- dw = CAMELLIA_SUBKEY_L(3) ^ CAMELLIA_SUBKEY_R(3),
- dw = CAMELLIA_RL8(dw);/* round 2 */
- CAMELLIA_SUBKEY_R(3) = CAMELLIA_SUBKEY_L(3) ^ dw,
- CAMELLIA_SUBKEY_L(3) = dw;
- dw = CAMELLIA_SUBKEY_L(4) ^ CAMELLIA_SUBKEY_R(4),
- dw = CAMELLIA_RL8(dw);/* round 3 */
- CAMELLIA_SUBKEY_R(4) = CAMELLIA_SUBKEY_L(4) ^ dw,
- CAMELLIA_SUBKEY_L(4) = dw;
- dw = CAMELLIA_SUBKEY_L(5) ^ CAMELLIA_SUBKEY_R(5),
- dw = CAMELLIA_RL8(dw);/* round 4 */
- CAMELLIA_SUBKEY_R(5) = CAMELLIA_SUBKEY_L(5) ^ dw,
- CAMELLIA_SUBKEY_L(5) = dw;
- dw = CAMELLIA_SUBKEY_L(6) ^ CAMELLIA_SUBKEY_R(6),
- dw = CAMELLIA_RL8(dw);/* round 5 */
- CAMELLIA_SUBKEY_R(6) = CAMELLIA_SUBKEY_L(6) ^ dw,
- CAMELLIA_SUBKEY_L(6) = dw;
- dw = CAMELLIA_SUBKEY_L(7) ^ CAMELLIA_SUBKEY_R(7),
- dw = CAMELLIA_RL8(dw);/* round 6 */
- CAMELLIA_SUBKEY_R(7) = CAMELLIA_SUBKEY_L(7) ^ dw,
- CAMELLIA_SUBKEY_L(7) = dw;
- dw = CAMELLIA_SUBKEY_L(10) ^ CAMELLIA_SUBKEY_R(10),
- dw = CAMELLIA_RL8(dw);/* round 7 */
- CAMELLIA_SUBKEY_R(10) = CAMELLIA_SUBKEY_L(10) ^ dw,
- CAMELLIA_SUBKEY_L(10) = dw;
- dw = CAMELLIA_SUBKEY_L(11) ^ CAMELLIA_SUBKEY_R(11),
- dw = CAMELLIA_RL8(dw);/* round 8 */
- CAMELLIA_SUBKEY_R(11) = CAMELLIA_SUBKEY_L(11) ^ dw,
- CAMELLIA_SUBKEY_L(11) = dw;
- dw = CAMELLIA_SUBKEY_L(12) ^ CAMELLIA_SUBKEY_R(12),
- dw = CAMELLIA_RL8(dw);/* round 9 */
- CAMELLIA_SUBKEY_R(12) = CAMELLIA_SUBKEY_L(12) ^ dw,
- CAMELLIA_SUBKEY_L(12) = dw;
- dw = CAMELLIA_SUBKEY_L(13) ^ CAMELLIA_SUBKEY_R(13),
- dw = CAMELLIA_RL8(dw);/* round 10 */
- CAMELLIA_SUBKEY_R(13) = CAMELLIA_SUBKEY_L(13) ^ dw,
- CAMELLIA_SUBKEY_L(13) = dw;
- dw = CAMELLIA_SUBKEY_L(14) ^ CAMELLIA_SUBKEY_R(14),
- dw = CAMELLIA_RL8(dw);/* round 11 */
- CAMELLIA_SUBKEY_R(14) = CAMELLIA_SUBKEY_L(14) ^ dw,
- CAMELLIA_SUBKEY_L(14) = dw;
- dw = CAMELLIA_SUBKEY_L(15) ^ CAMELLIA_SUBKEY_R(15),
- dw = CAMELLIA_RL8(dw);/* round 12 */
- CAMELLIA_SUBKEY_R(15) = CAMELLIA_SUBKEY_L(15) ^ dw,
- CAMELLIA_SUBKEY_L(15) = dw;
- dw = CAMELLIA_SUBKEY_L(18) ^ CAMELLIA_SUBKEY_R(18),
- dw = CAMELLIA_RL8(dw);/* round 13 */
- CAMELLIA_SUBKEY_R(18) = CAMELLIA_SUBKEY_L(18) ^ dw,
- CAMELLIA_SUBKEY_L(18) = dw;
- dw = CAMELLIA_SUBKEY_L(19) ^ CAMELLIA_SUBKEY_R(19),
- dw = CAMELLIA_RL8(dw);/* round 14 */
- CAMELLIA_SUBKEY_R(19) = CAMELLIA_SUBKEY_L(19) ^ dw,
- CAMELLIA_SUBKEY_L(19) = dw;
- dw = CAMELLIA_SUBKEY_L(20) ^ CAMELLIA_SUBKEY_R(20),
- dw = CAMELLIA_RL8(dw);/* round 15 */
- CAMELLIA_SUBKEY_R(20) = CAMELLIA_SUBKEY_L(20) ^ dw,
- CAMELLIA_SUBKEY_L(20) = dw;
- dw = CAMELLIA_SUBKEY_L(21) ^ CAMELLIA_SUBKEY_R(21),
- dw = CAMELLIA_RL8(dw);/* round 16 */
- CAMELLIA_SUBKEY_R(21) = CAMELLIA_SUBKEY_L(21) ^ dw,
- CAMELLIA_SUBKEY_L(21) = dw;
- dw = CAMELLIA_SUBKEY_L(22) ^ CAMELLIA_SUBKEY_R(22),
- dw = CAMELLIA_RL8(dw);/* round 17 */
- CAMELLIA_SUBKEY_R(22) = CAMELLIA_SUBKEY_L(22) ^ dw,
- CAMELLIA_SUBKEY_L(22) = dw;
- dw = CAMELLIA_SUBKEY_L(23) ^ CAMELLIA_SUBKEY_R(23),
- dw = CAMELLIA_RL8(dw);/* round 18 */
- CAMELLIA_SUBKEY_R(23) = CAMELLIA_SUBKEY_L(23) ^ dw,
- CAMELLIA_SUBKEY_L(23) = dw;
-
- return;
+ camellia_setup_tail(subkey, subL, subR, 24);
}
-
static void camellia_setup256(const unsigned char *key, u32 *subkey)
{
- u32 kll,klr,krl,krr; /* left half of key */
- u32 krll,krlr,krrl,krrr; /* right half of key */
+ u32 kll, klr, krl, krr; /* left half of key */
+ u32 krll, krlr, krrl, krrr; /* right half of key */
u32 il, ir, t0, t1, w0, w1; /* temporary variables */
- u32 kw4l, kw4r, dw, tl, tr;
u32 subL[34];
u32 subR[34];
/**
* key = (kll || klr || krl || krr || krll || krlr || krrl || krrr)
- * (|| is concatination)
+ * (|| is concatenation)
*/
-
- kll = GETU32(key );
- klr = GETU32(key + 4);
- krl = GETU32(key + 8);
- krr = GETU32(key + 12);
- krll = GETU32(key + 16);
- krlr = GETU32(key + 20);
- krrl = GETU32(key + 24);
- krrr = GETU32(key + 28);
+ GETU32(kll, key );
+ GETU32(klr, key + 4);
+ GETU32(krl, key + 8);
+ GETU32(krr, key + 12);
+ GETU32(krll, key + 16);
+ GETU32(krlr, key + 20);
+ GETU32(krrl, key + 24);
+ GETU32(krrr, key + 28);
/* generate KL dependent subkeys */
/* kw1 */
- SUBL(0) = kll; SUBR(0) = klr;
+ subL[0] = kll; subR[0] = klr;
/* kw2 */
- SUBL(1) = krl; SUBR(1) = krr;
- CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 45);
+ subL[1] = krl; subR[1] = krr;
+ ROLDQo32(kll, klr, krl, krr, w0, w1, 45);
/* k9 */
- SUBL(12) = kll; SUBR(12) = klr;
+ subL[12] = kll; subR[12] = klr;
/* k10 */
- SUBL(13) = krl; SUBR(13) = krr;
- CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+ subL[13] = krl; subR[13] = krr;
+ ROLDQ(kll, klr, krl, krr, w0, w1, 15);
/* kl3 */
- SUBL(16) = kll; SUBR(16) = klr;
+ subL[16] = kll; subR[16] = klr;
/* kl4 */
- SUBL(17) = krl; SUBR(17) = krr;
- CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
+ subL[17] = krl; subR[17] = krr;
+ ROLDQ(kll, klr, krl, krr, w0, w1, 17);
/* k17 */
- SUBL(22) = kll; SUBR(22) = klr;
+ subL[22] = kll; subR[22] = klr;
/* k18 */
- SUBL(23) = krl; SUBR(23) = krr;
- CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 34);
+ subL[23] = krl; subR[23] = krr;
+ ROLDQo32(kll, klr, krl, krr, w0, w1, 34);
/* k23 */
- SUBL(30) = kll; SUBR(30) = klr;
+ subL[30] = kll; subR[30] = klr;
/* k24 */
- SUBL(31) = krl; SUBR(31) = krr;
+ subL[31] = krl; subR[31] = krr;
/* generate KR dependent subkeys */
- CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15);
+ ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15);
/* k3 */
- SUBL(4) = krll; SUBR(4) = krlr;
+ subL[4] = krll; subR[4] = krlr;
/* k4 */
- SUBL(5) = krrl; SUBR(5) = krrr;
- CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15);
+ subL[5] = krrl; subR[5] = krrr;
+ ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15);
/* kl1 */
- SUBL(8) = krll; SUBR(8) = krlr;
+ subL[8] = krll; subR[8] = krlr;
/* kl2 */
- SUBL(9) = krrl; SUBR(9) = krrr;
- CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
+ subL[9] = krrl; subR[9] = krrr;
+ ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
/* k13 */
- SUBL(18) = krll; SUBR(18) = krlr;
+ subL[18] = krll; subR[18] = krlr;
/* k14 */
- SUBL(19) = krrl; SUBR(19) = krrr;
- CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34);
+ subL[19] = krrl; subR[19] = krrr;
+ ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34);
/* k19 */
- SUBL(26) = krll; SUBR(26) = krlr;
+ subL[26] = krll; subR[26] = krlr;
/* k20 */
- SUBL(27) = krrl; SUBR(27) = krrr;
- CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34);
+ subL[27] = krrl; subR[27] = krrr;
+ ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34);
/* generate KA */
- kll = SUBL(0) ^ krll; klr = SUBR(0) ^ krlr;
- krl = SUBL(1) ^ krrl; krr = SUBR(1) ^ krrr;
+ kll = subL[0] ^ krll; klr = subR[0] ^ krlr;
+ krl = subL[1] ^ krrl; krr = subR[1] ^ krrr;
CAMELLIA_F(kll, klr,
CAMELLIA_SIGMA1L, CAMELLIA_SIGMA1R,
w0, w1, il, ir, t0, t1);
@@ -885,310 +798,50 @@
krll ^= w0; krlr ^= w1;
/* generate KA dependent subkeys */
- CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+ ROLDQ(kll, klr, krl, krr, w0, w1, 15);
/* k5 */
- SUBL(6) = kll; SUBR(6) = klr;
+ subL[6] = kll; subR[6] = klr;
/* k6 */
- SUBL(7) = krl; SUBR(7) = krr;
- CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 30);
+ subL[7] = krl; subR[7] = krr;
+ ROLDQ(kll, klr, krl, krr, w0, w1, 30);
/* k11 */
- SUBL(14) = kll; SUBR(14) = klr;
+ subL[14] = kll; subR[14] = klr;
/* k12 */
- SUBL(15) = krl; SUBR(15) = krr;
+ subL[15] = krl; subR[15] = krr;
/* rotation left shift 32bit */
/* kl5 */
- SUBL(24) = klr; SUBR(24) = krl;
+ subL[24] = klr; subR[24] = krl;
/* kl6 */
- SUBL(25) = krr; SUBR(25) = kll;
+ subL[25] = krr; subR[25] = kll;
/* rotation left shift 49 from k11,k12 -> k21,k22 */
- CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 49);
+ ROLDQo32(kll, klr, krl, krr, w0, w1, 49);
/* k21 */
- SUBL(28) = kll; SUBR(28) = klr;
+ subL[28] = kll; subR[28] = klr;
/* k22 */
- SUBL(29) = krl; SUBR(29) = krr;
+ subL[29] = krl; subR[29] = krr;
/* generate KB dependent subkeys */
/* k1 */
- SUBL(2) = krll; SUBR(2) = krlr;
+ subL[2] = krll; subR[2] = krlr;
/* k2 */
- SUBL(3) = krrl; SUBR(3) = krrr;
- CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
+ subL[3] = krrl; subR[3] = krrr;
+ ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
/* k7 */
- SUBL(10) = krll; SUBR(10) = krlr;
+ subL[10] = krll; subR[10] = krlr;
/* k8 */
- SUBL(11) = krrl; SUBR(11) = krrr;
- CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
+ subL[11] = krrl; subR[11] = krrr;
+ ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
/* k15 */
- SUBL(20) = krll; SUBR(20) = krlr;
+ subL[20] = krll; subR[20] = krlr;
/* k16 */
- SUBL(21) = krrl; SUBR(21) = krrr;
- CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 51);
+ subL[21] = krrl; subR[21] = krrr;
+ ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 51);
/* kw3 */
- SUBL(32) = krll; SUBR(32) = krlr;
+ subL[32] = krll; subR[32] = krlr;
/* kw4 */
- SUBL(33) = krrl; SUBR(33) = krrr;
+ subL[33] = krrl; subR[33] = krrr;
- /* absorb kw2 to other subkeys */
- /* round 2 */
- SUBL(3) ^= SUBL(1); SUBR(3) ^= SUBR(1);
- /* round 4 */
- SUBL(5) ^= SUBL(1); SUBR(5) ^= SUBR(1);
- /* round 6 */
- SUBL(7) ^= SUBL(1); SUBR(7) ^= SUBR(1);
- SUBL(1) ^= SUBR(1) & ~SUBR(9);
- dw = SUBL(1) & SUBL(9),
- SUBR(1) ^= CAMELLIA_RL1(dw); /* modified for FLinv(kl2) */
- /* round 8 */
- SUBL(11) ^= SUBL(1); SUBR(11) ^= SUBR(1);
- /* round 10 */
- SUBL(13) ^= SUBL(1); SUBR(13) ^= SUBR(1);
- /* round 12 */
- SUBL(15) ^= SUBL(1); SUBR(15) ^= SUBR(1);
- SUBL(1) ^= SUBR(1) & ~SUBR(17);
- dw = SUBL(1) & SUBL(17),
- SUBR(1) ^= CAMELLIA_RL1(dw); /* modified for FLinv(kl4) */
- /* round 14 */
- SUBL(19) ^= SUBL(1); SUBR(19) ^= SUBR(1);
- /* round 16 */
- SUBL(21) ^= SUBL(1); SUBR(21) ^= SUBR(1);
- /* round 18 */
- SUBL(23) ^= SUBL(1); SUBR(23) ^= SUBR(1);
- SUBL(1) ^= SUBR(1) & ~SUBR(25);
- dw = SUBL(1) & SUBL(25),
- SUBR(1) ^= CAMELLIA_RL1(dw); /* modified for FLinv(kl6) */
- /* round 20 */
- SUBL(27) ^= SUBL(1); SUBR(27) ^= SUBR(1);
- /* round 22 */
- SUBL(29) ^= SUBL(1); SUBR(29) ^= SUBR(1);
- /* round 24 */
- SUBL(31) ^= SUBL(1); SUBR(31) ^= SUBR(1);
- /* kw3 */
- SUBL(32) ^= SUBL(1); SUBR(32) ^= SUBR(1);
-
-
- /* absorb kw4 to other subkeys */
- kw4l = SUBL(33); kw4r = SUBR(33);
- /* round 23 */
- SUBL(30) ^= kw4l; SUBR(30) ^= kw4r;
- /* round 21 */
- SUBL(28) ^= kw4l; SUBR(28) ^= kw4r;
- /* round 19 */
- SUBL(26) ^= kw4l; SUBR(26) ^= kw4r;
- kw4l ^= kw4r & ~SUBR(24);
- dw = kw4l & SUBL(24),
- kw4r ^= CAMELLIA_RL1(dw); /* modified for FL(kl5) */
- /* round 17 */
- SUBL(22) ^= kw4l; SUBR(22) ^= kw4r;
- /* round 15 */
- SUBL(20) ^= kw4l; SUBR(20) ^= kw4r;
- /* round 13 */
- SUBL(18) ^= kw4l; SUBR(18) ^= kw4r;
- kw4l ^= kw4r & ~SUBR(16);
- dw = kw4l & SUBL(16),
- kw4r ^= CAMELLIA_RL1(dw); /* modified for FL(kl3) */
- /* round 11 */
- SUBL(14) ^= kw4l; SUBR(14) ^= kw4r;
- /* round 9 */
- SUBL(12) ^= kw4l; SUBR(12) ^= kw4r;
- /* round 7 */
- SUBL(10) ^= kw4l; SUBR(10) ^= kw4r;
- kw4l ^= kw4r & ~SUBR(8);
- dw = kw4l & SUBL(8),
- kw4r ^= CAMELLIA_RL1(dw); /* modified for FL(kl1) */
- /* round 5 */
- SUBL(6) ^= kw4l; SUBR(6) ^= kw4r;
- /* round 3 */
- SUBL(4) ^= kw4l; SUBR(4) ^= kw4r;
- /* round 1 */
- SUBL(2) ^= kw4l; SUBR(2) ^= kw4r;
- /* kw1 */
- SUBL(0) ^= kw4l; SUBR(0) ^= kw4r;
-
- /* key XOR is end of F-function */
- CAMELLIA_SUBKEY_L(0) = SUBL(0) ^ SUBL(2);/* kw1 */
- CAMELLIA_SUBKEY_R(0) = SUBR(0) ^ SUBR(2);
- CAMELLIA_SUBKEY_L(2) = SUBL(3); /* round 1 */
- CAMELLIA_SUBKEY_R(2) = SUBR(3);
- CAMELLIA_SUBKEY_L(3) = SUBL(2) ^ SUBL(4); /* round 2 */
- CAMELLIA_SUBKEY_R(3) = SUBR(2) ^ SUBR(4);
- CAMELLIA_SUBKEY_L(4) = SUBL(3) ^ SUBL(5); /* round 3 */
- CAMELLIA_SUBKEY_R(4) = SUBR(3) ^ SUBR(5);
- CAMELLIA_SUBKEY_L(5) = SUBL(4) ^ SUBL(6); /* round 4 */
- CAMELLIA_SUBKEY_R(5) = SUBR(4) ^ SUBR(6);
- CAMELLIA_SUBKEY_L(6) = SUBL(5) ^ SUBL(7); /* round 5 */
- CAMELLIA_SUBKEY_R(6) = SUBR(5) ^ SUBR(7);
- tl = SUBL(10) ^ (SUBR(10) & ~SUBR(8));
- dw = tl & SUBL(8), /* FL(kl1) */
- tr = SUBR(10) ^ CAMELLIA_RL1(dw);
- CAMELLIA_SUBKEY_L(7) = SUBL(6) ^ tl; /* round 6 */
- CAMELLIA_SUBKEY_R(7) = SUBR(6) ^ tr;
- CAMELLIA_SUBKEY_L(8) = SUBL(8); /* FL(kl1) */
- CAMELLIA_SUBKEY_R(8) = SUBR(8);
- CAMELLIA_SUBKEY_L(9) = SUBL(9); /* FLinv(kl2) */
- CAMELLIA_SUBKEY_R(9) = SUBR(9);
- tl = SUBL(7) ^ (SUBR(7) & ~SUBR(9));
- dw = tl & SUBL(9), /* FLinv(kl2) */
- tr = SUBR(7) ^ CAMELLIA_RL1(dw);
- CAMELLIA_SUBKEY_L(10) = tl ^ SUBL(11); /* round 7 */
- CAMELLIA_SUBKEY_R(10) = tr ^ SUBR(11);
- CAMELLIA_SUBKEY_L(11) = SUBL(10) ^ SUBL(12); /* round 8 */
- CAMELLIA_SUBKEY_R(11) = SUBR(10) ^ SUBR(12);
- CAMELLIA_SUBKEY_L(12) = SUBL(11) ^ SUBL(13); /* round 9 */
- CAMELLIA_SUBKEY_R(12) = SUBR(11) ^ SUBR(13);
- CAMELLIA_SUBKEY_L(13) = SUBL(12) ^ SUBL(14); /* round 10 */
- CAMELLIA_SUBKEY_R(13) = SUBR(12) ^ SUBR(14);
- CAMELLIA_SUBKEY_L(14) = SUBL(13) ^ SUBL(15); /* round 11 */
- CAMELLIA_SUBKEY_R(14) = SUBR(13) ^ SUBR(15);
- tl = SUBL(18) ^ (SUBR(18) & ~SUBR(16));
- dw = tl & SUBL(16), /* FL(kl3) */
- tr = SUBR(18) ^ CAMELLIA_RL1(dw);
- CAMELLIA_SUBKEY_L(15) = SUBL(14) ^ tl; /* round 12 */
- CAMELLIA_SUBKEY_R(15) = SUBR(14) ^ tr;
- CAMELLIA_SUBKEY_L(16) = SUBL(16); /* FL(kl3) */
- CAMELLIA_SUBKEY_R(16) = SUBR(16);
- CAMELLIA_SUBKEY_L(17) = SUBL(17); /* FLinv(kl4) */
- CAMELLIA_SUBKEY_R(17) = SUBR(17);
- tl = SUBL(15) ^ (SUBR(15) & ~SUBR(17));
- dw = tl & SUBL(17), /* FLinv(kl4) */
- tr = SUBR(15) ^ CAMELLIA_RL1(dw);
- CAMELLIA_SUBKEY_L(18) = tl ^ SUBL(19); /* round 13 */
- CAMELLIA_SUBKEY_R(18) = tr ^ SUBR(19);
- CAMELLIA_SUBKEY_L(19) = SUBL(18) ^ SUBL(20); /* round 14 */
- CAMELLIA_SUBKEY_R(19) = SUBR(18) ^ SUBR(20);
- CAMELLIA_SUBKEY_L(20) = SUBL(19) ^ SUBL(21); /* round 15 */
- CAMELLIA_SUBKEY_R(20) = SUBR(19) ^ SUBR(21);
- CAMELLIA_SUBKEY_L(21) = SUBL(20) ^ SUBL(22); /* round 16 */
- CAMELLIA_SUBKEY_R(21) = SUBR(20) ^ SUBR(22);
- CAMELLIA_SUBKEY_L(22) = SUBL(21) ^ SUBL(23); /* round 17 */
- CAMELLIA_SUBKEY_R(22) = SUBR(21) ^ SUBR(23);
- tl = SUBL(26) ^ (SUBR(26)
- & ~SUBR(24));
- dw = tl & SUBL(24), /* FL(kl5) */
- tr = SUBR(26) ^ CAMELLIA_RL1(dw);
- CAMELLIA_SUBKEY_L(23) = SUBL(22) ^ tl; /* round 18 */
- CAMELLIA_SUBKEY_R(23) = SUBR(22) ^ tr;
- CAMELLIA_SUBKEY_L(24) = SUBL(24); /* FL(kl5) */
- CAMELLIA_SUBKEY_R(24) = SUBR(24);
- CAMELLIA_SUBKEY_L(25) = SUBL(25); /* FLinv(kl6) */
- CAMELLIA_SUBKEY_R(25) = SUBR(25);
- tl = SUBL(23) ^ (SUBR(23) &
- ~SUBR(25));
- dw = tl & SUBL(25), /* FLinv(kl6) */
- tr = SUBR(23) ^ CAMELLIA_RL1(dw);
- CAMELLIA_SUBKEY_L(26) = tl ^ SUBL(27); /* round 19 */
- CAMELLIA_SUBKEY_R(26) = tr ^ SUBR(27);
- CAMELLIA_SUBKEY_L(27) = SUBL(26) ^ SUBL(28); /* round 20 */
- CAMELLIA_SUBKEY_R(27) = SUBR(26) ^ SUBR(28);
- CAMELLIA_SUBKEY_L(28) = SUBL(27) ^ SUBL(29); /* round 21 */
- CAMELLIA_SUBKEY_R(28) = SUBR(27) ^ SUBR(29);
- CAMELLIA_SUBKEY_L(29) = SUBL(28) ^ SUBL(30); /* round 22 */
- CAMELLIA_SUBKEY_R(29) = SUBR(28) ^ SUBR(30);
- CAMELLIA_SUBKEY_L(30) = SUBL(29) ^ SUBL(31); /* round 23 */
- CAMELLIA_SUBKEY_R(30) = SUBR(29) ^ SUBR(31);
- CAMELLIA_SUBKEY_L(31) = SUBL(30); /* round 24 */
- CAMELLIA_SUBKEY_R(31) = SUBR(30);
- CAMELLIA_SUBKEY_L(32) = SUBL(32) ^ SUBL(31); /* kw3 */
- CAMELLIA_SUBKEY_R(32) = SUBR(32) ^ SUBR(31);
-
- /* apply the inverse of the last half of P-function */
- dw = CAMELLIA_SUBKEY_L(2) ^ CAMELLIA_SUBKEY_R(2),
- dw = CAMELLIA_RL8(dw);/* round 1 */
- CAMELLIA_SUBKEY_R(2) = CAMELLIA_SUBKEY_L(2) ^ dw,
- CAMELLIA_SUBKEY_L(2) = dw;
- dw = CAMELLIA_SUBKEY_L(3) ^ CAMELLIA_SUBKEY_R(3),
- dw = CAMELLIA_RL8(dw);/* round 2 */
- CAMELLIA_SUBKEY_R(3) = CAMELLIA_SUBKEY_L(3) ^ dw,
- CAMELLIA_SUBKEY_L(3) = dw;
- dw = CAMELLIA_SUBKEY_L(4) ^ CAMELLIA_SUBKEY_R(4),
- dw = CAMELLIA_RL8(dw);/* round 3 */
- CAMELLIA_SUBKEY_R(4) = CAMELLIA_SUBKEY_L(4) ^ dw,
- CAMELLIA_SUBKEY_L(4) = dw;
- dw = CAMELLIA_SUBKEY_L(5) ^ CAMELLIA_SUBKEY_R(5),
- dw = CAMELLIA_RL8(dw);/* round 4 */
- CAMELLIA_SUBKEY_R(5) = CAMELLIA_SUBKEY_L(5) ^ dw,
- CAMELLIA_SUBKEY_L(5) = dw;
- dw = CAMELLIA_SUBKEY_L(6) ^ CAMELLIA_SUBKEY_R(6),
- dw = CAMELLIA_RL8(dw);/* round 5 */
- CAMELLIA_SUBKEY_R(6) = CAMELLIA_SUBKEY_L(6) ^ dw,
- CAMELLIA_SUBKEY_L(6) = dw;
- dw = CAMELLIA_SUBKEY_L(7) ^ CAMELLIA_SUBKEY_R(7),
- dw = CAMELLIA_RL8(dw);/* round 6 */
- CAMELLIA_SUBKEY_R(7) = CAMELLIA_SUBKEY_L(7) ^ dw,
- CAMELLIA_SUBKEY_L(7) = dw;
- dw = CAMELLIA_SUBKEY_L(10) ^ CAMELLIA_SUBKEY_R(10),
- dw = CAMELLIA_RL8(dw);/* round 7 */
- CAMELLIA_SUBKEY_R(10) = CAMELLIA_SUBKEY_L(10) ^ dw,
- CAMELLIA_SUBKEY_L(10) = dw;
- dw = CAMELLIA_SUBKEY_L(11) ^ CAMELLIA_SUBKEY_R(11),
- dw = CAMELLIA_RL8(dw);/* round 8 */
- CAMELLIA_SUBKEY_R(11) = CAMELLIA_SUBKEY_L(11) ^ dw,
- CAMELLIA_SUBKEY_L(11) = dw;
- dw = CAMELLIA_SUBKEY_L(12) ^ CAMELLIA_SUBKEY_R(12),
- dw = CAMELLIA_RL8(dw);/* round 9 */
- CAMELLIA_SUBKEY_R(12) = CAMELLIA_SUBKEY_L(12) ^ dw,
- CAMELLIA_SUBKEY_L(12) = dw;
- dw = CAMELLIA_SUBKEY_L(13) ^ CAMELLIA_SUBKEY_R(13),
- dw = CAMELLIA_RL8(dw);/* round 10 */
- CAMELLIA_SUBKEY_R(13) = CAMELLIA_SUBKEY_L(13) ^ dw,
- CAMELLIA_SUBKEY_L(13) = dw;
- dw = CAMELLIA_SUBKEY_L(14) ^ CAMELLIA_SUBKEY_R(14),
- dw = CAMELLIA_RL8(dw);/* round 11 */
- CAMELLIA_SUBKEY_R(14) = CAMELLIA_SUBKEY_L(14) ^ dw,
- CAMELLIA_SUBKEY_L(14) = dw;
- dw = CAMELLIA_SUBKEY_L(15) ^ CAMELLIA_SUBKEY_R(15),
- dw = CAMELLIA_RL8(dw);/* round 12 */
- CAMELLIA_SUBKEY_R(15) = CAMELLIA_SUBKEY_L(15) ^ dw,
- CAMELLIA_SUBKEY_L(15) = dw;
- dw = CAMELLIA_SUBKEY_L(18) ^ CAMELLIA_SUBKEY_R(18),
- dw = CAMELLIA_RL8(dw);/* round 13 */
- CAMELLIA_SUBKEY_R(18) = CAMELLIA_SUBKEY_L(18) ^ dw,
- CAMELLIA_SUBKEY_L(18) = dw;
- dw = CAMELLIA_SUBKEY_L(19) ^ CAMELLIA_SUBKEY_R(19),
- dw = CAMELLIA_RL8(dw);/* round 14 */
- CAMELLIA_SUBKEY_R(19) = CAMELLIA_SUBKEY_L(19) ^ dw,
- CAMELLIA_SUBKEY_L(19) = dw;
- dw = CAMELLIA_SUBKEY_L(20) ^ CAMELLIA_SUBKEY_R(20),
- dw = CAMELLIA_RL8(dw);/* round 15 */
- CAMELLIA_SUBKEY_R(20) = CAMELLIA_SUBKEY_L(20) ^ dw,
- CAMELLIA_SUBKEY_L(20) = dw;
- dw = CAMELLIA_SUBKEY_L(21) ^ CAMELLIA_SUBKEY_R(21),
- dw = CAMELLIA_RL8(dw);/* round 16 */
- CAMELLIA_SUBKEY_R(21) = CAMELLIA_SUBKEY_L(21) ^ dw,
- CAMELLIA_SUBKEY_L(21) = dw;
- dw = CAMELLIA_SUBKEY_L(22) ^ CAMELLIA_SUBKEY_R(22),
- dw = CAMELLIA_RL8(dw);/* round 17 */
- CAMELLIA_SUBKEY_R(22) = CAMELLIA_SUBKEY_L(22) ^ dw,
- CAMELLIA_SUBKEY_L(22) = dw;
- dw = CAMELLIA_SUBKEY_L(23) ^ CAMELLIA_SUBKEY_R(23),
- dw = CAMELLIA_RL8(dw);/* round 18 */
- CAMELLIA_SUBKEY_R(23) = CAMELLIA_SUBKEY_L(23) ^ dw,
- CAMELLIA_SUBKEY_L(23) = dw;
- dw = CAMELLIA_SUBKEY_L(26) ^ CAMELLIA_SUBKEY_R(26),
- dw = CAMELLIA_RL8(dw);/* round 19 */
- CAMELLIA_SUBKEY_R(26) = CAMELLIA_SUBKEY_L(26) ^ dw,
- CAMELLIA_SUBKEY_L(26) = dw;
- dw = CAMELLIA_SUBKEY_L(27) ^ CAMELLIA_SUBKEY_R(27),
- dw = CAMELLIA_RL8(dw);/* round 20 */
- CAMELLIA_SUBKEY_R(27) = CAMELLIA_SUBKEY_L(27) ^ dw,
- CAMELLIA_SUBKEY_L(27) = dw;
- dw = CAMELLIA_SUBKEY_L(28) ^ CAMELLIA_SUBKEY_R(28),
- dw = CAMELLIA_RL8(dw);/* round 21 */
- CAMELLIA_SUBKEY_R(28) = CAMELLIA_SUBKEY_L(28) ^ dw,
- CAMELLIA_SUBKEY_L(28) = dw;
- dw = CAMELLIA_SUBKEY_L(29) ^ CAMELLIA_SUBKEY_R(29),
- dw = CAMELLIA_RL8(dw);/* round 22 */
- CAMELLIA_SUBKEY_R(29) = CAMELLIA_SUBKEY_L(29) ^ dw,
- CAMELLIA_SUBKEY_L(29) = dw;
- dw = CAMELLIA_SUBKEY_L(30) ^ CAMELLIA_SUBKEY_R(30),
- dw = CAMELLIA_RL8(dw);/* round 23 */
- CAMELLIA_SUBKEY_R(30) = CAMELLIA_SUBKEY_L(30) ^ dw,
- CAMELLIA_SUBKEY_L(30) = dw;
- dw = CAMELLIA_SUBKEY_L(31) ^ CAMELLIA_SUBKEY_R(31),
- dw = CAMELLIA_RL8(dw);/* round 24 */
- CAMELLIA_SUBKEY_R(31) = CAMELLIA_SUBKEY_L(31) ^ dw,
- CAMELLIA_SUBKEY_L(31) = dw;
-
- return;
+ camellia_setup_tail(subkey, subL, subR, 32);
}
static void camellia_setup192(const unsigned char *key, u32 *subkey)
@@ -1197,481 +850,167 @@
u32 krll, krlr, krrl,krrr;
memcpy(kk, key, 24);
- memcpy((unsigned char *)&krll, key+16,4);
- memcpy((unsigned char *)&krlr, key+20,4);
+ memcpy((unsigned char *)&krll, key+16, 4);
+ memcpy((unsigned char *)&krlr, key+20, 4);
krrl = ~krll;
krrr = ~krlr;
memcpy(kk+24, (unsigned char *)&krrl, 4);
memcpy(kk+28, (unsigned char *)&krrr, 4);
camellia_setup256(kk, subkey);
- return;
}
-/**
- * Stuff related to camellia encryption/decryption
+/*
+ * Encrypt/decrypt
*/
-static void camellia_encrypt128(const u32 *subkey, __be32 *io_text)
+#define CAMELLIA_FLS(ll, lr, rl, rr, kll, klr, krl, krr, t0, t1, t2, t3) \
+ do { \
+ t0 = kll; \
+ t2 = krr; \
+ t0 &= ll; \
+ t2 |= rr; \
+ rl ^= t2; \
+ lr ^= ROL1(t0); \
+ t3 = krl; \
+ t1 = klr; \
+ t3 &= rl; \
+ t1 |= lr; \
+ ll ^= t1; \
+ rr ^= ROL1(t3); \
+ } while(0)
+
+#define CAMELLIA_ROUNDSM(xl, xr, kl, kr, yl, yr, il, ir) \
+ do { \
+ ir = camellia_sp1110[(u8)xr]; \
+ il = camellia_sp1110[ (xl >> 24)]; \
+ ir ^= camellia_sp0222[ (xr >> 24)]; \
+ il ^= camellia_sp0222[(u8)(xl >> 16)]; \
+ ir ^= camellia_sp3033[(u8)(xr >> 16)]; \
+ il ^= camellia_sp3033[(u8)(xl >> 8)]; \
+ ir ^= camellia_sp4404[(u8)(xr >> 8)]; \
+ il ^= camellia_sp4404[(u8)xl]; \
+ il ^= kl; \
+ ir ^= il ^ kr; \
+ yl ^= ir; \
+ yr ^= ROR8(il) ^ ir; \
+ } while(0)
+
+/* max = 24: 128bit encrypt, max = 32: 256bit encrypt */
+static void camellia_do_encrypt(const u32 *subkey, u32 *io, unsigned max)
{
- u32 il,ir,t0,t1; /* temporary valiables */
+ u32 il,ir,t0,t1; /* temporary variables */
- u32 io[4];
+ /* pre whitening but absorb kw2 */
+ io[0] ^= SUBKEY_L(0);
+ io[1] ^= SUBKEY_R(0);
- io[0] = be32_to_cpu(io_text[0]);
- io[1] = be32_to_cpu(io_text[1]);
- io[2] = be32_to_cpu(io_text[2]);
- io[3] = be32_to_cpu(io_text[3]);
-
- /* pre whitening but absorb kw2*/
- io[0] ^= CAMELLIA_SUBKEY_L(0);
- io[1] ^= CAMELLIA_SUBKEY_R(0);
/* main iteration */
+#define ROUNDS(i) do { \
+ CAMELLIA_ROUNDSM(io[0],io[1], \
+ SUBKEY_L(i + 2),SUBKEY_R(i + 2), \
+ io[2],io[3],il,ir); \
+ CAMELLIA_ROUNDSM(io[2],io[3], \
+ SUBKEY_L(i + 3),SUBKEY_R(i + 3), \
+ io[0],io[1],il,ir); \
+ CAMELLIA_ROUNDSM(io[0],io[1], \
+ SUBKEY_L(i + 4),SUBKEY_R(i + 4), \
+ io[2],io[3],il,ir); \
+ CAMELLIA_ROUNDSM(io[2],io[3], \
+ SUBKEY_L(i + 5),SUBKEY_R(i + 5), \
+ io[0],io[1],il,ir); \
+ CAMELLIA_ROUNDSM(io[0],io[1], \
+ SUBKEY_L(i + 6),SUBKEY_R(i + 6), \
+ io[2],io[3],il,ir); \
+ CAMELLIA_ROUNDSM(io[2],io[3], \
+ SUBKEY_L(i + 7),SUBKEY_R(i + 7), \
+ io[0],io[1],il,ir); \
+} while (0)
+#define FLS(i) do { \
+ CAMELLIA_FLS(io[0],io[1],io[2],io[3], \
+ SUBKEY_L(i + 0),SUBKEY_R(i + 0), \
+ SUBKEY_L(i + 1),SUBKEY_R(i + 1), \
+ t0,t1,il,ir); \
+} while (0)
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(2),CAMELLIA_SUBKEY_R(2),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(3),CAMELLIA_SUBKEY_R(3),
- io[0],io[1],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(4),CAMELLIA_SUBKEY_R(4),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(5),CAMELLIA_SUBKEY_R(5),
- io[0],io[1],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(6),CAMELLIA_SUBKEY_R(6),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(7),CAMELLIA_SUBKEY_R(7),
- io[0],io[1],il,ir,t0,t1);
+ ROUNDS(0);
+ FLS(8);
+ ROUNDS(8);
+ FLS(16);
+ ROUNDS(16);
+ if (max == 32) {
+ FLS(24);
+ ROUNDS(24);
+ }
- CAMELLIA_FLS(io[0],io[1],io[2],io[3],
- CAMELLIA_SUBKEY_L(8),CAMELLIA_SUBKEY_R(8),
- CAMELLIA_SUBKEY_L(9),CAMELLIA_SUBKEY_R(9),
- t0,t1,il,ir);
-
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(10),CAMELLIA_SUBKEY_R(10),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(11),CAMELLIA_SUBKEY_R(11),
- io[0],io[1],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(12),CAMELLIA_SUBKEY_R(12),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(13),CAMELLIA_SUBKEY_R(13),
- io[0],io[1],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(14),CAMELLIA_SUBKEY_R(14),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(15),CAMELLIA_SUBKEY_R(15),
- io[0],io[1],il,ir,t0,t1);
-
- CAMELLIA_FLS(io[0],io[1],io[2],io[3],
- CAMELLIA_SUBKEY_L(16),CAMELLIA_SUBKEY_R(16),
- CAMELLIA_SUBKEY_L(17),CAMELLIA_SUBKEY_R(17),
- t0,t1,il,ir);
-
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(18),CAMELLIA_SUBKEY_R(18),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(19),CAMELLIA_SUBKEY_R(19),
- io[0],io[1],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(20),CAMELLIA_SUBKEY_R(20),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(21),CAMELLIA_SUBKEY_R(21),
- io[0],io[1],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(22),CAMELLIA_SUBKEY_R(22),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(23),CAMELLIA_SUBKEY_R(23),
- io[0],io[1],il,ir,t0,t1);
+#undef ROUNDS
+#undef FLS
/* post whitening but kw4 */
- io[2] ^= CAMELLIA_SUBKEY_L(24);
- io[3] ^= CAMELLIA_SUBKEY_R(24);
-
- t0 = io[0];
- t1 = io[1];
- io[0] = io[2];
- io[1] = io[3];
- io[2] = t0;
- io[3] = t1;
-
- io_text[0] = cpu_to_be32(io[0]);
- io_text[1] = cpu_to_be32(io[1]);
- io_text[2] = cpu_to_be32(io[2]);
- io_text[3] = cpu_to_be32(io[3]);
-
- return;
+ io[2] ^= SUBKEY_L(max);
+ io[3] ^= SUBKEY_R(max);
+ /* NB: io[0],[1] should be swapped with [2],[3] by caller! */
}
-static void camellia_decrypt128(const u32 *subkey, __be32 *io_text)
+static void camellia_do_decrypt(const u32 *subkey, u32 *io, unsigned i)
{
- u32 il,ir,t0,t1; /* temporary valiables */
+ u32 il,ir,t0,t1; /* temporary variables */
- u32 io[4];
-
- io[0] = be32_to_cpu(io_text[0]);
- io[1] = be32_to_cpu(io_text[1]);
- io[2] = be32_to_cpu(io_text[2]);
- io[3] = be32_to_cpu(io_text[3]);
-
- /* pre whitening but absorb kw2*/
- io[0] ^= CAMELLIA_SUBKEY_L(24);
- io[1] ^= CAMELLIA_SUBKEY_R(24);
+ /* pre whitening but absorb kw2 */
+ io[0] ^= SUBKEY_L(i);
+ io[1] ^= SUBKEY_R(i);
/* main iteration */
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(23),CAMELLIA_SUBKEY_R(23),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(22),CAMELLIA_SUBKEY_R(22),
- io[0],io[1],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(21),CAMELLIA_SUBKEY_R(21),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(20),CAMELLIA_SUBKEY_R(20),
- io[0],io[1],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(19),CAMELLIA_SUBKEY_R(19),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(18),CAMELLIA_SUBKEY_R(18),
- io[0],io[1],il,ir,t0,t1);
+#define ROUNDS(i) do { \
+ CAMELLIA_ROUNDSM(io[0],io[1], \
+ SUBKEY_L(i + 7),SUBKEY_R(i + 7), \
+ io[2],io[3],il,ir); \
+ CAMELLIA_ROUNDSM(io[2],io[3], \
+ SUBKEY_L(i + 6),SUBKEY_R(i + 6), \
+ io[0],io[1],il,ir); \
+ CAMELLIA_ROUNDSM(io[0],io[1], \
+ SUBKEY_L(i + 5),SUBKEY_R(i + 5), \
+ io[2],io[3],il,ir); \
+ CAMELLIA_ROUNDSM(io[2],io[3], \
+ SUBKEY_L(i + 4),SUBKEY_R(i + 4), \
+ io[0],io[1],il,ir); \
+ CAMELLIA_ROUNDSM(io[0],io[1], \
+ SUBKEY_L(i + 3),SUBKEY_R(i + 3), \
+ io[2],io[3],il,ir); \
+ CAMELLIA_ROUNDSM(io[2],io[3], \
+ SUBKEY_L(i + 2),SUBKEY_R(i + 2), \
+ io[0],io[1],il,ir); \
+} while (0)
+#define FLS(i) do { \
+ CAMELLIA_FLS(io[0],io[1],io[2],io[3], \
+ SUBKEY_L(i + 1),SUBKEY_R(i + 1), \
+ SUBKEY_L(i + 0),SUBKEY_R(i + 0), \
+ t0,t1,il,ir); \
+} while (0)
- CAMELLIA_FLS(io[0],io[1],io[2],io[3],
- CAMELLIA_SUBKEY_L(17),CAMELLIA_SUBKEY_R(17),
- CAMELLIA_SUBKEY_L(16),CAMELLIA_SUBKEY_R(16),
- t0,t1,il,ir);
+ if (i == 32) {
+ ROUNDS(24);
+ FLS(24);
+ }
+ ROUNDS(16);
+ FLS(16);
+ ROUNDS(8);
+ FLS(8);
+ ROUNDS(0);
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(15),CAMELLIA_SUBKEY_R(15),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(14),CAMELLIA_SUBKEY_R(14),
- io[0],io[1],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(13),CAMELLIA_SUBKEY_R(13),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(12),CAMELLIA_SUBKEY_R(12),
- io[0],io[1],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(11),CAMELLIA_SUBKEY_R(11),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(10),CAMELLIA_SUBKEY_R(10),
- io[0],io[1],il,ir,t0,t1);
-
- CAMELLIA_FLS(io[0],io[1],io[2],io[3],
- CAMELLIA_SUBKEY_L(9),CAMELLIA_SUBKEY_R(9),
- CAMELLIA_SUBKEY_L(8),CAMELLIA_SUBKEY_R(8),
- t0,t1,il,ir);
-
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(7),CAMELLIA_SUBKEY_R(7),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(6),CAMELLIA_SUBKEY_R(6),
- io[0],io[1],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(5),CAMELLIA_SUBKEY_R(5),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(4),CAMELLIA_SUBKEY_R(4),
- io[0],io[1],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(3),CAMELLIA_SUBKEY_R(3),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(2),CAMELLIA_SUBKEY_R(2),
- io[0],io[1],il,ir,t0,t1);
+#undef ROUNDS
+#undef FLS
/* post whitening but kw4 */
- io[2] ^= CAMELLIA_SUBKEY_L(0);
- io[3] ^= CAMELLIA_SUBKEY_R(0);
-
- t0 = io[0];
- t1 = io[1];
- io[0] = io[2];
- io[1] = io[3];
- io[2] = t0;
- io[3] = t1;
-
- io_text[0] = cpu_to_be32(io[0]);
- io_text[1] = cpu_to_be32(io[1]);
- io_text[2] = cpu_to_be32(io[2]);
- io_text[3] = cpu_to_be32(io[3]);
-
- return;
+ io[2] ^= SUBKEY_L(0);
+ io[3] ^= SUBKEY_R(0);
+ /* NB: 0,1 should be swapped with 2,3 by caller! */
}
-/**
- * stuff for 192 and 256bit encryption/decryption
- */
-static void camellia_encrypt256(const u32 *subkey, __be32 *io_text)
-{
- u32 il,ir,t0,t1; /* temporary valiables */
-
- u32 io[4];
-
- io[0] = be32_to_cpu(io_text[0]);
- io[1] = be32_to_cpu(io_text[1]);
- io[2] = be32_to_cpu(io_text[2]);
- io[3] = be32_to_cpu(io_text[3]);
-
- /* pre whitening but absorb kw2*/
- io[0] ^= CAMELLIA_SUBKEY_L(0);
- io[1] ^= CAMELLIA_SUBKEY_R(0);
-
- /* main iteration */
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(2),CAMELLIA_SUBKEY_R(2),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(3),CAMELLIA_SUBKEY_R(3),
- io[0],io[1],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(4),CAMELLIA_SUBKEY_R(4),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(5),CAMELLIA_SUBKEY_R(5),
- io[0],io[1],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(6),CAMELLIA_SUBKEY_R(6),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(7),CAMELLIA_SUBKEY_R(7),
- io[0],io[1],il,ir,t0,t1);
-
- CAMELLIA_FLS(io[0],io[1],io[2],io[3],
- CAMELLIA_SUBKEY_L(8),CAMELLIA_SUBKEY_R(8),
- CAMELLIA_SUBKEY_L(9),CAMELLIA_SUBKEY_R(9),
- t0,t1,il,ir);
-
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(10),CAMELLIA_SUBKEY_R(10),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(11),CAMELLIA_SUBKEY_R(11),
- io[0],io[1],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(12),CAMELLIA_SUBKEY_R(12),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(13),CAMELLIA_SUBKEY_R(13),
- io[0],io[1],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(14),CAMELLIA_SUBKEY_R(14),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(15),CAMELLIA_SUBKEY_R(15),
- io[0],io[1],il,ir,t0,t1);
-
- CAMELLIA_FLS(io[0],io[1],io[2],io[3],
- CAMELLIA_SUBKEY_L(16),CAMELLIA_SUBKEY_R(16),
- CAMELLIA_SUBKEY_L(17),CAMELLIA_SUBKEY_R(17),
- t0,t1,il,ir);
-
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(18),CAMELLIA_SUBKEY_R(18),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(19),CAMELLIA_SUBKEY_R(19),
- io[0],io[1],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(20),CAMELLIA_SUBKEY_R(20),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(21),CAMELLIA_SUBKEY_R(21),
- io[0],io[1],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(22),CAMELLIA_SUBKEY_R(22),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(23),CAMELLIA_SUBKEY_R(23),
- io[0],io[1],il,ir,t0,t1);
-
- CAMELLIA_FLS(io[0],io[1],io[2],io[3],
- CAMELLIA_SUBKEY_L(24),CAMELLIA_SUBKEY_R(24),
- CAMELLIA_SUBKEY_L(25),CAMELLIA_SUBKEY_R(25),
- t0,t1,il,ir);
-
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(26),CAMELLIA_SUBKEY_R(26),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(27),CAMELLIA_SUBKEY_R(27),
- io[0],io[1],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(28),CAMELLIA_SUBKEY_R(28),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(29),CAMELLIA_SUBKEY_R(29),
- io[0],io[1],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(30),CAMELLIA_SUBKEY_R(30),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(31),CAMELLIA_SUBKEY_R(31),
- io[0],io[1],il,ir,t0,t1);
-
- /* post whitening but kw4 */
- io[2] ^= CAMELLIA_SUBKEY_L(32);
- io[3] ^= CAMELLIA_SUBKEY_R(32);
-
- t0 = io[0];
- t1 = io[1];
- io[0] = io[2];
- io[1] = io[3];
- io[2] = t0;
- io[3] = t1;
-
- io_text[0] = cpu_to_be32(io[0]);
- io_text[1] = cpu_to_be32(io[1]);
- io_text[2] = cpu_to_be32(io[2]);
- io_text[3] = cpu_to_be32(io[3]);
-
- return;
-}
-
-
-static void camellia_decrypt256(const u32 *subkey, __be32 *io_text)
-{
- u32 il,ir,t0,t1; /* temporary valiables */
-
- u32 io[4];
-
- io[0] = be32_to_cpu(io_text[0]);
- io[1] = be32_to_cpu(io_text[1]);
- io[2] = be32_to_cpu(io_text[2]);
- io[3] = be32_to_cpu(io_text[3]);
-
- /* pre whitening but absorb kw2*/
- io[0] ^= CAMELLIA_SUBKEY_L(32);
- io[1] ^= CAMELLIA_SUBKEY_R(32);
-
- /* main iteration */
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(31),CAMELLIA_SUBKEY_R(31),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(30),CAMELLIA_SUBKEY_R(30),
- io[0],io[1],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(29),CAMELLIA_SUBKEY_R(29),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(28),CAMELLIA_SUBKEY_R(28),
- io[0],io[1],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(27),CAMELLIA_SUBKEY_R(27),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(26),CAMELLIA_SUBKEY_R(26),
- io[0],io[1],il,ir,t0,t1);
-
- CAMELLIA_FLS(io[0],io[1],io[2],io[3],
- CAMELLIA_SUBKEY_L(25),CAMELLIA_SUBKEY_R(25),
- CAMELLIA_SUBKEY_L(24),CAMELLIA_SUBKEY_R(24),
- t0,t1,il,ir);
-
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(23),CAMELLIA_SUBKEY_R(23),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(22),CAMELLIA_SUBKEY_R(22),
- io[0],io[1],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(21),CAMELLIA_SUBKEY_R(21),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(20),CAMELLIA_SUBKEY_R(20),
- io[0],io[1],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(19),CAMELLIA_SUBKEY_R(19),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(18),CAMELLIA_SUBKEY_R(18),
- io[0],io[1],il,ir,t0,t1);
-
- CAMELLIA_FLS(io[0],io[1],io[2],io[3],
- CAMELLIA_SUBKEY_L(17),CAMELLIA_SUBKEY_R(17),
- CAMELLIA_SUBKEY_L(16),CAMELLIA_SUBKEY_R(16),
- t0,t1,il,ir);
-
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(15),CAMELLIA_SUBKEY_R(15),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(14),CAMELLIA_SUBKEY_R(14),
- io[0],io[1],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(13),CAMELLIA_SUBKEY_R(13),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(12),CAMELLIA_SUBKEY_R(12),
- io[0],io[1],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(11),CAMELLIA_SUBKEY_R(11),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(10),CAMELLIA_SUBKEY_R(10),
- io[0],io[1],il,ir,t0,t1);
-
- CAMELLIA_FLS(io[0],io[1],io[2],io[3],
- CAMELLIA_SUBKEY_L(9),CAMELLIA_SUBKEY_R(9),
- CAMELLIA_SUBKEY_L(8),CAMELLIA_SUBKEY_R(8),
- t0,t1,il,ir);
-
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(7),CAMELLIA_SUBKEY_R(7),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(6),CAMELLIA_SUBKEY_R(6),
- io[0],io[1],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(5),CAMELLIA_SUBKEY_R(5),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(4),CAMELLIA_SUBKEY_R(4),
- io[0],io[1],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[0],io[1],
- CAMELLIA_SUBKEY_L(3),CAMELLIA_SUBKEY_R(3),
- io[2],io[3],il,ir,t0,t1);
- CAMELLIA_ROUNDSM(io[2],io[3],
- CAMELLIA_SUBKEY_L(2),CAMELLIA_SUBKEY_R(2),
- io[0],io[1],il,ir,t0,t1);
-
- /* post whitening but kw4 */
- io[2] ^= CAMELLIA_SUBKEY_L(0);
- io[3] ^= CAMELLIA_SUBKEY_R(0);
-
- t0 = io[0];
- t1 = io[1];
- io[0] = io[2];
- io[1] = io[3];
- io[2] = t0;
- io[3] = t1;
-
- io_text[0] = cpu_to_be32(io[0]);
- io_text[1] = cpu_to_be32(io[1]);
- io_text[2] = cpu_to_be32(io[2]);
- io_text[3] = cpu_to_be32(io[3]);
-
- return;
-}
-
+struct camellia_ctx {
+ int key_length;
+ u32 key_table[CAMELLIA_TABLE_BYTE_LEN / sizeof(u32)];
+};
static int
camellia_set_key(struct crypto_tfm *tfm, const u8 *in_key,
@@ -1688,7 +1027,7 @@
cctx->key_length = key_len;
- switch(key_len) {
+ switch (key_len) {
case 16:
camellia_setup128(key, cctx->key_table);
break;
@@ -1698,68 +1037,59 @@
case 32:
camellia_setup256(key, cctx->key_table);
break;
- default:
- break;
}
return 0;
}
-
static void camellia_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
{
const struct camellia_ctx *cctx = crypto_tfm_ctx(tfm);
const __be32 *src = (const __be32 *)in;
__be32 *dst = (__be32 *)out;
- __be32 tmp[4];
+ u32 tmp[4];
- memcpy(tmp, src, CAMELLIA_BLOCK_SIZE);
+ tmp[0] = be32_to_cpu(src[0]);
+ tmp[1] = be32_to_cpu(src[1]);
+ tmp[2] = be32_to_cpu(src[2]);
+ tmp[3] = be32_to_cpu(src[3]);
- switch (cctx->key_length) {
- case 16:
- camellia_encrypt128(cctx->key_table, tmp);
- break;
- case 24:
- /* fall through */
- case 32:
- camellia_encrypt256(cctx->key_table, tmp);
- break;
- default:
- break;
- }
+ camellia_do_encrypt(cctx->key_table, tmp,
+ cctx->key_length == 16 ? 24 : 32 /* for key lengths of 24 and 32 */
+ );
- memcpy(dst, tmp, CAMELLIA_BLOCK_SIZE);
+ /* do_encrypt returns 0,1 swapped with 2,3 */
+ dst[0] = cpu_to_be32(tmp[2]);
+ dst[1] = cpu_to_be32(tmp[3]);
+ dst[2] = cpu_to_be32(tmp[0]);
+ dst[3] = cpu_to_be32(tmp[1]);
}
-
static void camellia_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
{
const struct camellia_ctx *cctx = crypto_tfm_ctx(tfm);
const __be32 *src = (const __be32 *)in;
__be32 *dst = (__be32 *)out;
- __be32 tmp[4];
+ u32 tmp[4];
- memcpy(tmp, src, CAMELLIA_BLOCK_SIZE);
+ tmp[0] = be32_to_cpu(src[0]);
+ tmp[1] = be32_to_cpu(src[1]);
+ tmp[2] = be32_to_cpu(src[2]);
+ tmp[3] = be32_to_cpu(src[3]);
- switch (cctx->key_length) {
- case 16:
- camellia_decrypt128(cctx->key_table, tmp);
- break;
- case 24:
- /* fall through */
- case 32:
- camellia_decrypt256(cctx->key_table, tmp);
- break;
- default:
- break;
- }
+ camellia_do_decrypt(cctx->key_table, tmp,
+ cctx->key_length == 16 ? 24 : 32 /* for key lengths of 24 and 32 */
+ );
- memcpy(dst, tmp, CAMELLIA_BLOCK_SIZE);
+ /* do_decrypt returns 0,1 swapped with 2,3 */
+ dst[0] = cpu_to_be32(tmp[2]);
+ dst[1] = cpu_to_be32(tmp[3]);
+ dst[2] = cpu_to_be32(tmp[0]);
+ dst[3] = cpu_to_be32(tmp[1]);
}
-
static struct crypto_alg camellia_alg = {
.cra_name = "camellia",
.cra_driver_name = "camellia-generic",
@@ -1786,16 +1116,13 @@
return crypto_register_alg(&camellia_alg);
}
-
static void __exit camellia_fini(void)
{
crypto_unregister_alg(&camellia_alg);
}
-
module_init(camellia_init);
module_exit(camellia_fini);
-
MODULE_DESCRIPTION("Camellia Cipher Algorithm");
MODULE_LICENSE("GPL");
diff --git a/crypto/cast6.c b/crypto/cast6.c
index 136ab6d..5fd9420 100644
--- a/crypto/cast6.c
+++ b/crypto/cast6.c
@@ -369,7 +369,7 @@
};
/* forward octave */
-static inline void W(u32 *key, unsigned int i) {
+static void W(u32 *key, unsigned int i) {
u32 I;
key[6] ^= F1(key[7], Tr[i % 4][0], Tm[i][0]);
key[5] ^= F2(key[6], Tr[i % 4][1], Tm[i][1]);
@@ -428,7 +428,7 @@
}
/*forward quad round*/
-static inline void Q (u32 * block, u8 * Kr, u32 * Km) {
+static void Q (u32 * block, u8 * Kr, u32 * Km) {
u32 I;
block[2] ^= F1(block[3], Kr[0], Km[0]);
block[1] ^= F2(block[2], Kr[1], Km[1]);
@@ -437,7 +437,7 @@
}
/*reverse quad round*/
-static inline void QBAR (u32 * block, u8 * Kr, u32 * Km) {
+static void QBAR (u32 * block, u8 * Kr, u32 * Km) {
u32 I;
block[3] ^= F1(block[0], Kr[3], Km[3]);
block[0] ^= F3(block[1], Kr[2], Km[2]);
diff --git a/crypto/cbc.c b/crypto/cbc.c
index 1f2649e..6affff8 100644
--- a/crypto/cbc.c
+++ b/crypto/cbc.c
@@ -14,13 +14,13 @@
#include <linux/err.h>
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/log2.h>
#include <linux/module.h>
#include <linux/scatterlist.h>
#include <linux/slab.h>
struct crypto_cbc_ctx {
struct crypto_cipher *child;
- void (*xor)(u8 *dst, const u8 *src, unsigned int bs);
};
static int crypto_cbc_setkey(struct crypto_tfm *parent, const u8 *key,
@@ -41,9 +41,7 @@
static int crypto_cbc_encrypt_segment(struct blkcipher_desc *desc,
struct blkcipher_walk *walk,
- struct crypto_cipher *tfm,
- void (*xor)(u8 *, const u8 *,
- unsigned int))
+ struct crypto_cipher *tfm)
{
void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
crypto_cipher_alg(tfm)->cia_encrypt;
@@ -54,7 +52,7 @@
u8 *iv = walk->iv;
do {
- xor(iv, src, bsize);
+ crypto_xor(iv, src, bsize);
fn(crypto_cipher_tfm(tfm), dst, iv);
memcpy(iv, dst, bsize);
@@ -67,9 +65,7 @@
static int crypto_cbc_encrypt_inplace(struct blkcipher_desc *desc,
struct blkcipher_walk *walk,
- struct crypto_cipher *tfm,
- void (*xor)(u8 *, const u8 *,
- unsigned int))
+ struct crypto_cipher *tfm)
{
void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
crypto_cipher_alg(tfm)->cia_encrypt;
@@ -79,7 +75,7 @@
u8 *iv = walk->iv;
do {
- xor(src, iv, bsize);
+ crypto_xor(src, iv, bsize);
fn(crypto_cipher_tfm(tfm), src, src);
iv = src;
@@ -99,7 +95,6 @@
struct crypto_blkcipher *tfm = desc->tfm;
struct crypto_cbc_ctx *ctx = crypto_blkcipher_ctx(tfm);
struct crypto_cipher *child = ctx->child;
- void (*xor)(u8 *, const u8 *, unsigned int bs) = ctx->xor;
int err;
blkcipher_walk_init(&walk, dst, src, nbytes);
@@ -107,11 +102,9 @@
while ((nbytes = walk.nbytes)) {
if (walk.src.virt.addr == walk.dst.virt.addr)
- nbytes = crypto_cbc_encrypt_inplace(desc, &walk, child,
- xor);
+ nbytes = crypto_cbc_encrypt_inplace(desc, &walk, child);
else
- nbytes = crypto_cbc_encrypt_segment(desc, &walk, child,
- xor);
+ nbytes = crypto_cbc_encrypt_segment(desc, &walk, child);
err = blkcipher_walk_done(desc, &walk, nbytes);
}
@@ -120,9 +113,7 @@
static int crypto_cbc_decrypt_segment(struct blkcipher_desc *desc,
struct blkcipher_walk *walk,
- struct crypto_cipher *tfm,
- void (*xor)(u8 *, const u8 *,
- unsigned int))
+ struct crypto_cipher *tfm)
{
void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
crypto_cipher_alg(tfm)->cia_decrypt;
@@ -134,7 +125,7 @@
do {
fn(crypto_cipher_tfm(tfm), dst, src);
- xor(dst, iv, bsize);
+ crypto_xor(dst, iv, bsize);
iv = src;
src += bsize;
@@ -148,34 +139,29 @@
static int crypto_cbc_decrypt_inplace(struct blkcipher_desc *desc,
struct blkcipher_walk *walk,
- struct crypto_cipher *tfm,
- void (*xor)(u8 *, const u8 *,
- unsigned int))
+ struct crypto_cipher *tfm)
{
void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
crypto_cipher_alg(tfm)->cia_decrypt;
int bsize = crypto_cipher_blocksize(tfm);
- unsigned long alignmask = crypto_cipher_alignmask(tfm);
unsigned int nbytes = walk->nbytes;
u8 *src = walk->src.virt.addr;
- u8 stack[bsize + alignmask];
- u8 *first_iv = (u8 *)ALIGN((unsigned long)stack, alignmask + 1);
-
- memcpy(first_iv, walk->iv, bsize);
+ u8 last_iv[bsize];
/* Start of the last block. */
- src += nbytes - nbytes % bsize - bsize;
- memcpy(walk->iv, src, bsize);
+ src += nbytes - (nbytes & (bsize - 1)) - bsize;
+ memcpy(last_iv, src, bsize);
for (;;) {
fn(crypto_cipher_tfm(tfm), src, src);
if ((nbytes -= bsize) < bsize)
break;
- xor(src, src - bsize, bsize);
+ crypto_xor(src, src - bsize, bsize);
src -= bsize;
}
- xor(src, first_iv, bsize);
+ crypto_xor(src, walk->iv, bsize);
+ memcpy(walk->iv, last_iv, bsize);
return nbytes;
}
@@ -188,7 +174,6 @@
struct crypto_blkcipher *tfm = desc->tfm;
struct crypto_cbc_ctx *ctx = crypto_blkcipher_ctx(tfm);
struct crypto_cipher *child = ctx->child;
- void (*xor)(u8 *, const u8 *, unsigned int bs) = ctx->xor;
int err;
blkcipher_walk_init(&walk, dst, src, nbytes);
@@ -196,48 +181,15 @@
while ((nbytes = walk.nbytes)) {
if (walk.src.virt.addr == walk.dst.virt.addr)
- nbytes = crypto_cbc_decrypt_inplace(desc, &walk, child,
- xor);
+ nbytes = crypto_cbc_decrypt_inplace(desc, &walk, child);
else
- nbytes = crypto_cbc_decrypt_segment(desc, &walk, child,
- xor);
+ nbytes = crypto_cbc_decrypt_segment(desc, &walk, child);
err = blkcipher_walk_done(desc, &walk, nbytes);
}
return err;
}
-static void xor_byte(u8 *a, const u8 *b, unsigned int bs)
-{
- do {
- *a++ ^= *b++;
- } while (--bs);
-}
-
-static void xor_quad(u8 *dst, const u8 *src, unsigned int bs)
-{
- u32 *a = (u32 *)dst;
- u32 *b = (u32 *)src;
-
- do {
- *a++ ^= *b++;
- } while ((bs -= 4));
-}
-
-static void xor_64(u8 *a, const u8 *b, unsigned int bs)
-{
- ((u32 *)a)[0] ^= ((u32 *)b)[0];
- ((u32 *)a)[1] ^= ((u32 *)b)[1];
-}
-
-static void xor_128(u8 *a, const u8 *b, unsigned int bs)
-{
- ((u32 *)a)[0] ^= ((u32 *)b)[0];
- ((u32 *)a)[1] ^= ((u32 *)b)[1];
- ((u32 *)a)[2] ^= ((u32 *)b)[2];
- ((u32 *)a)[3] ^= ((u32 *)b)[3];
-}
-
static int crypto_cbc_init_tfm(struct crypto_tfm *tfm)
{
struct crypto_instance *inst = (void *)tfm->__crt_alg;
@@ -245,22 +197,6 @@
struct crypto_cbc_ctx *ctx = crypto_tfm_ctx(tfm);
struct crypto_cipher *cipher;
- switch (crypto_tfm_alg_blocksize(tfm)) {
- case 8:
- ctx->xor = xor_64;
- break;
-
- case 16:
- ctx->xor = xor_128;
- break;
-
- default:
- if (crypto_tfm_alg_blocksize(tfm) % 4)
- ctx->xor = xor_byte;
- else
- ctx->xor = xor_quad;
- }
-
cipher = crypto_spawn_cipher(spawn);
if (IS_ERR(cipher))
return PTR_ERR(cipher);
@@ -290,6 +226,10 @@
if (IS_ERR(alg))
return ERR_PTR(PTR_ERR(alg));
+ inst = ERR_PTR(-EINVAL);
+ if (!is_power_of_2(alg->cra_blocksize))
+ goto out_put_alg;
+
inst = crypto_alloc_instance("cbc", alg);
if (IS_ERR(inst))
goto out_put_alg;
@@ -300,8 +240,9 @@
inst->alg.cra_alignmask = alg->cra_alignmask;
inst->alg.cra_type = &crypto_blkcipher_type;
- if (!(alg->cra_blocksize % 4))
- inst->alg.cra_alignmask |= 3;
+ /* We access the data as u32s when xoring. */
+ inst->alg.cra_alignmask |= __alignof__(u32) - 1;
+
inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize;
inst->alg.cra_blkcipher.min_keysize = alg->cra_cipher.cia_min_keysize;
inst->alg.cra_blkcipher.max_keysize = alg->cra_cipher.cia_max_keysize;
diff --git a/crypto/ccm.c b/crypto/ccm.c
new file mode 100644
index 0000000..7cf7e5a
--- /dev/null
+++ b/crypto/ccm.c
@@ -0,0 +1,889 @@
+/*
+ * CCM: Counter with CBC-MAC
+ *
+ * (C) Copyright IBM Corp. 2007 - Joy Latten <latten@us.ibm.com>
+ *
+ * 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 <crypto/internal/aead.h>
+#include <crypto/internal/skcipher.h>
+#include <crypto/scatterwalk.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "internal.h"
+
+struct ccm_instance_ctx {
+ struct crypto_skcipher_spawn ctr;
+ struct crypto_spawn cipher;
+};
+
+struct crypto_ccm_ctx {
+ struct crypto_cipher *cipher;
+ struct crypto_ablkcipher *ctr;
+};
+
+struct crypto_rfc4309_ctx {
+ struct crypto_aead *child;
+ u8 nonce[3];
+};
+
+struct crypto_ccm_req_priv_ctx {
+ u8 odata[16];
+ u8 idata[16];
+ u8 auth_tag[16];
+ u32 ilen;
+ u32 flags;
+ struct scatterlist src[2];
+ struct scatterlist dst[2];
+ struct ablkcipher_request abreq;
+};
+
+static inline struct crypto_ccm_req_priv_ctx *crypto_ccm_reqctx(
+ struct aead_request *req)
+{
+ unsigned long align = crypto_aead_alignmask(crypto_aead_reqtfm(req));
+
+ return (void *)PTR_ALIGN((u8 *)aead_request_ctx(req), align + 1);
+}
+
+static int set_msg_len(u8 *block, unsigned int msglen, int csize)
+{
+ __be32 data;
+
+ memset(block, 0, csize);
+ block += csize;
+
+ if (csize >= 4)
+ csize = 4;
+ else if (msglen > (1 << (8 * csize)))
+ return -EOVERFLOW;
+
+ data = cpu_to_be32(msglen);
+ memcpy(block - csize, (u8 *)&data + 4 - csize, csize);
+
+ return 0;
+}
+
+static int crypto_ccm_setkey(struct crypto_aead *aead, const u8 *key,
+ unsigned int keylen)
+{
+ struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);
+ struct crypto_ablkcipher *ctr = ctx->ctr;
+ struct crypto_cipher *tfm = ctx->cipher;
+ int err = 0;
+
+ crypto_ablkcipher_clear_flags(ctr, CRYPTO_TFM_REQ_MASK);
+ crypto_ablkcipher_set_flags(ctr, crypto_aead_get_flags(aead) &
+ CRYPTO_TFM_REQ_MASK);
+ err = crypto_ablkcipher_setkey(ctr, key, keylen);
+ crypto_aead_set_flags(aead, crypto_ablkcipher_get_flags(ctr) &
+ CRYPTO_TFM_RES_MASK);
+ if (err)
+ goto out;
+
+ crypto_cipher_clear_flags(tfm, CRYPTO_TFM_REQ_MASK);
+ crypto_cipher_set_flags(tfm, crypto_aead_get_flags(aead) &
+ CRYPTO_TFM_REQ_MASK);
+ err = crypto_cipher_setkey(tfm, key, keylen);
+ crypto_aead_set_flags(aead, crypto_cipher_get_flags(tfm) &
+ CRYPTO_TFM_RES_MASK);
+
+out:
+ return err;
+}
+
+static int crypto_ccm_setauthsize(struct crypto_aead *tfm,
+ unsigned int authsize)
+{
+ switch (authsize) {
+ case 4:
+ case 6:
+ case 8:
+ case 10:
+ case 12:
+ case 14:
+ case 16:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int format_input(u8 *info, struct aead_request *req,
+ unsigned int cryptlen)
+{
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ unsigned int lp = req->iv[0];
+ unsigned int l = lp + 1;
+ unsigned int m;
+
+ m = crypto_aead_authsize(aead);
+
+ memcpy(info, req->iv, 16);
+
+ /* format control info per RFC 3610 and
+ * NIST Special Publication 800-38C
+ */
+ *info |= (8 * ((m - 2) / 2));
+ if (req->assoclen)
+ *info |= 64;
+
+ return set_msg_len(info + 16 - l, cryptlen, l);
+}
+
+static int format_adata(u8 *adata, unsigned int a)
+{
+ int len = 0;
+
+ /* add control info for associated data
+ * RFC 3610 and NIST Special Publication 800-38C
+ */
+ if (a < 65280) {
+ *(__be16 *)adata = cpu_to_be16(a);
+ len = 2;
+ } else {
+ *(__be16 *)adata = cpu_to_be16(0xfffe);
+ *(__be32 *)&adata[2] = cpu_to_be32(a);
+ len = 6;
+ }
+
+ return len;
+}
+
+static void compute_mac(struct crypto_cipher *tfm, u8 *data, int n,
+ struct crypto_ccm_req_priv_ctx *pctx)
+{
+ unsigned int bs = 16;
+ u8 *odata = pctx->odata;
+ u8 *idata = pctx->idata;
+ int datalen, getlen;
+
+ datalen = n;
+
+ /* first time in here, block may be partially filled. */
+ getlen = bs - pctx->ilen;
+ if (datalen >= getlen) {
+ memcpy(idata + pctx->ilen, data, getlen);
+ crypto_xor(odata, idata, bs);
+ crypto_cipher_encrypt_one(tfm, odata, odata);
+ datalen -= getlen;
+ data += getlen;
+ pctx->ilen = 0;
+ }
+
+ /* now encrypt rest of data */
+ while (datalen >= bs) {
+ crypto_xor(odata, data, bs);
+ crypto_cipher_encrypt_one(tfm, odata, odata);
+
+ datalen -= bs;
+ data += bs;
+ }
+
+ /* check and see if there's leftover data that wasn't
+ * enough to fill a block.
+ */
+ if (datalen) {
+ memcpy(idata + pctx->ilen, data, datalen);
+ pctx->ilen += datalen;
+ }
+}
+
+static void get_data_to_compute(struct crypto_cipher *tfm,
+ struct crypto_ccm_req_priv_ctx *pctx,
+ struct scatterlist *sg, unsigned int len)
+{
+ struct scatter_walk walk;
+ u8 *data_src;
+ int n;
+
+ scatterwalk_start(&walk, sg);
+
+ while (len) {
+ n = scatterwalk_clamp(&walk, len);
+ if (!n) {
+ scatterwalk_start(&walk, sg_next(walk.sg));
+ n = scatterwalk_clamp(&walk, len);
+ }
+ data_src = scatterwalk_map(&walk, 0);
+
+ compute_mac(tfm, data_src, n, pctx);
+ len -= n;
+
+ scatterwalk_unmap(data_src, 0);
+ scatterwalk_advance(&walk, n);
+ scatterwalk_done(&walk, 0, len);
+ if (len)
+ crypto_yield(pctx->flags);
+ }
+
+ /* any leftover needs padding and then encrypted */
+ if (pctx->ilen) {
+ int padlen;
+ u8 *odata = pctx->odata;
+ u8 *idata = pctx->idata;
+
+ padlen = 16 - pctx->ilen;
+ memset(idata + pctx->ilen, 0, padlen);
+ crypto_xor(odata, idata, 16);
+ crypto_cipher_encrypt_one(tfm, odata, odata);
+ pctx->ilen = 0;
+ }
+}
+
+static int crypto_ccm_auth(struct aead_request *req, struct scatterlist *plain,
+ unsigned int cryptlen)
+{
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);
+ struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
+ struct crypto_cipher *cipher = ctx->cipher;
+ unsigned int assoclen = req->assoclen;
+ u8 *odata = pctx->odata;
+ u8 *idata = pctx->idata;
+ int err;
+
+ /* format control data for input */
+ err = format_input(odata, req, cryptlen);
+ if (err)
+ goto out;
+
+ /* encrypt first block to use as start in computing mac */
+ crypto_cipher_encrypt_one(cipher, odata, odata);
+
+ /* format associated data and compute into mac */
+ if (assoclen) {
+ pctx->ilen = format_adata(idata, assoclen);
+ get_data_to_compute(cipher, pctx, req->assoc, req->assoclen);
+ }
+
+ /* compute plaintext into mac */
+ get_data_to_compute(cipher, pctx, plain, cryptlen);
+
+out:
+ return err;
+}
+
+static void crypto_ccm_encrypt_done(struct crypto_async_request *areq, int err)
+{
+ struct aead_request *req = areq->data;
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
+ u8 *odata = pctx->odata;
+
+ if (!err)
+ scatterwalk_map_and_copy(odata, req->dst, req->cryptlen,
+ crypto_aead_authsize(aead), 1);
+ aead_request_complete(req, err);
+}
+
+static inline int crypto_ccm_check_iv(const u8 *iv)
+{
+ /* 2 <= L <= 8, so 1 <= L' <= 7. */
+ if (1 > iv[0] || iv[0] > 7)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int crypto_ccm_encrypt(struct aead_request *req)
+{
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);
+ struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
+ struct ablkcipher_request *abreq = &pctx->abreq;
+ struct scatterlist *dst;
+ unsigned int cryptlen = req->cryptlen;
+ u8 *odata = pctx->odata;
+ u8 *iv = req->iv;
+ int err;
+
+ err = crypto_ccm_check_iv(iv);
+ if (err)
+ return err;
+
+ pctx->flags = aead_request_flags(req);
+
+ err = crypto_ccm_auth(req, req->src, cryptlen);
+ if (err)
+ return err;
+
+ /* Note: rfc 3610 and NIST 800-38C require counter of
+ * zero to encrypt auth tag.
+ */
+ memset(iv + 15 - iv[0], 0, iv[0] + 1);
+
+ sg_init_table(pctx->src, 2);
+ sg_set_buf(pctx->src, odata, 16);
+ scatterwalk_sg_chain(pctx->src, 2, req->src);
+
+ dst = pctx->src;
+ if (req->src != req->dst) {
+ sg_init_table(pctx->dst, 2);
+ sg_set_buf(pctx->dst, odata, 16);
+ scatterwalk_sg_chain(pctx->dst, 2, req->dst);
+ dst = pctx->dst;
+ }
+
+ ablkcipher_request_set_tfm(abreq, ctx->ctr);
+ ablkcipher_request_set_callback(abreq, pctx->flags,
+ crypto_ccm_encrypt_done, req);
+ ablkcipher_request_set_crypt(abreq, pctx->src, dst, cryptlen + 16, iv);
+ err = crypto_ablkcipher_encrypt(abreq);
+ if (err)
+ return err;
+
+ /* copy authtag to end of dst */
+ scatterwalk_map_and_copy(odata, req->dst, cryptlen,
+ crypto_aead_authsize(aead), 1);
+ return err;
+}
+
+static void crypto_ccm_decrypt_done(struct crypto_async_request *areq,
+ int err)
+{
+ struct aead_request *req = areq->data;
+ struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ unsigned int authsize = crypto_aead_authsize(aead);
+ unsigned int cryptlen = req->cryptlen - authsize;
+
+ if (!err) {
+ err = crypto_ccm_auth(req, req->dst, cryptlen);
+ if (!err && memcmp(pctx->auth_tag, pctx->odata, authsize))
+ err = -EBADMSG;
+ }
+ aead_request_complete(req, err);
+}
+
+static int crypto_ccm_decrypt(struct aead_request *req)
+{
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);
+ struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
+ struct ablkcipher_request *abreq = &pctx->abreq;
+ struct scatterlist *dst;
+ unsigned int authsize = crypto_aead_authsize(aead);
+ unsigned int cryptlen = req->cryptlen;
+ u8 *authtag = pctx->auth_tag;
+ u8 *odata = pctx->odata;
+ u8 *iv = req->iv;
+ int err;
+
+ if (cryptlen < authsize)
+ return -EINVAL;
+ cryptlen -= authsize;
+
+ err = crypto_ccm_check_iv(iv);
+ if (err)
+ return err;
+
+ pctx->flags = aead_request_flags(req);
+
+ scatterwalk_map_and_copy(authtag, req->src, cryptlen, authsize, 0);
+
+ memset(iv + 15 - iv[0], 0, iv[0] + 1);
+
+ sg_init_table(pctx->src, 2);
+ sg_set_buf(pctx->src, authtag, 16);
+ scatterwalk_sg_chain(pctx->src, 2, req->src);
+
+ dst = pctx->src;
+ if (req->src != req->dst) {
+ sg_init_table(pctx->dst, 2);
+ sg_set_buf(pctx->dst, authtag, 16);
+ scatterwalk_sg_chain(pctx->dst, 2, req->dst);
+ dst = pctx->dst;
+ }
+
+ ablkcipher_request_set_tfm(abreq, ctx->ctr);
+ ablkcipher_request_set_callback(abreq, pctx->flags,
+ crypto_ccm_decrypt_done, req);
+ ablkcipher_request_set_crypt(abreq, pctx->src, dst, cryptlen + 16, iv);
+ err = crypto_ablkcipher_decrypt(abreq);
+ if (err)
+ return err;
+
+ err = crypto_ccm_auth(req, req->dst, cryptlen);
+ if (err)
+ return err;
+
+ /* verify */
+ if (memcmp(authtag, odata, authsize))
+ return -EBADMSG;
+
+ return err;
+}
+
+static int crypto_ccm_init_tfm(struct crypto_tfm *tfm)
+{
+ struct crypto_instance *inst = (void *)tfm->__crt_alg;
+ struct ccm_instance_ctx *ictx = crypto_instance_ctx(inst);
+ struct crypto_ccm_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct crypto_cipher *cipher;
+ struct crypto_ablkcipher *ctr;
+ unsigned long align;
+ int err;
+
+ cipher = crypto_spawn_cipher(&ictx->cipher);
+ if (IS_ERR(cipher))
+ return PTR_ERR(cipher);
+
+ ctr = crypto_spawn_skcipher(&ictx->ctr);
+ err = PTR_ERR(ctr);
+ if (IS_ERR(ctr))
+ goto err_free_cipher;
+
+ ctx->cipher = cipher;
+ ctx->ctr = ctr;
+
+ align = crypto_tfm_alg_alignmask(tfm);
+ align &= ~(crypto_tfm_ctx_alignment() - 1);
+ tfm->crt_aead.reqsize = align +
+ sizeof(struct crypto_ccm_req_priv_ctx) +
+ crypto_ablkcipher_reqsize(ctr);
+
+ return 0;
+
+err_free_cipher:
+ crypto_free_cipher(cipher);
+ return err;
+}
+
+static void crypto_ccm_exit_tfm(struct crypto_tfm *tfm)
+{
+ struct crypto_ccm_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ crypto_free_cipher(ctx->cipher);
+ crypto_free_ablkcipher(ctx->ctr);
+}
+
+static struct crypto_instance *crypto_ccm_alloc_common(struct rtattr **tb,
+ const char *full_name,
+ const char *ctr_name,
+ const char *cipher_name)
+{
+ struct crypto_attr_type *algt;
+ struct crypto_instance *inst;
+ struct crypto_alg *ctr;
+ struct crypto_alg *cipher;
+ struct ccm_instance_ctx *ictx;
+ int err;
+
+ algt = crypto_get_attr_type(tb);
+ err = PTR_ERR(algt);
+ if (IS_ERR(algt))
+ return ERR_PTR(err);
+
+ if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
+ return ERR_PTR(-EINVAL);
+
+ cipher = crypto_alg_mod_lookup(cipher_name, CRYPTO_ALG_TYPE_CIPHER,
+ CRYPTO_ALG_TYPE_MASK);
+ err = PTR_ERR(cipher);
+ if (IS_ERR(cipher))
+ return ERR_PTR(err);
+
+ err = -EINVAL;
+ if (cipher->cra_blocksize != 16)
+ goto out_put_cipher;
+
+ inst = kzalloc(sizeof(*inst) + sizeof(*ictx), GFP_KERNEL);
+ err = -ENOMEM;
+ if (!inst)
+ goto out_put_cipher;
+
+ ictx = crypto_instance_ctx(inst);
+
+ err = crypto_init_spawn(&ictx->cipher, cipher, inst,
+ CRYPTO_ALG_TYPE_MASK);
+ if (err)
+ goto err_free_inst;
+
+ crypto_set_skcipher_spawn(&ictx->ctr, inst);
+ err = crypto_grab_skcipher(&ictx->ctr, ctr_name, 0,
+ crypto_requires_sync(algt->type,
+ algt->mask));
+ if (err)
+ goto err_drop_cipher;
+
+ ctr = crypto_skcipher_spawn_alg(&ictx->ctr);
+
+ /* Not a stream cipher? */
+ err = -EINVAL;
+ if (ctr->cra_blocksize != 1)
+ goto err_drop_ctr;
+
+ /* We want the real thing! */
+ if (ctr->cra_ablkcipher.ivsize != 16)
+ goto err_drop_ctr;
+
+ err = -ENAMETOOLONG;
+ if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
+ "ccm_base(%s,%s)", ctr->cra_driver_name,
+ cipher->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
+ goto err_drop_ctr;
+
+ memcpy(inst->alg.cra_name, full_name, CRYPTO_MAX_ALG_NAME);
+
+ inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD;
+ inst->alg.cra_flags |= ctr->cra_flags & CRYPTO_ALG_ASYNC;
+ inst->alg.cra_priority = cipher->cra_priority + ctr->cra_priority;
+ inst->alg.cra_blocksize = 1;
+ inst->alg.cra_alignmask = cipher->cra_alignmask | ctr->cra_alignmask |
+ (__alignof__(u32) - 1);
+ inst->alg.cra_type = &crypto_aead_type;
+ inst->alg.cra_aead.ivsize = 16;
+ inst->alg.cra_aead.maxauthsize = 16;
+ inst->alg.cra_ctxsize = sizeof(struct crypto_ccm_ctx);
+ inst->alg.cra_init = crypto_ccm_init_tfm;
+ inst->alg.cra_exit = crypto_ccm_exit_tfm;
+ inst->alg.cra_aead.setkey = crypto_ccm_setkey;
+ inst->alg.cra_aead.setauthsize = crypto_ccm_setauthsize;
+ inst->alg.cra_aead.encrypt = crypto_ccm_encrypt;
+ inst->alg.cra_aead.decrypt = crypto_ccm_decrypt;
+
+out:
+ crypto_mod_put(cipher);
+ return inst;
+
+err_drop_ctr:
+ crypto_drop_skcipher(&ictx->ctr);
+err_drop_cipher:
+ crypto_drop_spawn(&ictx->cipher);
+err_free_inst:
+ kfree(inst);
+out_put_cipher:
+ inst = ERR_PTR(err);
+ goto out;
+}
+
+static struct crypto_instance *crypto_ccm_alloc(struct rtattr **tb)
+{
+ int err;
+ const char *cipher_name;
+ char ctr_name[CRYPTO_MAX_ALG_NAME];
+ char full_name[CRYPTO_MAX_ALG_NAME];
+
+ cipher_name = crypto_attr_alg_name(tb[1]);
+ err = PTR_ERR(cipher_name);
+ if (IS_ERR(cipher_name))
+ return ERR_PTR(err);
+
+ if (snprintf(ctr_name, CRYPTO_MAX_ALG_NAME, "ctr(%s)",
+ cipher_name) >= CRYPTO_MAX_ALG_NAME)
+ return ERR_PTR(-ENAMETOOLONG);
+
+ if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "ccm(%s)", cipher_name) >=
+ CRYPTO_MAX_ALG_NAME)
+ return ERR_PTR(-ENAMETOOLONG);
+
+ return crypto_ccm_alloc_common(tb, full_name, ctr_name, cipher_name);
+}
+
+static void crypto_ccm_free(struct crypto_instance *inst)
+{
+ struct ccm_instance_ctx *ctx = crypto_instance_ctx(inst);
+
+ crypto_drop_spawn(&ctx->cipher);
+ crypto_drop_skcipher(&ctx->ctr);
+ kfree(inst);
+}
+
+static struct crypto_template crypto_ccm_tmpl = {
+ .name = "ccm",
+ .alloc = crypto_ccm_alloc,
+ .free = crypto_ccm_free,
+ .module = THIS_MODULE,
+};
+
+static struct crypto_instance *crypto_ccm_base_alloc(struct rtattr **tb)
+{
+ int err;
+ const char *ctr_name;
+ const char *cipher_name;
+ char full_name[CRYPTO_MAX_ALG_NAME];
+
+ ctr_name = crypto_attr_alg_name(tb[1]);
+ err = PTR_ERR(ctr_name);
+ if (IS_ERR(ctr_name))
+ return ERR_PTR(err);
+
+ cipher_name = crypto_attr_alg_name(tb[2]);
+ err = PTR_ERR(cipher_name);
+ if (IS_ERR(cipher_name))
+ return ERR_PTR(err);
+
+ if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "ccm_base(%s,%s)",
+ ctr_name, cipher_name) >= CRYPTO_MAX_ALG_NAME)
+ return ERR_PTR(-ENAMETOOLONG);
+
+ return crypto_ccm_alloc_common(tb, full_name, ctr_name, cipher_name);
+}
+
+static struct crypto_template crypto_ccm_base_tmpl = {
+ .name = "ccm_base",
+ .alloc = crypto_ccm_base_alloc,
+ .free = crypto_ccm_free,
+ .module = THIS_MODULE,
+};
+
+static int crypto_rfc4309_setkey(struct crypto_aead *parent, const u8 *key,
+ unsigned int keylen)
+{
+ struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(parent);
+ struct crypto_aead *child = ctx->child;
+ int err;
+
+ if (keylen < 3)
+ return -EINVAL;
+
+ keylen -= 3;
+ memcpy(ctx->nonce, key + keylen, 3);
+
+ crypto_aead_clear_flags(child, CRYPTO_TFM_REQ_MASK);
+ crypto_aead_set_flags(child, crypto_aead_get_flags(parent) &
+ CRYPTO_TFM_REQ_MASK);
+ err = crypto_aead_setkey(child, key, keylen);
+ crypto_aead_set_flags(parent, crypto_aead_get_flags(child) &
+ CRYPTO_TFM_RES_MASK);
+
+ return err;
+}
+
+static int crypto_rfc4309_setauthsize(struct crypto_aead *parent,
+ unsigned int authsize)
+{
+ struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(parent);
+
+ switch (authsize) {
+ case 8:
+ case 12:
+ case 16:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return crypto_aead_setauthsize(ctx->child, authsize);
+}
+
+static struct aead_request *crypto_rfc4309_crypt(struct aead_request *req)
+{
+ struct aead_request *subreq = aead_request_ctx(req);
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(aead);
+ struct crypto_aead *child = ctx->child;
+ u8 *iv = PTR_ALIGN((u8 *)(subreq + 1) + crypto_aead_reqsize(child),
+ crypto_aead_alignmask(child) + 1);
+
+ /* L' */
+ iv[0] = 3;
+
+ memcpy(iv + 1, ctx->nonce, 3);
+ memcpy(iv + 4, req->iv, 8);
+
+ aead_request_set_tfm(subreq, child);
+ aead_request_set_callback(subreq, req->base.flags, req->base.complete,
+ req->base.data);
+ aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen, iv);
+ aead_request_set_assoc(subreq, req->assoc, req->assoclen);
+
+ return subreq;
+}
+
+static int crypto_rfc4309_encrypt(struct aead_request *req)
+{
+ req = crypto_rfc4309_crypt(req);
+
+ return crypto_aead_encrypt(req);
+}
+
+static int crypto_rfc4309_decrypt(struct aead_request *req)
+{
+ req = crypto_rfc4309_crypt(req);
+
+ return crypto_aead_decrypt(req);
+}
+
+static int crypto_rfc4309_init_tfm(struct crypto_tfm *tfm)
+{
+ struct crypto_instance *inst = (void *)tfm->__crt_alg;
+ struct crypto_aead_spawn *spawn = crypto_instance_ctx(inst);
+ struct crypto_rfc4309_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct crypto_aead *aead;
+ unsigned long align;
+
+ aead = crypto_spawn_aead(spawn);
+ if (IS_ERR(aead))
+ return PTR_ERR(aead);
+
+ ctx->child = aead;
+
+ align = crypto_aead_alignmask(aead);
+ align &= ~(crypto_tfm_ctx_alignment() - 1);
+ tfm->crt_aead.reqsize = sizeof(struct aead_request) +
+ ALIGN(crypto_aead_reqsize(aead),
+ crypto_tfm_ctx_alignment()) +
+ align + 16;
+
+ return 0;
+}
+
+static void crypto_rfc4309_exit_tfm(struct crypto_tfm *tfm)
+{
+ struct crypto_rfc4309_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ crypto_free_aead(ctx->child);
+}
+
+static struct crypto_instance *crypto_rfc4309_alloc(struct rtattr **tb)
+{
+ struct crypto_attr_type *algt;
+ struct crypto_instance *inst;
+ struct crypto_aead_spawn *spawn;
+ struct crypto_alg *alg;
+ const char *ccm_name;
+ int err;
+
+ algt = crypto_get_attr_type(tb);
+ err = PTR_ERR(algt);
+ if (IS_ERR(algt))
+ return ERR_PTR(err);
+
+ if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
+ return ERR_PTR(-EINVAL);
+
+ ccm_name = crypto_attr_alg_name(tb[1]);
+ err = PTR_ERR(ccm_name);
+ if (IS_ERR(ccm_name))
+ return ERR_PTR(err);
+
+ inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
+ if (!inst)
+ return ERR_PTR(-ENOMEM);
+
+ spawn = crypto_instance_ctx(inst);
+ crypto_set_aead_spawn(spawn, inst);
+ err = crypto_grab_aead(spawn, ccm_name, 0,
+ crypto_requires_sync(algt->type, algt->mask));
+ if (err)
+ goto out_free_inst;
+
+ alg = crypto_aead_spawn_alg(spawn);
+
+ err = -EINVAL;
+
+ /* We only support 16-byte blocks. */
+ if (alg->cra_aead.ivsize != 16)
+ goto out_drop_alg;
+
+ /* Not a stream cipher? */
+ if (alg->cra_blocksize != 1)
+ goto out_drop_alg;
+
+ err = -ENAMETOOLONG;
+ if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
+ "rfc4309(%s)", alg->cra_name) >= CRYPTO_MAX_ALG_NAME ||
+ snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
+ "rfc4309(%s)", alg->cra_driver_name) >=
+ CRYPTO_MAX_ALG_NAME)
+ goto out_drop_alg;
+
+ inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD;
+ inst->alg.cra_flags |= alg->cra_flags & CRYPTO_ALG_ASYNC;
+ inst->alg.cra_priority = alg->cra_priority;
+ inst->alg.cra_blocksize = 1;
+ inst->alg.cra_alignmask = alg->cra_alignmask;
+ inst->alg.cra_type = &crypto_nivaead_type;
+
+ inst->alg.cra_aead.ivsize = 8;
+ inst->alg.cra_aead.maxauthsize = 16;
+
+ inst->alg.cra_ctxsize = sizeof(struct crypto_rfc4309_ctx);
+
+ inst->alg.cra_init = crypto_rfc4309_init_tfm;
+ inst->alg.cra_exit = crypto_rfc4309_exit_tfm;
+
+ inst->alg.cra_aead.setkey = crypto_rfc4309_setkey;
+ inst->alg.cra_aead.setauthsize = crypto_rfc4309_setauthsize;
+ inst->alg.cra_aead.encrypt = crypto_rfc4309_encrypt;
+ inst->alg.cra_aead.decrypt = crypto_rfc4309_decrypt;
+
+ inst->alg.cra_aead.geniv = "seqiv";
+
+out:
+ return inst;
+
+out_drop_alg:
+ crypto_drop_aead(spawn);
+out_free_inst:
+ kfree(inst);
+ inst = ERR_PTR(err);
+ goto out;
+}
+
+static void crypto_rfc4309_free(struct crypto_instance *inst)
+{
+ crypto_drop_spawn(crypto_instance_ctx(inst));
+ kfree(inst);
+}
+
+static struct crypto_template crypto_rfc4309_tmpl = {
+ .name = "rfc4309",
+ .alloc = crypto_rfc4309_alloc,
+ .free = crypto_rfc4309_free,
+ .module = THIS_MODULE,
+};
+
+static int __init crypto_ccm_module_init(void)
+{
+ int err;
+
+ err = crypto_register_template(&crypto_ccm_base_tmpl);
+ if (err)
+ goto out;
+
+ err = crypto_register_template(&crypto_ccm_tmpl);
+ if (err)
+ goto out_undo_base;
+
+ err = crypto_register_template(&crypto_rfc4309_tmpl);
+ if (err)
+ goto out_undo_ccm;
+
+out:
+ return err;
+
+out_undo_ccm:
+ crypto_unregister_template(&crypto_ccm_tmpl);
+out_undo_base:
+ crypto_unregister_template(&crypto_ccm_base_tmpl);
+ goto out;
+}
+
+static void __exit crypto_ccm_module_exit(void)
+{
+ crypto_unregister_template(&crypto_rfc4309_tmpl);
+ crypto_unregister_template(&crypto_ccm_tmpl);
+ crypto_unregister_template(&crypto_ccm_base_tmpl);
+}
+
+module_init(crypto_ccm_module_init);
+module_exit(crypto_ccm_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Counter with CBC MAC");
+MODULE_ALIAS("ccm_base");
+MODULE_ALIAS("rfc4309");
diff --git a/crypto/chainiv.c b/crypto/chainiv.c
new file mode 100644
index 0000000..d17fa04
--- /dev/null
+++ b/crypto/chainiv.c
@@ -0,0 +1,331 @@
+/*
+ * chainiv: Chain IV Generator
+ *
+ * Generate IVs simply be using the last block of the previous encryption.
+ * This is mainly useful for CBC with a synchronous algorithm.
+ *
+ * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+#include <crypto/internal/skcipher.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/random.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/workqueue.h>
+
+enum {
+ CHAINIV_STATE_INUSE = 0,
+};
+
+struct chainiv_ctx {
+ spinlock_t lock;
+ char iv[];
+};
+
+struct async_chainiv_ctx {
+ unsigned long state;
+
+ spinlock_t lock;
+ int err;
+
+ struct crypto_queue queue;
+ struct work_struct postponed;
+
+ char iv[];
+};
+
+static int chainiv_givencrypt(struct skcipher_givcrypt_request *req)
+{
+ struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
+ struct chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
+ struct ablkcipher_request *subreq = skcipher_givcrypt_reqctx(req);
+ unsigned int ivsize;
+ int err;
+
+ ablkcipher_request_set_tfm(subreq, skcipher_geniv_cipher(geniv));
+ ablkcipher_request_set_callback(subreq, req->creq.base.flags &
+ ~CRYPTO_TFM_REQ_MAY_SLEEP,
+ req->creq.base.complete,
+ req->creq.base.data);
+ ablkcipher_request_set_crypt(subreq, req->creq.src, req->creq.dst,
+ req->creq.nbytes, req->creq.info);
+
+ spin_lock_bh(&ctx->lock);
+
+ ivsize = crypto_ablkcipher_ivsize(geniv);
+
+ memcpy(req->giv, ctx->iv, ivsize);
+ memcpy(subreq->info, ctx->iv, ivsize);
+
+ err = crypto_ablkcipher_encrypt(subreq);
+ if (err)
+ goto unlock;
+
+ memcpy(ctx->iv, subreq->info, ivsize);
+
+unlock:
+ spin_unlock_bh(&ctx->lock);
+
+ return err;
+}
+
+static int chainiv_givencrypt_first(struct skcipher_givcrypt_request *req)
+{
+ struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
+ struct chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
+
+ spin_lock_bh(&ctx->lock);
+ if (crypto_ablkcipher_crt(geniv)->givencrypt !=
+ chainiv_givencrypt_first)
+ goto unlock;
+
+ crypto_ablkcipher_crt(geniv)->givencrypt = chainiv_givencrypt;
+ get_random_bytes(ctx->iv, crypto_ablkcipher_ivsize(geniv));
+
+unlock:
+ spin_unlock_bh(&ctx->lock);
+
+ return chainiv_givencrypt(req);
+}
+
+static int chainiv_init_common(struct crypto_tfm *tfm)
+{
+ tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request);
+
+ return skcipher_geniv_init(tfm);
+}
+
+static int chainiv_init(struct crypto_tfm *tfm)
+{
+ struct chainiv_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ spin_lock_init(&ctx->lock);
+
+ return chainiv_init_common(tfm);
+}
+
+static int async_chainiv_schedule_work(struct async_chainiv_ctx *ctx)
+{
+ int queued;
+
+ if (!ctx->queue.qlen) {
+ smp_mb__before_clear_bit();
+ clear_bit(CHAINIV_STATE_INUSE, &ctx->state);
+
+ if (!ctx->queue.qlen ||
+ test_and_set_bit(CHAINIV_STATE_INUSE, &ctx->state))
+ goto out;
+ }
+
+ queued = schedule_work(&ctx->postponed);
+ BUG_ON(!queued);
+
+out:
+ return ctx->err;
+}
+
+static int async_chainiv_postpone_request(struct skcipher_givcrypt_request *req)
+{
+ struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
+ struct async_chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
+ int err;
+
+ spin_lock_bh(&ctx->lock);
+ err = skcipher_enqueue_givcrypt(&ctx->queue, req);
+ spin_unlock_bh(&ctx->lock);
+
+ if (test_and_set_bit(CHAINIV_STATE_INUSE, &ctx->state))
+ return err;
+
+ ctx->err = err;
+ return async_chainiv_schedule_work(ctx);
+}
+
+static int async_chainiv_givencrypt_tail(struct skcipher_givcrypt_request *req)
+{
+ struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
+ struct async_chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
+ struct ablkcipher_request *subreq = skcipher_givcrypt_reqctx(req);
+ unsigned int ivsize = crypto_ablkcipher_ivsize(geniv);
+
+ memcpy(req->giv, ctx->iv, ivsize);
+ memcpy(subreq->info, ctx->iv, ivsize);
+
+ ctx->err = crypto_ablkcipher_encrypt(subreq);
+ if (ctx->err)
+ goto out;
+
+ memcpy(ctx->iv, subreq->info, ivsize);
+
+out:
+ return async_chainiv_schedule_work(ctx);
+}
+
+static int async_chainiv_givencrypt(struct skcipher_givcrypt_request *req)
+{
+ struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
+ struct async_chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
+ struct ablkcipher_request *subreq = skcipher_givcrypt_reqctx(req);
+
+ ablkcipher_request_set_tfm(subreq, skcipher_geniv_cipher(geniv));
+ ablkcipher_request_set_callback(subreq, req->creq.base.flags,
+ req->creq.base.complete,
+ req->creq.base.data);
+ ablkcipher_request_set_crypt(subreq, req->creq.src, req->creq.dst,
+ req->creq.nbytes, req->creq.info);
+
+ if (test_and_set_bit(CHAINIV_STATE_INUSE, &ctx->state))
+ goto postpone;
+
+ if (ctx->queue.qlen) {
+ clear_bit(CHAINIV_STATE_INUSE, &ctx->state);
+ goto postpone;
+ }
+
+ return async_chainiv_givencrypt_tail(req);
+
+postpone:
+ return async_chainiv_postpone_request(req);
+}
+
+static int async_chainiv_givencrypt_first(struct skcipher_givcrypt_request *req)
+{
+ struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
+ struct async_chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
+
+ if (test_and_set_bit(CHAINIV_STATE_INUSE, &ctx->state))
+ goto out;
+
+ if (crypto_ablkcipher_crt(geniv)->givencrypt !=
+ async_chainiv_givencrypt_first)
+ goto unlock;
+
+ crypto_ablkcipher_crt(geniv)->givencrypt = async_chainiv_givencrypt;
+ get_random_bytes(ctx->iv, crypto_ablkcipher_ivsize(geniv));
+
+unlock:
+ clear_bit(CHAINIV_STATE_INUSE, &ctx->state);
+
+out:
+ return async_chainiv_givencrypt(req);
+}
+
+static void async_chainiv_do_postponed(struct work_struct *work)
+{
+ struct async_chainiv_ctx *ctx = container_of(work,
+ struct async_chainiv_ctx,
+ postponed);
+ struct skcipher_givcrypt_request *req;
+ struct ablkcipher_request *subreq;
+
+ /* Only handle one request at a time to avoid hogging keventd. */
+ spin_lock_bh(&ctx->lock);
+ req = skcipher_dequeue_givcrypt(&ctx->queue);
+ spin_unlock_bh(&ctx->lock);
+
+ if (!req) {
+ async_chainiv_schedule_work(ctx);
+ return;
+ }
+
+ subreq = skcipher_givcrypt_reqctx(req);
+ subreq->base.flags |= CRYPTO_TFM_REQ_MAY_SLEEP;
+
+ async_chainiv_givencrypt_tail(req);
+}
+
+static int async_chainiv_init(struct crypto_tfm *tfm)
+{
+ struct async_chainiv_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ spin_lock_init(&ctx->lock);
+
+ crypto_init_queue(&ctx->queue, 100);
+ INIT_WORK(&ctx->postponed, async_chainiv_do_postponed);
+
+ return chainiv_init_common(tfm);
+}
+
+static void async_chainiv_exit(struct crypto_tfm *tfm)
+{
+ struct async_chainiv_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ BUG_ON(test_bit(CHAINIV_STATE_INUSE, &ctx->state) || ctx->queue.qlen);
+
+ skcipher_geniv_exit(tfm);
+}
+
+static struct crypto_template chainiv_tmpl;
+
+static struct crypto_instance *chainiv_alloc(struct rtattr **tb)
+{
+ struct crypto_attr_type *algt;
+ struct crypto_instance *inst;
+ int err;
+
+ algt = crypto_get_attr_type(tb);
+ err = PTR_ERR(algt);
+ if (IS_ERR(algt))
+ return ERR_PTR(err);
+
+ inst = skcipher_geniv_alloc(&chainiv_tmpl, tb, 0, 0);
+ if (IS_ERR(inst))
+ goto out;
+
+ inst->alg.cra_ablkcipher.givencrypt = chainiv_givencrypt_first;
+
+ inst->alg.cra_init = chainiv_init;
+ inst->alg.cra_exit = skcipher_geniv_exit;
+
+ inst->alg.cra_ctxsize = sizeof(struct chainiv_ctx);
+
+ if (!crypto_requires_sync(algt->type, algt->mask)) {
+ inst->alg.cra_flags |= CRYPTO_ALG_ASYNC;
+
+ inst->alg.cra_ablkcipher.givencrypt =
+ async_chainiv_givencrypt_first;
+
+ inst->alg.cra_init = async_chainiv_init;
+ inst->alg.cra_exit = async_chainiv_exit;
+
+ inst->alg.cra_ctxsize = sizeof(struct async_chainiv_ctx);
+ }
+
+ inst->alg.cra_ctxsize += inst->alg.cra_ablkcipher.ivsize;
+
+out:
+ return inst;
+}
+
+static struct crypto_template chainiv_tmpl = {
+ .name = "chainiv",
+ .alloc = chainiv_alloc,
+ .free = skcipher_geniv_free,
+ .module = THIS_MODULE,
+};
+
+static int __init chainiv_module_init(void)
+{
+ return crypto_register_template(&chainiv_tmpl);
+}
+
+static void __exit chainiv_module_exit(void)
+{
+ crypto_unregister_template(&chainiv_tmpl);
+}
+
+module_init(chainiv_module_init);
+module_exit(chainiv_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Chain IV Generator");
diff --git a/crypto/cryptd.c b/crypto/cryptd.c
index 8bf2da8..074298f 100644
--- a/crypto/cryptd.c
+++ b/crypto/cryptd.c
@@ -228,7 +228,7 @@
struct crypto_alg *alg;
alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_BLKCIPHER,
- CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
+ CRYPTO_ALG_TYPE_MASK);
if (IS_ERR(alg))
return ERR_PTR(PTR_ERR(alg));
@@ -236,13 +236,15 @@
if (IS_ERR(inst))
goto out_put_alg;
- inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER | CRYPTO_ALG_ASYNC;
+ inst->alg.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC;
inst->alg.cra_type = &crypto_ablkcipher_type;
inst->alg.cra_ablkcipher.ivsize = alg->cra_blkcipher.ivsize;
inst->alg.cra_ablkcipher.min_keysize = alg->cra_blkcipher.min_keysize;
inst->alg.cra_ablkcipher.max_keysize = alg->cra_blkcipher.max_keysize;
+ inst->alg.cra_ablkcipher.geniv = alg->cra_blkcipher.geniv;
+
inst->alg.cra_ctxsize = sizeof(struct cryptd_blkcipher_ctx);
inst->alg.cra_init = cryptd_blkcipher_init_tfm;
diff --git a/crypto/crypto_null.c b/crypto/crypto_null.c
index 29f7747..ff7b3de 100644
--- a/crypto/crypto_null.c
+++ b/crypto/crypto_null.c
@@ -16,15 +16,17 @@
* (at your option) any later version.
*
*/
+
+#include <crypto/internal/skcipher.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mm.h>
-#include <linux/crypto.h>
#include <linux/string.h>
#define NULL_KEY_SIZE 0
#define NULL_BLOCK_SIZE 1
#define NULL_DIGEST_SIZE 0
+#define NULL_IV_SIZE 0
static int null_compress(struct crypto_tfm *tfm, const u8 *src,
unsigned int slen, u8 *dst, unsigned int *dlen)
@@ -55,6 +57,26 @@
memcpy(dst, src, NULL_BLOCK_SIZE);
}
+static int skcipher_null_crypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst,
+ struct scatterlist *src, unsigned int nbytes)
+{
+ struct blkcipher_walk walk;
+ int err;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ err = blkcipher_walk_virt(desc, &walk);
+
+ while (walk.nbytes) {
+ if (walk.src.virt.addr != walk.dst.virt.addr)
+ memcpy(walk.dst.virt.addr, walk.src.virt.addr,
+ walk.nbytes);
+ err = blkcipher_walk_done(desc, &walk, 0);
+ }
+
+ return err;
+}
+
static struct crypto_alg compress_null = {
.cra_name = "compress_null",
.cra_flags = CRYPTO_ALG_TYPE_COMPRESS,
@@ -76,6 +98,7 @@
.cra_list = LIST_HEAD_INIT(digest_null.cra_list),
.cra_u = { .digest = {
.dia_digestsize = NULL_DIGEST_SIZE,
+ .dia_setkey = null_setkey,
.dia_init = null_init,
.dia_update = null_update,
.dia_final = null_final } }
@@ -96,6 +119,25 @@
.cia_decrypt = null_crypt } }
};
+static struct crypto_alg skcipher_null = {
+ .cra_name = "ecb(cipher_null)",
+ .cra_driver_name = "ecb-cipher_null",
+ .cra_priority = 100,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = NULL_BLOCK_SIZE,
+ .cra_type = &crypto_blkcipher_type,
+ .cra_ctxsize = 0,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(skcipher_null.cra_list),
+ .cra_u = { .blkcipher = {
+ .min_keysize = NULL_KEY_SIZE,
+ .max_keysize = NULL_KEY_SIZE,
+ .ivsize = NULL_IV_SIZE,
+ .setkey = null_setkey,
+ .encrypt = skcipher_null_crypt,
+ .decrypt = skcipher_null_crypt } }
+};
+
MODULE_ALIAS("compress_null");
MODULE_ALIAS("digest_null");
MODULE_ALIAS("cipher_null");
@@ -108,27 +150,35 @@
if (ret < 0)
goto out;
+ ret = crypto_register_alg(&skcipher_null);
+ if (ret < 0)
+ goto out_unregister_cipher;
+
ret = crypto_register_alg(&digest_null);
- if (ret < 0) {
- crypto_unregister_alg(&cipher_null);
- goto out;
- }
+ if (ret < 0)
+ goto out_unregister_skcipher;
ret = crypto_register_alg(&compress_null);
- if (ret < 0) {
- crypto_unregister_alg(&digest_null);
- crypto_unregister_alg(&cipher_null);
- goto out;
- }
+ if (ret < 0)
+ goto out_unregister_digest;
out:
return ret;
+
+out_unregister_digest:
+ crypto_unregister_alg(&digest_null);
+out_unregister_skcipher:
+ crypto_unregister_alg(&skcipher_null);
+out_unregister_cipher:
+ crypto_unregister_alg(&cipher_null);
+ goto out;
}
static void __exit fini(void)
{
crypto_unregister_alg(&compress_null);
crypto_unregister_alg(&digest_null);
+ crypto_unregister_alg(&skcipher_null);
crypto_unregister_alg(&cipher_null);
}
diff --git a/crypto/ctr.c b/crypto/ctr.c
new file mode 100644
index 0000000..2d7425f
--- /dev/null
+++ b/crypto/ctr.c
@@ -0,0 +1,422 @@
+/*
+ * CTR: Counter mode
+ *
+ * (C) Copyright IBM Corp. 2007 - Joy Latten <latten@us.ibm.com>
+ *
+ * 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 <crypto/algapi.h>
+#include <crypto/ctr.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/random.h>
+#include <linux/scatterlist.h>
+#include <linux/slab.h>
+
+struct crypto_ctr_ctx {
+ struct crypto_cipher *child;
+};
+
+struct crypto_rfc3686_ctx {
+ struct crypto_blkcipher *child;
+ u8 nonce[CTR_RFC3686_NONCE_SIZE];
+};
+
+static int crypto_ctr_setkey(struct crypto_tfm *parent, const u8 *key,
+ unsigned int keylen)
+{
+ struct crypto_ctr_ctx *ctx = crypto_tfm_ctx(parent);
+ struct crypto_cipher *child = ctx->child;
+ int err;
+
+ crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
+ crypto_cipher_set_flags(child, crypto_tfm_get_flags(parent) &
+ CRYPTO_TFM_REQ_MASK);
+ err = crypto_cipher_setkey(child, key, keylen);
+ crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) &
+ CRYPTO_TFM_RES_MASK);
+
+ return err;
+}
+
+static void crypto_ctr_crypt_final(struct blkcipher_walk *walk,
+ struct crypto_cipher *tfm)
+{
+ unsigned int bsize = crypto_cipher_blocksize(tfm);
+ unsigned long alignmask = crypto_cipher_alignmask(tfm);
+ u8 *ctrblk = walk->iv;
+ u8 tmp[bsize + alignmask];
+ u8 *keystream = PTR_ALIGN(tmp + 0, alignmask + 1);
+ u8 *src = walk->src.virt.addr;
+ u8 *dst = walk->dst.virt.addr;
+ unsigned int nbytes = walk->nbytes;
+
+ crypto_cipher_encrypt_one(tfm, keystream, ctrblk);
+ crypto_xor(keystream, src, nbytes);
+ memcpy(dst, keystream, nbytes);
+
+ crypto_inc(ctrblk, bsize);
+}
+
+static int crypto_ctr_crypt_segment(struct blkcipher_walk *walk,
+ struct crypto_cipher *tfm)
+{
+ void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
+ crypto_cipher_alg(tfm)->cia_encrypt;
+ unsigned int bsize = crypto_cipher_blocksize(tfm);
+ u8 *ctrblk = walk->iv;
+ u8 *src = walk->src.virt.addr;
+ u8 *dst = walk->dst.virt.addr;
+ unsigned int nbytes = walk->nbytes;
+
+ do {
+ /* create keystream */
+ fn(crypto_cipher_tfm(tfm), dst, ctrblk);
+ crypto_xor(dst, src, bsize);
+
+ /* increment counter in counterblock */
+ crypto_inc(ctrblk, bsize);
+
+ src += bsize;
+ dst += bsize;
+ } while ((nbytes -= bsize) >= bsize);
+
+ return nbytes;
+}
+
+static int crypto_ctr_crypt_inplace(struct blkcipher_walk *walk,
+ struct crypto_cipher *tfm)
+{
+ void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
+ crypto_cipher_alg(tfm)->cia_encrypt;
+ unsigned int bsize = crypto_cipher_blocksize(tfm);
+ unsigned long alignmask = crypto_cipher_alignmask(tfm);
+ unsigned int nbytes = walk->nbytes;
+ u8 *ctrblk = walk->iv;
+ u8 *src = walk->src.virt.addr;
+ u8 tmp[bsize + alignmask];
+ u8 *keystream = PTR_ALIGN(tmp + 0, alignmask + 1);
+
+ do {
+ /* create keystream */
+ fn(crypto_cipher_tfm(tfm), keystream, ctrblk);
+ crypto_xor(src, keystream, bsize);
+
+ /* increment counter in counterblock */
+ crypto_inc(ctrblk, bsize);
+
+ src += bsize;
+ } while ((nbytes -= bsize) >= bsize);
+
+ return nbytes;
+}
+
+static int crypto_ctr_crypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ struct blkcipher_walk walk;
+ struct crypto_blkcipher *tfm = desc->tfm;
+ struct crypto_ctr_ctx *ctx = crypto_blkcipher_ctx(tfm);
+ struct crypto_cipher *child = ctx->child;
+ unsigned int bsize = crypto_cipher_blocksize(child);
+ int err;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ err = blkcipher_walk_virt_block(desc, &walk, bsize);
+
+ while (walk.nbytes >= bsize) {
+ if (walk.src.virt.addr == walk.dst.virt.addr)
+ nbytes = crypto_ctr_crypt_inplace(&walk, child);
+ else
+ nbytes = crypto_ctr_crypt_segment(&walk, child);
+
+ err = blkcipher_walk_done(desc, &walk, nbytes);
+ }
+
+ if (walk.nbytes) {
+ crypto_ctr_crypt_final(&walk, child);
+ err = blkcipher_walk_done(desc, &walk, 0);
+ }
+
+ return err;
+}
+
+static int crypto_ctr_init_tfm(struct crypto_tfm *tfm)
+{
+ struct crypto_instance *inst = (void *)tfm->__crt_alg;
+ struct crypto_spawn *spawn = crypto_instance_ctx(inst);
+ struct crypto_ctr_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct crypto_cipher *cipher;
+
+ cipher = crypto_spawn_cipher(spawn);
+ if (IS_ERR(cipher))
+ return PTR_ERR(cipher);
+
+ ctx->child = cipher;
+
+ return 0;
+}
+
+static void crypto_ctr_exit_tfm(struct crypto_tfm *tfm)
+{
+ struct crypto_ctr_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ crypto_free_cipher(ctx->child);
+}
+
+static struct crypto_instance *crypto_ctr_alloc(struct rtattr **tb)
+{
+ struct crypto_instance *inst;
+ struct crypto_alg *alg;
+ int err;
+
+ err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
+ if (err)
+ return ERR_PTR(err);
+
+ alg = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_CIPHER,
+ CRYPTO_ALG_TYPE_MASK);
+ if (IS_ERR(alg))
+ return ERR_PTR(PTR_ERR(alg));
+
+ /* Block size must be >= 4 bytes. */
+ err = -EINVAL;
+ if (alg->cra_blocksize < 4)
+ goto out_put_alg;
+
+ /* If this is false we'd fail the alignment of crypto_inc. */
+ if (alg->cra_blocksize % 4)
+ goto out_put_alg;
+
+ inst = crypto_alloc_instance("ctr", alg);
+ if (IS_ERR(inst))
+ goto out;
+
+ inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER;
+ inst->alg.cra_priority = alg->cra_priority;
+ inst->alg.cra_blocksize = 1;
+ inst->alg.cra_alignmask = alg->cra_alignmask | (__alignof__(u32) - 1);
+ inst->alg.cra_type = &crypto_blkcipher_type;
+
+ inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize;
+ inst->alg.cra_blkcipher.min_keysize = alg->cra_cipher.cia_min_keysize;
+ inst->alg.cra_blkcipher.max_keysize = alg->cra_cipher.cia_max_keysize;
+
+ inst->alg.cra_ctxsize = sizeof(struct crypto_ctr_ctx);
+
+ inst->alg.cra_init = crypto_ctr_init_tfm;
+ inst->alg.cra_exit = crypto_ctr_exit_tfm;
+
+ inst->alg.cra_blkcipher.setkey = crypto_ctr_setkey;
+ inst->alg.cra_blkcipher.encrypt = crypto_ctr_crypt;
+ inst->alg.cra_blkcipher.decrypt = crypto_ctr_crypt;
+
+out:
+ crypto_mod_put(alg);
+ return inst;
+
+out_put_alg:
+ inst = ERR_PTR(err);
+ goto out;
+}
+
+static void crypto_ctr_free(struct crypto_instance *inst)
+{
+ crypto_drop_spawn(crypto_instance_ctx(inst));
+ kfree(inst);
+}
+
+static struct crypto_template crypto_ctr_tmpl = {
+ .name = "ctr",
+ .alloc = crypto_ctr_alloc,
+ .free = crypto_ctr_free,
+ .module = THIS_MODULE,
+};
+
+static int crypto_rfc3686_setkey(struct crypto_tfm *parent, const u8 *key,
+ unsigned int keylen)
+{
+ struct crypto_rfc3686_ctx *ctx = crypto_tfm_ctx(parent);
+ struct crypto_blkcipher *child = ctx->child;
+ int err;
+
+ /* the nonce is stored in bytes at end of key */
+ if (keylen < CTR_RFC3686_NONCE_SIZE)
+ return -EINVAL;
+
+ memcpy(ctx->nonce, key + (keylen - CTR_RFC3686_NONCE_SIZE),
+ CTR_RFC3686_NONCE_SIZE);
+
+ keylen -= CTR_RFC3686_NONCE_SIZE;
+
+ crypto_blkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
+ crypto_blkcipher_set_flags(child, crypto_tfm_get_flags(parent) &
+ CRYPTO_TFM_REQ_MASK);
+ err = crypto_blkcipher_setkey(child, key, keylen);
+ crypto_tfm_set_flags(parent, crypto_blkcipher_get_flags(child) &
+ CRYPTO_TFM_RES_MASK);
+
+ return err;
+}
+
+static int crypto_rfc3686_crypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst,
+ struct scatterlist *src, unsigned int nbytes)
+{
+ struct crypto_blkcipher *tfm = desc->tfm;
+ struct crypto_rfc3686_ctx *ctx = crypto_blkcipher_ctx(tfm);
+ struct crypto_blkcipher *child = ctx->child;
+ unsigned long alignmask = crypto_blkcipher_alignmask(tfm);
+ u8 ivblk[CTR_RFC3686_BLOCK_SIZE + alignmask];
+ u8 *iv = PTR_ALIGN(ivblk + 0, alignmask + 1);
+ u8 *info = desc->info;
+ int err;
+
+ /* set up counter block */
+ memcpy(iv, ctx->nonce, CTR_RFC3686_NONCE_SIZE);
+ memcpy(iv + CTR_RFC3686_NONCE_SIZE, info, CTR_RFC3686_IV_SIZE);
+
+ /* initialize counter portion of counter block */
+ *(__be32 *)(iv + CTR_RFC3686_NONCE_SIZE + CTR_RFC3686_IV_SIZE) =
+ cpu_to_be32(1);
+
+ desc->tfm = child;
+ desc->info = iv;
+ err = crypto_blkcipher_encrypt_iv(desc, dst, src, nbytes);
+ desc->tfm = tfm;
+ desc->info = info;
+
+ return err;
+}
+
+static int crypto_rfc3686_init_tfm(struct crypto_tfm *tfm)
+{
+ struct crypto_instance *inst = (void *)tfm->__crt_alg;
+ struct crypto_spawn *spawn = crypto_instance_ctx(inst);
+ struct crypto_rfc3686_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct crypto_blkcipher *cipher;
+
+ cipher = crypto_spawn_blkcipher(spawn);
+ if (IS_ERR(cipher))
+ return PTR_ERR(cipher);
+
+ ctx->child = cipher;
+
+ return 0;
+}
+
+static void crypto_rfc3686_exit_tfm(struct crypto_tfm *tfm)
+{
+ struct crypto_rfc3686_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ crypto_free_blkcipher(ctx->child);
+}
+
+static struct crypto_instance *crypto_rfc3686_alloc(struct rtattr **tb)
+{
+ struct crypto_instance *inst;
+ struct crypto_alg *alg;
+ int err;
+
+ err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
+ if (err)
+ return ERR_PTR(err);
+
+ alg = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_BLKCIPHER,
+ CRYPTO_ALG_TYPE_MASK);
+ err = PTR_ERR(alg);
+ if (IS_ERR(alg))
+ return ERR_PTR(err);
+
+ /* We only support 16-byte blocks. */
+ err = -EINVAL;
+ if (alg->cra_blkcipher.ivsize != CTR_RFC3686_BLOCK_SIZE)
+ goto out_put_alg;
+
+ /* Not a stream cipher? */
+ if (alg->cra_blocksize != 1)
+ goto out_put_alg;
+
+ inst = crypto_alloc_instance("rfc3686", alg);
+ if (IS_ERR(inst))
+ goto out;
+
+ inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER;
+ inst->alg.cra_priority = alg->cra_priority;
+ inst->alg.cra_blocksize = 1;
+ inst->alg.cra_alignmask = alg->cra_alignmask;
+ inst->alg.cra_type = &crypto_blkcipher_type;
+
+ inst->alg.cra_blkcipher.ivsize = CTR_RFC3686_IV_SIZE;
+ inst->alg.cra_blkcipher.min_keysize = alg->cra_blkcipher.min_keysize
+ + CTR_RFC3686_NONCE_SIZE;
+ inst->alg.cra_blkcipher.max_keysize = alg->cra_blkcipher.max_keysize
+ + CTR_RFC3686_NONCE_SIZE;
+
+ inst->alg.cra_blkcipher.geniv = "seqiv";
+
+ inst->alg.cra_ctxsize = sizeof(struct crypto_rfc3686_ctx);
+
+ inst->alg.cra_init = crypto_rfc3686_init_tfm;
+ inst->alg.cra_exit = crypto_rfc3686_exit_tfm;
+
+ inst->alg.cra_blkcipher.setkey = crypto_rfc3686_setkey;
+ inst->alg.cra_blkcipher.encrypt = crypto_rfc3686_crypt;
+ inst->alg.cra_blkcipher.decrypt = crypto_rfc3686_crypt;
+
+out:
+ crypto_mod_put(alg);
+ return inst;
+
+out_put_alg:
+ inst = ERR_PTR(err);
+ goto out;
+}
+
+static struct crypto_template crypto_rfc3686_tmpl = {
+ .name = "rfc3686",
+ .alloc = crypto_rfc3686_alloc,
+ .free = crypto_ctr_free,
+ .module = THIS_MODULE,
+};
+
+static int __init crypto_ctr_module_init(void)
+{
+ int err;
+
+ err = crypto_register_template(&crypto_ctr_tmpl);
+ if (err)
+ goto out;
+
+ err = crypto_register_template(&crypto_rfc3686_tmpl);
+ if (err)
+ goto out_drop_ctr;
+
+out:
+ return err;
+
+out_drop_ctr:
+ crypto_unregister_template(&crypto_ctr_tmpl);
+ goto out;
+}
+
+static void __exit crypto_ctr_module_exit(void)
+{
+ crypto_unregister_template(&crypto_rfc3686_tmpl);
+ crypto_unregister_template(&crypto_ctr_tmpl);
+}
+
+module_init(crypto_ctr_module_init);
+module_exit(crypto_ctr_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("CTR Counter block mode");
+MODULE_ALIAS("rfc3686");
diff --git a/crypto/des_generic.c b/crypto/des_generic.c
index 59966d1..355ecb7 100644
--- a/crypto/des_generic.c
+++ b/crypto/des_generic.c
@@ -20,13 +20,7 @@
#include <linux/crypto.h>
#include <linux/types.h>
-#define DES_KEY_SIZE 8
-#define DES_EXPKEY_WORDS 32
-#define DES_BLOCK_SIZE 8
-
-#define DES3_EDE_KEY_SIZE (3 * DES_KEY_SIZE)
-#define DES3_EDE_EXPKEY_WORDS (3 * DES_EXPKEY_WORDS)
-#define DES3_EDE_BLOCK_SIZE DES_BLOCK_SIZE
+#include <crypto/des.h>
#define ROL(x, r) ((x) = rol32((x), (r)))
#define ROR(x, r) ((x) = ror32((x), (r)))
@@ -634,7 +628,7 @@
* Choice 1 has operated on the key.
*
*/
-static unsigned long ekey(u32 *pe, const u8 *k)
+unsigned long des_ekey(u32 *pe, const u8 *k)
{
/* K&R: long is at least 32 bits */
unsigned long a, b, c, d, w;
@@ -709,6 +703,7 @@
/* Zero if weak key */
return w;
}
+EXPORT_SYMBOL_GPL(des_ekey);
/*
* Decryption key expansion
@@ -792,7 +787,7 @@
int ret;
/* Expand to tmp */
- ret = ekey(tmp, key);
+ ret = des_ekey(tmp, key);
if (unlikely(ret == 0) && (*flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
*flags |= CRYPTO_TFM_RES_WEAK_KEY;
@@ -879,9 +874,9 @@
return -EINVAL;
}
- ekey(expkey, key); expkey += DES_EXPKEY_WORDS; key += DES_KEY_SIZE;
+ des_ekey(expkey, key); expkey += DES_EXPKEY_WORDS; key += DES_KEY_SIZE;
dkey(expkey, key); expkey += DES_EXPKEY_WORDS; key += DES_KEY_SIZE;
- ekey(expkey, key);
+ des_ekey(expkey, key);
return 0;
}
diff --git a/crypto/digest.c b/crypto/digest.c
index 8871dec..6fd43bd 100644
--- a/crypto/digest.c
+++ b/crypto/digest.c
@@ -12,6 +12,7 @@
*
*/
+#include <crypto/scatterwalk.h>
#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/hardirq.h>
@@ -20,9 +21,6 @@
#include <linux/module.h>
#include <linux/scatterlist.h>
-#include "internal.h"
-#include "scatterwalk.h"
-
static int init(struct hash_desc *desc)
{
struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm);
diff --git a/crypto/eseqiv.c b/crypto/eseqiv.c
new file mode 100644
index 0000000..eb90d27
--- /dev/null
+++ b/crypto/eseqiv.c
@@ -0,0 +1,264 @@
+/*
+ * eseqiv: Encrypted Sequence Number IV Generator
+ *
+ * This generator generates an IV based on a sequence number by xoring it
+ * with a salt and then encrypting it with the same key as used to encrypt
+ * the plain text. This algorithm requires that the block size be equal
+ * to the IV size. It is mainly useful for CBC.
+ *
+ * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+#include <crypto/internal/skcipher.h>
+#include <crypto/scatterwalk.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/random.h>
+#include <linux/scatterlist.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+
+struct eseqiv_request_ctx {
+ struct scatterlist src[2];
+ struct scatterlist dst[2];
+ char tail[];
+};
+
+struct eseqiv_ctx {
+ spinlock_t lock;
+ unsigned int reqoff;
+ char salt[];
+};
+
+static void eseqiv_complete2(struct skcipher_givcrypt_request *req)
+{
+ struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
+ struct eseqiv_request_ctx *reqctx = skcipher_givcrypt_reqctx(req);
+
+ memcpy(req->giv, PTR_ALIGN((u8 *)reqctx->tail,
+ crypto_ablkcipher_alignmask(geniv) + 1),
+ crypto_ablkcipher_ivsize(geniv));
+}
+
+static void eseqiv_complete(struct crypto_async_request *base, int err)
+{
+ struct skcipher_givcrypt_request *req = base->data;
+
+ if (err)
+ goto out;
+
+ eseqiv_complete2(req);
+
+out:
+ skcipher_givcrypt_complete(req, err);
+}
+
+static void eseqiv_chain(struct scatterlist *head, struct scatterlist *sg,
+ int chain)
+{
+ if (chain) {
+ head->length += sg->length;
+ sg = scatterwalk_sg_next(sg);
+ }
+
+ if (sg)
+ scatterwalk_sg_chain(head, 2, sg);
+ else
+ sg_mark_end(head);
+}
+
+static int eseqiv_givencrypt(struct skcipher_givcrypt_request *req)
+{
+ struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
+ struct eseqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
+ struct eseqiv_request_ctx *reqctx = skcipher_givcrypt_reqctx(req);
+ struct ablkcipher_request *subreq;
+ crypto_completion_t complete;
+ void *data;
+ struct scatterlist *osrc, *odst;
+ struct scatterlist *dst;
+ struct page *srcp;
+ struct page *dstp;
+ u8 *giv;
+ u8 *vsrc;
+ u8 *vdst;
+ __be64 seq;
+ unsigned int ivsize;
+ unsigned int len;
+ int err;
+
+ subreq = (void *)(reqctx->tail + ctx->reqoff);
+ ablkcipher_request_set_tfm(subreq, skcipher_geniv_cipher(geniv));
+
+ giv = req->giv;
+ complete = req->creq.base.complete;
+ data = req->creq.base.data;
+
+ osrc = req->creq.src;
+ odst = req->creq.dst;
+ srcp = sg_page(osrc);
+ dstp = sg_page(odst);
+ vsrc = PageHighMem(srcp) ? NULL : page_address(srcp) + osrc->offset;
+ vdst = PageHighMem(dstp) ? NULL : page_address(dstp) + odst->offset;
+
+ ivsize = crypto_ablkcipher_ivsize(geniv);
+
+ if (vsrc != giv + ivsize && vdst != giv + ivsize) {
+ giv = PTR_ALIGN((u8 *)reqctx->tail,
+ crypto_ablkcipher_alignmask(geniv) + 1);
+ complete = eseqiv_complete;
+ data = req;
+ }
+
+ ablkcipher_request_set_callback(subreq, req->creq.base.flags, complete,
+ data);
+
+ sg_init_table(reqctx->src, 2);
+ sg_set_buf(reqctx->src, giv, ivsize);
+ eseqiv_chain(reqctx->src, osrc, vsrc == giv + ivsize);
+
+ dst = reqctx->src;
+ if (osrc != odst) {
+ sg_init_table(reqctx->dst, 2);
+ sg_set_buf(reqctx->dst, giv, ivsize);
+ eseqiv_chain(reqctx->dst, odst, vdst == giv + ivsize);
+
+ dst = reqctx->dst;
+ }
+
+ ablkcipher_request_set_crypt(subreq, reqctx->src, dst,
+ req->creq.nbytes, req->creq.info);
+
+ memcpy(req->creq.info, ctx->salt, ivsize);
+
+ len = ivsize;
+ if (ivsize > sizeof(u64)) {
+ memset(req->giv, 0, ivsize - sizeof(u64));
+ len = sizeof(u64);
+ }
+ seq = cpu_to_be64(req->seq);
+ memcpy(req->giv + ivsize - len, &seq, len);
+
+ err = crypto_ablkcipher_encrypt(subreq);
+ if (err)
+ goto out;
+
+ eseqiv_complete2(req);
+
+out:
+ return err;
+}
+
+static int eseqiv_givencrypt_first(struct skcipher_givcrypt_request *req)
+{
+ struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
+ struct eseqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
+
+ spin_lock_bh(&ctx->lock);
+ if (crypto_ablkcipher_crt(geniv)->givencrypt != eseqiv_givencrypt_first)
+ goto unlock;
+
+ crypto_ablkcipher_crt(geniv)->givencrypt = eseqiv_givencrypt;
+ get_random_bytes(ctx->salt, crypto_ablkcipher_ivsize(geniv));
+
+unlock:
+ spin_unlock_bh(&ctx->lock);
+
+ return eseqiv_givencrypt(req);
+}
+
+static int eseqiv_init(struct crypto_tfm *tfm)
+{
+ struct crypto_ablkcipher *geniv = __crypto_ablkcipher_cast(tfm);
+ struct eseqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
+ unsigned long alignmask;
+ unsigned int reqsize;
+
+ spin_lock_init(&ctx->lock);
+
+ alignmask = crypto_tfm_ctx_alignment() - 1;
+ reqsize = sizeof(struct eseqiv_request_ctx);
+
+ if (alignmask & reqsize) {
+ alignmask &= reqsize;
+ alignmask--;
+ }
+
+ alignmask = ~alignmask;
+ alignmask &= crypto_ablkcipher_alignmask(geniv);
+
+ reqsize += alignmask;
+ reqsize += crypto_ablkcipher_ivsize(geniv);
+ reqsize = ALIGN(reqsize, crypto_tfm_ctx_alignment());
+
+ ctx->reqoff = reqsize - sizeof(struct eseqiv_request_ctx);
+
+ tfm->crt_ablkcipher.reqsize = reqsize +
+ sizeof(struct ablkcipher_request);
+
+ return skcipher_geniv_init(tfm);
+}
+
+static struct crypto_template eseqiv_tmpl;
+
+static struct crypto_instance *eseqiv_alloc(struct rtattr **tb)
+{
+ struct crypto_instance *inst;
+ int err;
+
+ inst = skcipher_geniv_alloc(&eseqiv_tmpl, tb, 0, 0);
+ if (IS_ERR(inst))
+ goto out;
+
+ err = -EINVAL;
+ if (inst->alg.cra_ablkcipher.ivsize != inst->alg.cra_blocksize)
+ goto free_inst;
+
+ inst->alg.cra_ablkcipher.givencrypt = eseqiv_givencrypt_first;
+
+ inst->alg.cra_init = eseqiv_init;
+ inst->alg.cra_exit = skcipher_geniv_exit;
+
+ inst->alg.cra_ctxsize = sizeof(struct eseqiv_ctx);
+ inst->alg.cra_ctxsize += inst->alg.cra_ablkcipher.ivsize;
+
+out:
+ return inst;
+
+free_inst:
+ skcipher_geniv_free(inst);
+ inst = ERR_PTR(err);
+ goto out;
+}
+
+static struct crypto_template eseqiv_tmpl = {
+ .name = "eseqiv",
+ .alloc = eseqiv_alloc,
+ .free = skcipher_geniv_free,
+ .module = THIS_MODULE,
+};
+
+static int __init eseqiv_module_init(void)
+{
+ return crypto_register_template(&eseqiv_tmpl);
+}
+
+static void __exit eseqiv_module_exit(void)
+{
+ crypto_unregister_template(&eseqiv_tmpl);
+}
+
+module_init(eseqiv_module_init);
+module_exit(eseqiv_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Encrypted Sequence Number IV Generator");
diff --git a/crypto/gcm.c b/crypto/gcm.c
new file mode 100644
index 0000000..e70afd0
--- /dev/null
+++ b/crypto/gcm.c
@@ -0,0 +1,823 @@
+/*
+ * GCM: Galois/Counter Mode.
+ *
+ * Copyright (c) 2007 Nokia Siemens Networks - Mikko Herranen <mh1@iki.fi>
+ *
+ * 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 <crypto/gf128mul.h>
+#include <crypto/internal/aead.h>
+#include <crypto/internal/skcipher.h>
+#include <crypto/scatterwalk.h>
+#include <linux/completion.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+struct gcm_instance_ctx {
+ struct crypto_skcipher_spawn ctr;
+};
+
+struct crypto_gcm_ctx {
+ struct crypto_ablkcipher *ctr;
+ struct gf128mul_4k *gf128;
+};
+
+struct crypto_rfc4106_ctx {
+ struct crypto_aead *child;
+ u8 nonce[4];
+};
+
+struct crypto_gcm_ghash_ctx {
+ u32 bytes;
+ u32 flags;
+ struct gf128mul_4k *gf128;
+ u8 buffer[16];
+};
+
+struct crypto_gcm_req_priv_ctx {
+ u8 auth_tag[16];
+ u8 iauth_tag[16];
+ struct scatterlist src[2];
+ struct scatterlist dst[2];
+ struct crypto_gcm_ghash_ctx ghash;
+ struct ablkcipher_request abreq;
+};
+
+struct crypto_gcm_setkey_result {
+ int err;
+ struct completion completion;
+};
+
+static inline struct crypto_gcm_req_priv_ctx *crypto_gcm_reqctx(
+ struct aead_request *req)
+{
+ unsigned long align = crypto_aead_alignmask(crypto_aead_reqtfm(req));
+
+ return (void *)PTR_ALIGN((u8 *)aead_request_ctx(req), align + 1);
+}
+
+static void crypto_gcm_ghash_init(struct crypto_gcm_ghash_ctx *ctx, u32 flags,
+ struct gf128mul_4k *gf128)
+{
+ ctx->bytes = 0;
+ ctx->flags = flags;
+ ctx->gf128 = gf128;
+ memset(ctx->buffer, 0, 16);
+}
+
+static void crypto_gcm_ghash_update(struct crypto_gcm_ghash_ctx *ctx,
+ const u8 *src, unsigned int srclen)
+{
+ u8 *dst = ctx->buffer;
+
+ if (ctx->bytes) {
+ int n = min(srclen, ctx->bytes);
+ u8 *pos = dst + (16 - ctx->bytes);
+
+ ctx->bytes -= n;
+ srclen -= n;
+
+ while (n--)
+ *pos++ ^= *src++;
+
+ if (!ctx->bytes)
+ gf128mul_4k_lle((be128 *)dst, ctx->gf128);
+ }
+
+ while (srclen >= 16) {
+ crypto_xor(dst, src, 16);
+ gf128mul_4k_lle((be128 *)dst, ctx->gf128);
+ src += 16;
+ srclen -= 16;
+ }
+
+ if (srclen) {
+ ctx->bytes = 16 - srclen;
+ while (srclen--)
+ *dst++ ^= *src++;
+ }
+}
+
+static void crypto_gcm_ghash_update_sg(struct crypto_gcm_ghash_ctx *ctx,
+ struct scatterlist *sg, int len)
+{
+ struct scatter_walk walk;
+ u8 *src;
+ int n;
+
+ if (!len)
+ return;
+
+ scatterwalk_start(&walk, sg);
+
+ while (len) {
+ n = scatterwalk_clamp(&walk, len);
+
+ if (!n) {
+ scatterwalk_start(&walk, scatterwalk_sg_next(walk.sg));
+ n = scatterwalk_clamp(&walk, len);
+ }
+
+ src = scatterwalk_map(&walk, 0);
+
+ crypto_gcm_ghash_update(ctx, src, n);
+ len -= n;
+
+ scatterwalk_unmap(src, 0);
+ scatterwalk_advance(&walk, n);
+ scatterwalk_done(&walk, 0, len);
+ if (len)
+ crypto_yield(ctx->flags);
+ }
+}
+
+static void crypto_gcm_ghash_flush(struct crypto_gcm_ghash_ctx *ctx)
+{
+ u8 *dst = ctx->buffer;
+
+ if (ctx->bytes) {
+ u8 *tmp = dst + (16 - ctx->bytes);
+
+ while (ctx->bytes--)
+ *tmp++ ^= 0;
+
+ gf128mul_4k_lle((be128 *)dst, ctx->gf128);
+ }
+
+ ctx->bytes = 0;
+}
+
+static void crypto_gcm_ghash_final_xor(struct crypto_gcm_ghash_ctx *ctx,
+ unsigned int authlen,
+ unsigned int cryptlen, u8 *dst)
+{
+ u8 *buf = ctx->buffer;
+ u128 lengths;
+
+ lengths.a = cpu_to_be64(authlen * 8);
+ lengths.b = cpu_to_be64(cryptlen * 8);
+
+ crypto_gcm_ghash_flush(ctx);
+ crypto_xor(buf, (u8 *)&lengths, 16);
+ gf128mul_4k_lle((be128 *)buf, ctx->gf128);
+ crypto_xor(dst, buf, 16);
+}
+
+static void crypto_gcm_setkey_done(struct crypto_async_request *req, int err)
+{
+ struct crypto_gcm_setkey_result *result = req->data;
+
+ if (err == -EINPROGRESS)
+ return;
+
+ result->err = err;
+ complete(&result->completion);
+}
+
+static int crypto_gcm_setkey(struct crypto_aead *aead, const u8 *key,
+ unsigned int keylen)
+{
+ struct crypto_gcm_ctx *ctx = crypto_aead_ctx(aead);
+ struct crypto_ablkcipher *ctr = ctx->ctr;
+ struct {
+ be128 hash;
+ u8 iv[8];
+
+ struct crypto_gcm_setkey_result result;
+
+ struct scatterlist sg[1];
+ struct ablkcipher_request req;
+ } *data;
+ int err;
+
+ crypto_ablkcipher_clear_flags(ctr, CRYPTO_TFM_REQ_MASK);
+ crypto_ablkcipher_set_flags(ctr, crypto_aead_get_flags(aead) &
+ CRYPTO_TFM_REQ_MASK);
+
+ err = crypto_ablkcipher_setkey(ctr, key, keylen);
+ if (err)
+ return err;
+
+ crypto_aead_set_flags(aead, crypto_ablkcipher_get_flags(ctr) &
+ CRYPTO_TFM_RES_MASK);
+
+ data = kzalloc(sizeof(*data) + crypto_ablkcipher_reqsize(ctr),
+ GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ init_completion(&data->result.completion);
+ sg_init_one(data->sg, &data->hash, sizeof(data->hash));
+ ablkcipher_request_set_tfm(&data->req, ctr);
+ ablkcipher_request_set_callback(&data->req, CRYPTO_TFM_REQ_MAY_SLEEP |
+ CRYPTO_TFM_REQ_MAY_BACKLOG,
+ crypto_gcm_setkey_done,
+ &data->result);
+ ablkcipher_request_set_crypt(&data->req, data->sg, data->sg,
+ sizeof(data->hash), data->iv);
+
+ err = crypto_ablkcipher_encrypt(&data->req);
+ if (err == -EINPROGRESS || err == -EBUSY) {
+ err = wait_for_completion_interruptible(
+ &data->result.completion);
+ if (!err)
+ err = data->result.err;
+ }
+
+ if (err)
+ goto out;
+
+ if (ctx->gf128 != NULL)
+ gf128mul_free_4k(ctx->gf128);
+
+ ctx->gf128 = gf128mul_init_4k_lle(&data->hash);
+
+ if (ctx->gf128 == NULL)
+ err = -ENOMEM;
+
+out:
+ kfree(data);
+ return err;
+}
+
+static int crypto_gcm_setauthsize(struct crypto_aead *tfm,
+ unsigned int authsize)
+{
+ switch (authsize) {
+ case 4:
+ case 8:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void crypto_gcm_init_crypt(struct ablkcipher_request *ablk_req,
+ struct aead_request *req,
+ unsigned int cryptlen)
+{
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct crypto_gcm_ctx *ctx = crypto_aead_ctx(aead);
+ struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
+ u32 flags = req->base.tfm->crt_flags;
+ struct crypto_gcm_ghash_ctx *ghash = &pctx->ghash;
+ struct scatterlist *dst;
+ __be32 counter = cpu_to_be32(1);
+
+ memset(pctx->auth_tag, 0, sizeof(pctx->auth_tag));
+ memcpy(req->iv + 12, &counter, 4);
+
+ sg_init_table(pctx->src, 2);
+ sg_set_buf(pctx->src, pctx->auth_tag, sizeof(pctx->auth_tag));
+ scatterwalk_sg_chain(pctx->src, 2, req->src);
+
+ dst = pctx->src;
+ if (req->src != req->dst) {
+ sg_init_table(pctx->dst, 2);
+ sg_set_buf(pctx->dst, pctx->auth_tag, sizeof(pctx->auth_tag));
+ scatterwalk_sg_chain(pctx->dst, 2, req->dst);
+ dst = pctx->dst;
+ }
+
+ ablkcipher_request_set_tfm(ablk_req, ctx->ctr);
+ ablkcipher_request_set_crypt(ablk_req, pctx->src, dst,
+ cryptlen + sizeof(pctx->auth_tag),
+ req->iv);
+
+ crypto_gcm_ghash_init(ghash, flags, ctx->gf128);
+
+ crypto_gcm_ghash_update_sg(ghash, req->assoc, req->assoclen);
+ crypto_gcm_ghash_flush(ghash);
+}
+
+static int crypto_gcm_hash(struct aead_request *req)
+{
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
+ u8 *auth_tag = pctx->auth_tag;
+ struct crypto_gcm_ghash_ctx *ghash = &pctx->ghash;
+
+ crypto_gcm_ghash_update_sg(ghash, req->dst, req->cryptlen);
+ crypto_gcm_ghash_final_xor(ghash, req->assoclen, req->cryptlen,
+ auth_tag);
+
+ scatterwalk_map_and_copy(auth_tag, req->dst, req->cryptlen,
+ crypto_aead_authsize(aead), 1);
+ return 0;
+}
+
+static void crypto_gcm_encrypt_done(struct crypto_async_request *areq, int err)
+{
+ struct aead_request *req = areq->data;
+
+ if (!err)
+ err = crypto_gcm_hash(req);
+
+ aead_request_complete(req, err);
+}
+
+static int crypto_gcm_encrypt(struct aead_request *req)
+{
+ struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
+ struct ablkcipher_request *abreq = &pctx->abreq;
+ int err;
+
+ crypto_gcm_init_crypt(abreq, req, req->cryptlen);
+ ablkcipher_request_set_callback(abreq, aead_request_flags(req),
+ crypto_gcm_encrypt_done, req);
+
+ err = crypto_ablkcipher_encrypt(abreq);
+ if (err)
+ return err;
+
+ return crypto_gcm_hash(req);
+}
+
+static int crypto_gcm_verify(struct aead_request *req)
+{
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
+ struct crypto_gcm_ghash_ctx *ghash = &pctx->ghash;
+ u8 *auth_tag = pctx->auth_tag;
+ u8 *iauth_tag = pctx->iauth_tag;
+ unsigned int authsize = crypto_aead_authsize(aead);
+ unsigned int cryptlen = req->cryptlen - authsize;
+
+ crypto_gcm_ghash_final_xor(ghash, req->assoclen, cryptlen, auth_tag);
+
+ authsize = crypto_aead_authsize(aead);
+ scatterwalk_map_and_copy(iauth_tag, req->src, cryptlen, authsize, 0);
+ return memcmp(iauth_tag, auth_tag, authsize) ? -EBADMSG : 0;
+}
+
+static void crypto_gcm_decrypt_done(struct crypto_async_request *areq, int err)
+{
+ struct aead_request *req = areq->data;
+
+ if (!err)
+ err = crypto_gcm_verify(req);
+
+ aead_request_complete(req, err);
+}
+
+static int crypto_gcm_decrypt(struct aead_request *req)
+{
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
+ struct ablkcipher_request *abreq = &pctx->abreq;
+ struct crypto_gcm_ghash_ctx *ghash = &pctx->ghash;
+ unsigned int cryptlen = req->cryptlen;
+ unsigned int authsize = crypto_aead_authsize(aead);
+ int err;
+
+ if (cryptlen < authsize)
+ return -EINVAL;
+ cryptlen -= authsize;
+
+ crypto_gcm_init_crypt(abreq, req, cryptlen);
+ ablkcipher_request_set_callback(abreq, aead_request_flags(req),
+ crypto_gcm_decrypt_done, req);
+
+ crypto_gcm_ghash_update_sg(ghash, req->src, cryptlen);
+
+ err = crypto_ablkcipher_decrypt(abreq);
+ if (err)
+ return err;
+
+ return crypto_gcm_verify(req);
+}
+
+static int crypto_gcm_init_tfm(struct crypto_tfm *tfm)
+{
+ struct crypto_instance *inst = (void *)tfm->__crt_alg;
+ struct gcm_instance_ctx *ictx = crypto_instance_ctx(inst);
+ struct crypto_gcm_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct crypto_ablkcipher *ctr;
+ unsigned long align;
+ int err;
+
+ ctr = crypto_spawn_skcipher(&ictx->ctr);
+ err = PTR_ERR(ctr);
+ if (IS_ERR(ctr))
+ return err;
+
+ ctx->ctr = ctr;
+ ctx->gf128 = NULL;
+
+ align = crypto_tfm_alg_alignmask(tfm);
+ align &= ~(crypto_tfm_ctx_alignment() - 1);
+ tfm->crt_aead.reqsize = align +
+ sizeof(struct crypto_gcm_req_priv_ctx) +
+ crypto_ablkcipher_reqsize(ctr);
+
+ return 0;
+}
+
+static void crypto_gcm_exit_tfm(struct crypto_tfm *tfm)
+{
+ struct crypto_gcm_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ if (ctx->gf128 != NULL)
+ gf128mul_free_4k(ctx->gf128);
+
+ crypto_free_ablkcipher(ctx->ctr);
+}
+
+static struct crypto_instance *crypto_gcm_alloc_common(struct rtattr **tb,
+ const char *full_name,
+ const char *ctr_name)
+{
+ struct crypto_attr_type *algt;
+ struct crypto_instance *inst;
+ struct crypto_alg *ctr;
+ struct gcm_instance_ctx *ctx;
+ int err;
+
+ algt = crypto_get_attr_type(tb);
+ err = PTR_ERR(algt);
+ if (IS_ERR(algt))
+ return ERR_PTR(err);
+
+ if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
+ return ERR_PTR(-EINVAL);
+
+ inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
+ if (!inst)
+ return ERR_PTR(-ENOMEM);
+
+ ctx = crypto_instance_ctx(inst);
+ crypto_set_skcipher_spawn(&ctx->ctr, inst);
+ err = crypto_grab_skcipher(&ctx->ctr, ctr_name, 0,
+ crypto_requires_sync(algt->type,
+ algt->mask));
+ if (err)
+ goto err_free_inst;
+
+ ctr = crypto_skcipher_spawn_alg(&ctx->ctr);
+
+ /* We only support 16-byte blocks. */
+ if (ctr->cra_ablkcipher.ivsize != 16)
+ goto out_put_ctr;
+
+ /* Not a stream cipher? */
+ err = -EINVAL;
+ if (ctr->cra_blocksize != 1)
+ goto out_put_ctr;
+
+ err = -ENAMETOOLONG;
+ if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
+ "gcm_base(%s)", ctr->cra_driver_name) >=
+ CRYPTO_MAX_ALG_NAME)
+ goto out_put_ctr;
+
+ memcpy(inst->alg.cra_name, full_name, CRYPTO_MAX_ALG_NAME);
+
+ inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD;
+ inst->alg.cra_flags |= ctr->cra_flags & CRYPTO_ALG_ASYNC;
+ inst->alg.cra_priority = ctr->cra_priority;
+ inst->alg.cra_blocksize = 1;
+ inst->alg.cra_alignmask = ctr->cra_alignmask | (__alignof__(u64) - 1);
+ inst->alg.cra_type = &crypto_aead_type;
+ inst->alg.cra_aead.ivsize = 16;
+ inst->alg.cra_aead.maxauthsize = 16;
+ inst->alg.cra_ctxsize = sizeof(struct crypto_gcm_ctx);
+ inst->alg.cra_init = crypto_gcm_init_tfm;
+ inst->alg.cra_exit = crypto_gcm_exit_tfm;
+ inst->alg.cra_aead.setkey = crypto_gcm_setkey;
+ inst->alg.cra_aead.setauthsize = crypto_gcm_setauthsize;
+ inst->alg.cra_aead.encrypt = crypto_gcm_encrypt;
+ inst->alg.cra_aead.decrypt = crypto_gcm_decrypt;
+
+out:
+ return inst;
+
+out_put_ctr:
+ crypto_drop_skcipher(&ctx->ctr);
+err_free_inst:
+ kfree(inst);
+ inst = ERR_PTR(err);
+ goto out;
+}
+
+static struct crypto_instance *crypto_gcm_alloc(struct rtattr **tb)
+{
+ int err;
+ const char *cipher_name;
+ char ctr_name[CRYPTO_MAX_ALG_NAME];
+ char full_name[CRYPTO_MAX_ALG_NAME];
+
+ cipher_name = crypto_attr_alg_name(tb[1]);
+ err = PTR_ERR(cipher_name);
+ if (IS_ERR(cipher_name))
+ return ERR_PTR(err);
+
+ if (snprintf(ctr_name, CRYPTO_MAX_ALG_NAME, "ctr(%s)", cipher_name) >=
+ CRYPTO_MAX_ALG_NAME)
+ return ERR_PTR(-ENAMETOOLONG);
+
+ if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "gcm(%s)", cipher_name) >=
+ CRYPTO_MAX_ALG_NAME)
+ return ERR_PTR(-ENAMETOOLONG);
+
+ return crypto_gcm_alloc_common(tb, full_name, ctr_name);
+}
+
+static void crypto_gcm_free(struct crypto_instance *inst)
+{
+ struct gcm_instance_ctx *ctx = crypto_instance_ctx(inst);
+
+ crypto_drop_skcipher(&ctx->ctr);
+ kfree(inst);
+}
+
+static struct crypto_template crypto_gcm_tmpl = {
+ .name = "gcm",
+ .alloc = crypto_gcm_alloc,
+ .free = crypto_gcm_free,
+ .module = THIS_MODULE,
+};
+
+static struct crypto_instance *crypto_gcm_base_alloc(struct rtattr **tb)
+{
+ int err;
+ const char *ctr_name;
+ char full_name[CRYPTO_MAX_ALG_NAME];
+
+ ctr_name = crypto_attr_alg_name(tb[1]);
+ err = PTR_ERR(ctr_name);
+ if (IS_ERR(ctr_name))
+ return ERR_PTR(err);
+
+ if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "gcm_base(%s)",
+ ctr_name) >= CRYPTO_MAX_ALG_NAME)
+ return ERR_PTR(-ENAMETOOLONG);
+
+ return crypto_gcm_alloc_common(tb, full_name, ctr_name);
+}
+
+static struct crypto_template crypto_gcm_base_tmpl = {
+ .name = "gcm_base",
+ .alloc = crypto_gcm_base_alloc,
+ .free = crypto_gcm_free,
+ .module = THIS_MODULE,
+};
+
+static int crypto_rfc4106_setkey(struct crypto_aead *parent, const u8 *key,
+ unsigned int keylen)
+{
+ struct crypto_rfc4106_ctx *ctx = crypto_aead_ctx(parent);
+ struct crypto_aead *child = ctx->child;
+ int err;
+
+ if (keylen < 4)
+ return -EINVAL;
+
+ keylen -= 4;
+ memcpy(ctx->nonce, key + keylen, 4);
+
+ crypto_aead_clear_flags(child, CRYPTO_TFM_REQ_MASK);
+ crypto_aead_set_flags(child, crypto_aead_get_flags(parent) &
+ CRYPTO_TFM_REQ_MASK);
+ err = crypto_aead_setkey(child, key, keylen);
+ crypto_aead_set_flags(parent, crypto_aead_get_flags(child) &
+ CRYPTO_TFM_RES_MASK);
+
+ return err;
+}
+
+static int crypto_rfc4106_setauthsize(struct crypto_aead *parent,
+ unsigned int authsize)
+{
+ struct crypto_rfc4106_ctx *ctx = crypto_aead_ctx(parent);
+
+ switch (authsize) {
+ case 8:
+ case 12:
+ case 16:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return crypto_aead_setauthsize(ctx->child, authsize);
+}
+
+static struct aead_request *crypto_rfc4106_crypt(struct aead_request *req)
+{
+ struct aead_request *subreq = aead_request_ctx(req);
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct crypto_rfc4106_ctx *ctx = crypto_aead_ctx(aead);
+ struct crypto_aead *child = ctx->child;
+ u8 *iv = PTR_ALIGN((u8 *)(subreq + 1) + crypto_aead_reqsize(child),
+ crypto_aead_alignmask(child) + 1);
+
+ memcpy(iv, ctx->nonce, 4);
+ memcpy(iv + 4, req->iv, 8);
+
+ aead_request_set_tfm(subreq, child);
+ aead_request_set_callback(subreq, req->base.flags, req->base.complete,
+ req->base.data);
+ aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen, iv);
+ aead_request_set_assoc(subreq, req->assoc, req->assoclen);
+
+ return subreq;
+}
+
+static int crypto_rfc4106_encrypt(struct aead_request *req)
+{
+ req = crypto_rfc4106_crypt(req);
+
+ return crypto_aead_encrypt(req);
+}
+
+static int crypto_rfc4106_decrypt(struct aead_request *req)
+{
+ req = crypto_rfc4106_crypt(req);
+
+ return crypto_aead_decrypt(req);
+}
+
+static int crypto_rfc4106_init_tfm(struct crypto_tfm *tfm)
+{
+ struct crypto_instance *inst = (void *)tfm->__crt_alg;
+ struct crypto_aead_spawn *spawn = crypto_instance_ctx(inst);
+ struct crypto_rfc4106_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct crypto_aead *aead;
+ unsigned long align;
+
+ aead = crypto_spawn_aead(spawn);
+ if (IS_ERR(aead))
+ return PTR_ERR(aead);
+
+ ctx->child = aead;
+
+ align = crypto_aead_alignmask(aead);
+ align &= ~(crypto_tfm_ctx_alignment() - 1);
+ tfm->crt_aead.reqsize = sizeof(struct aead_request) +
+ ALIGN(crypto_aead_reqsize(aead),
+ crypto_tfm_ctx_alignment()) +
+ align + 16;
+
+ return 0;
+}
+
+static void crypto_rfc4106_exit_tfm(struct crypto_tfm *tfm)
+{
+ struct crypto_rfc4106_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ crypto_free_aead(ctx->child);
+}
+
+static struct crypto_instance *crypto_rfc4106_alloc(struct rtattr **tb)
+{
+ struct crypto_attr_type *algt;
+ struct crypto_instance *inst;
+ struct crypto_aead_spawn *spawn;
+ struct crypto_alg *alg;
+ const char *ccm_name;
+ int err;
+
+ algt = crypto_get_attr_type(tb);
+ err = PTR_ERR(algt);
+ if (IS_ERR(algt))
+ return ERR_PTR(err);
+
+ if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
+ return ERR_PTR(-EINVAL);
+
+ ccm_name = crypto_attr_alg_name(tb[1]);
+ err = PTR_ERR(ccm_name);
+ if (IS_ERR(ccm_name))
+ return ERR_PTR(err);
+
+ inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
+ if (!inst)
+ return ERR_PTR(-ENOMEM);
+
+ spawn = crypto_instance_ctx(inst);
+ crypto_set_aead_spawn(spawn, inst);
+ err = crypto_grab_aead(spawn, ccm_name, 0,
+ crypto_requires_sync(algt->type, algt->mask));
+ if (err)
+ goto out_free_inst;
+
+ alg = crypto_aead_spawn_alg(spawn);
+
+ err = -EINVAL;
+
+ /* We only support 16-byte blocks. */
+ if (alg->cra_aead.ivsize != 16)
+ goto out_drop_alg;
+
+ /* Not a stream cipher? */
+ if (alg->cra_blocksize != 1)
+ goto out_drop_alg;
+
+ err = -ENAMETOOLONG;
+ if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
+ "rfc4106(%s)", alg->cra_name) >= CRYPTO_MAX_ALG_NAME ||
+ snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
+ "rfc4106(%s)", alg->cra_driver_name) >=
+ CRYPTO_MAX_ALG_NAME)
+ goto out_drop_alg;
+
+ inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD;
+ inst->alg.cra_flags |= alg->cra_flags & CRYPTO_ALG_ASYNC;
+ inst->alg.cra_priority = alg->cra_priority;
+ inst->alg.cra_blocksize = 1;
+ inst->alg.cra_alignmask = alg->cra_alignmask;
+ inst->alg.cra_type = &crypto_nivaead_type;
+
+ inst->alg.cra_aead.ivsize = 8;
+ inst->alg.cra_aead.maxauthsize = 16;
+
+ inst->alg.cra_ctxsize = sizeof(struct crypto_rfc4106_ctx);
+
+ inst->alg.cra_init = crypto_rfc4106_init_tfm;
+ inst->alg.cra_exit = crypto_rfc4106_exit_tfm;
+
+ inst->alg.cra_aead.setkey = crypto_rfc4106_setkey;
+ inst->alg.cra_aead.setauthsize = crypto_rfc4106_setauthsize;
+ inst->alg.cra_aead.encrypt = crypto_rfc4106_encrypt;
+ inst->alg.cra_aead.decrypt = crypto_rfc4106_decrypt;
+
+ inst->alg.cra_aead.geniv = "seqiv";
+
+out:
+ return inst;
+
+out_drop_alg:
+ crypto_drop_aead(spawn);
+out_free_inst:
+ kfree(inst);
+ inst = ERR_PTR(err);
+ goto out;
+}
+
+static void crypto_rfc4106_free(struct crypto_instance *inst)
+{
+ crypto_drop_spawn(crypto_instance_ctx(inst));
+ kfree(inst);
+}
+
+static struct crypto_template crypto_rfc4106_tmpl = {
+ .name = "rfc4106",
+ .alloc = crypto_rfc4106_alloc,
+ .free = crypto_rfc4106_free,
+ .module = THIS_MODULE,
+};
+
+static int __init crypto_gcm_module_init(void)
+{
+ int err;
+
+ err = crypto_register_template(&crypto_gcm_base_tmpl);
+ if (err)
+ goto out;
+
+ err = crypto_register_template(&crypto_gcm_tmpl);
+ if (err)
+ goto out_undo_base;
+
+ err = crypto_register_template(&crypto_rfc4106_tmpl);
+ if (err)
+ goto out_undo_gcm;
+
+out:
+ return err;
+
+out_undo_gcm:
+ crypto_unregister_template(&crypto_gcm_tmpl);
+out_undo_base:
+ crypto_unregister_template(&crypto_gcm_base_tmpl);
+ goto out;
+}
+
+static void __exit crypto_gcm_module_exit(void)
+{
+ crypto_unregister_template(&crypto_rfc4106_tmpl);
+ crypto_unregister_template(&crypto_gcm_tmpl);
+ crypto_unregister_template(&crypto_gcm_base_tmpl);
+}
+
+module_init(crypto_gcm_module_init);
+module_exit(crypto_gcm_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Galois/Counter Mode");
+MODULE_AUTHOR("Mikko Herranen <mh1@iki.fi>");
+MODULE_ALIAS("gcm_base");
+MODULE_ALIAS("rfc4106");
diff --git a/crypto/hmac.c b/crypto/hmac.c
index 0f05be7..a1d016a 100644
--- a/crypto/hmac.c
+++ b/crypto/hmac.c
@@ -17,6 +17,7 @@
*/
#include <crypto/algapi.h>
+#include <crypto/scatterwalk.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/kernel.h>
@@ -160,7 +161,7 @@
sg_init_table(sg1, 2);
sg_set_buf(sg1, ipad, bs);
- sg_set_page(&sg1[1], (void *) sg, 0, 0);
+ scatterwalk_sg_chain(sg1, 2, sg);
sg_init_table(sg2, 1);
sg_set_buf(sg2, opad, bs + ds);
diff --git a/crypto/internal.h b/crypto/internal.h
index abb01f7..32f4c21 100644
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -25,7 +25,6 @@
#include <linux/notifier.h>
#include <linux/rwsem.h>
#include <linux/slab.h>
-#include <asm/kmap_types.h>
/* Crypto notification events. */
enum {
@@ -50,34 +49,6 @@
extern struct rw_semaphore crypto_alg_sem;
extern struct blocking_notifier_head crypto_chain;
-static inline enum km_type crypto_kmap_type(int out)
-{
- enum km_type type;
-
- if (in_softirq())
- type = out * (KM_SOFTIRQ1 - KM_SOFTIRQ0) + KM_SOFTIRQ0;
- else
- type = out * (KM_USER1 - KM_USER0) + KM_USER0;
-
- return type;
-}
-
-static inline void *crypto_kmap(struct page *page, int out)
-{
- return kmap_atomic(page, crypto_kmap_type(out));
-}
-
-static inline void crypto_kunmap(void *vaddr, int out)
-{
- kunmap_atomic(vaddr, crypto_kmap_type(out));
-}
-
-static inline void crypto_yield(u32 flags)
-{
- if (flags & CRYPTO_TFM_REQ_MAY_SLEEP)
- cond_resched();
-}
-
#ifdef CONFIG_PROC_FS
void __init crypto_init_proc(void);
void __exit crypto_exit_proc(void);
@@ -122,6 +93,8 @@
void crypto_exit_cipher_ops(struct crypto_tfm *tfm);
void crypto_exit_compress_ops(struct crypto_tfm *tfm);
+void crypto_larval_kill(struct crypto_alg *alg);
+struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask);
void crypto_larval_error(const char *name, u32 type, u32 mask);
void crypto_shoot_alg(struct crypto_alg *alg);
diff --git a/crypto/lzo.c b/crypto/lzo.c
new file mode 100644
index 0000000..48c3288
--- /dev/null
+++ b/crypto/lzo.c
@@ -0,0 +1,106 @@
+/*
+ * Cryptographic API.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/crypto.h>
+#include <linux/vmalloc.h>
+#include <linux/lzo.h>
+
+struct lzo_ctx {
+ void *lzo_comp_mem;
+};
+
+static int lzo_init(struct crypto_tfm *tfm)
+{
+ struct lzo_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ ctx->lzo_comp_mem = vmalloc(LZO1X_MEM_COMPRESS);
+ if (!ctx->lzo_comp_mem)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static void lzo_exit(struct crypto_tfm *tfm)
+{
+ struct lzo_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ vfree(ctx->lzo_comp_mem);
+}
+
+static int lzo_compress(struct crypto_tfm *tfm, const u8 *src,
+ unsigned int slen, u8 *dst, unsigned int *dlen)
+{
+ struct lzo_ctx *ctx = crypto_tfm_ctx(tfm);
+ size_t tmp_len = *dlen; /* size_t(ulong) <-> uint on 64 bit */
+ int err;
+
+ err = lzo1x_1_compress(src, slen, dst, &tmp_len, ctx->lzo_comp_mem);
+
+ if (err != LZO_E_OK)
+ return -EINVAL;
+
+ *dlen = tmp_len;
+ return 0;
+}
+
+static int lzo_decompress(struct crypto_tfm *tfm, const u8 *src,
+ unsigned int slen, u8 *dst, unsigned int *dlen)
+{
+ int err;
+ size_t tmp_len = *dlen; /* size_t(ulong) <-> uint on 64 bit */
+
+ err = lzo1x_decompress_safe(src, slen, dst, &tmp_len);
+
+ if (err != LZO_E_OK)
+ return -EINVAL;
+
+ *dlen = tmp_len;
+ return 0;
+
+}
+
+static struct crypto_alg alg = {
+ .cra_name = "lzo",
+ .cra_flags = CRYPTO_ALG_TYPE_COMPRESS,
+ .cra_ctxsize = sizeof(struct lzo_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(alg.cra_list),
+ .cra_init = lzo_init,
+ .cra_exit = lzo_exit,
+ .cra_u = { .compress = {
+ .coa_compress = lzo_compress,
+ .coa_decompress = lzo_decompress } }
+};
+
+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_LICENSE("GPL");
+MODULE_DESCRIPTION("LZO Compression Algorithm");
diff --git a/crypto/pcbc.c b/crypto/pcbc.c
index c3ed8a1..fe70477 100644
--- a/crypto/pcbc.c
+++ b/crypto/pcbc.c
@@ -24,7 +24,6 @@
struct crypto_pcbc_ctx {
struct crypto_cipher *child;
- void (*xor)(u8 *dst, const u8 *src, unsigned int bs);
};
static int crypto_pcbc_setkey(struct crypto_tfm *parent, const u8 *key,
@@ -45,9 +44,7 @@
static int crypto_pcbc_encrypt_segment(struct blkcipher_desc *desc,
struct blkcipher_walk *walk,
- struct crypto_cipher *tfm,
- void (*xor)(u8 *, const u8 *,
- unsigned int))
+ struct crypto_cipher *tfm)
{
void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
crypto_cipher_alg(tfm)->cia_encrypt;
@@ -58,10 +55,10 @@
u8 *iv = walk->iv;
do {
- xor(iv, src, bsize);
+ crypto_xor(iv, src, bsize);
fn(crypto_cipher_tfm(tfm), dst, iv);
memcpy(iv, dst, bsize);
- xor(iv, src, bsize);
+ crypto_xor(iv, src, bsize);
src += bsize;
dst += bsize;
@@ -72,9 +69,7 @@
static int crypto_pcbc_encrypt_inplace(struct blkcipher_desc *desc,
struct blkcipher_walk *walk,
- struct crypto_cipher *tfm,
- void (*xor)(u8 *, const u8 *,
- unsigned int))
+ struct crypto_cipher *tfm)
{
void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
crypto_cipher_alg(tfm)->cia_encrypt;
@@ -86,10 +81,10 @@
do {
memcpy(tmpbuf, src, bsize);
- xor(iv, tmpbuf, bsize);
+ crypto_xor(iv, src, bsize);
fn(crypto_cipher_tfm(tfm), src, iv);
- memcpy(iv, src, bsize);
- xor(iv, tmpbuf, bsize);
+ memcpy(iv, tmpbuf, bsize);
+ crypto_xor(iv, src, bsize);
src += bsize;
} while ((nbytes -= bsize) >= bsize);
@@ -107,7 +102,6 @@
struct crypto_blkcipher *tfm = desc->tfm;
struct crypto_pcbc_ctx *ctx = crypto_blkcipher_ctx(tfm);
struct crypto_cipher *child = ctx->child;
- void (*xor)(u8 *, const u8 *, unsigned int bs) = ctx->xor;
int err;
blkcipher_walk_init(&walk, dst, src, nbytes);
@@ -115,11 +109,11 @@
while ((nbytes = walk.nbytes)) {
if (walk.src.virt.addr == walk.dst.virt.addr)
- nbytes = crypto_pcbc_encrypt_inplace(desc, &walk, child,
- xor);
+ nbytes = crypto_pcbc_encrypt_inplace(desc, &walk,
+ child);
else
- nbytes = crypto_pcbc_encrypt_segment(desc, &walk, child,
- xor);
+ nbytes = crypto_pcbc_encrypt_segment(desc, &walk,
+ child);
err = blkcipher_walk_done(desc, &walk, nbytes);
}
@@ -128,9 +122,7 @@
static int crypto_pcbc_decrypt_segment(struct blkcipher_desc *desc,
struct blkcipher_walk *walk,
- struct crypto_cipher *tfm,
- void (*xor)(u8 *, const u8 *,
- unsigned int))
+ struct crypto_cipher *tfm)
{
void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
crypto_cipher_alg(tfm)->cia_decrypt;
@@ -142,9 +134,9 @@
do {
fn(crypto_cipher_tfm(tfm), dst, src);
- xor(dst, iv, bsize);
+ crypto_xor(dst, iv, bsize);
memcpy(iv, src, bsize);
- xor(iv, dst, bsize);
+ crypto_xor(iv, dst, bsize);
src += bsize;
dst += bsize;
@@ -157,9 +149,7 @@
static int crypto_pcbc_decrypt_inplace(struct blkcipher_desc *desc,
struct blkcipher_walk *walk,
- struct crypto_cipher *tfm,
- void (*xor)(u8 *, const u8 *,
- unsigned int))
+ struct crypto_cipher *tfm)
{
void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
crypto_cipher_alg(tfm)->cia_decrypt;
@@ -172,9 +162,9 @@
do {
memcpy(tmpbuf, src, bsize);
fn(crypto_cipher_tfm(tfm), src, src);
- xor(src, iv, bsize);
+ crypto_xor(src, iv, bsize);
memcpy(iv, tmpbuf, bsize);
- xor(iv, src, bsize);
+ crypto_xor(iv, src, bsize);
src += bsize;
} while ((nbytes -= bsize) >= bsize);
@@ -192,7 +182,6 @@
struct crypto_blkcipher *tfm = desc->tfm;
struct crypto_pcbc_ctx *ctx = crypto_blkcipher_ctx(tfm);
struct crypto_cipher *child = ctx->child;
- void (*xor)(u8 *, const u8 *, unsigned int bs) = ctx->xor;
int err;
blkcipher_walk_init(&walk, dst, src, nbytes);
@@ -200,48 +189,17 @@
while ((nbytes = walk.nbytes)) {
if (walk.src.virt.addr == walk.dst.virt.addr)
- nbytes = crypto_pcbc_decrypt_inplace(desc, &walk, child,
- xor);
+ nbytes = crypto_pcbc_decrypt_inplace(desc, &walk,
+ child);
else
- nbytes = crypto_pcbc_decrypt_segment(desc, &walk, child,
- xor);
+ nbytes = crypto_pcbc_decrypt_segment(desc, &walk,
+ child);
err = blkcipher_walk_done(desc, &walk, nbytes);
}
return err;
}
-static void xor_byte(u8 *a, const u8 *b, unsigned int bs)
-{
- do {
- *a++ ^= *b++;
- } while (--bs);
-}
-
-static void xor_quad(u8 *dst, const u8 *src, unsigned int bs)
-{
- u32 *a = (u32 *)dst;
- u32 *b = (u32 *)src;
-
- do {
- *a++ ^= *b++;
- } while ((bs -= 4));
-}
-
-static void xor_64(u8 *a, const u8 *b, unsigned int bs)
-{
- ((u32 *)a)[0] ^= ((u32 *)b)[0];
- ((u32 *)a)[1] ^= ((u32 *)b)[1];
-}
-
-static void xor_128(u8 *a, const u8 *b, unsigned int bs)
-{
- ((u32 *)a)[0] ^= ((u32 *)b)[0];
- ((u32 *)a)[1] ^= ((u32 *)b)[1];
- ((u32 *)a)[2] ^= ((u32 *)b)[2];
- ((u32 *)a)[3] ^= ((u32 *)b)[3];
-}
-
static int crypto_pcbc_init_tfm(struct crypto_tfm *tfm)
{
struct crypto_instance *inst = (void *)tfm->__crt_alg;
@@ -249,22 +207,6 @@
struct crypto_pcbc_ctx *ctx = crypto_tfm_ctx(tfm);
struct crypto_cipher *cipher;
- switch (crypto_tfm_alg_blocksize(tfm)) {
- case 8:
- ctx->xor = xor_64;
- break;
-
- case 16:
- ctx->xor = xor_128;
- break;
-
- default:
- if (crypto_tfm_alg_blocksize(tfm) % 4)
- ctx->xor = xor_byte;
- else
- ctx->xor = xor_quad;
- }
-
cipher = crypto_spawn_cipher(spawn);
if (IS_ERR(cipher))
return PTR_ERR(cipher);
@@ -304,8 +246,9 @@
inst->alg.cra_alignmask = alg->cra_alignmask;
inst->alg.cra_type = &crypto_blkcipher_type;
- if (!(alg->cra_blocksize % 4))
- inst->alg.cra_alignmask |= 3;
+ /* We access the data as u32s when xoring. */
+ inst->alg.cra_alignmask |= __alignof__(u32) - 1;
+
inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize;
inst->alg.cra_blkcipher.min_keysize = alg->cra_cipher.cia_min_keysize;
inst->alg.cra_blkcipher.max_keysize = alg->cra_cipher.cia_max_keysize;
diff --git a/crypto/salsa20_generic.c b/crypto/salsa20_generic.c
new file mode 100644
index 0000000..1fa4e4d
--- /dev/null
+++ b/crypto/salsa20_generic.c
@@ -0,0 +1,255 @@
+/*
+ * Salsa20: Salsa20 stream cipher algorithm
+ *
+ * Copyright (c) 2007 Tan Swee Heng <thesweeheng@gmail.com>
+ *
+ * Derived from:
+ * - salsa20.c: Public domain C code by Daniel J. Bernstein <djb@cr.yp.to>
+ *
+ * Salsa20 is a stream cipher candidate in eSTREAM, the ECRYPT Stream
+ * Cipher Project. It is designed by Daniel J. Bernstein <djb@cr.yp.to>.
+ * More information about eSTREAM and Salsa20 can be found here:
+ * http://www.ecrypt.eu.org/stream/
+ * http://cr.yp.to/snuffle.html
+ *
+ * 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/errno.h>
+#include <linux/crypto.h>
+#include <linux/types.h>
+#include <crypto/algapi.h>
+#include <asm/byteorder.h>
+
+#define SALSA20_IV_SIZE 8U
+#define SALSA20_MIN_KEY_SIZE 16U
+#define SALSA20_MAX_KEY_SIZE 32U
+
+/*
+ * Start of code taken from D. J. Bernstein's reference implementation.
+ * With some modifications and optimizations made to suit our needs.
+ */
+
+/*
+salsa20-ref.c version 20051118
+D. J. Bernstein
+Public domain.
+*/
+
+#define ROTATE(v,n) (((v) << (n)) | ((v) >> (32 - (n))))
+#define XOR(v,w) ((v) ^ (w))
+#define PLUS(v,w) (((v) + (w)))
+#define PLUSONE(v) (PLUS((v),1))
+#define U32TO8_LITTLE(p, v) \
+ { (p)[0] = (v >> 0) & 0xff; (p)[1] = (v >> 8) & 0xff; \
+ (p)[2] = (v >> 16) & 0xff; (p)[3] = (v >> 24) & 0xff; }
+#define U8TO32_LITTLE(p) \
+ (((u32)((p)[0]) ) | ((u32)((p)[1]) << 8) | \
+ ((u32)((p)[2]) << 16) | ((u32)((p)[3]) << 24) )
+
+struct salsa20_ctx
+{
+ u32 input[16];
+};
+
+static void salsa20_wordtobyte(u8 output[64], const u32 input[16])
+{
+ u32 x[16];
+ int i;
+
+ memcpy(x, input, sizeof(x));
+ for (i = 20; i > 0; i -= 2) {
+ x[ 4] = XOR(x[ 4],ROTATE(PLUS(x[ 0],x[12]), 7));
+ x[ 8] = XOR(x[ 8],ROTATE(PLUS(x[ 4],x[ 0]), 9));
+ x[12] = XOR(x[12],ROTATE(PLUS(x[ 8],x[ 4]),13));
+ x[ 0] = XOR(x[ 0],ROTATE(PLUS(x[12],x[ 8]),18));
+ x[ 9] = XOR(x[ 9],ROTATE(PLUS(x[ 5],x[ 1]), 7));
+ x[13] = XOR(x[13],ROTATE(PLUS(x[ 9],x[ 5]), 9));
+ x[ 1] = XOR(x[ 1],ROTATE(PLUS(x[13],x[ 9]),13));
+ x[ 5] = XOR(x[ 5],ROTATE(PLUS(x[ 1],x[13]),18));
+ x[14] = XOR(x[14],ROTATE(PLUS(x[10],x[ 6]), 7));
+ x[ 2] = XOR(x[ 2],ROTATE(PLUS(x[14],x[10]), 9));
+ x[ 6] = XOR(x[ 6],ROTATE(PLUS(x[ 2],x[14]),13));
+ x[10] = XOR(x[10],ROTATE(PLUS(x[ 6],x[ 2]),18));
+ x[ 3] = XOR(x[ 3],ROTATE(PLUS(x[15],x[11]), 7));
+ x[ 7] = XOR(x[ 7],ROTATE(PLUS(x[ 3],x[15]), 9));
+ x[11] = XOR(x[11],ROTATE(PLUS(x[ 7],x[ 3]),13));
+ x[15] = XOR(x[15],ROTATE(PLUS(x[11],x[ 7]),18));
+ x[ 1] = XOR(x[ 1],ROTATE(PLUS(x[ 0],x[ 3]), 7));
+ x[ 2] = XOR(x[ 2],ROTATE(PLUS(x[ 1],x[ 0]), 9));
+ x[ 3] = XOR(x[ 3],ROTATE(PLUS(x[ 2],x[ 1]),13));
+ x[ 0] = XOR(x[ 0],ROTATE(PLUS(x[ 3],x[ 2]),18));
+ x[ 6] = XOR(x[ 6],ROTATE(PLUS(x[ 5],x[ 4]), 7));
+ x[ 7] = XOR(x[ 7],ROTATE(PLUS(x[ 6],x[ 5]), 9));
+ x[ 4] = XOR(x[ 4],ROTATE(PLUS(x[ 7],x[ 6]),13));
+ x[ 5] = XOR(x[ 5],ROTATE(PLUS(x[ 4],x[ 7]),18));
+ x[11] = XOR(x[11],ROTATE(PLUS(x[10],x[ 9]), 7));
+ x[ 8] = XOR(x[ 8],ROTATE(PLUS(x[11],x[10]), 9));
+ x[ 9] = XOR(x[ 9],ROTATE(PLUS(x[ 8],x[11]),13));
+ x[10] = XOR(x[10],ROTATE(PLUS(x[ 9],x[ 8]),18));
+ x[12] = XOR(x[12],ROTATE(PLUS(x[15],x[14]), 7));
+ x[13] = XOR(x[13],ROTATE(PLUS(x[12],x[15]), 9));
+ x[14] = XOR(x[14],ROTATE(PLUS(x[13],x[12]),13));
+ x[15] = XOR(x[15],ROTATE(PLUS(x[14],x[13]),18));
+ }
+ for (i = 0; i < 16; ++i)
+ x[i] = PLUS(x[i],input[i]);
+ for (i = 0; i < 16; ++i)
+ U32TO8_LITTLE(output + 4 * i,x[i]);
+}
+
+static const char sigma[16] = "expand 32-byte k";
+static const char tau[16] = "expand 16-byte k";
+
+static void salsa20_keysetup(struct salsa20_ctx *ctx, const u8 *k, u32 kbytes)
+{
+ const char *constants;
+
+ ctx->input[1] = U8TO32_LITTLE(k + 0);
+ ctx->input[2] = U8TO32_LITTLE(k + 4);
+ ctx->input[3] = U8TO32_LITTLE(k + 8);
+ ctx->input[4] = U8TO32_LITTLE(k + 12);
+ if (kbytes == 32) { /* recommended */
+ k += 16;
+ constants = sigma;
+ } else { /* kbytes == 16 */
+ constants = tau;
+ }
+ ctx->input[11] = U8TO32_LITTLE(k + 0);
+ ctx->input[12] = U8TO32_LITTLE(k + 4);
+ ctx->input[13] = U8TO32_LITTLE(k + 8);
+ ctx->input[14] = U8TO32_LITTLE(k + 12);
+ ctx->input[0] = U8TO32_LITTLE(constants + 0);
+ ctx->input[5] = U8TO32_LITTLE(constants + 4);
+ ctx->input[10] = U8TO32_LITTLE(constants + 8);
+ ctx->input[15] = U8TO32_LITTLE(constants + 12);
+}
+
+static void salsa20_ivsetup(struct salsa20_ctx *ctx, const u8 *iv)
+{
+ ctx->input[6] = U8TO32_LITTLE(iv + 0);
+ ctx->input[7] = U8TO32_LITTLE(iv + 4);
+ ctx->input[8] = 0;
+ ctx->input[9] = 0;
+}
+
+static void salsa20_encrypt_bytes(struct salsa20_ctx *ctx, u8 *dst,
+ const u8 *src, unsigned int bytes)
+{
+ u8 buf[64];
+
+ if (dst != src)
+ memcpy(dst, src, bytes);
+
+ while (bytes) {
+ salsa20_wordtobyte(buf, ctx->input);
+
+ ctx->input[8] = PLUSONE(ctx->input[8]);
+ if (!ctx->input[8])
+ ctx->input[9] = PLUSONE(ctx->input[9]);
+
+ if (bytes <= 64) {
+ crypto_xor(dst, buf, bytes);
+ return;
+ }
+
+ crypto_xor(dst, buf, 64);
+ bytes -= 64;
+ dst += 64;
+ }
+}
+
+/*
+ * End of code taken from D. J. Bernstein's reference implementation.
+ */
+
+static int setkey(struct crypto_tfm *tfm, const u8 *key,
+ unsigned int keysize)
+{
+ struct salsa20_ctx *ctx = crypto_tfm_ctx(tfm);
+ salsa20_keysetup(ctx, key, keysize);
+ return 0;
+}
+
+static int encrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ struct blkcipher_walk walk;
+ struct crypto_blkcipher *tfm = desc->tfm;
+ struct salsa20_ctx *ctx = crypto_blkcipher_ctx(tfm);
+ int err;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ err = blkcipher_walk_virt_block(desc, &walk, 64);
+
+ salsa20_ivsetup(ctx, walk.iv);
+
+ if (likely(walk.nbytes == nbytes))
+ {
+ salsa20_encrypt_bytes(ctx, walk.dst.virt.addr,
+ walk.src.virt.addr, nbytes);
+ return blkcipher_walk_done(desc, &walk, 0);
+ }
+
+ while (walk.nbytes >= 64) {
+ salsa20_encrypt_bytes(ctx, walk.dst.virt.addr,
+ walk.src.virt.addr,
+ walk.nbytes - (walk.nbytes % 64));
+ err = blkcipher_walk_done(desc, &walk, walk.nbytes % 64);
+ }
+
+ if (walk.nbytes) {
+ salsa20_encrypt_bytes(ctx, walk.dst.virt.addr,
+ walk.src.virt.addr, walk.nbytes);
+ err = blkcipher_walk_done(desc, &walk, 0);
+ }
+
+ return err;
+}
+
+static struct crypto_alg alg = {
+ .cra_name = "salsa20",
+ .cra_driver_name = "salsa20-generic",
+ .cra_priority = 100,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_type = &crypto_blkcipher_type,
+ .cra_blocksize = 1,
+ .cra_ctxsize = sizeof(struct salsa20_ctx),
+ .cra_alignmask = 3,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(alg.cra_list),
+ .cra_u = {
+ .blkcipher = {
+ .setkey = setkey,
+ .encrypt = encrypt,
+ .decrypt = encrypt,
+ .min_keysize = SALSA20_MIN_KEY_SIZE,
+ .max_keysize = SALSA20_MAX_KEY_SIZE,
+ .ivsize = SALSA20_IV_SIZE,
+ }
+ }
+};
+
+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_LICENSE("GPL");
+MODULE_DESCRIPTION ("Salsa20 stream cipher algorithm");
+MODULE_ALIAS("salsa20");
diff --git a/crypto/scatterwalk.c b/crypto/scatterwalk.c
index b9bbda0..9aeeb52 100644
--- a/crypto/scatterwalk.c
+++ b/crypto/scatterwalk.c
@@ -13,6 +13,8 @@
* any later version.
*
*/
+
+#include <crypto/scatterwalk.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/module.h>
@@ -20,9 +22,6 @@
#include <linux/highmem.h>
#include <linux/scatterlist.h>
-#include "internal.h"
-#include "scatterwalk.h"
-
static inline void memcpy_dir(void *buf, void *sgdata, size_t nbytes, int out)
{
void *src = out ? buf : sgdata;
@@ -106,6 +105,9 @@
struct scatter_walk walk;
unsigned int offset = 0;
+ if (!nbytes)
+ return;
+
for (;;) {
scatterwalk_start(&walk, sg);
@@ -113,7 +115,7 @@
break;
offset += sg->length;
- sg = sg_next(sg);
+ sg = scatterwalk_sg_next(sg);
}
scatterwalk_advance(&walk, start - offset);
diff --git a/crypto/seqiv.c b/crypto/seqiv.c
new file mode 100644
index 0000000..b903aab
--- /dev/null
+++ b/crypto/seqiv.c
@@ -0,0 +1,345 @@
+/*
+ * seqiv: Sequence Number IV Generator
+ *
+ * This generator generates an IV based on a sequence number by xoring it
+ * with a salt. This algorithm is mainly useful for CTR and similar modes.
+ *
+ * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+#include <crypto/internal/aead.h>
+#include <crypto/internal/skcipher.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/random.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+
+struct seqiv_ctx {
+ spinlock_t lock;
+ u8 salt[] __attribute__ ((aligned(__alignof__(u32))));
+};
+
+static void seqiv_complete2(struct skcipher_givcrypt_request *req, int err)
+{
+ struct ablkcipher_request *subreq = skcipher_givcrypt_reqctx(req);
+ struct crypto_ablkcipher *geniv;
+
+ if (err == -EINPROGRESS)
+ return;
+
+ if (err)
+ goto out;
+
+ geniv = skcipher_givcrypt_reqtfm(req);
+ memcpy(req->creq.info, subreq->info, crypto_ablkcipher_ivsize(geniv));
+
+out:
+ kfree(subreq->info);
+}
+
+static void seqiv_complete(struct crypto_async_request *base, int err)
+{
+ struct skcipher_givcrypt_request *req = base->data;
+
+ seqiv_complete2(req, err);
+ skcipher_givcrypt_complete(req, err);
+}
+
+static void seqiv_aead_complete2(struct aead_givcrypt_request *req, int err)
+{
+ struct aead_request *subreq = aead_givcrypt_reqctx(req);
+ struct crypto_aead *geniv;
+
+ if (err == -EINPROGRESS)
+ return;
+
+ if (err)
+ goto out;
+
+ geniv = aead_givcrypt_reqtfm(req);
+ memcpy(req->areq.iv, subreq->iv, crypto_aead_ivsize(geniv));
+
+out:
+ kfree(subreq->iv);
+}
+
+static void seqiv_aead_complete(struct crypto_async_request *base, int err)
+{
+ struct aead_givcrypt_request *req = base->data;
+
+ seqiv_aead_complete2(req, err);
+ aead_givcrypt_complete(req, err);
+}
+
+static void seqiv_geniv(struct seqiv_ctx *ctx, u8 *info, u64 seq,
+ unsigned int ivsize)
+{
+ unsigned int len = ivsize;
+
+ if (ivsize > sizeof(u64)) {
+ memset(info, 0, ivsize - sizeof(u64));
+ len = sizeof(u64);
+ }
+ seq = cpu_to_be64(seq);
+ memcpy(info + ivsize - len, &seq, len);
+ crypto_xor(info, ctx->salt, ivsize);
+}
+
+static int seqiv_givencrypt(struct skcipher_givcrypt_request *req)
+{
+ struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
+ struct seqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
+ struct ablkcipher_request *subreq = skcipher_givcrypt_reqctx(req);
+ crypto_completion_t complete;
+ void *data;
+ u8 *info;
+ unsigned int ivsize;
+ int err;
+
+ ablkcipher_request_set_tfm(subreq, skcipher_geniv_cipher(geniv));
+
+ complete = req->creq.base.complete;
+ data = req->creq.base.data;
+ info = req->creq.info;
+
+ ivsize = crypto_ablkcipher_ivsize(geniv);
+
+ if (unlikely(!IS_ALIGNED((unsigned long)info,
+ crypto_ablkcipher_alignmask(geniv) + 1))) {
+ info = kmalloc(ivsize, req->creq.base.flags &
+ CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL:
+ GFP_ATOMIC);
+ if (!info)
+ return -ENOMEM;
+
+ complete = seqiv_complete;
+ data = req;
+ }
+
+ ablkcipher_request_set_callback(subreq, req->creq.base.flags, complete,
+ data);
+ ablkcipher_request_set_crypt(subreq, req->creq.src, req->creq.dst,
+ req->creq.nbytes, info);
+
+ seqiv_geniv(ctx, info, req->seq, ivsize);
+ memcpy(req->giv, info, ivsize);
+
+ err = crypto_ablkcipher_encrypt(subreq);
+ if (unlikely(info != req->creq.info))
+ seqiv_complete2(req, err);
+ return err;
+}
+
+static int seqiv_aead_givencrypt(struct aead_givcrypt_request *req)
+{
+ struct crypto_aead *geniv = aead_givcrypt_reqtfm(req);
+ struct seqiv_ctx *ctx = crypto_aead_ctx(geniv);
+ struct aead_request *areq = &req->areq;
+ struct aead_request *subreq = aead_givcrypt_reqctx(req);
+ crypto_completion_t complete;
+ void *data;
+ u8 *info;
+ unsigned int ivsize;
+ int err;
+
+ aead_request_set_tfm(subreq, aead_geniv_base(geniv));
+
+ complete = areq->base.complete;
+ data = areq->base.data;
+ info = areq->iv;
+
+ ivsize = crypto_aead_ivsize(geniv);
+
+ if (unlikely(!IS_ALIGNED((unsigned long)info,
+ crypto_aead_alignmask(geniv) + 1))) {
+ info = kmalloc(ivsize, areq->base.flags &
+ CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL:
+ GFP_ATOMIC);
+ if (!info)
+ return -ENOMEM;
+
+ complete = seqiv_aead_complete;
+ data = req;
+ }
+
+ aead_request_set_callback(subreq, areq->base.flags, complete, data);
+ aead_request_set_crypt(subreq, areq->src, areq->dst, areq->cryptlen,
+ info);
+ aead_request_set_assoc(subreq, areq->assoc, areq->assoclen);
+
+ seqiv_geniv(ctx, info, req->seq, ivsize);
+ memcpy(req->giv, info, ivsize);
+
+ err = crypto_aead_encrypt(subreq);
+ if (unlikely(info != areq->iv))
+ seqiv_aead_complete2(req, err);
+ return err;
+}
+
+static int seqiv_givencrypt_first(struct skcipher_givcrypt_request *req)
+{
+ struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
+ struct seqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
+
+ spin_lock_bh(&ctx->lock);
+ if (crypto_ablkcipher_crt(geniv)->givencrypt != seqiv_givencrypt_first)
+ goto unlock;
+
+ crypto_ablkcipher_crt(geniv)->givencrypt = seqiv_givencrypt;
+ get_random_bytes(ctx->salt, crypto_ablkcipher_ivsize(geniv));
+
+unlock:
+ spin_unlock_bh(&ctx->lock);
+
+ return seqiv_givencrypt(req);
+}
+
+static int seqiv_aead_givencrypt_first(struct aead_givcrypt_request *req)
+{
+ struct crypto_aead *geniv = aead_givcrypt_reqtfm(req);
+ struct seqiv_ctx *ctx = crypto_aead_ctx(geniv);
+
+ spin_lock_bh(&ctx->lock);
+ if (crypto_aead_crt(geniv)->givencrypt != seqiv_aead_givencrypt_first)
+ goto unlock;
+
+ crypto_aead_crt(geniv)->givencrypt = seqiv_aead_givencrypt;
+ get_random_bytes(ctx->salt, crypto_aead_ivsize(geniv));
+
+unlock:
+ spin_unlock_bh(&ctx->lock);
+
+ return seqiv_aead_givencrypt(req);
+}
+
+static int seqiv_init(struct crypto_tfm *tfm)
+{
+ struct crypto_ablkcipher *geniv = __crypto_ablkcipher_cast(tfm);
+ struct seqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
+
+ spin_lock_init(&ctx->lock);
+
+ tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request);
+
+ return skcipher_geniv_init(tfm);
+}
+
+static int seqiv_aead_init(struct crypto_tfm *tfm)
+{
+ struct crypto_aead *geniv = __crypto_aead_cast(tfm);
+ struct seqiv_ctx *ctx = crypto_aead_ctx(geniv);
+
+ spin_lock_init(&ctx->lock);
+
+ tfm->crt_aead.reqsize = sizeof(struct aead_request);
+
+ return aead_geniv_init(tfm);
+}
+
+static struct crypto_template seqiv_tmpl;
+
+static struct crypto_instance *seqiv_ablkcipher_alloc(struct rtattr **tb)
+{
+ struct crypto_instance *inst;
+
+ inst = skcipher_geniv_alloc(&seqiv_tmpl, tb, 0, 0);
+
+ if (IS_ERR(inst))
+ goto out;
+
+ inst->alg.cra_ablkcipher.givencrypt = seqiv_givencrypt_first;
+
+ inst->alg.cra_init = seqiv_init;
+ inst->alg.cra_exit = skcipher_geniv_exit;
+
+ inst->alg.cra_ctxsize += inst->alg.cra_ablkcipher.ivsize;
+
+out:
+ return inst;
+}
+
+static struct crypto_instance *seqiv_aead_alloc(struct rtattr **tb)
+{
+ struct crypto_instance *inst;
+
+ inst = aead_geniv_alloc(&seqiv_tmpl, tb, 0, 0);
+
+ if (IS_ERR(inst))
+ goto out;
+
+ inst->alg.cra_aead.givencrypt = seqiv_aead_givencrypt_first;
+
+ inst->alg.cra_init = seqiv_aead_init;
+ inst->alg.cra_exit = aead_geniv_exit;
+
+ inst->alg.cra_ctxsize = inst->alg.cra_aead.ivsize;
+
+out:
+ return inst;
+}
+
+static struct crypto_instance *seqiv_alloc(struct rtattr **tb)
+{
+ struct crypto_attr_type *algt;
+ struct crypto_instance *inst;
+ int err;
+
+ algt = crypto_get_attr_type(tb);
+ err = PTR_ERR(algt);
+ if (IS_ERR(algt))
+ return ERR_PTR(err);
+
+ if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & CRYPTO_ALG_TYPE_MASK)
+ inst = seqiv_ablkcipher_alloc(tb);
+ else
+ inst = seqiv_aead_alloc(tb);
+
+ if (IS_ERR(inst))
+ goto out;
+
+ inst->alg.cra_alignmask |= __alignof__(u32) - 1;
+ inst->alg.cra_ctxsize += sizeof(struct seqiv_ctx);
+
+out:
+ return inst;
+}
+
+static void seqiv_free(struct crypto_instance *inst)
+{
+ if ((inst->alg.cra_flags ^ CRYPTO_ALG_TYPE_AEAD) & CRYPTO_ALG_TYPE_MASK)
+ skcipher_geniv_free(inst);
+ else
+ aead_geniv_free(inst);
+}
+
+static struct crypto_template seqiv_tmpl = {
+ .name = "seqiv",
+ .alloc = seqiv_alloc,
+ .free = seqiv_free,
+ .module = THIS_MODULE,
+};
+
+static int __init seqiv_module_init(void)
+{
+ return crypto_register_template(&seqiv_tmpl);
+}
+
+static void __exit seqiv_module_exit(void)
+{
+ crypto_unregister_template(&seqiv_tmpl);
+}
+
+module_init(seqiv_module_init);
+module_exit(seqiv_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Sequence Number IV Generator");
diff --git a/crypto/sha256_generic.c b/crypto/sha256_generic.c
index fd3918b..3cc93fd 100644
--- a/crypto/sha256_generic.c
+++ b/crypto/sha256_generic.c
@@ -9,6 +9,7 @@
* Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com>
* Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ * SHA224 Support Copyright 2007 Intel Corporation <jonathan.lynch@intel.com>
*
* 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
@@ -218,6 +219,22 @@
memset(W, 0, 64 * sizeof(u32));
}
+
+static void sha224_init(struct crypto_tfm *tfm)
+{
+ struct sha256_ctx *sctx = crypto_tfm_ctx(tfm);
+ sctx->state[0] = SHA224_H0;
+ sctx->state[1] = SHA224_H1;
+ sctx->state[2] = SHA224_H2;
+ sctx->state[3] = SHA224_H3;
+ sctx->state[4] = SHA224_H4;
+ sctx->state[5] = SHA224_H5;
+ sctx->state[6] = SHA224_H6;
+ sctx->state[7] = SHA224_H7;
+ sctx->count[0] = 0;
+ sctx->count[1] = 0;
+}
+
static void sha256_init(struct crypto_tfm *tfm)
{
struct sha256_ctx *sctx = crypto_tfm_ctx(tfm);
@@ -294,8 +311,17 @@
memset(sctx, 0, sizeof(*sctx));
}
+static void sha224_final(struct crypto_tfm *tfm, u8 *hash)
+{
+ u8 D[SHA256_DIGEST_SIZE];
-static struct crypto_alg alg = {
+ sha256_final(tfm, D);
+
+ memcpy(hash, D, SHA224_DIGEST_SIZE);
+ memset(D, 0, SHA256_DIGEST_SIZE);
+}
+
+static struct crypto_alg sha256 = {
.cra_name = "sha256",
.cra_driver_name= "sha256-generic",
.cra_flags = CRYPTO_ALG_TYPE_DIGEST,
@@ -303,28 +329,58 @@
.cra_ctxsize = sizeof(struct sha256_ctx),
.cra_module = THIS_MODULE,
.cra_alignmask = 3,
- .cra_list = LIST_HEAD_INIT(alg.cra_list),
+ .cra_list = LIST_HEAD_INIT(sha256.cra_list),
.cra_u = { .digest = {
.dia_digestsize = SHA256_DIGEST_SIZE,
- .dia_init = sha256_init,
- .dia_update = sha256_update,
- .dia_final = sha256_final } }
+ .dia_init = sha256_init,
+ .dia_update = sha256_update,
+ .dia_final = sha256_final } }
+};
+
+static struct crypto_alg sha224 = {
+ .cra_name = "sha224",
+ .cra_driver_name = "sha224-generic",
+ .cra_flags = CRYPTO_ALG_TYPE_DIGEST,
+ .cra_blocksize = SHA224_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct sha256_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_alignmask = 3,
+ .cra_list = LIST_HEAD_INIT(sha224.cra_list),
+ .cra_u = { .digest = {
+ .dia_digestsize = SHA224_DIGEST_SIZE,
+ .dia_init = sha224_init,
+ .dia_update = sha256_update,
+ .dia_final = sha224_final } }
};
static int __init init(void)
{
- return crypto_register_alg(&alg);
+ int ret = 0;
+
+ ret = crypto_register_alg(&sha224);
+
+ if (ret < 0)
+ return ret;
+
+ ret = crypto_register_alg(&sha256);
+
+ if (ret < 0)
+ crypto_unregister_alg(&sha224);
+
+ return ret;
}
static void __exit fini(void)
{
- crypto_unregister_alg(&alg);
+ crypto_unregister_alg(&sha224);
+ crypto_unregister_alg(&sha256);
}
module_init(init);
module_exit(fini);
MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("SHA256 Secure Hash Algorithm");
+MODULE_DESCRIPTION("SHA-224 and SHA-256 Secure Hash Algorithm");
+MODULE_ALIAS("sha224");
MODULE_ALIAS("sha256");
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index 24141fb..1ab8c01 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -6,12 +6,16 @@
*
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
* Copyright (c) 2002 Jean-Francois Dive <jef@linuxbe.org>
+ * Copyright (c) 2007 Nokia Siemens Networks
*
* 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.
*
+ * 2007-11-13 Added GCM tests
+ * 2007-11-13 Added AEAD support
+ * 2007-11-06 Added SHA-224 and SHA-224-HMAC tests
* 2006-12-07 Added SHA384 HMAC and SHA512 HMAC tests
* 2004-08-09 Added cipher speed tests (Reyk Floeter <reyk@vantronix.net>)
* 2003-09-14 Rewritten by Kartikey Mahendra Bhatt
@@ -71,22 +75,23 @@
static int mode;
static char *xbuf;
+static char *axbuf;
static char *tvmem;
static char *check[] = {
- "des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
- "twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6",
+ "des", "md5", "des3_ede", "rot13", "sha1", "sha224", "sha256",
+ "blowfish", "twofish", "serpent", "sha384", "sha512", "md4", "aes",
+ "cast6", "arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea",
"arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea",
"khazad", "wp512", "wp384", "wp256", "tnepres", "xeta", "fcrypt",
- "camellia", "seed", NULL
+ "camellia", "seed", "salsa20", "lzo", NULL
};
static void hexdump(unsigned char *buf, unsigned int len)
{
- while (len--)
- printk("%02x", *buf++);
-
- printk("\n");
+ print_hex_dump(KERN_CONT, "", DUMP_PREFIX_OFFSET,
+ 16, 1,
+ buf, len, false);
}
static void tcrypt_complete(struct crypto_async_request *req, int err)
@@ -215,6 +220,238 @@
crypto_free_hash(tfm);
}
+static void test_aead(char *algo, int enc, struct aead_testvec *template,
+ unsigned int tcount)
+{
+ unsigned int ret, i, j, k, temp;
+ unsigned int tsize;
+ char *q;
+ struct crypto_aead *tfm;
+ char *key;
+ struct aead_testvec *aead_tv;
+ struct aead_request *req;
+ struct scatterlist sg[8];
+ struct scatterlist asg[8];
+ const char *e;
+ struct tcrypt_result result;
+ unsigned int authsize;
+
+ if (enc == ENCRYPT)
+ e = "encryption";
+ else
+ e = "decryption";
+
+ printk(KERN_INFO "\ntesting %s %s\n", algo, e);
+
+ tsize = sizeof(struct aead_testvec);
+ tsize *= tcount;
+
+ if (tsize > TVMEMSIZE) {
+ printk(KERN_INFO "template (%u) too big for tvmem (%u)\n",
+ tsize, TVMEMSIZE);
+ return;
+ }
+
+ memcpy(tvmem, template, tsize);
+ aead_tv = (void *)tvmem;
+
+ init_completion(&result.completion);
+
+ tfm = crypto_alloc_aead(algo, 0, 0);
+
+ if (IS_ERR(tfm)) {
+ printk(KERN_INFO "failed to load transform for %s: %ld\n",
+ algo, PTR_ERR(tfm));
+ return;
+ }
+
+ req = aead_request_alloc(tfm, GFP_KERNEL);
+ if (!req) {
+ printk(KERN_INFO "failed to allocate request for %s\n", algo);
+ goto out;
+ }
+
+ aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ tcrypt_complete, &result);
+
+ for (i = 0, j = 0; i < tcount; i++) {
+ if (!aead_tv[i].np) {
+ printk(KERN_INFO "test %u (%d bit key):\n",
+ ++j, aead_tv[i].klen * 8);
+
+ crypto_aead_clear_flags(tfm, ~0);
+ if (aead_tv[i].wk)
+ crypto_aead_set_flags(
+ tfm, CRYPTO_TFM_REQ_WEAK_KEY);
+ key = aead_tv[i].key;
+
+ ret = crypto_aead_setkey(tfm, key,
+ aead_tv[i].klen);
+ if (ret) {
+ printk(KERN_INFO "setkey() failed flags=%x\n",
+ crypto_aead_get_flags(tfm));
+
+ if (!aead_tv[i].fail)
+ goto out;
+ }
+
+ authsize = abs(aead_tv[i].rlen - aead_tv[i].ilen);
+ ret = crypto_aead_setauthsize(tfm, authsize);
+ if (ret) {
+ printk(KERN_INFO
+ "failed to set authsize = %u\n",
+ authsize);
+ goto out;
+ }
+
+ sg_init_one(&sg[0], aead_tv[i].input,
+ aead_tv[i].ilen + (enc ? authsize : 0));
+
+ sg_init_one(&asg[0], aead_tv[i].assoc,
+ aead_tv[i].alen);
+
+ aead_request_set_crypt(req, sg, sg,
+ aead_tv[i].ilen,
+ aead_tv[i].iv);
+
+ aead_request_set_assoc(req, asg, aead_tv[i].alen);
+
+ ret = enc ?
+ crypto_aead_encrypt(req) :
+ crypto_aead_decrypt(req);
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINPROGRESS:
+ case -EBUSY:
+ ret = wait_for_completion_interruptible(
+ &result.completion);
+ if (!ret && !(ret = result.err)) {
+ INIT_COMPLETION(result.completion);
+ break;
+ }
+ /* fall through */
+ default:
+ printk(KERN_INFO "%s () failed err=%d\n",
+ e, -ret);
+ goto out;
+ }
+
+ q = kmap(sg_page(&sg[0])) + sg[0].offset;
+ hexdump(q, aead_tv[i].rlen);
+
+ printk(KERN_INFO "enc/dec: %s\n",
+ memcmp(q, aead_tv[i].result,
+ aead_tv[i].rlen) ? "fail" : "pass");
+ }
+ }
+
+ printk(KERN_INFO "\ntesting %s %s across pages (chunking)\n", algo, e);
+ memset(xbuf, 0, XBUFSIZE);
+ memset(axbuf, 0, XBUFSIZE);
+
+ for (i = 0, j = 0; i < tcount; i++) {
+ if (aead_tv[i].np) {
+ printk(KERN_INFO "test %u (%d bit key):\n",
+ ++j, aead_tv[i].klen * 8);
+
+ crypto_aead_clear_flags(tfm, ~0);
+ if (aead_tv[i].wk)
+ crypto_aead_set_flags(
+ tfm, CRYPTO_TFM_REQ_WEAK_KEY);
+ key = aead_tv[i].key;
+
+ ret = crypto_aead_setkey(tfm, key, aead_tv[i].klen);
+ if (ret) {
+ printk(KERN_INFO "setkey() failed flags=%x\n",
+ crypto_aead_get_flags(tfm));
+
+ if (!aead_tv[i].fail)
+ goto out;
+ }
+
+ sg_init_table(sg, aead_tv[i].np);
+ for (k = 0, temp = 0; k < aead_tv[i].np; k++) {
+ memcpy(&xbuf[IDX[k]],
+ aead_tv[i].input + temp,
+ aead_tv[i].tap[k]);
+ temp += aead_tv[i].tap[k];
+ sg_set_buf(&sg[k], &xbuf[IDX[k]],
+ aead_tv[i].tap[k]);
+ }
+
+ authsize = abs(aead_tv[i].rlen - aead_tv[i].ilen);
+ ret = crypto_aead_setauthsize(tfm, authsize);
+ if (ret) {
+ printk(KERN_INFO
+ "failed to set authsize = %u\n",
+ authsize);
+ goto out;
+ }
+
+ if (enc)
+ sg[k - 1].length += authsize;
+
+ sg_init_table(asg, aead_tv[i].anp);
+ for (k = 0, temp = 0; k < aead_tv[i].anp; k++) {
+ memcpy(&axbuf[IDX[k]],
+ aead_tv[i].assoc + temp,
+ aead_tv[i].atap[k]);
+ temp += aead_tv[i].atap[k];
+ sg_set_buf(&asg[k], &axbuf[IDX[k]],
+ aead_tv[i].atap[k]);
+ }
+
+ aead_request_set_crypt(req, sg, sg,
+ aead_tv[i].ilen,
+ aead_tv[i].iv);
+
+ aead_request_set_assoc(req, asg, aead_tv[i].alen);
+
+ ret = enc ?
+ crypto_aead_encrypt(req) :
+ crypto_aead_decrypt(req);
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINPROGRESS:
+ case -EBUSY:
+ ret = wait_for_completion_interruptible(
+ &result.completion);
+ if (!ret && !(ret = result.err)) {
+ INIT_COMPLETION(result.completion);
+ break;
+ }
+ /* fall through */
+ default:
+ printk(KERN_INFO "%s () failed err=%d\n",
+ e, -ret);
+ goto out;
+ }
+
+ for (k = 0, temp = 0; k < aead_tv[i].np; k++) {
+ printk(KERN_INFO "page %u\n", k);
+ q = kmap(sg_page(&sg[k])) + sg[k].offset;
+ hexdump(q, aead_tv[i].tap[k]);
+ printk(KERN_INFO "%s\n",
+ memcmp(q, aead_tv[i].result + temp,
+ aead_tv[i].tap[k] -
+ (k < aead_tv[i].np - 1 || enc ?
+ 0 : authsize)) ?
+ "fail" : "pass");
+
+ temp += aead_tv[i].tap[k];
+ }
+ }
+ }
+
+out:
+ crypto_free_aead(tfm);
+ aead_request_free(req);
+}
+
static void test_cipher(char *algo, int enc,
struct cipher_testvec *template, unsigned int tcount)
{
@@ -237,15 +474,11 @@
printk("\ntesting %s %s\n", algo, e);
tsize = sizeof (struct cipher_testvec);
- tsize *= tcount;
-
if (tsize > TVMEMSIZE) {
printk("template (%u) too big for tvmem (%u)\n", tsize,
TVMEMSIZE);
return;
}
-
- memcpy(tvmem, template, tsize);
cipher_tv = (void *)tvmem;
init_completion(&result.completion);
@@ -269,33 +502,34 @@
j = 0;
for (i = 0; i < tcount; i++) {
- if (!(cipher_tv[i].np)) {
+ memcpy(cipher_tv, &template[i], tsize);
+ if (!(cipher_tv->np)) {
j++;
printk("test %u (%d bit key):\n",
- j, cipher_tv[i].klen * 8);
+ j, cipher_tv->klen * 8);
crypto_ablkcipher_clear_flags(tfm, ~0);
- if (cipher_tv[i].wk)
+ if (cipher_tv->wk)
crypto_ablkcipher_set_flags(
tfm, CRYPTO_TFM_REQ_WEAK_KEY);
- key = cipher_tv[i].key;
+ key = cipher_tv->key;
ret = crypto_ablkcipher_setkey(tfm, key,
- cipher_tv[i].klen);
+ cipher_tv->klen);
if (ret) {
printk("setkey() failed flags=%x\n",
crypto_ablkcipher_get_flags(tfm));
- if (!cipher_tv[i].fail)
+ if (!cipher_tv->fail)
goto out;
}
- sg_init_one(&sg[0], cipher_tv[i].input,
- cipher_tv[i].ilen);
+ sg_init_one(&sg[0], cipher_tv->input,
+ cipher_tv->ilen);
ablkcipher_request_set_crypt(req, sg, sg,
- cipher_tv[i].ilen,
- cipher_tv[i].iv);
+ cipher_tv->ilen,
+ cipher_tv->iv);
ret = enc ?
crypto_ablkcipher_encrypt(req) :
@@ -319,11 +553,11 @@
}
q = kmap(sg_page(&sg[0])) + sg[0].offset;
- hexdump(q, cipher_tv[i].rlen);
+ hexdump(q, cipher_tv->rlen);
printk("%s\n",
- memcmp(q, cipher_tv[i].result,
- cipher_tv[i].rlen) ? "fail" : "pass");
+ memcmp(q, cipher_tv->result,
+ cipher_tv->rlen) ? "fail" : "pass");
}
}
@@ -332,41 +566,42 @@
j = 0;
for (i = 0; i < tcount; i++) {
- if (cipher_tv[i].np) {
+ memcpy(cipher_tv, &template[i], tsize);
+ if (cipher_tv->np) {
j++;
printk("test %u (%d bit key):\n",
- j, cipher_tv[i].klen * 8);
+ j, cipher_tv->klen * 8);
crypto_ablkcipher_clear_flags(tfm, ~0);
- if (cipher_tv[i].wk)
+ if (cipher_tv->wk)
crypto_ablkcipher_set_flags(
tfm, CRYPTO_TFM_REQ_WEAK_KEY);
- key = cipher_tv[i].key;
+ key = cipher_tv->key;
ret = crypto_ablkcipher_setkey(tfm, key,
- cipher_tv[i].klen);
+ cipher_tv->klen);
if (ret) {
printk("setkey() failed flags=%x\n",
crypto_ablkcipher_get_flags(tfm));
- if (!cipher_tv[i].fail)
+ if (!cipher_tv->fail)
goto out;
}
temp = 0;
- sg_init_table(sg, cipher_tv[i].np);
- for (k = 0; k < cipher_tv[i].np; k++) {
+ sg_init_table(sg, cipher_tv->np);
+ for (k = 0; k < cipher_tv->np; k++) {
memcpy(&xbuf[IDX[k]],
- cipher_tv[i].input + temp,
- cipher_tv[i].tap[k]);
- temp += cipher_tv[i].tap[k];
+ cipher_tv->input + temp,
+ cipher_tv->tap[k]);
+ temp += cipher_tv->tap[k];
sg_set_buf(&sg[k], &xbuf[IDX[k]],
- cipher_tv[i].tap[k]);
+ cipher_tv->tap[k]);
}
ablkcipher_request_set_crypt(req, sg, sg,
- cipher_tv[i].ilen,
- cipher_tv[i].iv);
+ cipher_tv->ilen,
+ cipher_tv->iv);
ret = enc ?
crypto_ablkcipher_encrypt(req) :
@@ -390,15 +625,15 @@
}
temp = 0;
- for (k = 0; k < cipher_tv[i].np; k++) {
+ for (k = 0; k < cipher_tv->np; k++) {
printk("page %u\n", k);
q = kmap(sg_page(&sg[k])) + sg[k].offset;
- hexdump(q, cipher_tv[i].tap[k]);
+ hexdump(q, cipher_tv->tap[k]);
printk("%s\n",
- memcmp(q, cipher_tv[i].result + temp,
- cipher_tv[i].tap[k]) ? "fail" :
+ memcmp(q, cipher_tv->result + temp,
+ cipher_tv->tap[k]) ? "fail" :
"pass");
- temp += cipher_tv[i].tap[k];
+ temp += cipher_tv->tap[k];
}
}
}
@@ -800,7 +1035,8 @@
crypto_free_hash(tfm);
}
-static void test_deflate(void)
+static void test_comp(char *algo, struct comp_testvec *ctemplate,
+ struct comp_testvec *dtemplate, int ctcount, int dtcount)
{
unsigned int i;
char result[COMP_BUF_SIZE];
@@ -808,25 +1044,26 @@
struct comp_testvec *tv;
unsigned int tsize;
- printk("\ntesting deflate compression\n");
+ printk("\ntesting %s compression\n", algo);
- tsize = sizeof (deflate_comp_tv_template);
+ tsize = sizeof(struct comp_testvec);
+ tsize *= ctcount;
if (tsize > TVMEMSIZE) {
printk("template (%u) too big for tvmem (%u)\n", tsize,
TVMEMSIZE);
return;
}
- memcpy(tvmem, deflate_comp_tv_template, tsize);
+ memcpy(tvmem, ctemplate, tsize);
tv = (void *)tvmem;
- tfm = crypto_alloc_comp("deflate", 0, CRYPTO_ALG_ASYNC);
+ tfm = crypto_alloc_comp(algo, 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(tfm)) {
- printk("failed to load transform for deflate\n");
+ printk("failed to load transform for %s\n", algo);
return;
}
- for (i = 0; i < DEFLATE_COMP_TEST_VECTORS; i++) {
+ for (i = 0; i < ctcount; i++) {
int ilen, ret, dlen = COMP_BUF_SIZE;
printk("test %u:\n", i + 1);
@@ -845,19 +1082,20 @@
ilen, dlen);
}
- printk("\ntesting deflate decompression\n");
+ printk("\ntesting %s decompression\n", algo);
- tsize = sizeof (deflate_decomp_tv_template);
+ tsize = sizeof(struct comp_testvec);
+ tsize *= dtcount;
if (tsize > TVMEMSIZE) {
printk("template (%u) too big for tvmem (%u)\n", tsize,
TVMEMSIZE);
goto out;
}
- memcpy(tvmem, deflate_decomp_tv_template, tsize);
+ memcpy(tvmem, dtemplate, tsize);
tv = (void *)tvmem;
- for (i = 0; i < DEFLATE_DECOMP_TEST_VECTORS; i++) {
+ for (i = 0; i < dtcount; i++) {
int ilen, ret, dlen = COMP_BUF_SIZE;
printk("test %u:\n", i + 1);
@@ -918,6 +1156,8 @@
test_hash("md4", md4_tv_template, MD4_TEST_VECTORS);
+ test_hash("sha224", sha224_tv_template, SHA224_TEST_VECTORS);
+
test_hash("sha256", sha256_tv_template, SHA256_TEST_VECTORS);
//BLOWFISH
@@ -969,6 +1209,18 @@
AES_XTS_ENC_TEST_VECTORS);
test_cipher("xts(aes)", DECRYPT, aes_xts_dec_tv_template,
AES_XTS_DEC_TEST_VECTORS);
+ test_cipher("rfc3686(ctr(aes))", ENCRYPT, aes_ctr_enc_tv_template,
+ AES_CTR_ENC_TEST_VECTORS);
+ test_cipher("rfc3686(ctr(aes))", DECRYPT, aes_ctr_dec_tv_template,
+ AES_CTR_DEC_TEST_VECTORS);
+ test_aead("gcm(aes)", ENCRYPT, aes_gcm_enc_tv_template,
+ AES_GCM_ENC_TEST_VECTORS);
+ test_aead("gcm(aes)", DECRYPT, aes_gcm_dec_tv_template,
+ AES_GCM_DEC_TEST_VECTORS);
+ test_aead("ccm(aes)", ENCRYPT, aes_ccm_enc_tv_template,
+ AES_CCM_ENC_TEST_VECTORS);
+ test_aead("ccm(aes)", DECRYPT, aes_ccm_dec_tv_template,
+ AES_CCM_DEC_TEST_VECTORS);
//CAST5
test_cipher("ecb(cast5)", ENCRYPT, cast5_enc_tv_template,
@@ -1057,12 +1309,18 @@
test_hash("tgr192", tgr192_tv_template, TGR192_TEST_VECTORS);
test_hash("tgr160", tgr160_tv_template, TGR160_TEST_VECTORS);
test_hash("tgr128", tgr128_tv_template, TGR128_TEST_VECTORS);
- test_deflate();
+ test_comp("deflate", deflate_comp_tv_template,
+ deflate_decomp_tv_template, DEFLATE_COMP_TEST_VECTORS,
+ DEFLATE_DECOMP_TEST_VECTORS);
+ test_comp("lzo", lzo_comp_tv_template, lzo_decomp_tv_template,
+ LZO_COMP_TEST_VECTORS, LZO_DECOMP_TEST_VECTORS);
test_hash("crc32c", crc32c_tv_template, CRC32C_TEST_VECTORS);
test_hash("hmac(md5)", hmac_md5_tv_template,
HMAC_MD5_TEST_VECTORS);
test_hash("hmac(sha1)", hmac_sha1_tv_template,
HMAC_SHA1_TEST_VECTORS);
+ test_hash("hmac(sha224)", hmac_sha224_tv_template,
+ HMAC_SHA224_TEST_VECTORS);
test_hash("hmac(sha256)", hmac_sha256_tv_template,
HMAC_SHA256_TEST_VECTORS);
test_hash("hmac(sha384)", hmac_sha384_tv_template,
@@ -1156,6 +1414,10 @@
AES_XTS_ENC_TEST_VECTORS);
test_cipher("xts(aes)", DECRYPT, aes_xts_dec_tv_template,
AES_XTS_DEC_TEST_VECTORS);
+ test_cipher("rfc3686(ctr(aes))", ENCRYPT, aes_ctr_enc_tv_template,
+ AES_CTR_ENC_TEST_VECTORS);
+ test_cipher("rfc3686(ctr(aes))", DECRYPT, aes_ctr_dec_tv_template,
+ AES_CTR_DEC_TEST_VECTORS);
break;
case 11:
@@ -1167,7 +1429,9 @@
break;
case 13:
- test_deflate();
+ test_comp("deflate", deflate_comp_tv_template,
+ deflate_decomp_tv_template, DEFLATE_COMP_TEST_VECTORS,
+ DEFLATE_DECOMP_TEST_VECTORS);
break;
case 14:
@@ -1291,6 +1555,34 @@
camellia_cbc_dec_tv_template,
CAMELLIA_CBC_DEC_TEST_VECTORS);
break;
+ case 33:
+ test_hash("sha224", sha224_tv_template, SHA224_TEST_VECTORS);
+ break;
+
+ case 34:
+ test_cipher("salsa20", ENCRYPT,
+ salsa20_stream_enc_tv_template,
+ SALSA20_STREAM_ENC_TEST_VECTORS);
+ break;
+
+ case 35:
+ test_aead("gcm(aes)", ENCRYPT, aes_gcm_enc_tv_template,
+ AES_GCM_ENC_TEST_VECTORS);
+ test_aead("gcm(aes)", DECRYPT, aes_gcm_dec_tv_template,
+ AES_GCM_DEC_TEST_VECTORS);
+ break;
+
+ case 36:
+ test_comp("lzo", lzo_comp_tv_template, lzo_decomp_tv_template,
+ LZO_COMP_TEST_VECTORS, LZO_DECOMP_TEST_VECTORS);
+ break;
+
+ case 37:
+ test_aead("ccm(aes)", ENCRYPT, aes_ccm_enc_tv_template,
+ AES_CCM_ENC_TEST_VECTORS);
+ test_aead("ccm(aes)", DECRYPT, aes_ccm_dec_tv_template,
+ AES_CCM_DEC_TEST_VECTORS);
+ break;
case 100:
test_hash("hmac(md5)", hmac_md5_tv_template,
@@ -1317,6 +1609,15 @@
HMAC_SHA512_TEST_VECTORS);
break;
+ case 105:
+ test_hash("hmac(sha224)", hmac_sha224_tv_template,
+ HMAC_SHA224_TEST_VECTORS);
+ break;
+
+ case 106:
+ test_hash("xcbc(aes)", aes_xcbc128_tv_template,
+ XCBC_AES_TEST_VECTORS);
+ break;
case 200:
test_cipher_speed("ecb(aes)", ENCRYPT, sec, NULL, 0,
@@ -1400,6 +1701,11 @@
camellia_speed_template);
break;
+ case 206:
+ test_cipher_speed("salsa20", ENCRYPT, sec, NULL, 0,
+ salsa20_speed_template);
+ break;
+
case 300:
/* fall through */
@@ -1451,6 +1757,10 @@
test_hash_speed("tgr192", sec, generic_hash_speed_template);
if (mode > 300 && mode < 400) break;
+ case 313:
+ test_hash_speed("sha224", sec, generic_hash_speed_template);
+ if (mode > 300 && mode < 400) break;
+
case 399:
break;
@@ -1467,28 +1777,37 @@
static int __init init(void)
{
+ int err = -ENOMEM;
+
tvmem = kmalloc(TVMEMSIZE, GFP_KERNEL);
if (tvmem == NULL)
- return -ENOMEM;
+ return err;
xbuf = kmalloc(XBUFSIZE, GFP_KERNEL);
- if (xbuf == NULL) {
- kfree(tvmem);
- return -ENOMEM;
- }
+ if (xbuf == NULL)
+ goto err_free_tv;
+
+ axbuf = kmalloc(XBUFSIZE, GFP_KERNEL);
+ if (axbuf == NULL)
+ goto err_free_xbuf;
do_test();
- kfree(xbuf);
- kfree(tvmem);
-
/* We intentionaly return -EAGAIN to prevent keeping
* the module. It does all its work from init()
* and doesn't offer any runtime functionality
* => we don't need it in the memory, do we?
* -- mludvig
*/
- return -EAGAIN;
+ err = -EAGAIN;
+
+ kfree(axbuf);
+ err_free_xbuf:
+ kfree(xbuf);
+ err_free_tv:
+ kfree(tvmem);
+
+ return err;
}
/*
diff --git a/crypto/tcrypt.h b/crypto/tcrypt.h
index ec86138..f785e561 100644
--- a/crypto/tcrypt.h
+++ b/crypto/tcrypt.h
@@ -6,12 +6,15 @@
*
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
* Copyright (c) 2002 Jean-Francois Dive <jef@linuxbe.org>
+ * Copyright (c) 2007 Nokia Siemens Networks
*
* 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.
*
+ * 2007-11-13 Added GCM tests
+ * 2007-11-13 Added AEAD support
* 2006-12-07 Added SHA384 HMAC and SHA512 HMAC tests
* 2004-08-09 Cipher speed tests by Reyk Floeter <reyk@vantronix.net>
* 2003-09-14 Changes by Kartikey Mahendra Bhatt
@@ -40,8 +43,8 @@
struct cipher_testvec {
char key[MAX_KEYLEN] __attribute__ ((__aligned__(4)));
char iv[MAX_IVLEN];
- char input[512];
- char result[512];
+ char input[4100];
+ char result[4100];
unsigned char tap[MAX_TAP];
int np;
unsigned char fail;
@@ -51,6 +54,24 @@
unsigned short rlen;
};
+struct aead_testvec {
+ char key[MAX_KEYLEN] __attribute__ ((__aligned__(4)));
+ char iv[MAX_IVLEN];
+ char input[512];
+ char assoc[512];
+ char result[512];
+ unsigned char tap[MAX_TAP];
+ unsigned char atap[MAX_TAP];
+ int np;
+ int anp;
+ unsigned char fail;
+ unsigned char wk; /* weak key flag */
+ unsigned char klen;
+ unsigned short ilen;
+ unsigned short alen;
+ unsigned short rlen;
+};
+
struct cipher_speed {
unsigned char klen;
unsigned int blen;
@@ -173,6 +194,33 @@
}
};
+
+/*
+ * SHA224 test vectors from from FIPS PUB 180-2
+ */
+#define SHA224_TEST_VECTORS 2
+
+static struct hash_testvec sha224_tv_template[] = {
+ {
+ .plaintext = "abc",
+ .psize = 3,
+ .digest = { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22,
+ 0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3,
+ 0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7,
+ 0xE3, 0x6C, 0x9D, 0xA7},
+ }, {
+ .plaintext =
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ .psize = 56,
+ .digest = { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC,
+ 0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50,
+ 0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19,
+ 0x52, 0x52, 0x25, 0x25 },
+ .np = 2,
+ .tap = { 28, 28 }
+ }
+};
+
/*
* SHA256 test vectors from from NIST
*/
@@ -817,6 +865,121 @@
},
};
+
+/*
+ * SHA224 HMAC test vectors from RFC4231
+ */
+#define HMAC_SHA224_TEST_VECTORS 4
+
+static struct hash_testvec hmac_sha224_tv_template[] = {
+ {
+ .key = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b },
+ .ksize = 20,
+ /* ("Hi There") */
+ .plaintext = { 0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65 },
+ .psize = 8,
+ .digest = { 0x89, 0x6f, 0xb1, 0x12, 0x8a, 0xbb, 0xdf, 0x19,
+ 0x68, 0x32, 0x10, 0x7c, 0xd4, 0x9d, 0xf3, 0x3f,
+ 0x47, 0xb4, 0xb1, 0x16, 0x99, 0x12, 0xba, 0x4f,
+ 0x53, 0x68, 0x4b, 0x22},
+ }, {
+ .key = { 0x4a, 0x65, 0x66, 0x65 }, /* ("Jefe") */
+ .ksize = 4,
+ /* ("what do ya want for nothing?") */
+ .plaintext = { 0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20,
+ 0x79, 0x61, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20,
+ 0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68,
+ 0x69, 0x6e, 0x67, 0x3f },
+ .psize = 28,
+ .digest = { 0xa3, 0x0e, 0x01, 0x09, 0x8b, 0xc6, 0xdb, 0xbf,
+ 0x45, 0x69, 0x0f, 0x3a, 0x7e, 0x9e, 0x6d, 0x0f,
+ 0x8b, 0xbe, 0xa2, 0xa3, 0x9e, 0x61, 0x48, 0x00,
+ 0x8f, 0xd0, 0x5e, 0x44 },
+ .np = 4,
+ .tap = { 7, 7, 7, 7 }
+ }, {
+ .key = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa },
+ .ksize = 131,
+ /* ("Test Using Larger Than Block-Size Key - Hash Key First") */
+ .plaintext = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x69,
+ 0x6e, 0x67, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65,
+ 0x72, 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x42,
+ 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x53, 0x69, 0x7a,
+ 0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x2d, 0x20,
+ 0x48, 0x61, 0x73, 0x68, 0x20, 0x4b, 0x65, 0x79,
+ 0x20, 0x46, 0x69, 0x72, 0x73, 0x74 },
+ .psize = 54,
+ .digest = { 0x95, 0xe9, 0xa0, 0xdb, 0x96, 0x20, 0x95, 0xad,
+ 0xae, 0xbe, 0x9b, 0x2d, 0x6f, 0x0d, 0xbc, 0xe2,
+ 0xd4, 0x99, 0xf1, 0x12, 0xf2, 0xd2, 0xb7, 0x27,
+ 0x3f, 0xa6, 0x87, 0x0e },
+ }, {
+ .key = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa },
+ .ksize = 131,
+ /* ("This is a test using a larger than block-size key and a")
+ (" larger than block-size data. The key needs to be")
+ (" hashed before being used by the HMAC algorithm.") */
+ .plaintext = { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20,
+ 0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x75,
+ 0x73, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x6c,
+ 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74, 0x68,
+ 0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
+ 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x6b, 0x65,
+ 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20,
+ 0x6c, 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74,
+ 0x68, 0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63,
+ 0x6b, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x64,
+ 0x61, 0x74, 0x61, 0x2e, 0x20, 0x54, 0x68, 0x65,
+ 0x20, 0x6b, 0x65, 0x79, 0x20, 0x6e, 0x65, 0x65,
+ 0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65,
+ 0x20, 0x68, 0x61, 0x73, 0x68, 0x65, 0x64, 0x20,
+ 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x62,
+ 0x65, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x73, 0x65,
+ 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x48, 0x4d, 0x41, 0x43, 0x20, 0x61, 0x6c,
+ 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x2e },
+ .psize = 152,
+ .digest = { 0x3a, 0x85, 0x41, 0x66, 0xac, 0x5d, 0x9f, 0x02,
+ 0x3f, 0x54, 0xd5, 0x17, 0xd0, 0xb3, 0x9d, 0xbd,
+ 0x94, 0x67, 0x70, 0xdb, 0x9c, 0x2b, 0x95, 0xc9,
+ 0xf6, 0xf5, 0x65, 0xd1 },
+ },
+};
+
/*
* HMAC-SHA256 test vectors from
* draft-ietf-ipsec-ciph-sha-256-01.txt
@@ -2140,12 +2303,18 @@
*/
#define AES_ENC_TEST_VECTORS 3
#define AES_DEC_TEST_VECTORS 3
-#define AES_CBC_ENC_TEST_VECTORS 2
-#define AES_CBC_DEC_TEST_VECTORS 2
+#define AES_CBC_ENC_TEST_VECTORS 4
+#define AES_CBC_DEC_TEST_VECTORS 4
#define AES_LRW_ENC_TEST_VECTORS 8
#define AES_LRW_DEC_TEST_VECTORS 8
#define AES_XTS_ENC_TEST_VECTORS 4
#define AES_XTS_DEC_TEST_VECTORS 4
+#define AES_CTR_ENC_TEST_VECTORS 7
+#define AES_CTR_DEC_TEST_VECTORS 6
+#define AES_GCM_ENC_TEST_VECTORS 9
+#define AES_GCM_DEC_TEST_VECTORS 8
+#define AES_CCM_ENC_TEST_VECTORS 7
+#define AES_CCM_DEC_TEST_VECTORS 7
static struct cipher_testvec aes_enc_tv_template[] = {
{ /* From FIPS-197 */
@@ -2249,6 +2418,57 @@
0x75, 0x86, 0x60, 0x2d, 0x25, 0x3c, 0xff, 0xf9,
0x1b, 0x82, 0x66, 0xbe, 0xa6, 0xd6, 0x1a, 0xb1 },
.rlen = 32,
+ }, { /* From NIST SP800-38A */
+ .key = { 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
+ 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
+ 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b },
+ .klen = 24,
+ .iv = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ .input = { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+ 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+ 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
+ 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+ 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
+ 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+ 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
+ 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 },
+ .ilen = 64,
+ .result = { 0x4f, 0x02, 0x1d, 0xb2, 0x43, 0xbc, 0x63, 0x3d,
+ 0x71, 0x78, 0x18, 0x3a, 0x9f, 0xa0, 0x71, 0xe8,
+ 0xb4, 0xd9, 0xad, 0xa9, 0xad, 0x7d, 0xed, 0xf4,
+ 0xe5, 0xe7, 0x38, 0x76, 0x3f, 0x69, 0x14, 0x5a,
+ 0x57, 0x1b, 0x24, 0x20, 0x12, 0xfb, 0x7a, 0xe0,
+ 0x7f, 0xa9, 0xba, 0xac, 0x3d, 0xf1, 0x02, 0xe0,
+ 0x08, 0xb0, 0xe2, 0x79, 0x88, 0x59, 0x88, 0x81,
+ 0xd9, 0x20, 0xa9, 0xe6, 0x4f, 0x56, 0x15, 0xcd },
+ .rlen = 64,
+ }, {
+ .key = { 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
+ 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
+ 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
+ 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 },
+ .klen = 32,
+ .iv = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ .input = { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+ 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+ 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
+ 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+ 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
+ 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+ 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
+ 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 },
+ .ilen = 64,
+ .result = { 0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba,
+ 0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6,
+ 0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d,
+ 0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d,
+ 0x39, 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba, 0xcf,
+ 0xa5, 0x30, 0xe2, 0x63, 0x04, 0x23, 0x14, 0x61,
+ 0xb2, 0xeb, 0x05, 0xe2, 0xc3, 0x9b, 0xe9, 0xfc,
+ 0xda, 0x6c, 0x19, 0x07, 0x8c, 0x6a, 0x9d, 0x1b },
+ .rlen = 64,
},
};
@@ -2280,6 +2500,57 @@
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
.rlen = 32,
+ }, { /* From NIST SP800-38A */
+ .key = { 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
+ 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
+ 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b },
+ .klen = 24,
+ .iv = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ .input = { 0x4f, 0x02, 0x1d, 0xb2, 0x43, 0xbc, 0x63, 0x3d,
+ 0x71, 0x78, 0x18, 0x3a, 0x9f, 0xa0, 0x71, 0xe8,
+ 0xb4, 0xd9, 0xad, 0xa9, 0xad, 0x7d, 0xed, 0xf4,
+ 0xe5, 0xe7, 0x38, 0x76, 0x3f, 0x69, 0x14, 0x5a,
+ 0x57, 0x1b, 0x24, 0x20, 0x12, 0xfb, 0x7a, 0xe0,
+ 0x7f, 0xa9, 0xba, 0xac, 0x3d, 0xf1, 0x02, 0xe0,
+ 0x08, 0xb0, 0xe2, 0x79, 0x88, 0x59, 0x88, 0x81,
+ 0xd9, 0x20, 0xa9, 0xe6, 0x4f, 0x56, 0x15, 0xcd },
+ .ilen = 64,
+ .result = { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+ 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+ 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
+ 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+ 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
+ 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+ 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
+ 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 },
+ .rlen = 64,
+ }, {
+ .key = { 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
+ 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
+ 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
+ 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 },
+ .klen = 32,
+ .iv = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ .input = { 0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba,
+ 0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6,
+ 0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d,
+ 0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d,
+ 0x39, 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba, 0xcf,
+ 0xa5, 0x30, 0xe2, 0x63, 0x04, 0x23, 0x14, 0x61,
+ 0xb2, 0xeb, 0x05, 0xe2, 0xc3, 0x9b, 0xe9, 0xfc,
+ 0xda, 0x6c, 0x19, 0x07, 0x8c, 0x6a, 0x9d, 0x1b },
+ .ilen = 64,
+ .result = { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+ 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+ 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
+ 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+ 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
+ 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+ 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
+ 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 },
+ .rlen = 64,
},
};
@@ -3180,6 +3451,1843 @@
}
};
+
+static struct cipher_testvec aes_ctr_enc_tv_template[] = {
+ { /* From RFC 3686 */
+ .key = { 0xae, 0x68, 0x52, 0xf8, 0x12, 0x10, 0x67, 0xcc,
+ 0x4b, 0xf7, 0xa5, 0x76, 0x55, 0x77, 0xf3, 0x9e,
+ 0x00, 0x00, 0x00, 0x30 },
+ .klen = 20,
+ .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ .input = { "Single block msg" },
+ .ilen = 16,
+ .result = { 0xe4, 0x09, 0x5d, 0x4f, 0xb7, 0xa7, 0xb3, 0x79,
+ 0x2d, 0x61, 0x75, 0xa3, 0x26, 0x13, 0x11, 0xb8 },
+ .rlen = 16,
+ }, {
+ .key = { 0x7e, 0x24, 0x06, 0x78, 0x17, 0xfa, 0xe0, 0xd7,
+ 0x43, 0xd6, 0xce, 0x1f, 0x32, 0x53, 0x91, 0x63,
+ 0x00, 0x6c, 0xb6, 0xdb },
+ .klen = 20,
+ .iv = { 0xc0, 0x54, 0x3b, 0x59, 0xda, 0x48, 0xd9, 0x0b },
+ .input = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
+ .ilen = 32,
+ .result = { 0x51, 0x04, 0xa1, 0x06, 0x16, 0x8a, 0x72, 0xd9,
+ 0x79, 0x0d, 0x41, 0xee, 0x8e, 0xda, 0xd3, 0x88,
+ 0xeb, 0x2e, 0x1e, 0xfc, 0x46, 0xda, 0x57, 0xc8,
+ 0xfc, 0xe6, 0x30, 0xdf, 0x91, 0x41, 0xbe, 0x28 },
+ .rlen = 32,
+ }, {
+ .key = { 0x16, 0xaf, 0x5b, 0x14, 0x5f, 0xc9, 0xf5, 0x79,
+ 0xc1, 0x75, 0xf9, 0x3e, 0x3b, 0xfb, 0x0e, 0xed,
+ 0x86, 0x3d, 0x06, 0xcc, 0xfd, 0xb7, 0x85, 0x15,
+ 0x00, 0x00, 0x00, 0x48 },
+ .klen = 28,
+ .iv = { 0x36, 0x73, 0x3c, 0x14, 0x7d, 0x6d, 0x93, 0xcb },
+ .input = { "Single block msg" },
+ .ilen = 16,
+ .result = { 0x4b, 0x55, 0x38, 0x4f, 0xe2, 0x59, 0xc9, 0xc8,
+ 0x4e, 0x79, 0x35, 0xa0, 0x03, 0xcb, 0xe9, 0x28 },
+ .rlen = 16,
+ }, {
+ .key = { 0x7c, 0x5c, 0xb2, 0x40, 0x1b, 0x3d, 0xc3, 0x3c,
+ 0x19, 0xe7, 0x34, 0x08, 0x19, 0xe0, 0xf6, 0x9c,
+ 0x67, 0x8c, 0x3d, 0xb8, 0xe6, 0xf6, 0xa9, 0x1a,
+ 0x00, 0x96, 0xb0, 0x3b },
+ .klen = 28,
+ .iv = { 0x02, 0x0c, 0x6e, 0xad, 0xc2, 0xcb, 0x50, 0x0d },
+ .input = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
+ .ilen = 32,
+ .result = { 0x45, 0x32, 0x43, 0xfc, 0x60, 0x9b, 0x23, 0x32,
+ 0x7e, 0xdf, 0xaa, 0xfa, 0x71, 0x31, 0xcd, 0x9f,
+ 0x84, 0x90, 0x70, 0x1c, 0x5a, 0xd4, 0xa7, 0x9c,
+ 0xfc, 0x1f, 0xe0, 0xff, 0x42, 0xf4, 0xfb, 0x00 },
+ .rlen = 32,
+ }, {
+ .key = { 0x77, 0x6b, 0xef, 0xf2, 0x85, 0x1d, 0xb0, 0x6f,
+ 0x4c, 0x8a, 0x05, 0x42, 0xc8, 0x69, 0x6f, 0x6c,
+ 0x6a, 0x81, 0xaf, 0x1e, 0xec, 0x96, 0xb4, 0xd3,
+ 0x7f, 0xc1, 0xd6, 0x89, 0xe6, 0xc1, 0xc1, 0x04,
+ 0x00, 0x00, 0x00, 0x60 },
+ .klen = 36,
+ .iv = { 0xdb, 0x56, 0x72, 0xc9, 0x7a, 0xa8, 0xf0, 0xb2 },
+ .input = { "Single block msg" },
+ .ilen = 16,
+ .result = { 0x14, 0x5a, 0xd0, 0x1d, 0xbf, 0x82, 0x4e, 0xc7,
+ 0x56, 0x08, 0x63, 0xdc, 0x71, 0xe3, 0xe0, 0xc0 },
+ .rlen = 16,
+ }, {
+ .key = { 0xf6, 0xd6, 0x6d, 0x6b, 0xd5, 0x2d, 0x59, 0xbb,
+ 0x07, 0x96, 0x36, 0x58, 0x79, 0xef, 0xf8, 0x86,
+ 0xc6, 0x6d, 0xd5, 0x1a, 0x5b, 0x6a, 0x99, 0x74,
+ 0x4b, 0x50, 0x59, 0x0c, 0x87, 0xa2, 0x38, 0x84,
+ 0x00, 0xfa, 0xac, 0x24 },
+ .klen = 36,
+ .iv = { 0xc1, 0x58, 0x5e, 0xf1, 0x5a, 0x43, 0xd8, 0x75 },
+ .input = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
+ .ilen = 32,
+ .result = { 0xf0, 0x5e, 0x23, 0x1b, 0x38, 0x94, 0x61, 0x2c,
+ 0x49, 0xee, 0x00, 0x0b, 0x80, 0x4e, 0xb2, 0xa9,
+ 0xb8, 0x30, 0x6b, 0x50, 0x8f, 0x83, 0x9d, 0x6a,
+ 0x55, 0x30, 0x83, 0x1d, 0x93, 0x44, 0xaf, 0x1c },
+ .rlen = 32,
+ }, {
+ // generated using Crypto++
+ .key = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x00, 0x00, 0x00, 0x00,
+ },
+ .klen = 32 + 4,
+ .iv = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ .input = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+ 0x00, 0x03, 0x06, 0x09, 0x0c, 0x0f, 0x12, 0x15,
+ 0x18, 0x1b, 0x1e, 0x21, 0x24, 0x27, 0x2a, 0x2d,
+ 0x30, 0x33, 0x36, 0x39, 0x3c, 0x3f, 0x42, 0x45,
+ 0x48, 0x4b, 0x4e, 0x51, 0x54, 0x57, 0x5a, 0x5d,
+ 0x60, 0x63, 0x66, 0x69, 0x6c, 0x6f, 0x72, 0x75,
+ 0x78, 0x7b, 0x7e, 0x81, 0x84, 0x87, 0x8a, 0x8d,
+ 0x90, 0x93, 0x96, 0x99, 0x9c, 0x9f, 0xa2, 0xa5,
+ 0xa8, 0xab, 0xae, 0xb1, 0xb4, 0xb7, 0xba, 0xbd,
+ 0xc0, 0xc3, 0xc6, 0xc9, 0xcc, 0xcf, 0xd2, 0xd5,
+ 0xd8, 0xdb, 0xde, 0xe1, 0xe4, 0xe7, 0xea, 0xed,
+ 0xf0, 0xf3, 0xf6, 0xf9, 0xfc, 0xff, 0x02, 0x05,
+ 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17, 0x1a, 0x1d,
+ 0x20, 0x23, 0x26, 0x29, 0x2c, 0x2f, 0x32, 0x35,
+ 0x38, 0x3b, 0x3e, 0x41, 0x44, 0x47, 0x4a, 0x4d,
+ 0x50, 0x53, 0x56, 0x59, 0x5c, 0x5f, 0x62, 0x65,
+ 0x68, 0x6b, 0x6e, 0x71, 0x74, 0x77, 0x7a, 0x7d,
+ 0x80, 0x83, 0x86, 0x89, 0x8c, 0x8f, 0x92, 0x95,
+ 0x98, 0x9b, 0x9e, 0xa1, 0xa4, 0xa7, 0xaa, 0xad,
+ 0xb0, 0xb3, 0xb6, 0xb9, 0xbc, 0xbf, 0xc2, 0xc5,
+ 0xc8, 0xcb, 0xce, 0xd1, 0xd4, 0xd7, 0xda, 0xdd,
+ 0xe0, 0xe3, 0xe6, 0xe9, 0xec, 0xef, 0xf2, 0xf5,
+ 0xf8, 0xfb, 0xfe, 0x01, 0x04, 0x07, 0x0a, 0x0d,
+ 0x10, 0x13, 0x16, 0x19, 0x1c, 0x1f, 0x22, 0x25,
+ 0x28, 0x2b, 0x2e, 0x31, 0x34, 0x37, 0x3a, 0x3d,
+ 0x40, 0x43, 0x46, 0x49, 0x4c, 0x4f, 0x52, 0x55,
+ 0x58, 0x5b, 0x5e, 0x61, 0x64, 0x67, 0x6a, 0x6d,
+ 0x70, 0x73, 0x76, 0x79, 0x7c, 0x7f, 0x82, 0x85,
+ 0x88, 0x8b, 0x8e, 0x91, 0x94, 0x97, 0x9a, 0x9d,
+ 0xa0, 0xa3, 0xa6, 0xa9, 0xac, 0xaf, 0xb2, 0xb5,
+ 0xb8, 0xbb, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
+ 0xd0, 0xd3, 0xd6, 0xd9, 0xdc, 0xdf, 0xe2, 0xe5,
+ 0xe8, 0xeb, 0xee, 0xf1, 0xf4, 0xf7, 0xfa, 0xfd,
+ 0x00, 0x05, 0x0a, 0x0f, 0x14, 0x19, 0x1e, 0x23,
+ 0x28, 0x2d, 0x32, 0x37, 0x3c, 0x41, 0x46, 0x4b,
+ 0x50, 0x55, 0x5a, 0x5f, 0x64, 0x69, 0x6e, 0x73,
+ 0x78, 0x7d, 0x82, 0x87, 0x8c, 0x91, 0x96, 0x9b,
+ 0xa0, 0xa5, 0xaa, 0xaf, 0xb4, 0xb9, 0xbe, 0xc3,
+ 0xc8, 0xcd, 0xd2, 0xd7, 0xdc, 0xe1, 0xe6, 0xeb,
+ 0xf0, 0xf5, 0xfa, 0xff, 0x04, 0x09, 0x0e, 0x13,
+ 0x18, 0x1d, 0x22, 0x27, 0x2c, 0x31, 0x36, 0x3b,
+ 0x40, 0x45, 0x4a, 0x4f, 0x54, 0x59, 0x5e, 0x63,
+ 0x68, 0x6d, 0x72, 0x77, 0x7c, 0x81, 0x86, 0x8b,
+ 0x90, 0x95, 0x9a, 0x9f, 0xa4, 0xa9, 0xae, 0xb3,
+ 0xb8, 0xbd, 0xc2, 0xc7, 0xcc, 0xd1, 0xd6, 0xdb,
+ 0xe0, 0xe5, 0xea, 0xef, 0xf4, 0xf9, 0xfe, 0x03,
+ 0x08, 0x0d, 0x12, 0x17, 0x1c, 0x21, 0x26, 0x2b,
+ 0x30, 0x35, 0x3a, 0x3f, 0x44, 0x49, 0x4e, 0x53,
+ 0x58, 0x5d, 0x62, 0x67, 0x6c, 0x71, 0x76, 0x7b,
+ 0x80, 0x85, 0x8a, 0x8f, 0x94, 0x99, 0x9e, 0xa3,
+ 0xa8, 0xad, 0xb2, 0xb7, 0xbc, 0xc1, 0xc6, 0xcb,
+ 0xd0, 0xd5, 0xda, 0xdf, 0xe4, 0xe9, 0xee, 0xf3,
+ 0xf8, 0xfd, 0x02, 0x07, 0x0c, 0x11, 0x16, 0x1b,
+ 0x20, 0x25, 0x2a, 0x2f, 0x34, 0x39, 0x3e, 0x43,
+ 0x48, 0x4d, 0x52, 0x57, 0x5c, 0x61, 0x66, 0x6b,
+ 0x70, 0x75, 0x7a, 0x7f, 0x84, 0x89, 0x8e, 0x93,
+ 0x98, 0x9d, 0xa2, 0xa7, 0xac, 0xb1, 0xb6, 0xbb,
+ 0xc0, 0xc5, 0xca, 0xcf, 0xd4, 0xd9, 0xde, 0xe3,
+ 0xe8, 0xed, 0xf2, 0xf7, 0xfc, 0x01, 0x06, 0x0b,
+ 0x10, 0x15, 0x1a, 0x1f, 0x24, 0x29, 0x2e, 0x33,
+ 0x38, 0x3d, 0x42, 0x47, 0x4c, 0x51, 0x56, 0x5b,
+ 0x60, 0x65, 0x6a, 0x6f, 0x74, 0x79, 0x7e, 0x83,
+ 0x88, 0x8d, 0x92, 0x97, 0x9c, 0xa1, 0xa6, 0xab,
+ 0xb0, 0xb5, 0xba, 0xbf, 0xc4, 0xc9, 0xce, 0xd3,
+ 0xd8, 0xdd, 0xe2, 0xe7, 0xec, 0xf1, 0xf6, 0xfb,
+ 0x00, 0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31,
+ 0x38, 0x3f, 0x46, 0x4d, 0x54, 0x5b, 0x62, 0x69,
+ 0x70, 0x77, 0x7e, 0x85, 0x8c, 0x93, 0x9a, 0xa1,
+ 0xa8, 0xaf, 0xb6, 0xbd, 0xc4, 0xcb, 0xd2, 0xd9,
+ 0xe0, 0xe7, 0xee, 0xf5, 0xfc, 0x03, 0x0a, 0x11,
+ 0x18, 0x1f, 0x26, 0x2d, 0x34, 0x3b, 0x42, 0x49,
+ 0x50, 0x57, 0x5e, 0x65, 0x6c, 0x73, 0x7a, 0x81,
+ 0x88, 0x8f, 0x96, 0x9d, 0xa4, 0xab, 0xb2, 0xb9,
+ 0xc0, 0xc7, 0xce, 0xd5, 0xdc, 0xe3, 0xea, 0xf1,
+ 0xf8, 0xff, 0x06, 0x0d, 0x14, 0x1b, 0x22, 0x29,
+ 0x30, 0x37, 0x3e, 0x45, 0x4c, 0x53, 0x5a, 0x61,
+ 0x68, 0x6f, 0x76, 0x7d, 0x84, 0x8b, 0x92, 0x99,
+ 0xa0, 0xa7, 0xae, 0xb5, 0xbc, 0xc3, 0xca, 0xd1,
+ 0xd8, 0xdf, 0xe6, 0xed, 0xf4, 0xfb, 0x02, 0x09,
+ 0x10, 0x17, 0x1e, 0x25, 0x2c, 0x33, 0x3a, 0x41,
+ 0x48, 0x4f, 0x56, 0x5d, 0x64, 0x6b, 0x72, 0x79,
+ 0x80, 0x87, 0x8e, 0x95, 0x9c, 0xa3, 0xaa, 0xb1,
+ 0xb8, 0xbf, 0xc6, 0xcd, 0xd4, 0xdb, 0xe2, 0xe9,
+ 0xf0, 0xf7, 0xfe, 0x05, 0x0c, 0x13, 0x1a, 0x21,
+ 0x28, 0x2f, 0x36, 0x3d, 0x44, 0x4b, 0x52, 0x59,
+ 0x60, 0x67, 0x6e, 0x75, 0x7c, 0x83, 0x8a, 0x91,
+ 0x98, 0x9f, 0xa6, 0xad, 0xb4, 0xbb, 0xc2, 0xc9,
+ 0xd0, 0xd7, 0xde, 0xe5, 0xec, 0xf3, 0xfa, 0x01,
+ 0x08, 0x0f, 0x16, 0x1d, 0x24, 0x2b, 0x32, 0x39,
+ 0x40, 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71,
+ 0x78, 0x7f, 0x86, 0x8d, 0x94, 0x9b, 0xa2, 0xa9,
+ 0xb0, 0xb7, 0xbe, 0xc5, 0xcc, 0xd3, 0xda, 0xe1,
+ 0xe8, 0xef, 0xf6, 0xfd, 0x04, 0x0b, 0x12, 0x19,
+ 0x20, 0x27, 0x2e, 0x35, 0x3c, 0x43, 0x4a, 0x51,
+ 0x58, 0x5f, 0x66, 0x6d, 0x74, 0x7b, 0x82, 0x89,
+ 0x90, 0x97, 0x9e, 0xa5, 0xac, 0xb3, 0xba, 0xc1,
+ 0xc8, 0xcf, 0xd6, 0xdd, 0xe4, 0xeb, 0xf2, 0xf9,
+ 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f,
+ 0x48, 0x51, 0x5a, 0x63, 0x6c, 0x75, 0x7e, 0x87,
+ 0x90, 0x99, 0xa2, 0xab, 0xb4, 0xbd, 0xc6, 0xcf,
+ 0xd8, 0xe1, 0xea, 0xf3, 0xfc, 0x05, 0x0e, 0x17,
+ 0x20, 0x29, 0x32, 0x3b, 0x44, 0x4d, 0x56, 0x5f,
+ 0x68, 0x71, 0x7a, 0x83, 0x8c, 0x95, 0x9e, 0xa7,
+ 0xb0, 0xb9, 0xc2, 0xcb, 0xd4, 0xdd, 0xe6, 0xef,
+ 0xf8, 0x01, 0x0a, 0x13, 0x1c, 0x25, 0x2e, 0x37,
+ 0x40, 0x49, 0x52, 0x5b, 0x64, 0x6d, 0x76, 0x7f,
+ 0x88, 0x91, 0x9a, 0xa3, 0xac, 0xb5, 0xbe, 0xc7,
+ 0xd0, 0xd9, 0xe2, 0xeb, 0xf4, 0xfd, 0x06, 0x0f,
+ 0x18, 0x21, 0x2a, 0x33, 0x3c, 0x45, 0x4e, 0x57,
+ 0x60, 0x69, 0x72, 0x7b, 0x84, 0x8d, 0x96, 0x9f,
+ 0xa8, 0xb1, 0xba, 0xc3, 0xcc, 0xd5, 0xde, 0xe7,
+ 0xf0, 0xf9, 0x02, 0x0b, 0x14, 0x1d, 0x26, 0x2f,
+ 0x38, 0x41, 0x4a, 0x53, 0x5c, 0x65, 0x6e, 0x77,
+ 0x80, 0x89, 0x92, 0x9b, 0xa4, 0xad, 0xb6, 0xbf,
+ 0xc8, 0xd1, 0xda, 0xe3, 0xec, 0xf5, 0xfe, 0x07,
+ 0x10, 0x19, 0x22, 0x2b, 0x34, 0x3d, 0x46, 0x4f,
+ 0x58, 0x61, 0x6a, 0x73, 0x7c, 0x85, 0x8e, 0x97,
+ 0xa0, 0xa9, 0xb2, 0xbb, 0xc4, 0xcd, 0xd6, 0xdf,
+ 0xe8, 0xf1, 0xfa, 0x03, 0x0c, 0x15, 0x1e, 0x27,
+ 0x30, 0x39, 0x42, 0x4b, 0x54, 0x5d, 0x66, 0x6f,
+ 0x78, 0x81, 0x8a, 0x93, 0x9c, 0xa5, 0xae, 0xb7,
+ 0xc0, 0xc9, 0xd2, 0xdb, 0xe4, 0xed, 0xf6, 0xff,
+ 0x08, 0x11, 0x1a, 0x23, 0x2c, 0x35, 0x3e, 0x47,
+ 0x50, 0x59, 0x62, 0x6b, 0x74, 0x7d, 0x86, 0x8f,
+ 0x98, 0xa1, 0xaa, 0xb3, 0xbc, 0xc5, 0xce, 0xd7,
+ 0xe0, 0xe9, 0xf2, 0xfb, 0x04, 0x0d, 0x16, 0x1f,
+ 0x28, 0x31, 0x3a, 0x43, 0x4c, 0x55, 0x5e, 0x67,
+ 0x70, 0x79, 0x82, 0x8b, 0x94, 0x9d, 0xa6, 0xaf,
+ 0xb8, 0xc1, 0xca, 0xd3, 0xdc, 0xe5, 0xee, 0xf7,
+ 0x00, 0x0b, 0x16, 0x21, 0x2c, 0x37, 0x42, 0x4d,
+ 0x58, 0x63, 0x6e, 0x79, 0x84, 0x8f, 0x9a, 0xa5,
+ 0xb0, 0xbb, 0xc6, 0xd1, 0xdc, 0xe7, 0xf2, 0xfd,
+ 0x08, 0x13, 0x1e, 0x29, 0x34, 0x3f, 0x4a, 0x55,
+ 0x60, 0x6b, 0x76, 0x81, 0x8c, 0x97, 0xa2, 0xad,
+ 0xb8, 0xc3, 0xce, 0xd9, 0xe4, 0xef, 0xfa, 0x05,
+ 0x10, 0x1b, 0x26, 0x31, 0x3c, 0x47, 0x52, 0x5d,
+ 0x68, 0x73, 0x7e, 0x89, 0x94, 0x9f, 0xaa, 0xb5,
+ 0xc0, 0xcb, 0xd6, 0xe1, 0xec, 0xf7, 0x02, 0x0d,
+ 0x18, 0x23, 0x2e, 0x39, 0x44, 0x4f, 0x5a, 0x65,
+ 0x70, 0x7b, 0x86, 0x91, 0x9c, 0xa7, 0xb2, 0xbd,
+ 0xc8, 0xd3, 0xde, 0xe9, 0xf4, 0xff, 0x0a, 0x15,
+ 0x20, 0x2b, 0x36, 0x41, 0x4c, 0x57, 0x62, 0x6d,
+ 0x78, 0x83, 0x8e, 0x99, 0xa4, 0xaf, 0xba, 0xc5,
+ 0xd0, 0xdb, 0xe6, 0xf1, 0xfc, 0x07, 0x12, 0x1d,
+ 0x28, 0x33, 0x3e, 0x49, 0x54, 0x5f, 0x6a, 0x75,
+ 0x80, 0x8b, 0x96, 0xa1, 0xac, 0xb7, 0xc2, 0xcd,
+ 0xd8, 0xe3, 0xee, 0xf9, 0x04, 0x0f, 0x1a, 0x25,
+ 0x30, 0x3b, 0x46, 0x51, 0x5c, 0x67, 0x72, 0x7d,
+ 0x88, 0x93, 0x9e, 0xa9, 0xb4, 0xbf, 0xca, 0xd5,
+ 0xe0, 0xeb, 0xf6, 0x01, 0x0c, 0x17, 0x22, 0x2d,
+ 0x38, 0x43, 0x4e, 0x59, 0x64, 0x6f, 0x7a, 0x85,
+ 0x90, 0x9b, 0xa6, 0xb1, 0xbc, 0xc7, 0xd2, 0xdd,
+ 0xe8, 0xf3, 0xfe, 0x09, 0x14, 0x1f, 0x2a, 0x35,
+ 0x40, 0x4b, 0x56, 0x61, 0x6c, 0x77, 0x82, 0x8d,
+ 0x98, 0xa3, 0xae, 0xb9, 0xc4, 0xcf, 0xda, 0xe5,
+ 0xf0, 0xfb, 0x06, 0x11, 0x1c, 0x27, 0x32, 0x3d,
+ 0x48, 0x53, 0x5e, 0x69, 0x74, 0x7f, 0x8a, 0x95,
+ 0xa0, 0xab, 0xb6, 0xc1, 0xcc, 0xd7, 0xe2, 0xed,
+ 0xf8, 0x03, 0x0e, 0x19, 0x24, 0x2f, 0x3a, 0x45,
+ 0x50, 0x5b, 0x66, 0x71, 0x7c, 0x87, 0x92, 0x9d,
+ 0xa8, 0xb3, 0xbe, 0xc9, 0xd4, 0xdf, 0xea, 0xf5,
+ 0x00, 0x0d, 0x1a, 0x27, 0x34, 0x41, 0x4e, 0x5b,
+ 0x68, 0x75, 0x82, 0x8f, 0x9c, 0xa9, 0xb6, 0xc3,
+ 0xd0, 0xdd, 0xea, 0xf7, 0x04, 0x11, 0x1e, 0x2b,
+ 0x38, 0x45, 0x52, 0x5f, 0x6c, 0x79, 0x86, 0x93,
+ 0xa0, 0xad, 0xba, 0xc7, 0xd4, 0xe1, 0xee, 0xfb,
+ 0x08, 0x15, 0x22, 0x2f, 0x3c, 0x49, 0x56, 0x63,
+ 0x70, 0x7d, 0x8a, 0x97, 0xa4, 0xb1, 0xbe, 0xcb,
+ 0xd8, 0xe5, 0xf2, 0xff, 0x0c, 0x19, 0x26, 0x33,
+ 0x40, 0x4d, 0x5a, 0x67, 0x74, 0x81, 0x8e, 0x9b,
+ 0xa8, 0xb5, 0xc2, 0xcf, 0xdc, 0xe9, 0xf6, 0x03,
+ 0x10, 0x1d, 0x2a, 0x37, 0x44, 0x51, 0x5e, 0x6b,
+ 0x78, 0x85, 0x92, 0x9f, 0xac, 0xb9, 0xc6, 0xd3,
+ 0xe0, 0xed, 0xfa, 0x07, 0x14, 0x21, 0x2e, 0x3b,
+ 0x48, 0x55, 0x62, 0x6f, 0x7c, 0x89, 0x96, 0xa3,
+ 0xb0, 0xbd, 0xca, 0xd7, 0xe4, 0xf1, 0xfe, 0x0b,
+ 0x18, 0x25, 0x32, 0x3f, 0x4c, 0x59, 0x66, 0x73,
+ 0x80, 0x8d, 0x9a, 0xa7, 0xb4, 0xc1, 0xce, 0xdb,
+ 0xe8, 0xf5, 0x02, 0x0f, 0x1c, 0x29, 0x36, 0x43,
+ 0x50, 0x5d, 0x6a, 0x77, 0x84, 0x91, 0x9e, 0xab,
+ 0xb8, 0xc5, 0xd2, 0xdf, 0xec, 0xf9, 0x06, 0x13,
+ 0x20, 0x2d, 0x3a, 0x47, 0x54, 0x61, 0x6e, 0x7b,
+ 0x88, 0x95, 0xa2, 0xaf, 0xbc, 0xc9, 0xd6, 0xe3,
+ 0xf0, 0xfd, 0x0a, 0x17, 0x24, 0x31, 0x3e, 0x4b,
+ 0x58, 0x65, 0x72, 0x7f, 0x8c, 0x99, 0xa6, 0xb3,
+ 0xc0, 0xcd, 0xda, 0xe7, 0xf4, 0x01, 0x0e, 0x1b,
+ 0x28, 0x35, 0x42, 0x4f, 0x5c, 0x69, 0x76, 0x83,
+ 0x90, 0x9d, 0xaa, 0xb7, 0xc4, 0xd1, 0xde, 0xeb,
+ 0xf8, 0x05, 0x12, 0x1f, 0x2c, 0x39, 0x46, 0x53,
+ 0x60, 0x6d, 0x7a, 0x87, 0x94, 0xa1, 0xae, 0xbb,
+ 0xc8, 0xd5, 0xe2, 0xef, 0xfc, 0x09, 0x16, 0x23,
+ 0x30, 0x3d, 0x4a, 0x57, 0x64, 0x71, 0x7e, 0x8b,
+ 0x98, 0xa5, 0xb2, 0xbf, 0xcc, 0xd9, 0xe6, 0xf3,
+ 0x00, 0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69,
+ 0x78, 0x87, 0x96, 0xa5, 0xb4, 0xc3, 0xd2, 0xe1,
+ 0xf0, 0xff, 0x0e, 0x1d, 0x2c, 0x3b, 0x4a, 0x59,
+ 0x68, 0x77, 0x86, 0x95, 0xa4, 0xb3, 0xc2, 0xd1,
+ 0xe0, 0xef, 0xfe, 0x0d, 0x1c, 0x2b, 0x3a, 0x49,
+ 0x58, 0x67, 0x76, 0x85, 0x94, 0xa3, 0xb2, 0xc1,
+ 0xd0, 0xdf, 0xee, 0xfd, 0x0c, 0x1b, 0x2a, 0x39,
+ 0x48, 0x57, 0x66, 0x75, 0x84, 0x93, 0xa2, 0xb1,
+ 0xc0, 0xcf, 0xde, 0xed, 0xfc, 0x0b, 0x1a, 0x29,
+ 0x38, 0x47, 0x56, 0x65, 0x74, 0x83, 0x92, 0xa1,
+ 0xb0, 0xbf, 0xce, 0xdd, 0xec, 0xfb, 0x0a, 0x19,
+ 0x28, 0x37, 0x46, 0x55, 0x64, 0x73, 0x82, 0x91,
+ 0xa0, 0xaf, 0xbe, 0xcd, 0xdc, 0xeb, 0xfa, 0x09,
+ 0x18, 0x27, 0x36, 0x45, 0x54, 0x63, 0x72, 0x81,
+ 0x90, 0x9f, 0xae, 0xbd, 0xcc, 0xdb, 0xea, 0xf9,
+ 0x08, 0x17, 0x26, 0x35, 0x44, 0x53, 0x62, 0x71,
+ 0x80, 0x8f, 0x9e, 0xad, 0xbc, 0xcb, 0xda, 0xe9,
+ 0xf8, 0x07, 0x16, 0x25, 0x34, 0x43, 0x52, 0x61,
+ 0x70, 0x7f, 0x8e, 0x9d, 0xac, 0xbb, 0xca, 0xd9,
+ 0xe8, 0xf7, 0x06, 0x15, 0x24, 0x33, 0x42, 0x51,
+ 0x60, 0x6f, 0x7e, 0x8d, 0x9c, 0xab, 0xba, 0xc9,
+ 0xd8, 0xe7, 0xf6, 0x05, 0x14, 0x23, 0x32, 0x41,
+ 0x50, 0x5f, 0x6e, 0x7d, 0x8c, 0x9b, 0xaa, 0xb9,
+ 0xc8, 0xd7, 0xe6, 0xf5, 0x04, 0x13, 0x22, 0x31,
+ 0x40, 0x4f, 0x5e, 0x6d, 0x7c, 0x8b, 0x9a, 0xa9,
+ 0xb8, 0xc7, 0xd6, 0xe5, 0xf4, 0x03, 0x12, 0x21,
+ 0x30, 0x3f, 0x4e, 0x5d, 0x6c, 0x7b, 0x8a, 0x99,
+ 0xa8, 0xb7, 0xc6, 0xd5, 0xe4, 0xf3, 0x02, 0x11,
+ 0x20, 0x2f, 0x3e, 0x4d, 0x5c, 0x6b, 0x7a, 0x89,
+ 0x98, 0xa7, 0xb6, 0xc5, 0xd4, 0xe3, 0xf2, 0x01,
+ 0x10, 0x1f, 0x2e, 0x3d, 0x4c, 0x5b, 0x6a, 0x79,
+ 0x88, 0x97, 0xa6, 0xb5, 0xc4, 0xd3, 0xe2, 0xf1,
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
+ 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87,
+ 0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0x0f,
+ 0x20, 0x31, 0x42, 0x53, 0x64, 0x75, 0x86, 0x97,
+ 0xa8, 0xb9, 0xca, 0xdb, 0xec, 0xfd, 0x0e, 0x1f,
+ 0x30, 0x41, 0x52, 0x63, 0x74, 0x85, 0x96, 0xa7,
+ 0xb8, 0xc9, 0xda, 0xeb, 0xfc, 0x0d, 0x1e, 0x2f,
+ 0x40, 0x51, 0x62, 0x73, 0x84, 0x95, 0xa6, 0xb7,
+ 0xc8, 0xd9, 0xea, 0xfb, 0x0c, 0x1d, 0x2e, 0x3f,
+ 0x50, 0x61, 0x72, 0x83, 0x94, 0xa5, 0xb6, 0xc7,
+ 0xd8, 0xe9, 0xfa, 0x0b, 0x1c, 0x2d, 0x3e, 0x4f,
+ 0x60, 0x71, 0x82, 0x93, 0xa4, 0xb5, 0xc6, 0xd7,
+ 0xe8, 0xf9, 0x0a, 0x1b, 0x2c, 0x3d, 0x4e, 0x5f,
+ 0x70, 0x81, 0x92, 0xa3, 0xb4, 0xc5, 0xd6, 0xe7,
+ 0xf8, 0x09, 0x1a, 0x2b, 0x3c, 0x4d, 0x5e, 0x6f,
+ 0x80, 0x91, 0xa2, 0xb3, 0xc4, 0xd5, 0xe6, 0xf7,
+ 0x08, 0x19, 0x2a, 0x3b, 0x4c, 0x5d, 0x6e, 0x7f,
+ 0x90, 0xa1, 0xb2, 0xc3, 0xd4, 0xe5, 0xf6, 0x07,
+ 0x18, 0x29, 0x3a, 0x4b, 0x5c, 0x6d, 0x7e, 0x8f,
+ 0xa0, 0xb1, 0xc2, 0xd3, 0xe4, 0xf5, 0x06, 0x17,
+ 0x28, 0x39, 0x4a, 0x5b, 0x6c, 0x7d, 0x8e, 0x9f,
+ 0xb0, 0xc1, 0xd2, 0xe3, 0xf4, 0x05, 0x16, 0x27,
+ 0x38, 0x49, 0x5a, 0x6b, 0x7c, 0x8d, 0x9e, 0xaf,
+ 0xc0, 0xd1, 0xe2, 0xf3, 0x04, 0x15, 0x26, 0x37,
+ 0x48, 0x59, 0x6a, 0x7b, 0x8c, 0x9d, 0xae, 0xbf,
+ 0xd0, 0xe1, 0xf2, 0x03, 0x14, 0x25, 0x36, 0x47,
+ 0x58, 0x69, 0x7a, 0x8b, 0x9c, 0xad, 0xbe, 0xcf,
+ 0xe0, 0xf1, 0x02, 0x13, 0x24, 0x35, 0x46, 0x57,
+ 0x68, 0x79, 0x8a, 0x9b, 0xac, 0xbd, 0xce, 0xdf,
+ 0xf0, 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67,
+ 0x78, 0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef,
+ 0x00, 0x13, 0x26, 0x39, 0x4c, 0x5f, 0x72, 0x85,
+ 0x98, 0xab, 0xbe, 0xd1, 0xe4, 0xf7, 0x0a, 0x1d,
+ 0x30, 0x43, 0x56, 0x69, 0x7c, 0x8f, 0xa2, 0xb5,
+ 0xc8, 0xdb, 0xee, 0x01, 0x14, 0x27, 0x3a, 0x4d,
+ 0x60, 0x73, 0x86, 0x99, 0xac, 0xbf, 0xd2, 0xe5,
+ 0xf8, 0x0b, 0x1e, 0x31, 0x44, 0x57, 0x6a, 0x7d,
+ 0x90, 0xa3, 0xb6, 0xc9, 0xdc, 0xef, 0x02, 0x15,
+ 0x28, 0x3b, 0x4e, 0x61, 0x74, 0x87, 0x9a, 0xad,
+ 0xc0, 0xd3, 0xe6, 0xf9, 0x0c, 0x1f, 0x32, 0x45,
+ 0x58, 0x6b, 0x7e, 0x91, 0xa4, 0xb7, 0xca, 0xdd,
+ 0xf0, 0x03, 0x16, 0x29, 0x3c, 0x4f, 0x62, 0x75,
+ 0x88, 0x9b, 0xae, 0xc1, 0xd4, 0xe7, 0xfa, 0x0d,
+ 0x20, 0x33, 0x46, 0x59, 0x6c, 0x7f, 0x92, 0xa5,
+ 0xb8, 0xcb, 0xde, 0xf1, 0x04, 0x17, 0x2a, 0x3d,
+ 0x50, 0x63, 0x76, 0x89, 0x9c, 0xaf, 0xc2, 0xd5,
+ 0xe8, 0xfb, 0x0e, 0x21, 0x34, 0x47, 0x5a, 0x6d,
+ 0x80, 0x93, 0xa6, 0xb9, 0xcc, 0xdf, 0xf2, 0x05,
+ 0x18, 0x2b, 0x3e, 0x51, 0x64, 0x77, 0x8a, 0x9d,
+ 0xb0, 0xc3, 0xd6, 0xe9, 0xfc, 0x0f, 0x22, 0x35,
+ 0x48, 0x5b, 0x6e, 0x81, 0x94, 0xa7, 0xba, 0xcd,
+ 0xe0, 0xf3, 0x06, 0x19, 0x2c, 0x3f, 0x52, 0x65,
+ 0x78, 0x8b, 0x9e, 0xb1, 0xc4, 0xd7, 0xea, 0xfd,
+ 0x10, 0x23, 0x36, 0x49, 0x5c, 0x6f, 0x82, 0x95,
+ 0xa8, 0xbb, 0xce, 0xe1, 0xf4, 0x07, 0x1a, 0x2d,
+ 0x40, 0x53, 0x66, 0x79, 0x8c, 0x9f, 0xb2, 0xc5,
+ 0xd8, 0xeb, 0xfe, 0x11, 0x24, 0x37, 0x4a, 0x5d,
+ 0x70, 0x83, 0x96, 0xa9, 0xbc, 0xcf, 0xe2, 0xf5,
+ 0x08, 0x1b, 0x2e, 0x41, 0x54, 0x67, 0x7a, 0x8d,
+ 0xa0, 0xb3, 0xc6, 0xd9, 0xec, 0xff, 0x12, 0x25,
+ 0x38, 0x4b, 0x5e, 0x71, 0x84, 0x97, 0xaa, 0xbd,
+ 0xd0, 0xe3, 0xf6, 0x09, 0x1c, 0x2f, 0x42, 0x55,
+ 0x68, 0x7b, 0x8e, 0xa1, 0xb4, 0xc7, 0xda, 0xed,
+ 0x00, 0x15, 0x2a, 0x3f, 0x54, 0x69, 0x7e, 0x93,
+ 0xa8, 0xbd, 0xd2, 0xe7, 0xfc, 0x11, 0x26, 0x3b,
+ 0x50, 0x65, 0x7a, 0x8f, 0xa4, 0xb9, 0xce, 0xe3,
+ 0xf8, 0x0d, 0x22, 0x37, 0x4c, 0x61, 0x76, 0x8b,
+ 0xa0, 0xb5, 0xca, 0xdf, 0xf4, 0x09, 0x1e, 0x33,
+ 0x48, 0x5d, 0x72, 0x87, 0x9c, 0xb1, 0xc6, 0xdb,
+ 0xf0, 0x05, 0x1a, 0x2f, 0x44, 0x59, 0x6e, 0x83,
+ 0x98, 0xad, 0xc2, 0xd7, 0xec, 0x01, 0x16, 0x2b,
+ 0x40, 0x55, 0x6a, 0x7f, 0x94, 0xa9, 0xbe, 0xd3,
+ 0xe8, 0xfd, 0x12, 0x27, 0x3c, 0x51, 0x66, 0x7b,
+ 0x90, 0xa5, 0xba, 0xcf, 0xe4, 0xf9, 0x0e, 0x23,
+ 0x38, 0x4d, 0x62, 0x77, 0x8c, 0xa1, 0xb6, 0xcb,
+ 0xe0, 0xf5, 0x0a, 0x1f, 0x34, 0x49, 0x5e, 0x73,
+ 0x88, 0x9d, 0xb2, 0xc7, 0xdc, 0xf1, 0x06, 0x1b,
+ 0x30, 0x45, 0x5a, 0x6f, 0x84, 0x99, 0xae, 0xc3,
+ 0xd8, 0xed, 0x02, 0x17, 0x2c, 0x41, 0x56, 0x6b,
+ 0x80, 0x95, 0xaa, 0xbf, 0xd4, 0xe9, 0xfe, 0x13,
+ 0x28, 0x3d, 0x52, 0x67, 0x7c, 0x91, 0xa6, 0xbb,
+ 0xd0, 0xe5, 0xfa, 0x0f, 0x24, 0x39, 0x4e, 0x63,
+ 0x78, 0x8d, 0xa2, 0xb7, 0xcc, 0xe1, 0xf6, 0x0b,
+ 0x20, 0x35, 0x4a, 0x5f, 0x74, 0x89, 0x9e, 0xb3,
+ 0xc8, 0xdd, 0xf2, 0x07, 0x1c, 0x31, 0x46, 0x5b,
+ 0x70, 0x85, 0x9a, 0xaf, 0xc4, 0xd9, 0xee, 0x03,
+ 0x18, 0x2d, 0x42, 0x57, 0x6c, 0x81, 0x96, 0xab,
+ 0xc0, 0xd5, 0xea, 0xff, 0x14, 0x29, 0x3e, 0x53,
+ 0x68, 0x7d, 0x92, 0xa7, 0xbc, 0xd1, 0xe6, 0xfb,
+ 0x10, 0x25, 0x3a, 0x4f, 0x64, 0x79, 0x8e, 0xa3,
+ 0xb8, 0xcd, 0xe2, 0xf7, 0x0c, 0x21, 0x36, 0x4b,
+ 0x60, 0x75, 0x8a, 0x9f, 0xb4, 0xc9, 0xde, 0xf3,
+ 0x08, 0x1d, 0x32, 0x47, 0x5c, 0x71, 0x86, 0x9b,
+ 0xb0, 0xc5, 0xda, 0xef, 0x04, 0x19, 0x2e, 0x43,
+ 0x58, 0x6d, 0x82, 0x97, 0xac, 0xc1, 0xd6, 0xeb,
+ 0x00, 0x17, 0x2e, 0x45, 0x5c, 0x73, 0x8a, 0xa1,
+ 0xb8, 0xcf, 0xe6, 0xfd, 0x14, 0x2b, 0x42, 0x59,
+ 0x70, 0x87, 0x9e, 0xb5, 0xcc, 0xe3, 0xfa, 0x11,
+ 0x28, 0x3f, 0x56, 0x6d, 0x84, 0x9b, 0xb2, 0xc9,
+ 0xe0, 0xf7, 0x0e, 0x25, 0x3c, 0x53, 0x6a, 0x81,
+ 0x98, 0xaf, 0xc6, 0xdd, 0xf4, 0x0b, 0x22, 0x39,
+ 0x50, 0x67, 0x7e, 0x95, 0xac, 0xc3, 0xda, 0xf1,
+ 0x08, 0x1f, 0x36, 0x4d, 0x64, 0x7b, 0x92, 0xa9,
+ 0xc0, 0xd7, 0xee, 0x05, 0x1c, 0x33, 0x4a, 0x61,
+ 0x78, 0x8f, 0xa6, 0xbd, 0xd4, 0xeb, 0x02, 0x19,
+ 0x30, 0x47, 0x5e, 0x75, 0x8c, 0xa3, 0xba, 0xd1,
+ 0xe8, 0xff, 0x16, 0x2d, 0x44, 0x5b, 0x72, 0x89,
+ 0xa0, 0xb7, 0xce, 0xe5, 0xfc, 0x13, 0x2a, 0x41,
+ 0x58, 0x6f, 0x86, 0x9d, 0xb4, 0xcb, 0xe2, 0xf9,
+ 0x10, 0x27, 0x3e, 0x55, 0x6c, 0x83, 0x9a, 0xb1,
+ 0xc8, 0xdf, 0xf6, 0x0d, 0x24, 0x3b, 0x52, 0x69,
+ 0x80, 0x97, 0xae, 0xc5, 0xdc, 0xf3, 0x0a, 0x21,
+ 0x38, 0x4f, 0x66, 0x7d, 0x94, 0xab, 0xc2, 0xd9,
+ 0xf0, 0x07, 0x1e, 0x35, 0x4c, 0x63, 0x7a, 0x91,
+ 0xa8, 0xbf, 0xd6, 0xed, 0x04, 0x1b, 0x32, 0x49,
+ 0x60, 0x77, 0x8e, 0xa5, 0xbc, 0xd3, 0xea, 0x01,
+ 0x18, 0x2f, 0x46, 0x5d, 0x74, 0x8b, 0xa2, 0xb9,
+ 0xd0, 0xe7, 0xfe, 0x15, 0x2c, 0x43, 0x5a, 0x71,
+ 0x88, 0x9f, 0xb6, 0xcd, 0xe4, 0xfb, 0x12, 0x29,
+ 0x40, 0x57, 0x6e, 0x85, 0x9c, 0xb3, 0xca, 0xe1,
+ 0xf8, 0x0f, 0x26, 0x3d, 0x54, 0x6b, 0x82, 0x99,
+ 0xb0, 0xc7, 0xde, 0xf5, 0x0c, 0x23, 0x3a, 0x51,
+ 0x68, 0x7f, 0x96, 0xad, 0xc4, 0xdb, 0xf2, 0x09,
+ 0x20, 0x37, 0x4e, 0x65, 0x7c, 0x93, 0xaa, 0xc1,
+ 0xd8, 0xef, 0x06, 0x1d, 0x34, 0x4b, 0x62, 0x79,
+ 0x90, 0xa7, 0xbe, 0xd5, 0xec, 0x03, 0x1a, 0x31,
+ 0x48, 0x5f, 0x76, 0x8d, 0xa4, 0xbb, 0xd2, 0xe9,
+ 0x00, 0x19, 0x32, 0x4b, 0x64, 0x7d, 0x96, 0xaf,
+ 0xc8, 0xe1, 0xfa, 0x13, 0x2c, 0x45, 0x5e, 0x77,
+ 0x90, 0xa9, 0xc2, 0xdb, 0xf4, 0x0d, 0x26, 0x3f,
+ 0x58, 0x71, 0x8a, 0xa3, 0xbc, 0xd5, 0xee, 0x07,
+ 0x20, 0x39, 0x52, 0x6b, 0x84, 0x9d, 0xb6, 0xcf,
+ 0xe8, 0x01, 0x1a, 0x33, 0x4c, 0x65, 0x7e, 0x97,
+ 0xb0, 0xc9, 0xe2, 0xfb, 0x14, 0x2d, 0x46, 0x5f,
+ 0x78, 0x91, 0xaa, 0xc3, 0xdc, 0xf5, 0x0e, 0x27,
+ 0x40, 0x59, 0x72, 0x8b, 0xa4, 0xbd, 0xd6, 0xef,
+ 0x08, 0x21, 0x3a, 0x53, 0x6c, 0x85, 0x9e, 0xb7,
+ 0xd0, 0xe9, 0x02, 0x1b, 0x34, 0x4d, 0x66, 0x7f,
+ 0x98, 0xb1, 0xca, 0xe3, 0xfc, 0x15, 0x2e, 0x47,
+ 0x60, 0x79, 0x92, 0xab, 0xc4, 0xdd, 0xf6, 0x0f,
+ 0x28, 0x41, 0x5a, 0x73, 0x8c, 0xa5, 0xbe, 0xd7,
+ 0xf0, 0x09, 0x22, 0x3b, 0x54, 0x6d, 0x86, 0x9f,
+ 0xb8, 0xd1, 0xea, 0x03, 0x1c, 0x35, 0x4e, 0x67,
+ 0x80, 0x99, 0xb2, 0xcb, 0xe4, 0xfd, 0x16, 0x2f,
+ 0x48, 0x61, 0x7a, 0x93, 0xac, 0xc5, 0xde, 0xf7,
+ 0x10, 0x29, 0x42, 0x5b, 0x74, 0x8d, 0xa6, 0xbf,
+ 0xd8, 0xf1, 0x0a, 0x23, 0x3c, 0x55, 0x6e, 0x87,
+ 0xa0, 0xb9, 0xd2, 0xeb, 0x04, 0x1d, 0x36, 0x4f,
+ 0x68, 0x81, 0x9a, 0xb3, 0xcc, 0xe5, 0xfe, 0x17,
+ 0x30, 0x49, 0x62, 0x7b, 0x94, 0xad, 0xc6, 0xdf,
+ 0xf8, 0x11, 0x2a, 0x43, 0x5c, 0x75, 0x8e, 0xa7,
+ 0xc0, 0xd9, 0xf2, 0x0b, 0x24, 0x3d, 0x56, 0x6f,
+ 0x88, 0xa1, 0xba, 0xd3, 0xec, 0x05, 0x1e, 0x37,
+ 0x50, 0x69, 0x82, 0x9b, 0xb4, 0xcd, 0xe6, 0xff,
+ 0x18, 0x31, 0x4a, 0x63, 0x7c, 0x95, 0xae, 0xc7,
+ 0xe0, 0xf9, 0x12, 0x2b, 0x44, 0x5d, 0x76, 0x8f,
+ 0xa8, 0xc1, 0xda, 0xf3, 0x0c, 0x25, 0x3e, 0x57,
+ 0x70, 0x89, 0xa2, 0xbb, 0xd4, 0xed, 0x06, 0x1f,
+ 0x38, 0x51, 0x6a, 0x83, 0x9c, 0xb5, 0xce, 0xe7,
+ 0x00, 0x1b, 0x36, 0x51, 0x6c, 0x87, 0xa2, 0xbd,
+ 0xd8, 0xf3, 0x0e, 0x29, 0x44, 0x5f, 0x7a, 0x95,
+ 0xb0, 0xcb, 0xe6, 0x01, 0x1c, 0x37, 0x52, 0x6d,
+ 0x88, 0xa3, 0xbe, 0xd9, 0xf4, 0x0f, 0x2a, 0x45,
+ 0x60, 0x7b, 0x96, 0xb1, 0xcc, 0xe7, 0x02, 0x1d,
+ 0x38, 0x53, 0x6e, 0x89, 0xa4, 0xbf, 0xda, 0xf5,
+ 0x10, 0x2b, 0x46, 0x61, 0x7c, 0x97, 0xb2, 0xcd,
+ 0xe8, 0x03, 0x1e, 0x39, 0x54, 0x6f, 0x8a, 0xa5,
+ 0xc0, 0xdb, 0xf6, 0x11, 0x2c, 0x47, 0x62, 0x7d,
+ 0x98, 0xb3, 0xce, 0xe9, 0x04, 0x1f, 0x3a, 0x55,
+ 0x70, 0x8b, 0xa6, 0xc1, 0xdc, 0xf7, 0x12, 0x2d,
+ 0x48, 0x63, 0x7e, 0x99, 0xb4, 0xcf, 0xea, 0x05,
+ 0x20, 0x3b, 0x56, 0x71, 0x8c, 0xa7, 0xc2, 0xdd,
+ 0xf8, 0x13, 0x2e, 0x49, 0x64, 0x7f, 0x9a, 0xb5,
+ 0xd0, 0xeb, 0x06, 0x21, 0x3c, 0x57, 0x72, 0x8d,
+ 0xa8, 0xc3, 0xde, 0xf9, 0x14, 0x2f, 0x4a, 0x65,
+ 0x80, 0x9b, 0xb6, 0xd1, 0xec, 0x07, 0x22, 0x3d,
+ 0x58, 0x73, 0x8e, 0xa9, 0xc4, 0xdf, 0xfa, 0x15,
+ 0x30, 0x4b, 0x66, 0x81, 0x9c, 0xb7, 0xd2, 0xed,
+ 0x08, 0x23, 0x3e, 0x59, 0x74, 0x8f, 0xaa, 0xc5,
+ 0xe0, 0xfb, 0x16, 0x31, 0x4c, 0x67, 0x82, 0x9d,
+ 0xb8, 0xd3, 0xee, 0x09, 0x24, 0x3f, 0x5a, 0x75,
+ 0x90, 0xab, 0xc6, 0xe1, 0xfc, 0x17, 0x32, 0x4d,
+ 0x68, 0x83, 0x9e, 0xb9, 0xd4, 0xef, 0x0a, 0x25,
+ 0x40, 0x5b, 0x76, 0x91, 0xac, 0xc7, 0xe2, 0xfd,
+ 0x18, 0x33, 0x4e, 0x69, 0x84, 0x9f, 0xba, 0xd5,
+ 0xf0, 0x0b, 0x26, 0x41, 0x5c, 0x77, 0x92, 0xad,
+ 0xc8, 0xe3, 0xfe, 0x19, 0x34, 0x4f, 0x6a, 0x85,
+ 0xa0, 0xbb, 0xd6, 0xf1, 0x0c, 0x27, 0x42, 0x5d,
+ 0x78, 0x93, 0xae, 0xc9, 0xe4, 0xff, 0x1a, 0x35,
+ 0x50, 0x6b, 0x86, 0xa1, 0xbc, 0xd7, 0xf2, 0x0d,
+ 0x28, 0x43, 0x5e, 0x79, 0x94, 0xaf, 0xca, 0xe5,
+ 0x00, 0x1d, 0x3a, 0x57, 0x74, 0x91, 0xae, 0xcb,
+ 0xe8, 0x05, 0x22, 0x3f, 0x5c, 0x79, 0x96, 0xb3,
+ 0xd0, 0xed, 0x0a, 0x27, 0x44, 0x61, 0x7e, 0x9b,
+ 0xb8, 0xd5, 0xf2, 0x0f, 0x2c, 0x49, 0x66, 0x83,
+ 0xa0, 0xbd, 0xda, 0xf7, 0x14, 0x31, 0x4e, 0x6b,
+ 0x88, 0xa5, 0xc2, 0xdf, 0xfc, 0x19, 0x36, 0x53,
+ 0x70, 0x8d, 0xaa, 0xc7, 0xe4, 0x01, 0x1e, 0x3b,
+ 0x58, 0x75, 0x92, 0xaf, 0xcc, 0xe9, 0x06, 0x23,
+ 0x40, 0x5d, 0x7a, 0x97, 0xb4, 0xd1, 0xee, 0x0b,
+ 0x28, 0x45, 0x62, 0x7f, 0x9c, 0xb9, 0xd6, 0xf3,
+ 0x10, 0x2d, 0x4a, 0x67, 0x84, 0xa1, 0xbe, 0xdb,
+ 0xf8, 0x15, 0x32, 0x4f, 0x6c, 0x89, 0xa6, 0xc3,
+ 0xe0, 0xfd, 0x1a, 0x37, 0x54, 0x71, 0x8e, 0xab,
+ 0xc8, 0xe5, 0x02, 0x1f, 0x3c, 0x59, 0x76, 0x93,
+ 0xb0, 0xcd, 0xea, 0x07, 0x24, 0x41, 0x5e, 0x7b,
+ 0x98, 0xb5, 0xd2, 0xef, 0x0c, 0x29, 0x46, 0x63,
+ 0x80, 0x9d, 0xba, 0xd7, 0xf4, 0x11, 0x2e, 0x4b,
+ 0x68, 0x85, 0xa2, 0xbf, 0xdc, 0xf9, 0x16, 0x33,
+ 0x50, 0x6d, 0x8a, 0xa7, 0xc4, 0xe1, 0xfe, 0x1b,
+ 0x38, 0x55, 0x72, 0x8f, 0xac, 0xc9, 0xe6, 0x03,
+ 0x20, 0x3d, 0x5a, 0x77, 0x94, 0xb1, 0xce, 0xeb,
+ 0x08, 0x25, 0x42, 0x5f, 0x7c, 0x99, 0xb6, 0xd3,
+ 0xf0, 0x0d, 0x2a, 0x47, 0x64, 0x81, 0x9e, 0xbb,
+ 0xd8, 0xf5, 0x12, 0x2f, 0x4c, 0x69, 0x86, 0xa3,
+ 0xc0, 0xdd, 0xfa, 0x17, 0x34, 0x51, 0x6e, 0x8b,
+ 0xa8, 0xc5, 0xe2, 0xff, 0x1c, 0x39, 0x56, 0x73,
+ 0x90, 0xad, 0xca, 0xe7, 0x04, 0x21, 0x3e, 0x5b,
+ 0x78, 0x95, 0xb2, 0xcf, 0xec, 0x09, 0x26, 0x43,
+ 0x60, 0x7d, 0x9a, 0xb7, 0xd4, 0xf1, 0x0e, 0x2b,
+ 0x48, 0x65, 0x82, 0x9f, 0xbc, 0xd9, 0xf6, 0x13,
+ 0x30, 0x4d, 0x6a, 0x87, 0xa4, 0xc1, 0xde, 0xfb,
+ 0x18, 0x35, 0x52, 0x6f, 0x8c, 0xa9, 0xc6, 0xe3,
+ 0x00, 0x1f, 0x3e, 0x5d, 0x7c, 0x9b, 0xba, 0xd9,
+ 0xf8, 0x17, 0x36, 0x55, 0x74, 0x93, 0xb2, 0xd1,
+ 0xf0, 0x0f, 0x2e, 0x4d, 0x6c, 0x8b, 0xaa, 0xc9,
+ 0xe8, 0x07, 0x26, 0x45, 0x64, 0x83, 0xa2, 0xc1,
+ 0xe0, 0xff, 0x1e, 0x3d, 0x5c, 0x7b, 0x9a, 0xb9,
+ 0xd8, 0xf7, 0x16, 0x35, 0x54, 0x73, 0x92, 0xb1,
+ 0xd0, 0xef, 0x0e, 0x2d, 0x4c, 0x6b, 0x8a, 0xa9,
+ 0xc8, 0xe7, 0x06, 0x25, 0x44, 0x63, 0x82, 0xa1,
+ 0xc0, 0xdf, 0xfe, 0x1d, 0x3c, 0x5b, 0x7a, 0x99,
+ 0xb8, 0xd7, 0xf6, 0x15, 0x34, 0x53, 0x72, 0x91,
+ 0xb0, 0xcf, 0xee, 0x0d, 0x2c, 0x4b, 0x6a, 0x89,
+ 0xa8, 0xc7, 0xe6, 0x05, 0x24, 0x43, 0x62, 0x81,
+ 0xa0, 0xbf, 0xde, 0xfd, 0x1c, 0x3b, 0x5a, 0x79,
+ 0x98, 0xb7, 0xd6, 0xf5, 0x14, 0x33, 0x52, 0x71,
+ 0x90, 0xaf, 0xce, 0xed, 0x0c, 0x2b, 0x4a, 0x69,
+ 0x88, 0xa7, 0xc6, 0xe5, 0x04, 0x23, 0x42, 0x61,
+ 0x80, 0x9f, 0xbe, 0xdd, 0xfc, 0x1b, 0x3a, 0x59,
+ 0x78, 0x97, 0xb6, 0xd5, 0xf4, 0x13, 0x32, 0x51,
+ 0x70, 0x8f, 0xae, 0xcd, 0xec, 0x0b, 0x2a, 0x49,
+ 0x68, 0x87, 0xa6, 0xc5, 0xe4, 0x03, 0x22, 0x41,
+ 0x60, 0x7f, 0x9e, 0xbd, 0xdc, 0xfb, 0x1a, 0x39,
+ 0x58, 0x77, 0x96, 0xb5, 0xd4, 0xf3, 0x12, 0x31,
+ 0x50, 0x6f, 0x8e, 0xad, 0xcc, 0xeb, 0x0a, 0x29,
+ 0x48, 0x67, 0x86, 0xa5, 0xc4, 0xe3, 0x02, 0x21,
+ 0x40, 0x5f, 0x7e, 0x9d, 0xbc, 0xdb, 0xfa, 0x19,
+ 0x38, 0x57, 0x76, 0x95, 0xb4, 0xd3, 0xf2, 0x11,
+ 0x30, 0x4f, 0x6e, 0x8d, 0xac, 0xcb, 0xea, 0x09,
+ 0x28, 0x47, 0x66, 0x85, 0xa4, 0xc3, 0xe2, 0x01,
+ 0x20, 0x3f, 0x5e, 0x7d, 0x9c, 0xbb, 0xda, 0xf9,
+ 0x18, 0x37, 0x56, 0x75, 0x94, 0xb3, 0xd2, 0xf1,
+ 0x10, 0x2f, 0x4e, 0x6d, 0x8c, 0xab, 0xca, 0xe9,
+ 0x08, 0x27, 0x46, 0x65, 0x84, 0xa3, 0xc2, 0xe1,
+ 0x00, 0x21, 0x42, 0x63,
+ },
+ .ilen = 4100,
+ .result = {
+ 0xf0, 0x5c, 0x74, 0xad, 0x4e, 0xbc, 0x99, 0xe2,
+ 0xae, 0xff, 0x91, 0x3a, 0x44, 0xcf, 0x38, 0x32,
+ 0x1e, 0xad, 0xa7, 0xcd, 0xa1, 0x39, 0x95, 0xaa,
+ 0x10, 0xb1, 0xb3, 0x2e, 0x04, 0x31, 0x8f, 0x86,
+ 0xf2, 0x62, 0x74, 0x70, 0x0c, 0xa4, 0x46, 0x08,
+ 0xa8, 0xb7, 0x99, 0xa8, 0xe9, 0xd2, 0x73, 0x79,
+ 0x7e, 0x6e, 0xd4, 0x8f, 0x1e, 0xc7, 0x8e, 0x31,
+ 0x0b, 0xfa, 0x4b, 0xce, 0xfd, 0xf3, 0x57, 0x71,
+ 0xe9, 0x46, 0x03, 0xa5, 0x3d, 0x34, 0x00, 0xe2,
+ 0x18, 0xff, 0x75, 0x6d, 0x06, 0x2d, 0x00, 0xab,
+ 0xb9, 0x3e, 0x6c, 0x59, 0xc5, 0x84, 0x06, 0xb5,
+ 0x8b, 0xd0, 0x89, 0x9c, 0x4a, 0x79, 0x16, 0xc6,
+ 0x3d, 0x74, 0x54, 0xfa, 0x44, 0xcd, 0x23, 0x26,
+ 0x5c, 0xcf, 0x7e, 0x28, 0x92, 0x32, 0xbf, 0xdf,
+ 0xa7, 0x20, 0x3c, 0x74, 0x58, 0x2a, 0x9a, 0xde,
+ 0x61, 0x00, 0x1c, 0x4f, 0xff, 0x59, 0xc4, 0x22,
+ 0xac, 0x3c, 0xd0, 0xe8, 0x6c, 0xf9, 0x97, 0x1b,
+ 0x58, 0x9b, 0xad, 0x71, 0xe8, 0xa9, 0xb5, 0x0d,
+ 0xee, 0x2f, 0x04, 0x1f, 0x7f, 0xbc, 0x99, 0xee,
+ 0x84, 0xff, 0x42, 0x60, 0xdc, 0x3a, 0x18, 0xa5,
+ 0x81, 0xf9, 0xef, 0xdc, 0x7a, 0x0f, 0x65, 0x41,
+ 0x2f, 0xa3, 0xd3, 0xf9, 0xc2, 0xcb, 0xc0, 0x4d,
+ 0x8f, 0xd3, 0x76, 0x96, 0xad, 0x49, 0x6d, 0x38,
+ 0x3d, 0x39, 0x0b, 0x6c, 0x80, 0xb7, 0x54, 0x69,
+ 0xf0, 0x2c, 0x90, 0x02, 0x29, 0x0d, 0x1c, 0x12,
+ 0xad, 0x55, 0xc3, 0x8b, 0x68, 0xd9, 0xcc, 0xb3,
+ 0xb2, 0x64, 0x33, 0x90, 0x5e, 0xca, 0x4b, 0xe2,
+ 0xfb, 0x75, 0xdc, 0x63, 0xf7, 0x9f, 0x82, 0x74,
+ 0xf0, 0xc9, 0xaa, 0x7f, 0xe9, 0x2a, 0x9b, 0x33,
+ 0xbc, 0x88, 0x00, 0x7f, 0xca, 0xb2, 0x1f, 0x14,
+ 0xdb, 0xc5, 0x8e, 0x7b, 0x11, 0x3c, 0x3e, 0x08,
+ 0xf3, 0x83, 0xe8, 0xe0, 0x94, 0x86, 0x2e, 0x92,
+ 0x78, 0x6b, 0x01, 0xc9, 0xc7, 0x83, 0xba, 0x21,
+ 0x6a, 0x25, 0x15, 0x33, 0x4e, 0x45, 0x08, 0xec,
+ 0x35, 0xdb, 0xe0, 0x6e, 0x31, 0x51, 0x79, 0xa9,
+ 0x42, 0x44, 0x65, 0xc1, 0xa0, 0xf1, 0xf9, 0x2a,
+ 0x70, 0xd5, 0xb6, 0xc6, 0xc1, 0x8c, 0x39, 0xfc,
+ 0x25, 0xa6, 0x55, 0xd9, 0xdd, 0x2d, 0x4c, 0xec,
+ 0x49, 0xc6, 0xeb, 0x0e, 0xa8, 0x25, 0x2a, 0x16,
+ 0x1b, 0x66, 0x84, 0xda, 0xe2, 0x92, 0xe5, 0xc0,
+ 0xc8, 0x53, 0x07, 0xaf, 0x80, 0x84, 0xec, 0xfd,
+ 0xcd, 0xd1, 0x6e, 0xcd, 0x6f, 0x6a, 0xf5, 0x36,
+ 0xc5, 0x15, 0xe5, 0x25, 0x7d, 0x77, 0xd1, 0x1a,
+ 0x93, 0x36, 0xa9, 0xcf, 0x7c, 0xa4, 0x54, 0x4a,
+ 0x06, 0x51, 0x48, 0x4e, 0xf6, 0x59, 0x87, 0xd2,
+ 0x04, 0x02, 0xef, 0xd3, 0x44, 0xde, 0x76, 0x31,
+ 0xb3, 0x34, 0x17, 0x1b, 0x9d, 0x66, 0x11, 0x9f,
+ 0x1e, 0xcc, 0x17, 0xe9, 0xc7, 0x3c, 0x1b, 0xe7,
+ 0xcb, 0x50, 0x08, 0xfc, 0xdc, 0x2b, 0x24, 0xdb,
+ 0x65, 0x83, 0xd0, 0x3b, 0xe3, 0x30, 0xea, 0x94,
+ 0x6c, 0xe7, 0xe8, 0x35, 0x32, 0xc7, 0xdb, 0x64,
+ 0xb4, 0x01, 0xab, 0x36, 0x2c, 0x77, 0x13, 0xaf,
+ 0xf8, 0x2b, 0x88, 0x3f, 0x54, 0x39, 0xc4, 0x44,
+ 0xfe, 0xef, 0x6f, 0x68, 0x34, 0xbe, 0x0f, 0x05,
+ 0x16, 0x6d, 0xf6, 0x0a, 0x30, 0xe7, 0xe3, 0xed,
+ 0xc4, 0xde, 0x3c, 0x1b, 0x13, 0xd8, 0xdb, 0xfe,
+ 0x41, 0x62, 0xe5, 0x28, 0xd4, 0x8d, 0xa3, 0xc7,
+ 0x93, 0x97, 0xc6, 0x48, 0x45, 0x1d, 0x9f, 0x83,
+ 0xdf, 0x4b, 0x40, 0x3e, 0x42, 0x25, 0x87, 0x80,
+ 0x4c, 0x7d, 0xa8, 0xd4, 0x98, 0x23, 0x95, 0x75,
+ 0x41, 0x8c, 0xda, 0x41, 0x9b, 0xd4, 0xa7, 0x06,
+ 0xb5, 0xf1, 0x71, 0x09, 0x53, 0xbe, 0xca, 0xbf,
+ 0x32, 0x03, 0xed, 0xf0, 0x50, 0x1c, 0x56, 0x39,
+ 0x5b, 0xa4, 0x75, 0x18, 0xf7, 0x9b, 0x58, 0xef,
+ 0x53, 0xfc, 0x2a, 0x38, 0x23, 0x15, 0x75, 0xcd,
+ 0x45, 0xe5, 0x5a, 0x82, 0x55, 0xba, 0x21, 0xfa,
+ 0xd4, 0xbd, 0xc6, 0x94, 0x7c, 0xc5, 0x80, 0x12,
+ 0xf7, 0x4b, 0x32, 0xc4, 0x9a, 0x82, 0xd8, 0x28,
+ 0x8f, 0xd9, 0xc2, 0x0f, 0x60, 0x03, 0xbe, 0x5e,
+ 0x21, 0xd6, 0x5f, 0x58, 0xbf, 0x5c, 0xb1, 0x32,
+ 0x82, 0x8d, 0xa9, 0xe5, 0xf2, 0x66, 0x1a, 0xc0,
+ 0xa0, 0xbc, 0x58, 0x2f, 0x71, 0xf5, 0x2f, 0xed,
+ 0xd1, 0x26, 0xb9, 0xd8, 0x49, 0x5a, 0x07, 0x19,
+ 0x01, 0x7c, 0x59, 0xb0, 0xf8, 0xa4, 0xb7, 0xd3,
+ 0x7b, 0x1a, 0x8c, 0x38, 0xf4, 0x50, 0xa4, 0x59,
+ 0xb0, 0xcc, 0x41, 0x0b, 0x88, 0x7f, 0xe5, 0x31,
+ 0xb3, 0x42, 0xba, 0xa2, 0x7e, 0xd4, 0x32, 0x71,
+ 0x45, 0x87, 0x48, 0xa9, 0xc2, 0xf2, 0x89, 0xb3,
+ 0xe4, 0xa7, 0x7e, 0x52, 0x15, 0x61, 0xfa, 0xfe,
+ 0xc9, 0xdd, 0x81, 0xeb, 0x13, 0xab, 0xab, 0xc3,
+ 0x98, 0x59, 0xd8, 0x16, 0x3d, 0x14, 0x7a, 0x1c,
+ 0x3c, 0x41, 0x9a, 0x16, 0x16, 0x9b, 0xd2, 0xd2,
+ 0x69, 0x3a, 0x29, 0x23, 0xac, 0x86, 0x32, 0xa5,
+ 0x48, 0x9c, 0x9e, 0xf3, 0x47, 0x77, 0x81, 0x70,
+ 0x24, 0xe8, 0x85, 0xd2, 0xf5, 0xb5, 0xfa, 0xff,
+ 0x59, 0x6a, 0xd3, 0x50, 0x59, 0x43, 0x59, 0xde,
+ 0xd9, 0xf1, 0x55, 0xa5, 0x0c, 0xc3, 0x1a, 0x1a,
+ 0x18, 0x34, 0x0d, 0x1a, 0x63, 0x33, 0xed, 0x10,
+ 0xe0, 0x1d, 0x2a, 0x18, 0xd2, 0xc0, 0x54, 0xa8,
+ 0xca, 0xb5, 0x9a, 0xd3, 0xdd, 0xca, 0x45, 0x84,
+ 0x50, 0xe7, 0x0f, 0xfe, 0xa4, 0x99, 0x5a, 0xbe,
+ 0x43, 0x2d, 0x9a, 0xcb, 0x92, 0x3f, 0x5a, 0x1d,
+ 0x85, 0xd8, 0xc9, 0xdf, 0x68, 0xc9, 0x12, 0x80,
+ 0x56, 0x0c, 0xdc, 0x00, 0xdc, 0x3a, 0x7d, 0x9d,
+ 0xa3, 0xa2, 0xe8, 0x4d, 0xbf, 0xf9, 0x70, 0xa0,
+ 0xa4, 0x13, 0x4f, 0x6b, 0xaf, 0x0a, 0x89, 0x7f,
+ 0xda, 0xf0, 0xbf, 0x9b, 0xc8, 0x1d, 0xe5, 0xf8,
+ 0x2e, 0x8b, 0x07, 0xb5, 0x73, 0x1b, 0xcc, 0xa2,
+ 0xa6, 0xad, 0x30, 0xbc, 0x78, 0x3c, 0x5b, 0x10,
+ 0xfa, 0x5e, 0x62, 0x2d, 0x9e, 0x64, 0xb3, 0x33,
+ 0xce, 0xf9, 0x1f, 0x86, 0xe7, 0x8b, 0xa2, 0xb8,
+ 0xe8, 0x99, 0x57, 0x8c, 0x11, 0xed, 0x66, 0xd9,
+ 0x3c, 0x72, 0xb9, 0xc3, 0xe6, 0x4e, 0x17, 0x3a,
+ 0x6a, 0xcb, 0x42, 0x24, 0x06, 0xed, 0x3e, 0x4e,
+ 0xa3, 0xe8, 0x6a, 0x94, 0xda, 0x0d, 0x4e, 0xd5,
+ 0x14, 0x19, 0xcf, 0xb6, 0x26, 0xd8, 0x2e, 0xcc,
+ 0x64, 0x76, 0x38, 0x49, 0x4d, 0xfe, 0x30, 0x6d,
+ 0xe4, 0xc8, 0x8c, 0x7b, 0xc4, 0xe0, 0x35, 0xba,
+ 0x22, 0x6e, 0x76, 0xe1, 0x1a, 0xf2, 0x53, 0xc3,
+ 0x28, 0xa2, 0x82, 0x1f, 0x61, 0x69, 0xad, 0xc1,
+ 0x7b, 0x28, 0x4b, 0x1e, 0x6c, 0x85, 0x95, 0x9b,
+ 0x51, 0xb5, 0x17, 0x7f, 0x12, 0x69, 0x8c, 0x24,
+ 0xd5, 0xc7, 0x5a, 0x5a, 0x11, 0x54, 0xff, 0x5a,
+ 0xf7, 0x16, 0xc3, 0x91, 0xa6, 0xf0, 0xdc, 0x0a,
+ 0xb6, 0xa7, 0x4a, 0x0d, 0x7a, 0x58, 0xfe, 0xa5,
+ 0xf5, 0xcb, 0x8f, 0x7b, 0x0e, 0xea, 0x57, 0xe7,
+ 0xbd, 0x79, 0xd6, 0x1c, 0x88, 0x23, 0x6c, 0xf2,
+ 0x4d, 0x29, 0x77, 0x53, 0x35, 0x6a, 0x00, 0x8d,
+ 0xcd, 0xa3, 0x58, 0xbe, 0x77, 0x99, 0x18, 0xf8,
+ 0xe6, 0xe1, 0x8f, 0xe9, 0x37, 0x8f, 0xe3, 0xe2,
+ 0x5a, 0x8a, 0x93, 0x25, 0xaf, 0xf3, 0x78, 0x80,
+ 0xbe, 0xa6, 0x1b, 0xc6, 0xac, 0x8b, 0x1c, 0x91,
+ 0x58, 0xe1, 0x9f, 0x89, 0x35, 0x9d, 0x1d, 0x21,
+ 0x29, 0x9f, 0xf4, 0x99, 0x02, 0x27, 0x0f, 0xa8,
+ 0x4f, 0x79, 0x94, 0x2b, 0x33, 0x2c, 0xda, 0xa2,
+ 0x26, 0x39, 0x83, 0x94, 0xef, 0x27, 0xd8, 0x53,
+ 0x8f, 0x66, 0x0d, 0xe4, 0x41, 0x7d, 0x34, 0xcd,
+ 0x43, 0x7c, 0x95, 0x0a, 0x53, 0xef, 0x66, 0xda,
+ 0x7e, 0x9b, 0xf3, 0x93, 0xaf, 0xd0, 0x73, 0x71,
+ 0xba, 0x40, 0x9b, 0x74, 0xf8, 0xd7, 0xd7, 0x41,
+ 0x6d, 0xaf, 0x72, 0x9c, 0x8d, 0x21, 0x87, 0x3c,
+ 0xfd, 0x0a, 0x90, 0xa9, 0x47, 0x96, 0x9e, 0xd3,
+ 0x88, 0xee, 0x73, 0xcf, 0x66, 0x2f, 0x52, 0x56,
+ 0x6d, 0xa9, 0x80, 0x4c, 0xe2, 0x6f, 0x62, 0x88,
+ 0x3f, 0x0e, 0x54, 0x17, 0x48, 0x80, 0x5d, 0xd3,
+ 0xc3, 0xda, 0x25, 0x3d, 0xa1, 0xc8, 0xcb, 0x9f,
+ 0x9b, 0x70, 0xb3, 0xa1, 0xeb, 0x04, 0x52, 0xa1,
+ 0xf2, 0x22, 0x0f, 0xfc, 0xc8, 0x18, 0xfa, 0xf9,
+ 0x85, 0x9c, 0xf1, 0xac, 0xeb, 0x0c, 0x02, 0x46,
+ 0x75, 0xd2, 0xf5, 0x2c, 0xe3, 0xd2, 0x59, 0x94,
+ 0x12, 0xf3, 0x3c, 0xfc, 0xd7, 0x92, 0xfa, 0x36,
+ 0xba, 0x61, 0x34, 0x38, 0x7c, 0xda, 0x48, 0x3e,
+ 0x08, 0xc9, 0x39, 0x23, 0x5e, 0x02, 0x2c, 0x1a,
+ 0x18, 0x7e, 0xb4, 0xd9, 0xfd, 0x9e, 0x40, 0x02,
+ 0xb1, 0x33, 0x37, 0x32, 0xe7, 0xde, 0xd6, 0xd0,
+ 0x7c, 0x58, 0x65, 0x4b, 0xf8, 0x34, 0x27, 0x9c,
+ 0x44, 0xb4, 0xbd, 0xe9, 0xe9, 0x4c, 0x78, 0x7d,
+ 0x4b, 0x9f, 0xce, 0xb1, 0xcd, 0x47, 0xa5, 0x37,
+ 0xe5, 0x6d, 0xbd, 0xb9, 0x43, 0x94, 0x0a, 0xd4,
+ 0xd6, 0xf9, 0x04, 0x5f, 0xb5, 0x66, 0x6c, 0x1a,
+ 0x35, 0x12, 0xe3, 0x36, 0x28, 0x27, 0x36, 0x58,
+ 0x01, 0x2b, 0x79, 0xe4, 0xba, 0x6d, 0x10, 0x7d,
+ 0x65, 0xdf, 0x84, 0x95, 0xf4, 0xd5, 0xb6, 0x8f,
+ 0x2b, 0x9f, 0x96, 0x00, 0x86, 0x60, 0xf0, 0x21,
+ 0x76, 0xa8, 0x6a, 0x8c, 0x28, 0x1c, 0xb3, 0x6b,
+ 0x97, 0xd7, 0xb6, 0x53, 0x2a, 0xcc, 0xab, 0x40,
+ 0x9d, 0x62, 0x79, 0x58, 0x52, 0xe6, 0x65, 0xb7,
+ 0xab, 0x55, 0x67, 0x9c, 0x89, 0x7c, 0x03, 0xb0,
+ 0x73, 0x59, 0xc5, 0x81, 0xf5, 0x18, 0x17, 0x5c,
+ 0x89, 0xf3, 0x78, 0x35, 0x44, 0x62, 0x78, 0x72,
+ 0xd0, 0x96, 0xeb, 0x31, 0xe7, 0x87, 0x77, 0x14,
+ 0x99, 0x51, 0xf2, 0x59, 0x26, 0x9e, 0xb5, 0xa6,
+ 0x45, 0xfe, 0x6e, 0xbd, 0x07, 0x4c, 0x94, 0x5a,
+ 0xa5, 0x7d, 0xfc, 0xf1, 0x2b, 0x77, 0xe2, 0xfe,
+ 0x17, 0xd4, 0x84, 0xa0, 0xac, 0xb5, 0xc7, 0xda,
+ 0xa9, 0x1a, 0xb6, 0xf3, 0x74, 0x11, 0xb4, 0x9d,
+ 0xfb, 0x79, 0x2e, 0x04, 0x2d, 0x50, 0x28, 0x83,
+ 0xbf, 0xc6, 0x52, 0xd3, 0x34, 0xd6, 0xe8, 0x7a,
+ 0xb6, 0xea, 0xe7, 0xa8, 0x6c, 0x15, 0x1e, 0x2c,
+ 0x57, 0xbc, 0x48, 0x4e, 0x5f, 0x5c, 0xb6, 0x92,
+ 0xd2, 0x49, 0x77, 0x81, 0x6d, 0x90, 0x70, 0xae,
+ 0x98, 0xa1, 0x03, 0x0d, 0x6b, 0xb9, 0x77, 0x14,
+ 0xf1, 0x4e, 0x23, 0xd3, 0xf8, 0x68, 0xbd, 0xc2,
+ 0xfe, 0x04, 0xb7, 0x5c, 0xc5, 0x17, 0x60, 0x8f,
+ 0x65, 0x54, 0xa4, 0x7a, 0x42, 0xdc, 0x18, 0x0d,
+ 0xb5, 0xcf, 0x0f, 0xd3, 0xc7, 0x91, 0x66, 0x1b,
+ 0x45, 0x42, 0x27, 0x75, 0x50, 0xe5, 0xee, 0xb8,
+ 0x7f, 0x33, 0x2c, 0xba, 0x4a, 0x92, 0x4d, 0x2c,
+ 0x3c, 0xe3, 0x0d, 0x80, 0x01, 0xba, 0x0d, 0x29,
+ 0xd8, 0x3c, 0xe9, 0x13, 0x16, 0x57, 0xe6, 0xea,
+ 0x94, 0x52, 0xe7, 0x00, 0x4d, 0x30, 0xb0, 0x0f,
+ 0x35, 0xb8, 0xb8, 0xa7, 0xb1, 0xb5, 0x3b, 0x44,
+ 0xe1, 0x2f, 0xfd, 0x88, 0xed, 0x43, 0xe7, 0x52,
+ 0x10, 0x93, 0xb3, 0x8a, 0x30, 0x6b, 0x0a, 0xf7,
+ 0x23, 0xc6, 0x50, 0x9d, 0x4a, 0xb0, 0xde, 0xc3,
+ 0xdc, 0x9b, 0x2f, 0x01, 0x56, 0x36, 0x09, 0xc5,
+ 0x2f, 0x6b, 0xfe, 0xf1, 0xd8, 0x27, 0x45, 0x03,
+ 0x30, 0x5e, 0x5c, 0x5b, 0xb4, 0x62, 0x0e, 0x1a,
+ 0xa9, 0x21, 0x2b, 0x92, 0x94, 0x87, 0x62, 0x57,
+ 0x4c, 0x10, 0x74, 0x1a, 0xf1, 0x0a, 0xc5, 0x84,
+ 0x3b, 0x9e, 0x72, 0x02, 0xd7, 0xcc, 0x09, 0x56,
+ 0xbd, 0x54, 0xc1, 0xf0, 0xc3, 0xe3, 0xb3, 0xf8,
+ 0xd2, 0x0d, 0x61, 0xcb, 0xef, 0xce, 0x0d, 0x05,
+ 0xb0, 0x98, 0xd9, 0x8e, 0x4f, 0xf9, 0xbc, 0x93,
+ 0xa6, 0xea, 0xc8, 0xcf, 0x10, 0x53, 0x4b, 0xf1,
+ 0xec, 0xfc, 0x89, 0xf9, 0x64, 0xb0, 0x22, 0xbf,
+ 0x9e, 0x55, 0x46, 0x9f, 0x7c, 0x50, 0x8e, 0x84,
+ 0x54, 0x20, 0x98, 0xd7, 0x6c, 0x40, 0x1e, 0xdb,
+ 0x69, 0x34, 0x78, 0x61, 0x24, 0x21, 0x9c, 0x8a,
+ 0xb3, 0x62, 0x31, 0x8b, 0x6e, 0xf5, 0x2a, 0x35,
+ 0x86, 0x13, 0xb1, 0x6c, 0x64, 0x2e, 0x41, 0xa5,
+ 0x05, 0xf2, 0x42, 0xba, 0xd2, 0x3a, 0x0d, 0x8e,
+ 0x8a, 0x59, 0x94, 0x3c, 0xcf, 0x36, 0x27, 0x82,
+ 0xc2, 0x45, 0xee, 0x58, 0xcd, 0x88, 0xb4, 0xec,
+ 0xde, 0xb2, 0x96, 0x0a, 0xaf, 0x38, 0x6f, 0x88,
+ 0xd7, 0xd8, 0xe1, 0xdf, 0xb9, 0x96, 0xa9, 0x0a,
+ 0xb1, 0x95, 0x28, 0x86, 0x20, 0xe9, 0x17, 0x49,
+ 0xa2, 0x29, 0x38, 0xaa, 0xa5, 0xe9, 0x6e, 0xf1,
+ 0x19, 0x27, 0xc0, 0xd5, 0x2a, 0x22, 0xc3, 0x0b,
+ 0xdb, 0x7c, 0x73, 0x10, 0xb9, 0xba, 0x89, 0x76,
+ 0x54, 0xae, 0x7d, 0x71, 0xb3, 0x93, 0xf6, 0x32,
+ 0xe6, 0x47, 0x43, 0x55, 0xac, 0xa0, 0x0d, 0xc2,
+ 0x93, 0x27, 0x4a, 0x8e, 0x0e, 0x74, 0x15, 0xc7,
+ 0x0b, 0x85, 0xd9, 0x0c, 0xa9, 0x30, 0x7a, 0x3e,
+ 0xea, 0x8f, 0x85, 0x6d, 0x3a, 0x12, 0x4f, 0x72,
+ 0x69, 0x58, 0x7a, 0x80, 0xbb, 0xb5, 0x97, 0xf3,
+ 0xcf, 0x70, 0xd2, 0x5d, 0xdd, 0x4d, 0x21, 0x79,
+ 0x54, 0x4d, 0xe4, 0x05, 0xe8, 0xbd, 0xc2, 0x62,
+ 0xb1, 0x3b, 0x77, 0x1c, 0xd6, 0x5c, 0xf3, 0xa0,
+ 0x79, 0x00, 0xa8, 0x6c, 0x29, 0xd9, 0x18, 0x24,
+ 0x36, 0xa2, 0x46, 0xc0, 0x96, 0x65, 0x7f, 0xbd,
+ 0x2a, 0xed, 0x36, 0x16, 0x0c, 0xaa, 0x9f, 0xf4,
+ 0xc5, 0xb4, 0xe2, 0x12, 0xed, 0x69, 0xed, 0x4f,
+ 0x26, 0x2c, 0x39, 0x52, 0x89, 0x98, 0xe7, 0x2c,
+ 0x99, 0xa4, 0x9e, 0xa3, 0x9b, 0x99, 0x46, 0x7a,
+ 0x3a, 0xdc, 0xa8, 0x59, 0xa3, 0xdb, 0xc3, 0x3b,
+ 0x95, 0x0d, 0x3b, 0x09, 0x6e, 0xee, 0x83, 0x5d,
+ 0x32, 0x4d, 0xed, 0xab, 0xfa, 0x98, 0x14, 0x4e,
+ 0xc3, 0x15, 0x45, 0x53, 0x61, 0xc4, 0x93, 0xbd,
+ 0x90, 0xf4, 0x99, 0x95, 0x4c, 0xe6, 0x76, 0x92,
+ 0x29, 0x90, 0x46, 0x30, 0x92, 0x69, 0x7d, 0x13,
+ 0xf2, 0xa5, 0xcd, 0x69, 0x49, 0x44, 0xb2, 0x0f,
+ 0x63, 0x40, 0x36, 0x5f, 0x09, 0xe2, 0x78, 0xf8,
+ 0x91, 0xe3, 0xe2, 0xfa, 0x10, 0xf7, 0xc8, 0x24,
+ 0xa8, 0x89, 0x32, 0x5c, 0x37, 0x25, 0x1d, 0xb2,
+ 0xea, 0x17, 0x8a, 0x0a, 0xa9, 0x64, 0xc3, 0x7c,
+ 0x3c, 0x7c, 0xbd, 0xc6, 0x79, 0x34, 0xe7, 0xe2,
+ 0x85, 0x8e, 0xbf, 0xf8, 0xde, 0x92, 0xa0, 0xae,
+ 0x20, 0xc4, 0xf6, 0xbb, 0x1f, 0x38, 0x19, 0x0e,
+ 0xe8, 0x79, 0x9c, 0xa1, 0x23, 0xe9, 0x54, 0x7e,
+ 0x37, 0x2f, 0xe2, 0x94, 0x32, 0xaf, 0xa0, 0x23,
+ 0x49, 0xe4, 0xc0, 0xb3, 0xac, 0x00, 0x8f, 0x36,
+ 0x05, 0xc4, 0xa6, 0x96, 0xec, 0x05, 0x98, 0x4f,
+ 0x96, 0x67, 0x57, 0x1f, 0x20, 0x86, 0x1b, 0x2d,
+ 0x69, 0xe4, 0x29, 0x93, 0x66, 0x5f, 0xaf, 0x6b,
+ 0x88, 0x26, 0x2c, 0x67, 0x02, 0x4b, 0x52, 0xd0,
+ 0x83, 0x7a, 0x43, 0x1f, 0xc0, 0x71, 0x15, 0x25,
+ 0x77, 0x65, 0x08, 0x60, 0x11, 0x76, 0x4c, 0x8d,
+ 0xed, 0xa9, 0x27, 0xc6, 0xb1, 0x2a, 0x2c, 0x6a,
+ 0x4a, 0x97, 0xf5, 0xc6, 0xb7, 0x70, 0x42, 0xd3,
+ 0x03, 0xd1, 0x24, 0x95, 0xec, 0x6d, 0xab, 0x38,
+ 0x72, 0xce, 0xe2, 0x8b, 0x33, 0xd7, 0x51, 0x09,
+ 0xdc, 0x45, 0xe0, 0x09, 0x96, 0x32, 0xf3, 0xc4,
+ 0x84, 0xdc, 0x73, 0x73, 0x2d, 0x1b, 0x11, 0x98,
+ 0xc5, 0x0e, 0x69, 0x28, 0x94, 0xc7, 0xb5, 0x4d,
+ 0xc8, 0x8a, 0xd0, 0xaa, 0x13, 0x2e, 0x18, 0x74,
+ 0xdd, 0xd1, 0x1e, 0xf3, 0x90, 0xe8, 0xfc, 0x9a,
+ 0x72, 0x4a, 0x0e, 0xd1, 0xe4, 0xfb, 0x0d, 0x96,
+ 0xd1, 0x0c, 0x79, 0x85, 0x1b, 0x1c, 0xfe, 0xe1,
+ 0x62, 0x8f, 0x7a, 0x73, 0x32, 0xab, 0xc8, 0x18,
+ 0x69, 0xe3, 0x34, 0x30, 0xdf, 0x13, 0xa6, 0xe5,
+ 0xe8, 0x0e, 0x67, 0x7f, 0x81, 0x11, 0xb4, 0x60,
+ 0xc7, 0xbd, 0x79, 0x65, 0x50, 0xdc, 0xc4, 0x5b,
+ 0xde, 0x39, 0xa4, 0x01, 0x72, 0x63, 0xf3, 0xd1,
+ 0x64, 0x4e, 0xdf, 0xfc, 0x27, 0x92, 0x37, 0x0d,
+ 0x57, 0xcd, 0x11, 0x4f, 0x11, 0x04, 0x8e, 0x1d,
+ 0x16, 0xf7, 0xcd, 0x92, 0x9a, 0x99, 0x30, 0x14,
+ 0xf1, 0x7c, 0x67, 0x1b, 0x1f, 0x41, 0x0b, 0xe8,
+ 0x32, 0xe8, 0xb8, 0xc1, 0x4f, 0x54, 0x86, 0x4f,
+ 0xe5, 0x79, 0x81, 0x73, 0xcd, 0x43, 0x59, 0x68,
+ 0x73, 0x02, 0x3b, 0x78, 0x21, 0x72, 0x43, 0x00,
+ 0x49, 0x17, 0xf7, 0x00, 0xaf, 0x68, 0x24, 0x53,
+ 0x05, 0x0a, 0xc3, 0x33, 0xe0, 0x33, 0x3f, 0x69,
+ 0xd2, 0x84, 0x2f, 0x0b, 0xed, 0xde, 0x04, 0xf4,
+ 0x11, 0x94, 0x13, 0x69, 0x51, 0x09, 0x28, 0xde,
+ 0x57, 0x5c, 0xef, 0xdc, 0x9a, 0x49, 0x1c, 0x17,
+ 0x97, 0xf3, 0x96, 0xc1, 0x7f, 0x5d, 0x2e, 0x7d,
+ 0x55, 0xb8, 0xb3, 0x02, 0x09, 0xb3, 0x1f, 0xe7,
+ 0xc9, 0x8d, 0xa3, 0x36, 0x34, 0x8a, 0x77, 0x13,
+ 0x30, 0x63, 0x4c, 0xa5, 0xcd, 0xc3, 0xe0, 0x7e,
+ 0x05, 0xa1, 0x7b, 0x0c, 0xcb, 0x74, 0x47, 0x31,
+ 0x62, 0x03, 0x43, 0xf1, 0x87, 0xb4, 0xb0, 0x85,
+ 0x87, 0x8e, 0x4b, 0x25, 0xc7, 0xcf, 0xae, 0x4b,
+ 0x36, 0x46, 0x3e, 0x62, 0xbc, 0x6f, 0xeb, 0x5f,
+ 0x73, 0xac, 0xe6, 0x07, 0xee, 0xc1, 0xa1, 0xd6,
+ 0xc4, 0xab, 0xc9, 0xd6, 0x89, 0x45, 0xe1, 0xf1,
+ 0x04, 0x4e, 0x1a, 0x6f, 0xbb, 0x4f, 0x3a, 0xa3,
+ 0xa0, 0xcb, 0xa3, 0x0a, 0xd8, 0x71, 0x35, 0x55,
+ 0xe4, 0xbc, 0x2e, 0x04, 0x06, 0xe6, 0xff, 0x5b,
+ 0x1c, 0xc0, 0x11, 0x7c, 0xc5, 0x17, 0xf3, 0x38,
+ 0xcf, 0xe9, 0xba, 0x0f, 0x0e, 0xef, 0x02, 0xc2,
+ 0x8d, 0xc6, 0xbc, 0x4b, 0x67, 0x20, 0x95, 0xd7,
+ 0x2c, 0x45, 0x5b, 0x86, 0x44, 0x8c, 0x6f, 0x2e,
+ 0x7e, 0x9f, 0x1c, 0x77, 0xba, 0x6b, 0x0e, 0xa3,
+ 0x69, 0xdc, 0xab, 0x24, 0x57, 0x60, 0x47, 0xc1,
+ 0xd1, 0xa5, 0x9d, 0x23, 0xe6, 0xb1, 0x37, 0xfe,
+ 0x93, 0xd2, 0x4c, 0x46, 0xf9, 0x0c, 0xc6, 0xfb,
+ 0xd6, 0x9d, 0x99, 0x69, 0xab, 0x7a, 0x07, 0x0c,
+ 0x65, 0xe7, 0xc4, 0x08, 0x96, 0xe2, 0xa5, 0x01,
+ 0x3f, 0x46, 0x07, 0x05, 0x7e, 0xe8, 0x9a, 0x90,
+ 0x50, 0xdc, 0xe9, 0x7a, 0xea, 0xa1, 0x39, 0x6e,
+ 0x66, 0xe4, 0x6f, 0xa5, 0x5f, 0xb2, 0xd9, 0x5b,
+ 0xf5, 0xdb, 0x2a, 0x32, 0xf0, 0x11, 0x6f, 0x7c,
+ 0x26, 0x10, 0x8f, 0x3d, 0x80, 0xe9, 0x58, 0xf7,
+ 0xe0, 0xa8, 0x57, 0xf8, 0xdb, 0x0e, 0xce, 0x99,
+ 0x63, 0x19, 0x3d, 0xd5, 0xec, 0x1b, 0x77, 0x69,
+ 0x98, 0xf6, 0xe4, 0x5f, 0x67, 0x17, 0x4b, 0x09,
+ 0x85, 0x62, 0x82, 0x70, 0x18, 0xe2, 0x9a, 0x78,
+ 0xe2, 0x62, 0xbd, 0xb4, 0xf1, 0x42, 0xc6, 0xfb,
+ 0x08, 0xd0, 0xbd, 0xeb, 0x4e, 0x09, 0xf2, 0xc8,
+ 0x1e, 0xdc, 0x3d, 0x32, 0x21, 0x56, 0x9c, 0x4f,
+ 0x35, 0xf3, 0x61, 0x06, 0x72, 0x84, 0xc4, 0x32,
+ 0xf2, 0xf1, 0xfa, 0x0b, 0x2f, 0xc3, 0xdb, 0x02,
+ 0x04, 0xc2, 0xde, 0x57, 0x64, 0x60, 0x8d, 0xcf,
+ 0xcb, 0x86, 0x5d, 0x97, 0x3e, 0xb1, 0x9c, 0x01,
+ 0xd6, 0x28, 0x8f, 0x99, 0xbc, 0x46, 0xeb, 0x05,
+ 0xaf, 0x7e, 0xb8, 0x21, 0x2a, 0x56, 0x85, 0x1c,
+ 0xb3, 0x71, 0xa0, 0xde, 0xca, 0x96, 0xf1, 0x78,
+ 0x49, 0xa2, 0x99, 0x81, 0x80, 0x5c, 0x01, 0xf5,
+ 0xa0, 0xa2, 0x56, 0x63, 0xe2, 0x70, 0x07, 0xa5,
+ 0x95, 0xd6, 0x85, 0xeb, 0x36, 0x9e, 0xa9, 0x51,
+ 0x66, 0x56, 0x5f, 0x1d, 0x02, 0x19, 0xe2, 0xf6,
+ 0x4f, 0x73, 0x38, 0x09, 0x75, 0x64, 0x48, 0xe0,
+ 0xf1, 0x7e, 0x0e, 0xe8, 0x9d, 0xf9, 0xed, 0x94,
+ 0xfe, 0x16, 0x26, 0x62, 0x49, 0x74, 0xf4, 0xb0,
+ 0xd4, 0xa9, 0x6c, 0xb0, 0xfd, 0x53, 0xe9, 0x81,
+ 0xe0, 0x7a, 0xbf, 0xcf, 0xb5, 0xc4, 0x01, 0x81,
+ 0x79, 0x99, 0x77, 0x01, 0x3b, 0xe9, 0xa2, 0xb6,
+ 0xe6, 0x6a, 0x8a, 0x9e, 0x56, 0x1c, 0x8d, 0x1e,
+ 0x8f, 0x06, 0x55, 0x2c, 0x6c, 0xdc, 0x92, 0x87,
+ 0x64, 0x3b, 0x4b, 0x19, 0xa1, 0x13, 0x64, 0x1d,
+ 0x4a, 0xe9, 0xc0, 0x00, 0xb8, 0x95, 0xef, 0x6b,
+ 0x1a, 0x86, 0x6d, 0x37, 0x52, 0x02, 0xc2, 0xe0,
+ 0xc8, 0xbb, 0x42, 0x0c, 0x02, 0x21, 0x4a, 0xc9,
+ 0xef, 0xa0, 0x54, 0xe4, 0x5e, 0x16, 0x53, 0x81,
+ 0x70, 0x62, 0x10, 0xaf, 0xde, 0xb8, 0xb5, 0xd3,
+ 0xe8, 0x5e, 0x6c, 0xc3, 0x8a, 0x3e, 0x18, 0x07,
+ 0xf2, 0x2f, 0x7d, 0xa7, 0xe1, 0x3d, 0x4e, 0xb4,
+ 0x26, 0xa7, 0xa3, 0x93, 0x86, 0xb2, 0x04, 0x1e,
+ 0x53, 0x5d, 0x86, 0xd6, 0xde, 0x65, 0xca, 0xe3,
+ 0x4e, 0xc1, 0xcf, 0xef, 0xc8, 0x70, 0x1b, 0x83,
+ 0x13, 0xdd, 0x18, 0x8b, 0x0d, 0x76, 0xd2, 0xf6,
+ 0x37, 0x7a, 0x93, 0x7a, 0x50, 0x11, 0x9f, 0x96,
+ 0x86, 0x25, 0xfd, 0xac, 0xdc, 0xbe, 0x18, 0x93,
+ 0x19, 0x6b, 0xec, 0x58, 0x4f, 0xb9, 0x75, 0xa7,
+ 0xdd, 0x3f, 0x2f, 0xec, 0xc8, 0x5a, 0x84, 0xab,
+ 0xd5, 0xe4, 0x8a, 0x07, 0xf6, 0x4d, 0x23, 0xd6,
+ 0x03, 0xfb, 0x03, 0x6a, 0xea, 0x66, 0xbf, 0xd4,
+ 0xb1, 0x34, 0xfb, 0x78, 0xe9, 0x55, 0xdc, 0x7c,
+ 0x3d, 0x9c, 0xe5, 0x9a, 0xac, 0xc3, 0x7a, 0x80,
+ 0x24, 0x6d, 0xa0, 0xef, 0x25, 0x7c, 0xb7, 0xea,
+ 0xce, 0x4d, 0x5f, 0x18, 0x60, 0xce, 0x87, 0x22,
+ 0x66, 0x2f, 0xd5, 0xdd, 0xdd, 0x02, 0x21, 0x75,
+ 0x82, 0xa0, 0x1f, 0x58, 0xc6, 0xd3, 0x62, 0xf7,
+ 0x32, 0xd8, 0xaf, 0x1e, 0x07, 0x77, 0x51, 0x96,
+ 0xd5, 0x6b, 0x1e, 0x7e, 0x80, 0x02, 0xe8, 0x67,
+ 0xea, 0x17, 0x0b, 0x10, 0xd2, 0x3f, 0x28, 0x25,
+ 0x4f, 0x05, 0x77, 0x02, 0x14, 0x69, 0xf0, 0x2c,
+ 0xbe, 0x0c, 0xf1, 0x74, 0x30, 0xd1, 0xb9, 0x9b,
+ 0xfc, 0x8c, 0xbb, 0x04, 0x16, 0xd9, 0xba, 0xc3,
+ 0xbc, 0x91, 0x8a, 0xc4, 0x30, 0xa4, 0xb0, 0x12,
+ 0x4c, 0x21, 0x87, 0xcb, 0xc9, 0x1d, 0x16, 0x96,
+ 0x07, 0x6f, 0x23, 0x54, 0xb9, 0x6f, 0x79, 0xe5,
+ 0x64, 0xc0, 0x64, 0xda, 0xb1, 0xae, 0xdd, 0x60,
+ 0x6c, 0x1a, 0x9d, 0xd3, 0x04, 0x8e, 0x45, 0xb0,
+ 0x92, 0x61, 0xd0, 0x48, 0x81, 0xed, 0x5e, 0x1d,
+ 0xa0, 0xc9, 0xa4, 0x33, 0xc7, 0x13, 0x51, 0x5d,
+ 0x7f, 0x83, 0x73, 0xb6, 0x70, 0x18, 0x65, 0x3e,
+ 0x2f, 0x0e, 0x7a, 0x12, 0x39, 0x98, 0xab, 0xd8,
+ 0x7e, 0x6f, 0xa3, 0xd1, 0xba, 0x56, 0xad, 0xbd,
+ 0xf0, 0x03, 0x01, 0x1c, 0x85, 0x35, 0x9f, 0xeb,
+ 0x19, 0x63, 0xa1, 0xaf, 0xfe, 0x2d, 0x35, 0x50,
+ 0x39, 0xa0, 0x65, 0x7c, 0x95, 0x7e, 0x6b, 0xfe,
+ 0xc1, 0xac, 0x07, 0x7c, 0x98, 0x4f, 0xbe, 0x57,
+ 0xa7, 0x22, 0xec, 0xe2, 0x7e, 0x29, 0x09, 0x53,
+ 0xe8, 0xbf, 0xb4, 0x7e, 0x3f, 0x8f, 0xfc, 0x14,
+ 0xce, 0x54, 0xf9, 0x18, 0x58, 0xb5, 0xff, 0x44,
+ 0x05, 0x9d, 0xce, 0x1b, 0xb6, 0x82, 0x23, 0xc8,
+ 0x2e, 0xbc, 0x69, 0xbb, 0x4a, 0x29, 0x0f, 0x65,
+ 0x94, 0xf0, 0x63, 0x06, 0x0e, 0xef, 0x8c, 0xbd,
+ 0xff, 0xfd, 0xb0, 0x21, 0x6e, 0x57, 0x05, 0x75,
+ 0xda, 0xd5, 0xc4, 0xeb, 0x8d, 0x32, 0xf7, 0x50,
+ 0xd3, 0x6f, 0x22, 0xed, 0x5f, 0x8e, 0xa2, 0x5b,
+ 0x80, 0x8c, 0xc8, 0x78, 0x40, 0x24, 0x4b, 0x89,
+ 0x30, 0xce, 0x7a, 0x97, 0x0e, 0xc4, 0xaf, 0xef,
+ 0x9b, 0xb4, 0xcd, 0x66, 0x74, 0x14, 0x04, 0x2b,
+ 0xf7, 0xce, 0x0b, 0x1c, 0x6e, 0xc2, 0x78, 0x8c,
+ 0xca, 0xc5, 0xd0, 0x1c, 0x95, 0x4a, 0x91, 0x2d,
+ 0xa7, 0x20, 0xeb, 0x86, 0x52, 0xb7, 0x67, 0xd8,
+ 0x0c, 0xd6, 0x04, 0x14, 0xde, 0x51, 0x74, 0x75,
+ 0xe7, 0x11, 0xb4, 0x87, 0xa3, 0x3d, 0x2d, 0xad,
+ 0x4f, 0xef, 0xa0, 0x0f, 0x70, 0x00, 0x6d, 0x13,
+ 0x19, 0x1d, 0x41, 0x50, 0xe9, 0xd8, 0xf0, 0x32,
+ 0x71, 0xbc, 0xd3, 0x11, 0xf2, 0xac, 0xbe, 0xaf,
+ 0x75, 0x46, 0x65, 0x4e, 0x07, 0x34, 0x37, 0xa3,
+ 0x89, 0xfe, 0x75, 0xd4, 0x70, 0x4c, 0xc6, 0x3f,
+ 0x69, 0x24, 0x0e, 0x38, 0x67, 0x43, 0x8c, 0xde,
+ 0x06, 0xb5, 0xb8, 0xe7, 0xc4, 0xf0, 0x41, 0x8f,
+ 0xf0, 0xbd, 0x2f, 0x0b, 0xb9, 0x18, 0xf8, 0xde,
+ 0x64, 0xb1, 0xdb, 0xee, 0x00, 0x50, 0x77, 0xe1,
+ 0xc7, 0xff, 0xa6, 0xfa, 0xdd, 0x70, 0xf4, 0xe3,
+ 0x93, 0xe9, 0x77, 0x35, 0x3d, 0x4b, 0x2f, 0x2b,
+ 0x6d, 0x55, 0xf0, 0xfc, 0x88, 0x54, 0x4e, 0x89,
+ 0xc1, 0x8a, 0x23, 0x31, 0x2d, 0x14, 0x2a, 0xb8,
+ 0x1b, 0x15, 0xdd, 0x9e, 0x6e, 0x7b, 0xda, 0x05,
+ 0x91, 0x7d, 0x62, 0x64, 0x96, 0x72, 0xde, 0xfc,
+ 0xc1, 0xec, 0xf0, 0x23, 0x51, 0x6f, 0xdb, 0x5b,
+ 0x1d, 0x08, 0x57, 0xce, 0x09, 0xb8, 0xf6, 0xcd,
+ 0x8d, 0x95, 0xf2, 0x20, 0xbf, 0x0f, 0x20, 0x57,
+ 0x98, 0x81, 0x84, 0x4f, 0x15, 0x5c, 0x76, 0xe7,
+ 0x3e, 0x0a, 0x3a, 0x6c, 0xc4, 0x8a, 0xbe, 0x78,
+ 0x74, 0x77, 0xc3, 0x09, 0x4b, 0x5d, 0x48, 0xe4,
+ 0xc8, 0xcb, 0x0b, 0xea, 0x17, 0x28, 0xcf, 0xcf,
+ 0x31, 0x32, 0x44, 0xa4, 0xe5, 0x0e, 0x1a, 0x98,
+ 0x94, 0xc4, 0xf0, 0xff, 0xae, 0x3e, 0x44, 0xe8,
+ 0xa5, 0xb3, 0xb5, 0x37, 0x2f, 0xe8, 0xaf, 0x6f,
+ 0x28, 0xc1, 0x37, 0x5f, 0x31, 0xd2, 0xb9, 0x33,
+ 0xb1, 0xb2, 0x52, 0x94, 0x75, 0x2c, 0x29, 0x59,
+ 0x06, 0xc2, 0x25, 0xe8, 0x71, 0x65, 0x4e, 0xed,
+ 0xc0, 0x9c, 0xb1, 0xbb, 0x25, 0xdc, 0x6c, 0xe7,
+ 0x4b, 0xa5, 0x7a, 0x54, 0x7a, 0x60, 0xff, 0x7a,
+ 0xe0, 0x50, 0x40, 0x96, 0x35, 0x63, 0xe4, 0x0b,
+ 0x76, 0xbd, 0xa4, 0x65, 0x00, 0x1b, 0x57, 0x88,
+ 0xae, 0xed, 0x39, 0x88, 0x42, 0x11, 0x3c, 0xed,
+ 0x85, 0x67, 0x7d, 0xb9, 0x68, 0x82, 0xe9, 0x43,
+ 0x3c, 0x47, 0x53, 0xfa, 0xe8, 0xf8, 0x9f, 0x1f,
+ 0x9f, 0xef, 0x0f, 0xf7, 0x30, 0xd9, 0x30, 0x0e,
+ 0xb9, 0x9f, 0x69, 0x18, 0x2f, 0x7e, 0xf8, 0xf8,
+ 0xf8, 0x8c, 0x0f, 0xd4, 0x02, 0x4d, 0xea, 0xcd,
+ 0x0a, 0x9c, 0x6f, 0x71, 0x6d, 0x5a, 0x4c, 0x60,
+ 0xce, 0x20, 0x56, 0x32, 0xc6, 0xc5, 0x99, 0x1f,
+ 0x09, 0xe6, 0x4e, 0x18, 0x1a, 0x15, 0x13, 0xa8,
+ 0x7d, 0xb1, 0x6b, 0xc0, 0xb2, 0x6d, 0xf8, 0x26,
+ 0x66, 0xf8, 0x3d, 0x18, 0x74, 0x70, 0x66, 0x7a,
+ 0x34, 0x17, 0xde, 0xba, 0x47, 0xf1, 0x06, 0x18,
+ 0xcb, 0xaf, 0xeb, 0x4a, 0x1e, 0x8f, 0xa7, 0x77,
+ 0xe0, 0x3b, 0x78, 0x62, 0x66, 0xc9, 0x10, 0xea,
+ 0x1f, 0xb7, 0x29, 0x0a, 0x45, 0xa1, 0x1d, 0x1e,
+ 0x1d, 0xe2, 0x65, 0x61, 0x50, 0x9c, 0xd7, 0x05,
+ 0xf2, 0x0b, 0x5b, 0x12, 0x61, 0x02, 0xc8, 0xe5,
+ 0x63, 0x4f, 0x20, 0x0c, 0x07, 0x17, 0x33, 0x5e,
+ 0x03, 0x9a, 0x53, 0x0f, 0x2e, 0x55, 0xfe, 0x50,
+ 0x43, 0x7d, 0xd0, 0xb6, 0x7e, 0x5a, 0xda, 0xae,
+ 0x58, 0xef, 0x15, 0xa9, 0x83, 0xd9, 0x46, 0xb1,
+ 0x42, 0xaa, 0xf5, 0x02, 0x6c, 0xce, 0x92, 0x06,
+ 0x1b, 0xdb, 0x66, 0x45, 0x91, 0x79, 0xc2, 0x2d,
+ 0xe6, 0x53, 0xd3, 0x14, 0xfd, 0xbb, 0x44, 0x63,
+ 0xc6, 0xd7, 0x3d, 0x7a, 0x0c, 0x75, 0x78, 0x9d,
+ 0x5c, 0xa6, 0x39, 0xb3, 0xe5, 0x63, 0xca, 0x8b,
+ 0xfe, 0xd3, 0xef, 0x60, 0x83, 0xf6, 0x8e, 0x70,
+ 0xb6, 0x67, 0xc7, 0x77, 0xed, 0x23, 0xef, 0x4c,
+ 0xf0, 0xed, 0x2d, 0x07, 0x59, 0x6f, 0xc1, 0x01,
+ 0x34, 0x37, 0x08, 0xab, 0xd9, 0x1f, 0x09, 0xb1,
+ 0xce, 0x5b, 0x17, 0xff, 0x74, 0xf8, 0x9c, 0xd5,
+ 0x2c, 0x56, 0x39, 0x79, 0x0f, 0x69, 0x44, 0x75,
+ 0x58, 0x27, 0x01, 0xc4, 0xbf, 0xa7, 0xa1, 0x1d,
+ 0x90, 0x17, 0x77, 0x86, 0x5a, 0x3f, 0xd9, 0xd1,
+ 0x0e, 0xa0, 0x10, 0xf8, 0xec, 0x1e, 0xa5, 0x7f,
+ 0x5e, 0x36, 0xd1, 0xe3, 0x04, 0x2c, 0x70, 0xf7,
+ 0x8e, 0xc0, 0x98, 0x2f, 0x6c, 0x94, 0x2b, 0x41,
+ 0xb7, 0x60, 0x00, 0xb7, 0x2e, 0xb8, 0x02, 0x8d,
+ 0xb8, 0xb0, 0xd3, 0x86, 0xba, 0x1d, 0xd7, 0x90,
+ 0xd6, 0xb6, 0xe1, 0xfc, 0xd7, 0xd8, 0x28, 0x06,
+ 0x63, 0x9b, 0xce, 0x61, 0x24, 0x79, 0xc0, 0x70,
+ 0x52, 0xd0, 0xb6, 0xd4, 0x28, 0x95, 0x24, 0x87,
+ 0x03, 0x1f, 0xb7, 0x9a, 0xda, 0xa3, 0xfb, 0x52,
+ 0x5b, 0x68, 0xe7, 0x4c, 0x8c, 0x24, 0xe1, 0x42,
+ 0xf7, 0xd5, 0xfd, 0xad, 0x06, 0x32, 0x9f, 0xba,
+ 0xc1, 0xfc, 0xdd, 0xc6, 0xfc, 0xfc, 0xb3, 0x38,
+ 0x74, 0x56, 0x58, 0x40, 0x02, 0x37, 0x52, 0x2c,
+ 0x55, 0xcc, 0xb3, 0x9e, 0x7a, 0xe9, 0xd4, 0x38,
+ 0x41, 0x5e, 0x0c, 0x35, 0xe2, 0x11, 0xd1, 0x13,
+ 0xf8, 0xb7, 0x8d, 0x72, 0x6b, 0x22, 0x2a, 0xb0,
+ 0xdb, 0x08, 0xba, 0x35, 0xb9, 0x3f, 0xc8, 0xd3,
+ 0x24, 0x90, 0xec, 0x58, 0xd2, 0x09, 0xc7, 0x2d,
+ 0xed, 0x38, 0x80, 0x36, 0x72, 0x43, 0x27, 0x49,
+ 0x4a, 0x80, 0x8a, 0xa2, 0xe8, 0xd3, 0xda, 0x30,
+ 0x7d, 0xb6, 0x82, 0x37, 0x86, 0x92, 0x86, 0x3e,
+ 0x08, 0xb2, 0x28, 0x5a, 0x55, 0x44, 0x24, 0x7d,
+ 0x40, 0x48, 0x8a, 0xb6, 0x89, 0x58, 0x08, 0xa0,
+ 0xd6, 0x6d, 0x3a, 0x17, 0xbf, 0xf6, 0x54, 0xa2,
+ 0xf5, 0xd3, 0x8c, 0x0f, 0x78, 0x12, 0x57, 0x8b,
+ 0xd5, 0xc2, 0xfd, 0x58, 0x5b, 0x7f, 0x38, 0xe3,
+ 0xcc, 0xb7, 0x7c, 0x48, 0xb3, 0x20, 0xe8, 0x81,
+ 0x14, 0x32, 0x45, 0x05, 0xe0, 0xdb, 0x9f, 0x75,
+ 0x85, 0xb4, 0x6a, 0xfc, 0x95, 0xe3, 0x54, 0x22,
+ 0x12, 0xee, 0x30, 0xfe, 0xd8, 0x30, 0xef, 0x34,
+ 0x50, 0xab, 0x46, 0x30, 0x98, 0x2f, 0xb7, 0xc0,
+ 0x15, 0xa2, 0x83, 0xb6, 0xf2, 0x06, 0x21, 0xa2,
+ 0xc3, 0x26, 0x37, 0x14, 0xd1, 0x4d, 0xb5, 0x10,
+ 0x52, 0x76, 0x4d, 0x6a, 0xee, 0xb5, 0x2b, 0x15,
+ 0xb7, 0xf9, 0x51, 0xe8, 0x2a, 0xaf, 0xc7, 0xfa,
+ 0x77, 0xaf, 0xb0, 0x05, 0x4d, 0xd1, 0x68, 0x8e,
+ 0x74, 0x05, 0x9f, 0x9d, 0x93, 0xa5, 0x3e, 0x7f,
+ 0x4e, 0x5f, 0x9d, 0xcb, 0x09, 0xc7, 0x83, 0xe3,
+ 0x02, 0x9d, 0x27, 0x1f, 0xef, 0x85, 0x05, 0x8d,
+ 0xec, 0x55, 0x88, 0x0f, 0x0d, 0x7c, 0x4c, 0xe8,
+ 0xa1, 0x75, 0xa0, 0xd8, 0x06, 0x47, 0x14, 0xef,
+ 0xaa, 0x61, 0xcf, 0x26, 0x15, 0xad, 0xd8, 0xa3,
+ 0xaa, 0x75, 0xf2, 0x78, 0x4a, 0x5a, 0x61, 0xdf,
+ 0x8b, 0xc7, 0x04, 0xbc, 0xb2, 0x32, 0xd2, 0x7e,
+ 0x42, 0xee, 0xb4, 0x2f, 0x51, 0xff, 0x7b, 0x2e,
+ 0xd3, 0x02, 0xe8, 0xdc, 0x5d, 0x0d, 0x50, 0xdc,
+ 0xae, 0xb7, 0x46, 0xf9, 0xa8, 0xe6, 0xd0, 0x16,
+ 0xcc, 0xe6, 0x2c, 0x81, 0xc7, 0xad, 0xe9, 0xf0,
+ 0x05, 0x72, 0x6d, 0x3d, 0x0a, 0x7a, 0xa9, 0x02,
+ 0xac, 0x82, 0x93, 0x6e, 0xb6, 0x1c, 0x28, 0xfc,
+ 0x44, 0x12, 0xfb, 0x73, 0x77, 0xd4, 0x13, 0x39,
+ 0x29, 0x88, 0x8a, 0xf3, 0x5c, 0xa6, 0x36, 0xa0,
+ 0x2a, 0xed, 0x7e, 0xb1, 0x1d, 0xd6, 0x4c, 0x6b,
+ 0x41, 0x01, 0x18, 0x5d, 0x5d, 0x07, 0x97, 0xa6,
+ 0x4b, 0xef, 0x31, 0x18, 0xea, 0xac, 0xb1, 0x84,
+ 0x21, 0xed, 0xda, 0x86,
+ },
+ .rlen = 4100,
+ },
+};
+
+static struct cipher_testvec aes_ctr_dec_tv_template[] = {
+ { /* From RFC 3686 */
+ .key = { 0xae, 0x68, 0x52, 0xf8, 0x12, 0x10, 0x67, 0xcc,
+ 0x4b, 0xf7, 0xa5, 0x76, 0x55, 0x77, 0xf3, 0x9e,
+ 0x00, 0x00, 0x00, 0x30 },
+ .klen = 20,
+ .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ .input = { 0xe4, 0x09, 0x5d, 0x4f, 0xb7, 0xa7, 0xb3, 0x79,
+ 0x2d, 0x61, 0x75, 0xa3, 0x26, 0x13, 0x11, 0xb8 },
+ .ilen = 16,
+ .result = { "Single block msg" },
+ .rlen = 16,
+ }, {
+ .key = { 0x7e, 0x24, 0x06, 0x78, 0x17, 0xfa, 0xe0, 0xd7,
+ 0x43, 0xd6, 0xce, 0x1f, 0x32, 0x53, 0x91, 0x63,
+ 0x00, 0x6c, 0xb6, 0xdb },
+ .klen = 20,
+ .iv = { 0xc0, 0x54, 0x3b, 0x59, 0xda, 0x48, 0xd9, 0x0b },
+ .input = { 0x51, 0x04, 0xa1, 0x06, 0x16, 0x8a, 0x72, 0xd9,
+ 0x79, 0x0d, 0x41, 0xee, 0x8e, 0xda, 0xd3, 0x88,
+ 0xeb, 0x2e, 0x1e, 0xfc, 0x46, 0xda, 0x57, 0xc8,
+ 0xfc, 0xe6, 0x30, 0xdf, 0x91, 0x41, 0xbe, 0x28 },
+ .ilen = 32,
+ .result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
+ .rlen = 32,
+ }, {
+ .key = { 0x16, 0xaf, 0x5b, 0x14, 0x5f, 0xc9, 0xf5, 0x79,
+ 0xc1, 0x75, 0xf9, 0x3e, 0x3b, 0xfb, 0x0e, 0xed,
+ 0x86, 0x3d, 0x06, 0xcc, 0xfd, 0xb7, 0x85, 0x15,
+ 0x00, 0x00, 0x00, 0x48 },
+ .klen = 28,
+ .iv = { 0x36, 0x73, 0x3c, 0x14, 0x7d, 0x6d, 0x93, 0xcb },
+ .input = { 0x4b, 0x55, 0x38, 0x4f, 0xe2, 0x59, 0xc9, 0xc8,
+ 0x4e, 0x79, 0x35, 0xa0, 0x03, 0xcb, 0xe9, 0x28 },
+ .ilen = 16,
+ .result = { "Single block msg" },
+ .rlen = 16,
+ }, {
+ .key = { 0x7c, 0x5c, 0xb2, 0x40, 0x1b, 0x3d, 0xc3, 0x3c,
+ 0x19, 0xe7, 0x34, 0x08, 0x19, 0xe0, 0xf6, 0x9c,
+ 0x67, 0x8c, 0x3d, 0xb8, 0xe6, 0xf6, 0xa9, 0x1a,
+ 0x00, 0x96, 0xb0, 0x3b },
+ .klen = 28,
+ .iv = { 0x02, 0x0c, 0x6e, 0xad, 0xc2, 0xcb, 0x50, 0x0d },
+ .input = { 0x45, 0x32, 0x43, 0xfc, 0x60, 0x9b, 0x23, 0x32,
+ 0x7e, 0xdf, 0xaa, 0xfa, 0x71, 0x31, 0xcd, 0x9f,
+ 0x84, 0x90, 0x70, 0x1c, 0x5a, 0xd4, 0xa7, 0x9c,
+ 0xfc, 0x1f, 0xe0, 0xff, 0x42, 0xf4, 0xfb, 0x00 },
+ .ilen = 32,
+ .result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
+ .rlen = 32,
+ }, {
+ .key = { 0x77, 0x6b, 0xef, 0xf2, 0x85, 0x1d, 0xb0, 0x6f,
+ 0x4c, 0x8a, 0x05, 0x42, 0xc8, 0x69, 0x6f, 0x6c,
+ 0x6a, 0x81, 0xaf, 0x1e, 0xec, 0x96, 0xb4, 0xd3,
+ 0x7f, 0xc1, 0xd6, 0x89, 0xe6, 0xc1, 0xc1, 0x04,
+ 0x00, 0x00, 0x00, 0x60 },
+ .klen = 36,
+ .iv = { 0xdb, 0x56, 0x72, 0xc9, 0x7a, 0xa8, 0xf0, 0xb2 },
+ .input = { 0x14, 0x5a, 0xd0, 0x1d, 0xbf, 0x82, 0x4e, 0xc7,
+ 0x56, 0x08, 0x63, 0xdc, 0x71, 0xe3, 0xe0, 0xc0 },
+ .ilen = 16,
+ .result = { "Single block msg" },
+ .rlen = 16,
+ }, {
+ .key = { 0xf6, 0xd6, 0x6d, 0x6b, 0xd5, 0x2d, 0x59, 0xbb,
+ 0x07, 0x96, 0x36, 0x58, 0x79, 0xef, 0xf8, 0x86,
+ 0xc6, 0x6d, 0xd5, 0x1a, 0x5b, 0x6a, 0x99, 0x74,
+ 0x4b, 0x50, 0x59, 0x0c, 0x87, 0xa2, 0x38, 0x84,
+ 0x00, 0xfa, 0xac, 0x24 },
+ .klen = 36,
+ .iv = { 0xc1, 0x58, 0x5e, 0xf1, 0x5a, 0x43, 0xd8, 0x75 },
+ .input = { 0xf0, 0x5e, 0x23, 0x1b, 0x38, 0x94, 0x61, 0x2c,
+ 0x49, 0xee, 0x00, 0x0b, 0x80, 0x4e, 0xb2, 0xa9,
+ 0xb8, 0x30, 0x6b, 0x50, 0x8f, 0x83, 0x9d, 0x6a,
+ 0x55, 0x30, 0x83, 0x1d, 0x93, 0x44, 0xaf, 0x1c },
+ .ilen = 32,
+ .result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
+ .rlen = 32,
+ },
+};
+
+static struct aead_testvec aes_gcm_enc_tv_template[] = {
+ { /* From McGrew & Viega - http://citeseer.ist.psu.edu/656989.html */
+ .klen = 16,
+ .result = { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
+ 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
+ .rlen = 16,
+ }, {
+ .klen = 16,
+ .ilen = 16,
+ .result = { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
+ 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78,
+ 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
+ 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
+ .rlen = 32,
+ }, {
+ .key = { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
+ .klen = 16,
+ .iv = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88 },
+ .input = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
+ .ilen = 64,
+ .result = { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
+ 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
+ 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
+ 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
+ 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
+ 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
+ 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
+ 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85,
+ 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
+ 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
+ .rlen = 80,
+ }, {
+ .key = { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
+ .klen = 16,
+ .iv = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88 },
+ .input = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39 },
+ .ilen = 60,
+ .assoc = { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xab, 0xad, 0xda, 0xd2 },
+ .alen = 20,
+ .result = { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
+ 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
+ 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
+ 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
+ 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
+ 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
+ 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
+ 0x3d, 0x58, 0xe0, 0x91,
+ 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
+ 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
+ .rlen = 76,
+ }, {
+ .klen = 24,
+ .result = { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
+ 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
+ .rlen = 16,
+ }, {
+ .klen = 24,
+ .ilen = 16,
+ .result = { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
+ 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00,
+ 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
+ 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
+ .rlen = 32,
+ }, {
+ .key = { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c },
+ .klen = 24,
+ .iv = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88 },
+ .input = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
+ .ilen = 64,
+ .result = { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
+ 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
+ 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
+ 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
+ 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
+ 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
+ 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
+ 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56,
+ 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
+ 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
+ .rlen = 80,
+ }, {
+ .key = { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c },
+ .klen = 24,
+ .iv = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88 },
+ .input = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39 },
+ .ilen = 60,
+ .assoc = { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xab, 0xad, 0xda, 0xd2 },
+ .alen = 20,
+ .result = { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
+ 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
+ 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
+ 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
+ 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
+ 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
+ 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
+ 0xcc, 0xda, 0x27, 0x10,
+ 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
+ 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
+ .rlen = 76,
+ .np = 2,
+ .tap = { 32, 28 },
+ .anp = 2,
+ .atap = { 8, 12 }
+ }, {
+ .klen = 32,
+ .result = { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
+ 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
+ .rlen = 16,
+ }
+};
+
+static struct aead_testvec aes_gcm_dec_tv_template[] = {
+ { /* From McGrew & Viega - http://citeseer.ist.psu.edu/656989.html */
+ .klen = 32,
+ .input = { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
+ 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18,
+ 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
+ 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
+ .ilen = 32,
+ .rlen = 16,
+ }, {
+ .key = { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
+ .klen = 32,
+ .iv = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88 },
+ .input = { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
+ 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
+ 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
+ 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
+ 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
+ 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
+ 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
+ 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad,
+ 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
+ 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
+ .ilen = 80,
+ .result = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
+ .rlen = 64,
+ }, {
+ .key = { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
+ .klen = 32,
+ .iv = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88 },
+ .input = { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
+ 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
+ 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
+ 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
+ 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
+ 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
+ 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
+ 0xbc, 0xc9, 0xf6, 0x62,
+ 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
+ 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
+ .ilen = 76,
+ .assoc = { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xab, 0xad, 0xda, 0xd2 },
+ .alen = 20,
+ .result = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39 },
+ .rlen = 60,
+ .np = 2,
+ .tap = { 48, 28 },
+ .anp = 3,
+ .atap = { 8, 8, 4 }
+ }, {
+ .key = { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
+ .klen = 16,
+ .iv = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88 },
+ .input = { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
+ 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
+ 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
+ 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
+ 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
+ 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
+ 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
+ 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85,
+ 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
+ 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
+ .ilen = 80,
+ .result = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
+ .rlen = 64,
+ }, {
+ .key = { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
+ .klen = 16,
+ .iv = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88 },
+ .input = { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
+ 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
+ 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
+ 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
+ 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
+ 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
+ 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
+ 0x3d, 0x58, 0xe0, 0x91,
+ 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
+ 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
+ .ilen = 76,
+ .assoc = { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xab, 0xad, 0xda, 0xd2 },
+ .alen = 20,
+ .result = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39 },
+ .rlen = 60,
+ }, {
+ .klen = 24,
+ .input = { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
+ 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00,
+ 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
+ 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
+ .ilen = 32,
+ .rlen = 16,
+ }, {
+ .key = { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c },
+ .klen = 24,
+ .iv = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88 },
+ .input = { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
+ 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
+ 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
+ 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
+ 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
+ 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
+ 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
+ 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56,
+ 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
+ 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
+ .ilen = 80,
+ .result = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
+ .rlen = 64,
+ }, {
+ .key = { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c },
+ .klen = 24,
+ .iv = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88 },
+ .input = { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
+ 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
+ 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
+ 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
+ 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
+ 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
+ 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
+ 0xcc, 0xda, 0x27, 0x10,
+ 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
+ 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
+ .ilen = 76,
+ .assoc = { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xab, 0xad, 0xda, 0xd2 },
+ .alen = 20,
+ .result = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39 },
+ .rlen = 60,
+ }
+};
+
+static struct aead_testvec aes_ccm_enc_tv_template[] = {
+ { /* From RFC 3610 */
+ .key = { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
+ .klen = 16,
+ .iv = { 0x01, 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
+ .assoc = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 },
+ .alen = 8,
+ .input = { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e },
+ .ilen = 23,
+ .result = { 0x58, 0x8c, 0x97, 0x9a, 0x61, 0xc6, 0x63, 0xd2,
+ 0xf0, 0x66, 0xd0, 0xc2, 0xc0, 0xf9, 0x89, 0x80,
+ 0x6d, 0x5f, 0x6b, 0x61, 0xda, 0xc3, 0x84, 0x17,
+ 0xe8, 0xd1, 0x2c, 0xfd, 0xf9, 0x26, 0xe0 },
+ .rlen = 31,
+ }, {
+ .key = { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
+ .klen = 16,
+ .iv = { 0x01, 0x00, 0x00, 0x00, 0x07, 0x06, 0x05, 0x04,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
+ .assoc = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b },
+ .alen = 12,
+ .input = { 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
+ 0x1c, 0x1d, 0x1e, 0x1f },
+ .ilen = 20,
+ .result = { 0xdc, 0xf1, 0xfb, 0x7b, 0x5d, 0x9e, 0x23, 0xfb,
+ 0x9d, 0x4e, 0x13, 0x12, 0x53, 0x65, 0x8a, 0xd8,
+ 0x6e, 0xbd, 0xca, 0x3e, 0x51, 0xe8, 0x3f, 0x07,
+ 0x7d, 0x9c, 0x2d, 0x93 },
+ .rlen = 28,
+ }, {
+ .key = { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
+ .klen = 16,
+ .iv = { 0x01, 0x00, 0x00, 0x00, 0x0b, 0x0a, 0x09, 0x08,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
+ .assoc = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 },
+ .alen = 8,
+ .input = { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20 },
+ .ilen = 25,
+ .result = { 0x82, 0x53, 0x1a, 0x60, 0xcc, 0x24, 0x94, 0x5a,
+ 0x4b, 0x82, 0x79, 0x18, 0x1a, 0xb5, 0xc8, 0x4d,
+ 0xf2, 0x1c, 0xe7, 0xf9, 0xb7, 0x3f, 0x42, 0xe1,
+ 0x97, 0xea, 0x9c, 0x07, 0xe5, 0x6b, 0x5e, 0xb1,
+ 0x7e, 0x5f, 0x4e },
+ .rlen = 35,
+ }, {
+ .key = { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
+ .klen = 16,
+ .iv = { 0x01, 0x00, 0x00, 0x00, 0x0c, 0x0b, 0x0a, 0x09,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
+ .assoc = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b },
+ .alen = 12,
+ .input = { 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
+ 0x1c, 0x1d, 0x1e },
+ .ilen = 19,
+ .result = { 0x07, 0x34, 0x25, 0x94, 0x15, 0x77, 0x85, 0x15,
+ 0x2b, 0x07, 0x40, 0x98, 0x33, 0x0a, 0xbb, 0x14,
+ 0x1b, 0x94, 0x7b, 0x56, 0x6a, 0xa9, 0x40, 0x6b,
+ 0x4d, 0x99, 0x99, 0x88, 0xdd },
+ .rlen = 29,
+ }, {
+ .key = { 0xd7, 0x82, 0x8d, 0x13, 0xb2, 0xb0, 0xbd, 0xc3,
+ 0x25, 0xa7, 0x62, 0x36, 0xdf, 0x93, 0xcc, 0x6b },
+ .klen = 16,
+ .iv = { 0x01, 0x00, 0x33, 0x56, 0x8e, 0xf7, 0xb2, 0x63,
+ 0x3c, 0x96, 0x96, 0x76, 0x6c, 0xfa, 0x00, 0x00 },
+ .assoc = { 0x63, 0x01, 0x8f, 0x76, 0xdc, 0x8a, 0x1b, 0xcb },
+ .alen = 8,
+ .input = { 0x90, 0x20, 0xea, 0x6f, 0x91, 0xbd, 0xd8, 0x5a,
+ 0xfa, 0x00, 0x39, 0xba, 0x4b, 0xaf, 0xf9, 0xbf,
+ 0xb7, 0x9c, 0x70, 0x28, 0x94, 0x9c, 0xd0, 0xec },
+ .ilen = 24,
+ .result = { 0x4c, 0xcb, 0x1e, 0x7c, 0xa9, 0x81, 0xbe, 0xfa,
+ 0xa0, 0x72, 0x6c, 0x55, 0xd3, 0x78, 0x06, 0x12,
+ 0x98, 0xc8, 0x5c, 0x92, 0x81, 0x4a, 0xbc, 0x33,
+ 0xc5, 0x2e, 0xe8, 0x1d, 0x7d, 0x77, 0xc0, 0x8a },
+ .rlen = 32,
+ }, {
+ .key = { 0xd7, 0x82, 0x8d, 0x13, 0xb2, 0xb0, 0xbd, 0xc3,
+ 0x25, 0xa7, 0x62, 0x36, 0xdf, 0x93, 0xcc, 0x6b },
+ .klen = 16,
+ .iv = { 0x01, 0x00, 0xd5, 0x60, 0x91, 0x2d, 0x3f, 0x70,
+ 0x3c, 0x96, 0x96, 0x76, 0x6c, 0xfa, 0x00, 0x00 },
+ .assoc = { 0xcd, 0x90, 0x44, 0xd2, 0xb7, 0x1f, 0xdb, 0x81,
+ 0x20, 0xea, 0x60, 0xc0 },
+ .alen = 12,
+ .input = { 0x64, 0x35, 0xac, 0xba, 0xfb, 0x11, 0xa8, 0x2e,
+ 0x2f, 0x07, 0x1d, 0x7c, 0xa4, 0xa5, 0xeb, 0xd9,
+ 0x3a, 0x80, 0x3b, 0xa8, 0x7f },
+ .ilen = 21,
+ .result = { 0x00, 0x97, 0x69, 0xec, 0xab, 0xdf, 0x48, 0x62,
+ 0x55, 0x94, 0xc5, 0x92, 0x51, 0xe6, 0x03, 0x57,
+ 0x22, 0x67, 0x5e, 0x04, 0xc8, 0x47, 0x09, 0x9e,
+ 0x5a, 0xe0, 0x70, 0x45, 0x51 },
+ .rlen = 29,
+ }, {
+ .key = { 0xd7, 0x82, 0x8d, 0x13, 0xb2, 0xb0, 0xbd, 0xc3,
+ 0x25, 0xa7, 0x62, 0x36, 0xdf, 0x93, 0xcc, 0x6b },
+ .klen = 16,
+ .iv = { 0x01, 0x00, 0x42, 0xff, 0xf8, 0xf1, 0x95, 0x1c,
+ 0x3c, 0x96, 0x96, 0x76, 0x6c, 0xfa, 0x00, 0x00 },
+ .assoc = { 0xd8, 0x5b, 0xc7, 0xe6, 0x9f, 0x94, 0x4f, 0xb8 },
+ .alen = 8,
+ .input = { 0x8a, 0x19, 0xb9, 0x50, 0xbc, 0xf7, 0x1a, 0x01,
+ 0x8e, 0x5e, 0x67, 0x01, 0xc9, 0x17, 0x87, 0x65,
+ 0x98, 0x09, 0xd6, 0x7d, 0xbe, 0xdd, 0x18 },
+ .ilen = 23,
+ .result = { 0xbc, 0x21, 0x8d, 0xaa, 0x94, 0x74, 0x27, 0xb6,
+ 0xdb, 0x38, 0x6a, 0x99, 0xac, 0x1a, 0xef, 0x23,
+ 0xad, 0xe0, 0xb5, 0x29, 0x39, 0xcb, 0x6a, 0x63,
+ 0x7c, 0xf9, 0xbe, 0xc2, 0x40, 0x88, 0x97, 0xc6,
+ 0xba },
+ .rlen = 33,
+ },
+};
+
+static struct aead_testvec aes_ccm_dec_tv_template[] = {
+ { /* From RFC 3610 */
+ .key = { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
+ .klen = 16,
+ .iv = { 0x01, 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
+ .assoc = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 },
+ .alen = 8,
+ .input = { 0x58, 0x8c, 0x97, 0x9a, 0x61, 0xc6, 0x63, 0xd2,
+ 0xf0, 0x66, 0xd0, 0xc2, 0xc0, 0xf9, 0x89, 0x80,
+ 0x6d, 0x5f, 0x6b, 0x61, 0xda, 0xc3, 0x84, 0x17,
+ 0xe8, 0xd1, 0x2c, 0xfd, 0xf9, 0x26, 0xe0 },
+ .ilen = 31,
+ .result = { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e },
+ .rlen = 23,
+ }, {
+ .key = { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
+ .klen = 16,
+ .iv = { 0x01, 0x00, 0x00, 0x00, 0x07, 0x06, 0x05, 0x04,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
+ .assoc = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b },
+ .alen = 12,
+ .input = { 0xdc, 0xf1, 0xfb, 0x7b, 0x5d, 0x9e, 0x23, 0xfb,
+ 0x9d, 0x4e, 0x13, 0x12, 0x53, 0x65, 0x8a, 0xd8,
+ 0x6e, 0xbd, 0xca, 0x3e, 0x51, 0xe8, 0x3f, 0x07,
+ 0x7d, 0x9c, 0x2d, 0x93 },
+ .ilen = 28,
+ .result = { 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
+ 0x1c, 0x1d, 0x1e, 0x1f },
+ .rlen = 20,
+ }, {
+ .key = { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
+ .klen = 16,
+ .iv = { 0x01, 0x00, 0x00, 0x00, 0x0b, 0x0a, 0x09, 0x08,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
+ .assoc = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 },
+ .alen = 8,
+ .input = { 0x82, 0x53, 0x1a, 0x60, 0xcc, 0x24, 0x94, 0x5a,
+ 0x4b, 0x82, 0x79, 0x18, 0x1a, 0xb5, 0xc8, 0x4d,
+ 0xf2, 0x1c, 0xe7, 0xf9, 0xb7, 0x3f, 0x42, 0xe1,
+ 0x97, 0xea, 0x9c, 0x07, 0xe5, 0x6b, 0x5e, 0xb1,
+ 0x7e, 0x5f, 0x4e },
+ .ilen = 35,
+ .result = { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20 },
+ .rlen = 25,
+ }, {
+ .key = { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
+ .klen = 16,
+ .iv = { 0x01, 0x00, 0x00, 0x00, 0x0c, 0x0b, 0x0a, 0x09,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
+ .assoc = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b },
+ .alen = 12,
+ .input = { 0x07, 0x34, 0x25, 0x94, 0x15, 0x77, 0x85, 0x15,
+ 0x2b, 0x07, 0x40, 0x98, 0x33, 0x0a, 0xbb, 0x14,
+ 0x1b, 0x94, 0x7b, 0x56, 0x6a, 0xa9, 0x40, 0x6b,
+ 0x4d, 0x99, 0x99, 0x88, 0xdd },
+ .ilen = 29,
+ .result = { 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
+ 0x1c, 0x1d, 0x1e },
+ .rlen = 19,
+ }, {
+ .key = { 0xd7, 0x82, 0x8d, 0x13, 0xb2, 0xb0, 0xbd, 0xc3,
+ 0x25, 0xa7, 0x62, 0x36, 0xdf, 0x93, 0xcc, 0x6b },
+ .klen = 16,
+ .iv = { 0x01, 0x00, 0x33, 0x56, 0x8e, 0xf7, 0xb2, 0x63,
+ 0x3c, 0x96, 0x96, 0x76, 0x6c, 0xfa, 0x00, 0x00 },
+ .assoc = { 0x63, 0x01, 0x8f, 0x76, 0xdc, 0x8a, 0x1b, 0xcb },
+ .alen = 8,
+ .input = { 0x4c, 0xcb, 0x1e, 0x7c, 0xa9, 0x81, 0xbe, 0xfa,
+ 0xa0, 0x72, 0x6c, 0x55, 0xd3, 0x78, 0x06, 0x12,
+ 0x98, 0xc8, 0x5c, 0x92, 0x81, 0x4a, 0xbc, 0x33,
+ 0xc5, 0x2e, 0xe8, 0x1d, 0x7d, 0x77, 0xc0, 0x8a },
+ .ilen = 32,
+ .result = { 0x90, 0x20, 0xea, 0x6f, 0x91, 0xbd, 0xd8, 0x5a,
+ 0xfa, 0x00, 0x39, 0xba, 0x4b, 0xaf, 0xf9, 0xbf,
+ 0xb7, 0x9c, 0x70, 0x28, 0x94, 0x9c, 0xd0, 0xec },
+ .rlen = 24,
+ }, {
+ .key = { 0xd7, 0x82, 0x8d, 0x13, 0xb2, 0xb0, 0xbd, 0xc3,
+ 0x25, 0xa7, 0x62, 0x36, 0xdf, 0x93, 0xcc, 0x6b },
+ .klen = 16,
+ .iv = { 0x01, 0x00, 0xd5, 0x60, 0x91, 0x2d, 0x3f, 0x70,
+ 0x3c, 0x96, 0x96, 0x76, 0x6c, 0xfa, 0x00, 0x00 },
+ .assoc = { 0xcd, 0x90, 0x44, 0xd2, 0xb7, 0x1f, 0xdb, 0x81,
+ 0x20, 0xea, 0x60, 0xc0 },
+ .alen = 12,
+ .input = { 0x00, 0x97, 0x69, 0xec, 0xab, 0xdf, 0x48, 0x62,
+ 0x55, 0x94, 0xc5, 0x92, 0x51, 0xe6, 0x03, 0x57,
+ 0x22, 0x67, 0x5e, 0x04, 0xc8, 0x47, 0x09, 0x9e,
+ 0x5a, 0xe0, 0x70, 0x45, 0x51 },
+ .ilen = 29,
+ .result = { 0x64, 0x35, 0xac, 0xba, 0xfb, 0x11, 0xa8, 0x2e,
+ 0x2f, 0x07, 0x1d, 0x7c, 0xa4, 0xa5, 0xeb, 0xd9,
+ 0x3a, 0x80, 0x3b, 0xa8, 0x7f },
+ .rlen = 21,
+ }, {
+ .key = { 0xd7, 0x82, 0x8d, 0x13, 0xb2, 0xb0, 0xbd, 0xc3,
+ 0x25, 0xa7, 0x62, 0x36, 0xdf, 0x93, 0xcc, 0x6b },
+ .klen = 16,
+ .iv = { 0x01, 0x00, 0x42, 0xff, 0xf8, 0xf1, 0x95, 0x1c,
+ 0x3c, 0x96, 0x96, 0x76, 0x6c, 0xfa, 0x00, 0x00 },
+ .assoc = { 0xd8, 0x5b, 0xc7, 0xe6, 0x9f, 0x94, 0x4f, 0xb8 },
+ .alen = 8,
+ .input = { 0xbc, 0x21, 0x8d, 0xaa, 0x94, 0x74, 0x27, 0xb6,
+ 0xdb, 0x38, 0x6a, 0x99, 0xac, 0x1a, 0xef, 0x23,
+ 0xad, 0xe0, 0xb5, 0x29, 0x39, 0xcb, 0x6a, 0x63,
+ 0x7c, 0xf9, 0xbe, 0xc2, 0x40, 0x88, 0x97, 0xc6,
+ 0xba },
+ .ilen = 33,
+ .result = { 0x8a, 0x19, 0xb9, 0x50, 0xbc, 0xf7, 0x1a, 0x01,
+ 0x8e, 0x5e, 0x67, 0x01, 0xc9, 0x17, 0x87, 0x65,
+ 0x98, 0x09, 0xd6, 0x7d, 0xbe, 0xdd, 0x18 },
+ .rlen = 23,
+ },
+};
+
/* Cast5 test vectors from RFC 2144 */
#define CAST5_ENC_TEST_VECTORS 3
#define CAST5_DEC_TEST_VECTORS 3
@@ -4317,6 +6425,1211 @@
}
};
+#define SALSA20_STREAM_ENC_TEST_VECTORS 5
+static struct cipher_testvec salsa20_stream_enc_tv_template[] = {
+ /*
+ * Testvectors from verified.test-vectors submitted to ECRYPT.
+ * They are truncated to size 39, 64, 111, 129 to test a variety
+ * of input length.
+ */
+ { /* Set 3, vector 0 */
+ .key = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+ },
+ .klen = 16,
+ .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ .input = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ .ilen = 39,
+ .result = {
+ 0x2D, 0xD5, 0xC3, 0xF7, 0xBA, 0x2B, 0x20, 0xF7,
+ 0x68, 0x02, 0x41, 0x0C, 0x68, 0x86, 0x88, 0x89,
+ 0x5A, 0xD8, 0xC1, 0xBD, 0x4E, 0xA6, 0xC9, 0xB1,
+ 0x40, 0xFB, 0x9B, 0x90, 0xE2, 0x10, 0x49, 0xBF,
+ 0x58, 0x3F, 0x52, 0x79, 0x70, 0xEB, 0xC1,
+ },
+ .rlen = 39,
+ }, { /* Set 5, vector 0 */
+ .key = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ },
+ .klen = 16,
+ .iv = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ .input = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ .ilen = 64,
+ .result = {
+ 0xB6, 0x6C, 0x1E, 0x44, 0x46, 0xDD, 0x95, 0x57,
+ 0xE5, 0x78, 0xE2, 0x23, 0xB0, 0xB7, 0x68, 0x01,
+ 0x7B, 0x23, 0xB2, 0x67, 0xBB, 0x02, 0x34, 0xAE,
+ 0x46, 0x26, 0xBF, 0x44, 0x3F, 0x21, 0x97, 0x76,
+ 0x43, 0x6F, 0xB1, 0x9F, 0xD0, 0xE8, 0x86, 0x6F,
+ 0xCD, 0x0D, 0xE9, 0xA9, 0x53, 0x8F, 0x4A, 0x09,
+ 0xCA, 0x9A, 0xC0, 0x73, 0x2E, 0x30, 0xBC, 0xF9,
+ 0x8E, 0x4F, 0x13, 0xE4, 0xB9, 0xE2, 0x01, 0xD9,
+ },
+ .rlen = 64,
+ }, { /* Set 3, vector 27 */
+ .key = {
+ 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22,
+ 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A,
+ 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32,
+ 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A
+ },
+ .klen = 32,
+ .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ .input = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ .ilen = 111,
+ .result = {
+ 0xAE, 0x39, 0x50, 0x8E, 0xAC, 0x9A, 0xEC, 0xE7,
+ 0xBF, 0x97, 0xBB, 0x20, 0xB9, 0xDE, 0xE4, 0x1F,
+ 0x87, 0xD9, 0x47, 0xF8, 0x28, 0x91, 0x35, 0x98,
+ 0xDB, 0x72, 0xCC, 0x23, 0x29, 0x48, 0x56, 0x5E,
+ 0x83, 0x7E, 0x0B, 0xF3, 0x7D, 0x5D, 0x38, 0x7B,
+ 0x2D, 0x71, 0x02, 0xB4, 0x3B, 0xB5, 0xD8, 0x23,
+ 0xB0, 0x4A, 0xDF, 0x3C, 0xEC, 0xB6, 0xD9, 0x3B,
+ 0x9B, 0xA7, 0x52, 0xBE, 0xC5, 0xD4, 0x50, 0x59,
+
+ 0x15, 0x14, 0xB4, 0x0E, 0x40, 0xE6, 0x53, 0xD1,
+ 0x83, 0x9C, 0x5B, 0xA0, 0x92, 0x29, 0x6B, 0x5E,
+ 0x96, 0x5B, 0x1E, 0x2F, 0xD3, 0xAC, 0xC1, 0x92,
+ 0xB1, 0x41, 0x3F, 0x19, 0x2F, 0xC4, 0x3B, 0xC6,
+ 0x95, 0x46, 0x45, 0x54, 0xE9, 0x75, 0x03, 0x08,
+ 0x44, 0xAF, 0xE5, 0x8A, 0x81, 0x12, 0x09,
+ },
+ .rlen = 111,
+
+ }, { /* Set 5, vector 27 */
+ .key = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ },
+ .klen = 32,
+ .iv = { 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00 },
+ .input = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ 0x00,
+ },
+ .ilen = 129,
+ .result = {
+ 0xD2, 0xDB, 0x1A, 0x5C, 0xF1, 0xC1, 0xAC, 0xDB,
+ 0xE8, 0x1A, 0x7A, 0x43, 0x40, 0xEF, 0x53, 0x43,
+ 0x5E, 0x7F, 0x4B, 0x1A, 0x50, 0x52, 0x3F, 0x8D,
+ 0x28, 0x3D, 0xCF, 0x85, 0x1D, 0x69, 0x6E, 0x60,
+ 0xF2, 0xDE, 0x74, 0x56, 0x18, 0x1B, 0x84, 0x10,
+ 0xD4, 0x62, 0xBA, 0x60, 0x50, 0xF0, 0x61, 0xF2,
+ 0x1C, 0x78, 0x7F, 0xC1, 0x24, 0x34, 0xAF, 0x58,
+ 0xBF, 0x2C, 0x59, 0xCA, 0x90, 0x77, 0xF3, 0xB0,
+
+ 0x5B, 0x4A, 0xDF, 0x89, 0xCE, 0x2C, 0x2F, 0xFC,
+ 0x67, 0xF0, 0xE3, 0x45, 0xE8, 0xB3, 0xB3, 0x75,
+ 0xA0, 0x95, 0x71, 0xA1, 0x29, 0x39, 0x94, 0xCA,
+ 0x45, 0x2F, 0xBD, 0xCB, 0x10, 0xB6, 0xBE, 0x9F,
+ 0x8E, 0xF9, 0xB2, 0x01, 0x0A, 0x5A, 0x0A, 0xB7,
+ 0x6B, 0x9D, 0x70, 0x8E, 0x4B, 0xD6, 0x2F, 0xCD,
+ 0x2E, 0x40, 0x48, 0x75, 0xE9, 0xE2, 0x21, 0x45,
+ 0x0B, 0xC9, 0xB6, 0xB5, 0x66, 0xBC, 0x9A, 0x59,
+
+ 0x5A,
+ },
+ .rlen = 129,
+ }, { /* large test vector generated using Crypto++ */
+ .key = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ },
+ .klen = 32,
+ .iv = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ .input = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+ 0x00, 0x03, 0x06, 0x09, 0x0c, 0x0f, 0x12, 0x15,
+ 0x18, 0x1b, 0x1e, 0x21, 0x24, 0x27, 0x2a, 0x2d,
+ 0x30, 0x33, 0x36, 0x39, 0x3c, 0x3f, 0x42, 0x45,
+ 0x48, 0x4b, 0x4e, 0x51, 0x54, 0x57, 0x5a, 0x5d,
+ 0x60, 0x63, 0x66, 0x69, 0x6c, 0x6f, 0x72, 0x75,
+ 0x78, 0x7b, 0x7e, 0x81, 0x84, 0x87, 0x8a, 0x8d,
+ 0x90, 0x93, 0x96, 0x99, 0x9c, 0x9f, 0xa2, 0xa5,
+ 0xa8, 0xab, 0xae, 0xb1, 0xb4, 0xb7, 0xba, 0xbd,
+ 0xc0, 0xc3, 0xc6, 0xc9, 0xcc, 0xcf, 0xd2, 0xd5,
+ 0xd8, 0xdb, 0xde, 0xe1, 0xe4, 0xe7, 0xea, 0xed,
+ 0xf0, 0xf3, 0xf6, 0xf9, 0xfc, 0xff, 0x02, 0x05,
+ 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17, 0x1a, 0x1d,
+ 0x20, 0x23, 0x26, 0x29, 0x2c, 0x2f, 0x32, 0x35,
+ 0x38, 0x3b, 0x3e, 0x41, 0x44, 0x47, 0x4a, 0x4d,
+ 0x50, 0x53, 0x56, 0x59, 0x5c, 0x5f, 0x62, 0x65,
+ 0x68, 0x6b, 0x6e, 0x71, 0x74, 0x77, 0x7a, 0x7d,
+ 0x80, 0x83, 0x86, 0x89, 0x8c, 0x8f, 0x92, 0x95,
+ 0x98, 0x9b, 0x9e, 0xa1, 0xa4, 0xa7, 0xaa, 0xad,
+ 0xb0, 0xb3, 0xb6, 0xb9, 0xbc, 0xbf, 0xc2, 0xc5,
+ 0xc8, 0xcb, 0xce, 0xd1, 0xd4, 0xd7, 0xda, 0xdd,
+ 0xe0, 0xe3, 0xe6, 0xe9, 0xec, 0xef, 0xf2, 0xf5,
+ 0xf8, 0xfb, 0xfe, 0x01, 0x04, 0x07, 0x0a, 0x0d,
+ 0x10, 0x13, 0x16, 0x19, 0x1c, 0x1f, 0x22, 0x25,
+ 0x28, 0x2b, 0x2e, 0x31, 0x34, 0x37, 0x3a, 0x3d,
+ 0x40, 0x43, 0x46, 0x49, 0x4c, 0x4f, 0x52, 0x55,
+ 0x58, 0x5b, 0x5e, 0x61, 0x64, 0x67, 0x6a, 0x6d,
+ 0x70, 0x73, 0x76, 0x79, 0x7c, 0x7f, 0x82, 0x85,
+ 0x88, 0x8b, 0x8e, 0x91, 0x94, 0x97, 0x9a, 0x9d,
+ 0xa0, 0xa3, 0xa6, 0xa9, 0xac, 0xaf, 0xb2, 0xb5,
+ 0xb8, 0xbb, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
+ 0xd0, 0xd3, 0xd6, 0xd9, 0xdc, 0xdf, 0xe2, 0xe5,
+ 0xe8, 0xeb, 0xee, 0xf1, 0xf4, 0xf7, 0xfa, 0xfd,
+ 0x00, 0x05, 0x0a, 0x0f, 0x14, 0x19, 0x1e, 0x23,
+ 0x28, 0x2d, 0x32, 0x37, 0x3c, 0x41, 0x46, 0x4b,
+ 0x50, 0x55, 0x5a, 0x5f, 0x64, 0x69, 0x6e, 0x73,
+ 0x78, 0x7d, 0x82, 0x87, 0x8c, 0x91, 0x96, 0x9b,
+ 0xa0, 0xa5, 0xaa, 0xaf, 0xb4, 0xb9, 0xbe, 0xc3,
+ 0xc8, 0xcd, 0xd2, 0xd7, 0xdc, 0xe1, 0xe6, 0xeb,
+ 0xf0, 0xf5, 0xfa, 0xff, 0x04, 0x09, 0x0e, 0x13,
+ 0x18, 0x1d, 0x22, 0x27, 0x2c, 0x31, 0x36, 0x3b,
+ 0x40, 0x45, 0x4a, 0x4f, 0x54, 0x59, 0x5e, 0x63,
+ 0x68, 0x6d, 0x72, 0x77, 0x7c, 0x81, 0x86, 0x8b,
+ 0x90, 0x95, 0x9a, 0x9f, 0xa4, 0xa9, 0xae, 0xb3,
+ 0xb8, 0xbd, 0xc2, 0xc7, 0xcc, 0xd1, 0xd6, 0xdb,
+ 0xe0, 0xe5, 0xea, 0xef, 0xf4, 0xf9, 0xfe, 0x03,
+ 0x08, 0x0d, 0x12, 0x17, 0x1c, 0x21, 0x26, 0x2b,
+ 0x30, 0x35, 0x3a, 0x3f, 0x44, 0x49, 0x4e, 0x53,
+ 0x58, 0x5d, 0x62, 0x67, 0x6c, 0x71, 0x76, 0x7b,
+ 0x80, 0x85, 0x8a, 0x8f, 0x94, 0x99, 0x9e, 0xa3,
+ 0xa8, 0xad, 0xb2, 0xb7, 0xbc, 0xc1, 0xc6, 0xcb,
+ 0xd0, 0xd5, 0xda, 0xdf, 0xe4, 0xe9, 0xee, 0xf3,
+ 0xf8, 0xfd, 0x02, 0x07, 0x0c, 0x11, 0x16, 0x1b,
+ 0x20, 0x25, 0x2a, 0x2f, 0x34, 0x39, 0x3e, 0x43,
+ 0x48, 0x4d, 0x52, 0x57, 0x5c, 0x61, 0x66, 0x6b,
+ 0x70, 0x75, 0x7a, 0x7f, 0x84, 0x89, 0x8e, 0x93,
+ 0x98, 0x9d, 0xa2, 0xa7, 0xac, 0xb1, 0xb6, 0xbb,
+ 0xc0, 0xc5, 0xca, 0xcf, 0xd4, 0xd9, 0xde, 0xe3,
+ 0xe8, 0xed, 0xf2, 0xf7, 0xfc, 0x01, 0x06, 0x0b,
+ 0x10, 0x15, 0x1a, 0x1f, 0x24, 0x29, 0x2e, 0x33,
+ 0x38, 0x3d, 0x42, 0x47, 0x4c, 0x51, 0x56, 0x5b,
+ 0x60, 0x65, 0x6a, 0x6f, 0x74, 0x79, 0x7e, 0x83,
+ 0x88, 0x8d, 0x92, 0x97, 0x9c, 0xa1, 0xa6, 0xab,
+ 0xb0, 0xb5, 0xba, 0xbf, 0xc4, 0xc9, 0xce, 0xd3,
+ 0xd8, 0xdd, 0xe2, 0xe7, 0xec, 0xf1, 0xf6, 0xfb,
+ 0x00, 0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31,
+ 0x38, 0x3f, 0x46, 0x4d, 0x54, 0x5b, 0x62, 0x69,
+ 0x70, 0x77, 0x7e, 0x85, 0x8c, 0x93, 0x9a, 0xa1,
+ 0xa8, 0xaf, 0xb6, 0xbd, 0xc4, 0xcb, 0xd2, 0xd9,
+ 0xe0, 0xe7, 0xee, 0xf5, 0xfc, 0x03, 0x0a, 0x11,
+ 0x18, 0x1f, 0x26, 0x2d, 0x34, 0x3b, 0x42, 0x49,
+ 0x50, 0x57, 0x5e, 0x65, 0x6c, 0x73, 0x7a, 0x81,
+ 0x88, 0x8f, 0x96, 0x9d, 0xa4, 0xab, 0xb2, 0xb9,
+ 0xc0, 0xc7, 0xce, 0xd5, 0xdc, 0xe3, 0xea, 0xf1,
+ 0xf8, 0xff, 0x06, 0x0d, 0x14, 0x1b, 0x22, 0x29,
+ 0x30, 0x37, 0x3e, 0x45, 0x4c, 0x53, 0x5a, 0x61,
+ 0x68, 0x6f, 0x76, 0x7d, 0x84, 0x8b, 0x92, 0x99,
+ 0xa0, 0xa7, 0xae, 0xb5, 0xbc, 0xc3, 0xca, 0xd1,
+ 0xd8, 0xdf, 0xe6, 0xed, 0xf4, 0xfb, 0x02, 0x09,
+ 0x10, 0x17, 0x1e, 0x25, 0x2c, 0x33, 0x3a, 0x41,
+ 0x48, 0x4f, 0x56, 0x5d, 0x64, 0x6b, 0x72, 0x79,
+ 0x80, 0x87, 0x8e, 0x95, 0x9c, 0xa3, 0xaa, 0xb1,
+ 0xb8, 0xbf, 0xc6, 0xcd, 0xd4, 0xdb, 0xe2, 0xe9,
+ 0xf0, 0xf7, 0xfe, 0x05, 0x0c, 0x13, 0x1a, 0x21,
+ 0x28, 0x2f, 0x36, 0x3d, 0x44, 0x4b, 0x52, 0x59,
+ 0x60, 0x67, 0x6e, 0x75, 0x7c, 0x83, 0x8a, 0x91,
+ 0x98, 0x9f, 0xa6, 0xad, 0xb4, 0xbb, 0xc2, 0xc9,
+ 0xd0, 0xd7, 0xde, 0xe5, 0xec, 0xf3, 0xfa, 0x01,
+ 0x08, 0x0f, 0x16, 0x1d, 0x24, 0x2b, 0x32, 0x39,
+ 0x40, 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71,
+ 0x78, 0x7f, 0x86, 0x8d, 0x94, 0x9b, 0xa2, 0xa9,
+ 0xb0, 0xb7, 0xbe, 0xc5, 0xcc, 0xd3, 0xda, 0xe1,
+ 0xe8, 0xef, 0xf6, 0xfd, 0x04, 0x0b, 0x12, 0x19,
+ 0x20, 0x27, 0x2e, 0x35, 0x3c, 0x43, 0x4a, 0x51,
+ 0x58, 0x5f, 0x66, 0x6d, 0x74, 0x7b, 0x82, 0x89,
+ 0x90, 0x97, 0x9e, 0xa5, 0xac, 0xb3, 0xba, 0xc1,
+ 0xc8, 0xcf, 0xd6, 0xdd, 0xe4, 0xeb, 0xf2, 0xf9,
+ 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f,
+ 0x48, 0x51, 0x5a, 0x63, 0x6c, 0x75, 0x7e, 0x87,
+ 0x90, 0x99, 0xa2, 0xab, 0xb4, 0xbd, 0xc6, 0xcf,
+ 0xd8, 0xe1, 0xea, 0xf3, 0xfc, 0x05, 0x0e, 0x17,
+ 0x20, 0x29, 0x32, 0x3b, 0x44, 0x4d, 0x56, 0x5f,
+ 0x68, 0x71, 0x7a, 0x83, 0x8c, 0x95, 0x9e, 0xa7,
+ 0xb0, 0xb9, 0xc2, 0xcb, 0xd4, 0xdd, 0xe6, 0xef,
+ 0xf8, 0x01, 0x0a, 0x13, 0x1c, 0x25, 0x2e, 0x37,
+ 0x40, 0x49, 0x52, 0x5b, 0x64, 0x6d, 0x76, 0x7f,
+ 0x88, 0x91, 0x9a, 0xa3, 0xac, 0xb5, 0xbe, 0xc7,
+ 0xd0, 0xd9, 0xe2, 0xeb, 0xf4, 0xfd, 0x06, 0x0f,
+ 0x18, 0x21, 0x2a, 0x33, 0x3c, 0x45, 0x4e, 0x57,
+ 0x60, 0x69, 0x72, 0x7b, 0x84, 0x8d, 0x96, 0x9f,
+ 0xa8, 0xb1, 0xba, 0xc3, 0xcc, 0xd5, 0xde, 0xe7,
+ 0xf0, 0xf9, 0x02, 0x0b, 0x14, 0x1d, 0x26, 0x2f,
+ 0x38, 0x41, 0x4a, 0x53, 0x5c, 0x65, 0x6e, 0x77,
+ 0x80, 0x89, 0x92, 0x9b, 0xa4, 0xad, 0xb6, 0xbf,
+ 0xc8, 0xd1, 0xda, 0xe3, 0xec, 0xf5, 0xfe, 0x07,
+ 0x10, 0x19, 0x22, 0x2b, 0x34, 0x3d, 0x46, 0x4f,
+ 0x58, 0x61, 0x6a, 0x73, 0x7c, 0x85, 0x8e, 0x97,
+ 0xa0, 0xa9, 0xb2, 0xbb, 0xc4, 0xcd, 0xd6, 0xdf,
+ 0xe8, 0xf1, 0xfa, 0x03, 0x0c, 0x15, 0x1e, 0x27,
+ 0x30, 0x39, 0x42, 0x4b, 0x54, 0x5d, 0x66, 0x6f,
+ 0x78, 0x81, 0x8a, 0x93, 0x9c, 0xa5, 0xae, 0xb7,
+ 0xc0, 0xc9, 0xd2, 0xdb, 0xe4, 0xed, 0xf6, 0xff,
+ 0x08, 0x11, 0x1a, 0x23, 0x2c, 0x35, 0x3e, 0x47,
+ 0x50, 0x59, 0x62, 0x6b, 0x74, 0x7d, 0x86, 0x8f,
+ 0x98, 0xa1, 0xaa, 0xb3, 0xbc, 0xc5, 0xce, 0xd7,
+ 0xe0, 0xe9, 0xf2, 0xfb, 0x04, 0x0d, 0x16, 0x1f,
+ 0x28, 0x31, 0x3a, 0x43, 0x4c, 0x55, 0x5e, 0x67,
+ 0x70, 0x79, 0x82, 0x8b, 0x94, 0x9d, 0xa6, 0xaf,
+ 0xb8, 0xc1, 0xca, 0xd3, 0xdc, 0xe5, 0xee, 0xf7,
+ 0x00, 0x0b, 0x16, 0x21, 0x2c, 0x37, 0x42, 0x4d,
+ 0x58, 0x63, 0x6e, 0x79, 0x84, 0x8f, 0x9a, 0xa5,
+ 0xb0, 0xbb, 0xc6, 0xd1, 0xdc, 0xe7, 0xf2, 0xfd,
+ 0x08, 0x13, 0x1e, 0x29, 0x34, 0x3f, 0x4a, 0x55,
+ 0x60, 0x6b, 0x76, 0x81, 0x8c, 0x97, 0xa2, 0xad,
+ 0xb8, 0xc3, 0xce, 0xd9, 0xe4, 0xef, 0xfa, 0x05,
+ 0x10, 0x1b, 0x26, 0x31, 0x3c, 0x47, 0x52, 0x5d,
+ 0x68, 0x73, 0x7e, 0x89, 0x94, 0x9f, 0xaa, 0xb5,
+ 0xc0, 0xcb, 0xd6, 0xe1, 0xec, 0xf7, 0x02, 0x0d,
+ 0x18, 0x23, 0x2e, 0x39, 0x44, 0x4f, 0x5a, 0x65,
+ 0x70, 0x7b, 0x86, 0x91, 0x9c, 0xa7, 0xb2, 0xbd,
+ 0xc8, 0xd3, 0xde, 0xe9, 0xf4, 0xff, 0x0a, 0x15,
+ 0x20, 0x2b, 0x36, 0x41, 0x4c, 0x57, 0x62, 0x6d,
+ 0x78, 0x83, 0x8e, 0x99, 0xa4, 0xaf, 0xba, 0xc5,
+ 0xd0, 0xdb, 0xe6, 0xf1, 0xfc, 0x07, 0x12, 0x1d,
+ 0x28, 0x33, 0x3e, 0x49, 0x54, 0x5f, 0x6a, 0x75,
+ 0x80, 0x8b, 0x96, 0xa1, 0xac, 0xb7, 0xc2, 0xcd,
+ 0xd8, 0xe3, 0xee, 0xf9, 0x04, 0x0f, 0x1a, 0x25,
+ 0x30, 0x3b, 0x46, 0x51, 0x5c, 0x67, 0x72, 0x7d,
+ 0x88, 0x93, 0x9e, 0xa9, 0xb4, 0xbf, 0xca, 0xd5,
+ 0xe0, 0xeb, 0xf6, 0x01, 0x0c, 0x17, 0x22, 0x2d,
+ 0x38, 0x43, 0x4e, 0x59, 0x64, 0x6f, 0x7a, 0x85,
+ 0x90, 0x9b, 0xa6, 0xb1, 0xbc, 0xc7, 0xd2, 0xdd,
+ 0xe8, 0xf3, 0xfe, 0x09, 0x14, 0x1f, 0x2a, 0x35,
+ 0x40, 0x4b, 0x56, 0x61, 0x6c, 0x77, 0x82, 0x8d,
+ 0x98, 0xa3, 0xae, 0xb9, 0xc4, 0xcf, 0xda, 0xe5,
+ 0xf0, 0xfb, 0x06, 0x11, 0x1c, 0x27, 0x32, 0x3d,
+ 0x48, 0x53, 0x5e, 0x69, 0x74, 0x7f, 0x8a, 0x95,
+ 0xa0, 0xab, 0xb6, 0xc1, 0xcc, 0xd7, 0xe2, 0xed,
+ 0xf8, 0x03, 0x0e, 0x19, 0x24, 0x2f, 0x3a, 0x45,
+ 0x50, 0x5b, 0x66, 0x71, 0x7c, 0x87, 0x92, 0x9d,
+ 0xa8, 0xb3, 0xbe, 0xc9, 0xd4, 0xdf, 0xea, 0xf5,
+ 0x00, 0x0d, 0x1a, 0x27, 0x34, 0x41, 0x4e, 0x5b,
+ 0x68, 0x75, 0x82, 0x8f, 0x9c, 0xa9, 0xb6, 0xc3,
+ 0xd0, 0xdd, 0xea, 0xf7, 0x04, 0x11, 0x1e, 0x2b,
+ 0x38, 0x45, 0x52, 0x5f, 0x6c, 0x79, 0x86, 0x93,
+ 0xa0, 0xad, 0xba, 0xc7, 0xd4, 0xe1, 0xee, 0xfb,
+ 0x08, 0x15, 0x22, 0x2f, 0x3c, 0x49, 0x56, 0x63,
+ 0x70, 0x7d, 0x8a, 0x97, 0xa4, 0xb1, 0xbe, 0xcb,
+ 0xd8, 0xe5, 0xf2, 0xff, 0x0c, 0x19, 0x26, 0x33,
+ 0x40, 0x4d, 0x5a, 0x67, 0x74, 0x81, 0x8e, 0x9b,
+ 0xa8, 0xb5, 0xc2, 0xcf, 0xdc, 0xe9, 0xf6, 0x03,
+ 0x10, 0x1d, 0x2a, 0x37, 0x44, 0x51, 0x5e, 0x6b,
+ 0x78, 0x85, 0x92, 0x9f, 0xac, 0xb9, 0xc6, 0xd3,
+ 0xe0, 0xed, 0xfa, 0x07, 0x14, 0x21, 0x2e, 0x3b,
+ 0x48, 0x55, 0x62, 0x6f, 0x7c, 0x89, 0x96, 0xa3,
+ 0xb0, 0xbd, 0xca, 0xd7, 0xe4, 0xf1, 0xfe, 0x0b,
+ 0x18, 0x25, 0x32, 0x3f, 0x4c, 0x59, 0x66, 0x73,
+ 0x80, 0x8d, 0x9a, 0xa7, 0xb4, 0xc1, 0xce, 0xdb,
+ 0xe8, 0xf5, 0x02, 0x0f, 0x1c, 0x29, 0x36, 0x43,
+ 0x50, 0x5d, 0x6a, 0x77, 0x84, 0x91, 0x9e, 0xab,
+ 0xb8, 0xc5, 0xd2, 0xdf, 0xec, 0xf9, 0x06, 0x13,
+ 0x20, 0x2d, 0x3a, 0x47, 0x54, 0x61, 0x6e, 0x7b,
+ 0x88, 0x95, 0xa2, 0xaf, 0xbc, 0xc9, 0xd6, 0xe3,
+ 0xf0, 0xfd, 0x0a, 0x17, 0x24, 0x31, 0x3e, 0x4b,
+ 0x58, 0x65, 0x72, 0x7f, 0x8c, 0x99, 0xa6, 0xb3,
+ 0xc0, 0xcd, 0xda, 0xe7, 0xf4, 0x01, 0x0e, 0x1b,
+ 0x28, 0x35, 0x42, 0x4f, 0x5c, 0x69, 0x76, 0x83,
+ 0x90, 0x9d, 0xaa, 0xb7, 0xc4, 0xd1, 0xde, 0xeb,
+ 0xf8, 0x05, 0x12, 0x1f, 0x2c, 0x39, 0x46, 0x53,
+ 0x60, 0x6d, 0x7a, 0x87, 0x94, 0xa1, 0xae, 0xbb,
+ 0xc8, 0xd5, 0xe2, 0xef, 0xfc, 0x09, 0x16, 0x23,
+ 0x30, 0x3d, 0x4a, 0x57, 0x64, 0x71, 0x7e, 0x8b,
+ 0x98, 0xa5, 0xb2, 0xbf, 0xcc, 0xd9, 0xe6, 0xf3,
+ 0x00, 0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69,
+ 0x78, 0x87, 0x96, 0xa5, 0xb4, 0xc3, 0xd2, 0xe1,
+ 0xf0, 0xff, 0x0e, 0x1d, 0x2c, 0x3b, 0x4a, 0x59,
+ 0x68, 0x77, 0x86, 0x95, 0xa4, 0xb3, 0xc2, 0xd1,
+ 0xe0, 0xef, 0xfe, 0x0d, 0x1c, 0x2b, 0x3a, 0x49,
+ 0x58, 0x67, 0x76, 0x85, 0x94, 0xa3, 0xb2, 0xc1,
+ 0xd0, 0xdf, 0xee, 0xfd, 0x0c, 0x1b, 0x2a, 0x39,
+ 0x48, 0x57, 0x66, 0x75, 0x84, 0x93, 0xa2, 0xb1,
+ 0xc0, 0xcf, 0xde, 0xed, 0xfc, 0x0b, 0x1a, 0x29,
+ 0x38, 0x47, 0x56, 0x65, 0x74, 0x83, 0x92, 0xa1,
+ 0xb0, 0xbf, 0xce, 0xdd, 0xec, 0xfb, 0x0a, 0x19,
+ 0x28, 0x37, 0x46, 0x55, 0x64, 0x73, 0x82, 0x91,
+ 0xa0, 0xaf, 0xbe, 0xcd, 0xdc, 0xeb, 0xfa, 0x09,
+ 0x18, 0x27, 0x36, 0x45, 0x54, 0x63, 0x72, 0x81,
+ 0x90, 0x9f, 0xae, 0xbd, 0xcc, 0xdb, 0xea, 0xf9,
+ 0x08, 0x17, 0x26, 0x35, 0x44, 0x53, 0x62, 0x71,
+ 0x80, 0x8f, 0x9e, 0xad, 0xbc, 0xcb, 0xda, 0xe9,
+ 0xf8, 0x07, 0x16, 0x25, 0x34, 0x43, 0x52, 0x61,
+ 0x70, 0x7f, 0x8e, 0x9d, 0xac, 0xbb, 0xca, 0xd9,
+ 0xe8, 0xf7, 0x06, 0x15, 0x24, 0x33, 0x42, 0x51,
+ 0x60, 0x6f, 0x7e, 0x8d, 0x9c, 0xab, 0xba, 0xc9,
+ 0xd8, 0xe7, 0xf6, 0x05, 0x14, 0x23, 0x32, 0x41,
+ 0x50, 0x5f, 0x6e, 0x7d, 0x8c, 0x9b, 0xaa, 0xb9,
+ 0xc8, 0xd7, 0xe6, 0xf5, 0x04, 0x13, 0x22, 0x31,
+ 0x40, 0x4f, 0x5e, 0x6d, 0x7c, 0x8b, 0x9a, 0xa9,
+ 0xb8, 0xc7, 0xd6, 0xe5, 0xf4, 0x03, 0x12, 0x21,
+ 0x30, 0x3f, 0x4e, 0x5d, 0x6c, 0x7b, 0x8a, 0x99,
+ 0xa8, 0xb7, 0xc6, 0xd5, 0xe4, 0xf3, 0x02, 0x11,
+ 0x20, 0x2f, 0x3e, 0x4d, 0x5c, 0x6b, 0x7a, 0x89,
+ 0x98, 0xa7, 0xb6, 0xc5, 0xd4, 0xe3, 0xf2, 0x01,
+ 0x10, 0x1f, 0x2e, 0x3d, 0x4c, 0x5b, 0x6a, 0x79,
+ 0x88, 0x97, 0xa6, 0xb5, 0xc4, 0xd3, 0xe2, 0xf1,
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
+ 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87,
+ 0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0x0f,
+ 0x20, 0x31, 0x42, 0x53, 0x64, 0x75, 0x86, 0x97,
+ 0xa8, 0xb9, 0xca, 0xdb, 0xec, 0xfd, 0x0e, 0x1f,
+ 0x30, 0x41, 0x52, 0x63, 0x74, 0x85, 0x96, 0xa7,
+ 0xb8, 0xc9, 0xda, 0xeb, 0xfc, 0x0d, 0x1e, 0x2f,
+ 0x40, 0x51, 0x62, 0x73, 0x84, 0x95, 0xa6, 0xb7,
+ 0xc8, 0xd9, 0xea, 0xfb, 0x0c, 0x1d, 0x2e, 0x3f,
+ 0x50, 0x61, 0x72, 0x83, 0x94, 0xa5, 0xb6, 0xc7,
+ 0xd8, 0xe9, 0xfa, 0x0b, 0x1c, 0x2d, 0x3e, 0x4f,
+ 0x60, 0x71, 0x82, 0x93, 0xa4, 0xb5, 0xc6, 0xd7,
+ 0xe8, 0xf9, 0x0a, 0x1b, 0x2c, 0x3d, 0x4e, 0x5f,
+ 0x70, 0x81, 0x92, 0xa3, 0xb4, 0xc5, 0xd6, 0xe7,
+ 0xf8, 0x09, 0x1a, 0x2b, 0x3c, 0x4d, 0x5e, 0x6f,
+ 0x80, 0x91, 0xa2, 0xb3, 0xc4, 0xd5, 0xe6, 0xf7,
+ 0x08, 0x19, 0x2a, 0x3b, 0x4c, 0x5d, 0x6e, 0x7f,
+ 0x90, 0xa1, 0xb2, 0xc3, 0xd4, 0xe5, 0xf6, 0x07,
+ 0x18, 0x29, 0x3a, 0x4b, 0x5c, 0x6d, 0x7e, 0x8f,
+ 0xa0, 0xb1, 0xc2, 0xd3, 0xe4, 0xf5, 0x06, 0x17,
+ 0x28, 0x39, 0x4a, 0x5b, 0x6c, 0x7d, 0x8e, 0x9f,
+ 0xb0, 0xc1, 0xd2, 0xe3, 0xf4, 0x05, 0x16, 0x27,
+ 0x38, 0x49, 0x5a, 0x6b, 0x7c, 0x8d, 0x9e, 0xaf,
+ 0xc0, 0xd1, 0xe2, 0xf3, 0x04, 0x15, 0x26, 0x37,
+ 0x48, 0x59, 0x6a, 0x7b, 0x8c, 0x9d, 0xae, 0xbf,
+ 0xd0, 0xe1, 0xf2, 0x03, 0x14, 0x25, 0x36, 0x47,
+ 0x58, 0x69, 0x7a, 0x8b, 0x9c, 0xad, 0xbe, 0xcf,
+ 0xe0, 0xf1, 0x02, 0x13, 0x24, 0x35, 0x46, 0x57,
+ 0x68, 0x79, 0x8a, 0x9b, 0xac, 0xbd, 0xce, 0xdf,
+ 0xf0, 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67,
+ 0x78, 0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef,
+ 0x00, 0x13, 0x26, 0x39, 0x4c, 0x5f, 0x72, 0x85,
+ 0x98, 0xab, 0xbe, 0xd1, 0xe4, 0xf7, 0x0a, 0x1d,
+ 0x30, 0x43, 0x56, 0x69, 0x7c, 0x8f, 0xa2, 0xb5,
+ 0xc8, 0xdb, 0xee, 0x01, 0x14, 0x27, 0x3a, 0x4d,
+ 0x60, 0x73, 0x86, 0x99, 0xac, 0xbf, 0xd2, 0xe5,
+ 0xf8, 0x0b, 0x1e, 0x31, 0x44, 0x57, 0x6a, 0x7d,
+ 0x90, 0xa3, 0xb6, 0xc9, 0xdc, 0xef, 0x02, 0x15,
+ 0x28, 0x3b, 0x4e, 0x61, 0x74, 0x87, 0x9a, 0xad,
+ 0xc0, 0xd3, 0xe6, 0xf9, 0x0c, 0x1f, 0x32, 0x45,
+ 0x58, 0x6b, 0x7e, 0x91, 0xa4, 0xb7, 0xca, 0xdd,
+ 0xf0, 0x03, 0x16, 0x29, 0x3c, 0x4f, 0x62, 0x75,
+ 0x88, 0x9b, 0xae, 0xc1, 0xd4, 0xe7, 0xfa, 0x0d,
+ 0x20, 0x33, 0x46, 0x59, 0x6c, 0x7f, 0x92, 0xa5,
+ 0xb8, 0xcb, 0xde, 0xf1, 0x04, 0x17, 0x2a, 0x3d,
+ 0x50, 0x63, 0x76, 0x89, 0x9c, 0xaf, 0xc2, 0xd5,
+ 0xe8, 0xfb, 0x0e, 0x21, 0x34, 0x47, 0x5a, 0x6d,
+ 0x80, 0x93, 0xa6, 0xb9, 0xcc, 0xdf, 0xf2, 0x05,
+ 0x18, 0x2b, 0x3e, 0x51, 0x64, 0x77, 0x8a, 0x9d,
+ 0xb0, 0xc3, 0xd6, 0xe9, 0xfc, 0x0f, 0x22, 0x35,
+ 0x48, 0x5b, 0x6e, 0x81, 0x94, 0xa7, 0xba, 0xcd,
+ 0xe0, 0xf3, 0x06, 0x19, 0x2c, 0x3f, 0x52, 0x65,
+ 0x78, 0x8b, 0x9e, 0xb1, 0xc4, 0xd7, 0xea, 0xfd,
+ 0x10, 0x23, 0x36, 0x49, 0x5c, 0x6f, 0x82, 0x95,
+ 0xa8, 0xbb, 0xce, 0xe1, 0xf4, 0x07, 0x1a, 0x2d,
+ 0x40, 0x53, 0x66, 0x79, 0x8c, 0x9f, 0xb2, 0xc5,
+ 0xd8, 0xeb, 0xfe, 0x11, 0x24, 0x37, 0x4a, 0x5d,
+ 0x70, 0x83, 0x96, 0xa9, 0xbc, 0xcf, 0xe2, 0xf5,
+ 0x08, 0x1b, 0x2e, 0x41, 0x54, 0x67, 0x7a, 0x8d,
+ 0xa0, 0xb3, 0xc6, 0xd9, 0xec, 0xff, 0x12, 0x25,
+ 0x38, 0x4b, 0x5e, 0x71, 0x84, 0x97, 0xaa, 0xbd,
+ 0xd0, 0xe3, 0xf6, 0x09, 0x1c, 0x2f, 0x42, 0x55,
+ 0x68, 0x7b, 0x8e, 0xa1, 0xb4, 0xc7, 0xda, 0xed,
+ 0x00, 0x15, 0x2a, 0x3f, 0x54, 0x69, 0x7e, 0x93,
+ 0xa8, 0xbd, 0xd2, 0xe7, 0xfc, 0x11, 0x26, 0x3b,
+ 0x50, 0x65, 0x7a, 0x8f, 0xa4, 0xb9, 0xce, 0xe3,
+ 0xf8, 0x0d, 0x22, 0x37, 0x4c, 0x61, 0x76, 0x8b,
+ 0xa0, 0xb5, 0xca, 0xdf, 0xf4, 0x09, 0x1e, 0x33,
+ 0x48, 0x5d, 0x72, 0x87, 0x9c, 0xb1, 0xc6, 0xdb,
+ 0xf0, 0x05, 0x1a, 0x2f, 0x44, 0x59, 0x6e, 0x83,
+ 0x98, 0xad, 0xc2, 0xd7, 0xec, 0x01, 0x16, 0x2b,
+ 0x40, 0x55, 0x6a, 0x7f, 0x94, 0xa9, 0xbe, 0xd3,
+ 0xe8, 0xfd, 0x12, 0x27, 0x3c, 0x51, 0x66, 0x7b,
+ 0x90, 0xa5, 0xba, 0xcf, 0xe4, 0xf9, 0x0e, 0x23,
+ 0x38, 0x4d, 0x62, 0x77, 0x8c, 0xa1, 0xb6, 0xcb,
+ 0xe0, 0xf5, 0x0a, 0x1f, 0x34, 0x49, 0x5e, 0x73,
+ 0x88, 0x9d, 0xb2, 0xc7, 0xdc, 0xf1, 0x06, 0x1b,
+ 0x30, 0x45, 0x5a, 0x6f, 0x84, 0x99, 0xae, 0xc3,
+ 0xd8, 0xed, 0x02, 0x17, 0x2c, 0x41, 0x56, 0x6b,
+ 0x80, 0x95, 0xaa, 0xbf, 0xd4, 0xe9, 0xfe, 0x13,
+ 0x28, 0x3d, 0x52, 0x67, 0x7c, 0x91, 0xa6, 0xbb,
+ 0xd0, 0xe5, 0xfa, 0x0f, 0x24, 0x39, 0x4e, 0x63,
+ 0x78, 0x8d, 0xa2, 0xb7, 0xcc, 0xe1, 0xf6, 0x0b,
+ 0x20, 0x35, 0x4a, 0x5f, 0x74, 0x89, 0x9e, 0xb3,
+ 0xc8, 0xdd, 0xf2, 0x07, 0x1c, 0x31, 0x46, 0x5b,
+ 0x70, 0x85, 0x9a, 0xaf, 0xc4, 0xd9, 0xee, 0x03,
+ 0x18, 0x2d, 0x42, 0x57, 0x6c, 0x81, 0x96, 0xab,
+ 0xc0, 0xd5, 0xea, 0xff, 0x14, 0x29, 0x3e, 0x53,
+ 0x68, 0x7d, 0x92, 0xa7, 0xbc, 0xd1, 0xe6, 0xfb,
+ 0x10, 0x25, 0x3a, 0x4f, 0x64, 0x79, 0x8e, 0xa3,
+ 0xb8, 0xcd, 0xe2, 0xf7, 0x0c, 0x21, 0x36, 0x4b,
+ 0x60, 0x75, 0x8a, 0x9f, 0xb4, 0xc9, 0xde, 0xf3,
+ 0x08, 0x1d, 0x32, 0x47, 0x5c, 0x71, 0x86, 0x9b,
+ 0xb0, 0xc5, 0xda, 0xef, 0x04, 0x19, 0x2e, 0x43,
+ 0x58, 0x6d, 0x82, 0x97, 0xac, 0xc1, 0xd6, 0xeb,
+ 0x00, 0x17, 0x2e, 0x45, 0x5c, 0x73, 0x8a, 0xa1,
+ 0xb8, 0xcf, 0xe6, 0xfd, 0x14, 0x2b, 0x42, 0x59,
+ 0x70, 0x87, 0x9e, 0xb5, 0xcc, 0xe3, 0xfa, 0x11,
+ 0x28, 0x3f, 0x56, 0x6d, 0x84, 0x9b, 0xb2, 0xc9,
+ 0xe0, 0xf7, 0x0e, 0x25, 0x3c, 0x53, 0x6a, 0x81,
+ 0x98, 0xaf, 0xc6, 0xdd, 0xf4, 0x0b, 0x22, 0x39,
+ 0x50, 0x67, 0x7e, 0x95, 0xac, 0xc3, 0xda, 0xf1,
+ 0x08, 0x1f, 0x36, 0x4d, 0x64, 0x7b, 0x92, 0xa9,
+ 0xc0, 0xd7, 0xee, 0x05, 0x1c, 0x33, 0x4a, 0x61,
+ 0x78, 0x8f, 0xa6, 0xbd, 0xd4, 0xeb, 0x02, 0x19,
+ 0x30, 0x47, 0x5e, 0x75, 0x8c, 0xa3, 0xba, 0xd1,
+ 0xe8, 0xff, 0x16, 0x2d, 0x44, 0x5b, 0x72, 0x89,
+ 0xa0, 0xb7, 0xce, 0xe5, 0xfc, 0x13, 0x2a, 0x41,
+ 0x58, 0x6f, 0x86, 0x9d, 0xb4, 0xcb, 0xe2, 0xf9,
+ 0x10, 0x27, 0x3e, 0x55, 0x6c, 0x83, 0x9a, 0xb1,
+ 0xc8, 0xdf, 0xf6, 0x0d, 0x24, 0x3b, 0x52, 0x69,
+ 0x80, 0x97, 0xae, 0xc5, 0xdc, 0xf3, 0x0a, 0x21,
+ 0x38, 0x4f, 0x66, 0x7d, 0x94, 0xab, 0xc2, 0xd9,
+ 0xf0, 0x07, 0x1e, 0x35, 0x4c, 0x63, 0x7a, 0x91,
+ 0xa8, 0xbf, 0xd6, 0xed, 0x04, 0x1b, 0x32, 0x49,
+ 0x60, 0x77, 0x8e, 0xa5, 0xbc, 0xd3, 0xea, 0x01,
+ 0x18, 0x2f, 0x46, 0x5d, 0x74, 0x8b, 0xa2, 0xb9,
+ 0xd0, 0xe7, 0xfe, 0x15, 0x2c, 0x43, 0x5a, 0x71,
+ 0x88, 0x9f, 0xb6, 0xcd, 0xe4, 0xfb, 0x12, 0x29,
+ 0x40, 0x57, 0x6e, 0x85, 0x9c, 0xb3, 0xca, 0xe1,
+ 0xf8, 0x0f, 0x26, 0x3d, 0x54, 0x6b, 0x82, 0x99,
+ 0xb0, 0xc7, 0xde, 0xf5, 0x0c, 0x23, 0x3a, 0x51,
+ 0x68, 0x7f, 0x96, 0xad, 0xc4, 0xdb, 0xf2, 0x09,
+ 0x20, 0x37, 0x4e, 0x65, 0x7c, 0x93, 0xaa, 0xc1,
+ 0xd8, 0xef, 0x06, 0x1d, 0x34, 0x4b, 0x62, 0x79,
+ 0x90, 0xa7, 0xbe, 0xd5, 0xec, 0x03, 0x1a, 0x31,
+ 0x48, 0x5f, 0x76, 0x8d, 0xa4, 0xbb, 0xd2, 0xe9,
+ 0x00, 0x19, 0x32, 0x4b, 0x64, 0x7d, 0x96, 0xaf,
+ 0xc8, 0xe1, 0xfa, 0x13, 0x2c, 0x45, 0x5e, 0x77,
+ 0x90, 0xa9, 0xc2, 0xdb, 0xf4, 0x0d, 0x26, 0x3f,
+ 0x58, 0x71, 0x8a, 0xa3, 0xbc, 0xd5, 0xee, 0x07,
+ 0x20, 0x39, 0x52, 0x6b, 0x84, 0x9d, 0xb6, 0xcf,
+ 0xe8, 0x01, 0x1a, 0x33, 0x4c, 0x65, 0x7e, 0x97,
+ 0xb0, 0xc9, 0xe2, 0xfb, 0x14, 0x2d, 0x46, 0x5f,
+ 0x78, 0x91, 0xaa, 0xc3, 0xdc, 0xf5, 0x0e, 0x27,
+ 0x40, 0x59, 0x72, 0x8b, 0xa4, 0xbd, 0xd6, 0xef,
+ 0x08, 0x21, 0x3a, 0x53, 0x6c, 0x85, 0x9e, 0xb7,
+ 0xd0, 0xe9, 0x02, 0x1b, 0x34, 0x4d, 0x66, 0x7f,
+ 0x98, 0xb1, 0xca, 0xe3, 0xfc, 0x15, 0x2e, 0x47,
+ 0x60, 0x79, 0x92, 0xab, 0xc4, 0xdd, 0xf6, 0x0f,
+ 0x28, 0x41, 0x5a, 0x73, 0x8c, 0xa5, 0xbe, 0xd7,
+ 0xf0, 0x09, 0x22, 0x3b, 0x54, 0x6d, 0x86, 0x9f,
+ 0xb8, 0xd1, 0xea, 0x03, 0x1c, 0x35, 0x4e, 0x67,
+ 0x80, 0x99, 0xb2, 0xcb, 0xe4, 0xfd, 0x16, 0x2f,
+ 0x48, 0x61, 0x7a, 0x93, 0xac, 0xc5, 0xde, 0xf7,
+ 0x10, 0x29, 0x42, 0x5b, 0x74, 0x8d, 0xa6, 0xbf,
+ 0xd8, 0xf1, 0x0a, 0x23, 0x3c, 0x55, 0x6e, 0x87,
+ 0xa0, 0xb9, 0xd2, 0xeb, 0x04, 0x1d, 0x36, 0x4f,
+ 0x68, 0x81, 0x9a, 0xb3, 0xcc, 0xe5, 0xfe, 0x17,
+ 0x30, 0x49, 0x62, 0x7b, 0x94, 0xad, 0xc6, 0xdf,
+ 0xf8, 0x11, 0x2a, 0x43, 0x5c, 0x75, 0x8e, 0xa7,
+ 0xc0, 0xd9, 0xf2, 0x0b, 0x24, 0x3d, 0x56, 0x6f,
+ 0x88, 0xa1, 0xba, 0xd3, 0xec, 0x05, 0x1e, 0x37,
+ 0x50, 0x69, 0x82, 0x9b, 0xb4, 0xcd, 0xe6, 0xff,
+ 0x18, 0x31, 0x4a, 0x63, 0x7c, 0x95, 0xae, 0xc7,
+ 0xe0, 0xf9, 0x12, 0x2b, 0x44, 0x5d, 0x76, 0x8f,
+ 0xa8, 0xc1, 0xda, 0xf3, 0x0c, 0x25, 0x3e, 0x57,
+ 0x70, 0x89, 0xa2, 0xbb, 0xd4, 0xed, 0x06, 0x1f,
+ 0x38, 0x51, 0x6a, 0x83, 0x9c, 0xb5, 0xce, 0xe7,
+ 0x00, 0x1b, 0x36, 0x51, 0x6c, 0x87, 0xa2, 0xbd,
+ 0xd8, 0xf3, 0x0e, 0x29, 0x44, 0x5f, 0x7a, 0x95,
+ 0xb0, 0xcb, 0xe6, 0x01, 0x1c, 0x37, 0x52, 0x6d,
+ 0x88, 0xa3, 0xbe, 0xd9, 0xf4, 0x0f, 0x2a, 0x45,
+ 0x60, 0x7b, 0x96, 0xb1, 0xcc, 0xe7, 0x02, 0x1d,
+ 0x38, 0x53, 0x6e, 0x89, 0xa4, 0xbf, 0xda, 0xf5,
+ 0x10, 0x2b, 0x46, 0x61, 0x7c, 0x97, 0xb2, 0xcd,
+ 0xe8, 0x03, 0x1e, 0x39, 0x54, 0x6f, 0x8a, 0xa5,
+ 0xc0, 0xdb, 0xf6, 0x11, 0x2c, 0x47, 0x62, 0x7d,
+ 0x98, 0xb3, 0xce, 0xe9, 0x04, 0x1f, 0x3a, 0x55,
+ 0x70, 0x8b, 0xa6, 0xc1, 0xdc, 0xf7, 0x12, 0x2d,
+ 0x48, 0x63, 0x7e, 0x99, 0xb4, 0xcf, 0xea, 0x05,
+ 0x20, 0x3b, 0x56, 0x71, 0x8c, 0xa7, 0xc2, 0xdd,
+ 0xf8, 0x13, 0x2e, 0x49, 0x64, 0x7f, 0x9a, 0xb5,
+ 0xd0, 0xeb, 0x06, 0x21, 0x3c, 0x57, 0x72, 0x8d,
+ 0xa8, 0xc3, 0xde, 0xf9, 0x14, 0x2f, 0x4a, 0x65,
+ 0x80, 0x9b, 0xb6, 0xd1, 0xec, 0x07, 0x22, 0x3d,
+ 0x58, 0x73, 0x8e, 0xa9, 0xc4, 0xdf, 0xfa, 0x15,
+ 0x30, 0x4b, 0x66, 0x81, 0x9c, 0xb7, 0xd2, 0xed,
+ 0x08, 0x23, 0x3e, 0x59, 0x74, 0x8f, 0xaa, 0xc5,
+ 0xe0, 0xfb, 0x16, 0x31, 0x4c, 0x67, 0x82, 0x9d,
+ 0xb8, 0xd3, 0xee, 0x09, 0x24, 0x3f, 0x5a, 0x75,
+ 0x90, 0xab, 0xc6, 0xe1, 0xfc, 0x17, 0x32, 0x4d,
+ 0x68, 0x83, 0x9e, 0xb9, 0xd4, 0xef, 0x0a, 0x25,
+ 0x40, 0x5b, 0x76, 0x91, 0xac, 0xc7, 0xe2, 0xfd,
+ 0x18, 0x33, 0x4e, 0x69, 0x84, 0x9f, 0xba, 0xd5,
+ 0xf0, 0x0b, 0x26, 0x41, 0x5c, 0x77, 0x92, 0xad,
+ 0xc8, 0xe3, 0xfe, 0x19, 0x34, 0x4f, 0x6a, 0x85,
+ 0xa0, 0xbb, 0xd6, 0xf1, 0x0c, 0x27, 0x42, 0x5d,
+ 0x78, 0x93, 0xae, 0xc9, 0xe4, 0xff, 0x1a, 0x35,
+ 0x50, 0x6b, 0x86, 0xa1, 0xbc, 0xd7, 0xf2, 0x0d,
+ 0x28, 0x43, 0x5e, 0x79, 0x94, 0xaf, 0xca, 0xe5,
+ 0x00, 0x1d, 0x3a, 0x57, 0x74, 0x91, 0xae, 0xcb,
+ 0xe8, 0x05, 0x22, 0x3f, 0x5c, 0x79, 0x96, 0xb3,
+ 0xd0, 0xed, 0x0a, 0x27, 0x44, 0x61, 0x7e, 0x9b,
+ 0xb8, 0xd5, 0xf2, 0x0f, 0x2c, 0x49, 0x66, 0x83,
+ 0xa0, 0xbd, 0xda, 0xf7, 0x14, 0x31, 0x4e, 0x6b,
+ 0x88, 0xa5, 0xc2, 0xdf, 0xfc, 0x19, 0x36, 0x53,
+ 0x70, 0x8d, 0xaa, 0xc7, 0xe4, 0x01, 0x1e, 0x3b,
+ 0x58, 0x75, 0x92, 0xaf, 0xcc, 0xe9, 0x06, 0x23,
+ 0x40, 0x5d, 0x7a, 0x97, 0xb4, 0xd1, 0xee, 0x0b,
+ 0x28, 0x45, 0x62, 0x7f, 0x9c, 0xb9, 0xd6, 0xf3,
+ 0x10, 0x2d, 0x4a, 0x67, 0x84, 0xa1, 0xbe, 0xdb,
+ 0xf8, 0x15, 0x32, 0x4f, 0x6c, 0x89, 0xa6, 0xc3,
+ 0xe0, 0xfd, 0x1a, 0x37, 0x54, 0x71, 0x8e, 0xab,
+ 0xc8, 0xe5, 0x02, 0x1f, 0x3c, 0x59, 0x76, 0x93,
+ 0xb0, 0xcd, 0xea, 0x07, 0x24, 0x41, 0x5e, 0x7b,
+ 0x98, 0xb5, 0xd2, 0xef, 0x0c, 0x29, 0x46, 0x63,
+ 0x80, 0x9d, 0xba, 0xd7, 0xf4, 0x11, 0x2e, 0x4b,
+ 0x68, 0x85, 0xa2, 0xbf, 0xdc, 0xf9, 0x16, 0x33,
+ 0x50, 0x6d, 0x8a, 0xa7, 0xc4, 0xe1, 0xfe, 0x1b,
+ 0x38, 0x55, 0x72, 0x8f, 0xac, 0xc9, 0xe6, 0x03,
+ 0x20, 0x3d, 0x5a, 0x77, 0x94, 0xb1, 0xce, 0xeb,
+ 0x08, 0x25, 0x42, 0x5f, 0x7c, 0x99, 0xb6, 0xd3,
+ 0xf0, 0x0d, 0x2a, 0x47, 0x64, 0x81, 0x9e, 0xbb,
+ 0xd8, 0xf5, 0x12, 0x2f, 0x4c, 0x69, 0x86, 0xa3,
+ 0xc0, 0xdd, 0xfa, 0x17, 0x34, 0x51, 0x6e, 0x8b,
+ 0xa8, 0xc5, 0xe2, 0xff, 0x1c, 0x39, 0x56, 0x73,
+ 0x90, 0xad, 0xca, 0xe7, 0x04, 0x21, 0x3e, 0x5b,
+ 0x78, 0x95, 0xb2, 0xcf, 0xec, 0x09, 0x26, 0x43,
+ 0x60, 0x7d, 0x9a, 0xb7, 0xd4, 0xf1, 0x0e, 0x2b,
+ 0x48, 0x65, 0x82, 0x9f, 0xbc, 0xd9, 0xf6, 0x13,
+ 0x30, 0x4d, 0x6a, 0x87, 0xa4, 0xc1, 0xde, 0xfb,
+ 0x18, 0x35, 0x52, 0x6f, 0x8c, 0xa9, 0xc6, 0xe3,
+ 0x00, 0x1f, 0x3e, 0x5d, 0x7c, 0x9b, 0xba, 0xd9,
+ 0xf8, 0x17, 0x36, 0x55, 0x74, 0x93, 0xb2, 0xd1,
+ 0xf0, 0x0f, 0x2e, 0x4d, 0x6c, 0x8b, 0xaa, 0xc9,
+ 0xe8, 0x07, 0x26, 0x45, 0x64, 0x83, 0xa2, 0xc1,
+ 0xe0, 0xff, 0x1e, 0x3d, 0x5c, 0x7b, 0x9a, 0xb9,
+ 0xd8, 0xf7, 0x16, 0x35, 0x54, 0x73, 0x92, 0xb1,
+ 0xd0, 0xef, 0x0e, 0x2d, 0x4c, 0x6b, 0x8a, 0xa9,
+ 0xc8, 0xe7, 0x06, 0x25, 0x44, 0x63, 0x82, 0xa1,
+ 0xc0, 0xdf, 0xfe, 0x1d, 0x3c, 0x5b, 0x7a, 0x99,
+ 0xb8, 0xd7, 0xf6, 0x15, 0x34, 0x53, 0x72, 0x91,
+ 0xb0, 0xcf, 0xee, 0x0d, 0x2c, 0x4b, 0x6a, 0x89,
+ 0xa8, 0xc7, 0xe6, 0x05, 0x24, 0x43, 0x62, 0x81,
+ 0xa0, 0xbf, 0xde, 0xfd, 0x1c, 0x3b, 0x5a, 0x79,
+ 0x98, 0xb7, 0xd6, 0xf5, 0x14, 0x33, 0x52, 0x71,
+ 0x90, 0xaf, 0xce, 0xed, 0x0c, 0x2b, 0x4a, 0x69,
+ 0x88, 0xa7, 0xc6, 0xe5, 0x04, 0x23, 0x42, 0x61,
+ 0x80, 0x9f, 0xbe, 0xdd, 0xfc, 0x1b, 0x3a, 0x59,
+ 0x78, 0x97, 0xb6, 0xd5, 0xf4, 0x13, 0x32, 0x51,
+ 0x70, 0x8f, 0xae, 0xcd, 0xec, 0x0b, 0x2a, 0x49,
+ 0x68, 0x87, 0xa6, 0xc5, 0xe4, 0x03, 0x22, 0x41,
+ 0x60, 0x7f, 0x9e, 0xbd, 0xdc, 0xfb, 0x1a, 0x39,
+ 0x58, 0x77, 0x96, 0xb5, 0xd4, 0xf3, 0x12, 0x31,
+ 0x50, 0x6f, 0x8e, 0xad, 0xcc, 0xeb, 0x0a, 0x29,
+ 0x48, 0x67, 0x86, 0xa5, 0xc4, 0xe3, 0x02, 0x21,
+ 0x40, 0x5f, 0x7e, 0x9d, 0xbc, 0xdb, 0xfa, 0x19,
+ 0x38, 0x57, 0x76, 0x95, 0xb4, 0xd3, 0xf2, 0x11,
+ 0x30, 0x4f, 0x6e, 0x8d, 0xac, 0xcb, 0xea, 0x09,
+ 0x28, 0x47, 0x66, 0x85, 0xa4, 0xc3, 0xe2, 0x01,
+ 0x20, 0x3f, 0x5e, 0x7d, 0x9c, 0xbb, 0xda, 0xf9,
+ 0x18, 0x37, 0x56, 0x75, 0x94, 0xb3, 0xd2, 0xf1,
+ 0x10, 0x2f, 0x4e, 0x6d, 0x8c, 0xab, 0xca, 0xe9,
+ 0x08, 0x27, 0x46, 0x65, 0x84, 0xa3, 0xc2, 0xe1,
+ 0x00, 0x21, 0x42, 0x63,
+ },
+ .ilen = 4100,
+ .result = {
+ 0xb5, 0x81, 0xf5, 0x64, 0x18, 0x73, 0xe3, 0xf0,
+ 0x4c, 0x13, 0xf2, 0x77, 0x18, 0x60, 0x65, 0x5e,
+ 0x29, 0x01, 0xce, 0x98, 0x55, 0x53, 0xf9, 0x0c,
+ 0x2a, 0x08, 0xd5, 0x09, 0xb3, 0x57, 0x55, 0x56,
+ 0xc5, 0xe9, 0x56, 0x90, 0xcb, 0x6a, 0xa3, 0xc0,
+ 0xff, 0xc4, 0x79, 0xb4, 0xd2, 0x97, 0x5d, 0xc4,
+ 0x43, 0xd1, 0xfe, 0x94, 0x7b, 0x88, 0x06, 0x5a,
+ 0xb2, 0x9e, 0x2c, 0xfc, 0x44, 0x03, 0xb7, 0x90,
+ 0xa0, 0xc1, 0xba, 0x6a, 0x33, 0xb8, 0xc7, 0xb2,
+ 0x9d, 0xe1, 0x12, 0x4f, 0xc0, 0x64, 0xd4, 0x01,
+ 0xfe, 0x8c, 0x7a, 0x66, 0xf7, 0xe6, 0x5a, 0x91,
+ 0xbb, 0xde, 0x56, 0x86, 0xab, 0x65, 0x21, 0x30,
+ 0x00, 0x84, 0x65, 0x24, 0xa5, 0x7d, 0x85, 0xb4,
+ 0xe3, 0x17, 0xed, 0x3a, 0xb7, 0x6f, 0xb4, 0x0b,
+ 0x0b, 0xaf, 0x15, 0xae, 0x5a, 0x8f, 0xf2, 0x0c,
+ 0x2f, 0x27, 0xf4, 0x09, 0xd8, 0xd2, 0x96, 0xb7,
+ 0x71, 0xf2, 0xc5, 0x99, 0x4d, 0x7e, 0x7f, 0x75,
+ 0x77, 0x89, 0x30, 0x8b, 0x59, 0xdb, 0xa2, 0xb2,
+ 0xa0, 0xf3, 0x19, 0x39, 0x2b, 0xc5, 0x7e, 0x3f,
+ 0x4f, 0xd9, 0xd3, 0x56, 0x28, 0x97, 0x44, 0xdc,
+ 0xc0, 0x8b, 0x77, 0x24, 0xd9, 0x52, 0xe7, 0xc5,
+ 0xaf, 0xf6, 0x7d, 0x59, 0xb2, 0x44, 0x05, 0x1d,
+ 0xb1, 0xb0, 0x11, 0xa5, 0x0f, 0xec, 0x33, 0xe1,
+ 0x6d, 0x1b, 0x4e, 0x1f, 0xff, 0x57, 0x91, 0xb4,
+ 0x5b, 0x9a, 0x96, 0xc5, 0x53, 0xbc, 0xae, 0x20,
+ 0x3c, 0xbb, 0x14, 0xe2, 0xe8, 0x22, 0x33, 0xc1,
+ 0x5e, 0x76, 0x9e, 0x46, 0x99, 0xf6, 0x2a, 0x15,
+ 0xc6, 0x97, 0x02, 0xa0, 0x66, 0x43, 0xd1, 0xa6,
+ 0x31, 0xa6, 0x9f, 0xfb, 0xf4, 0xd3, 0x69, 0xe5,
+ 0xcd, 0x76, 0x95, 0xb8, 0x7a, 0x82, 0x7f, 0x21,
+ 0x45, 0xff, 0x3f, 0xce, 0x55, 0xf6, 0x95, 0x10,
+ 0x08, 0x77, 0x10, 0x43, 0xc6, 0xf3, 0x09, 0xe5,
+ 0x68, 0xe7, 0x3c, 0xad, 0x00, 0x52, 0x45, 0x0d,
+ 0xfe, 0x2d, 0xc6, 0xc2, 0x94, 0x8c, 0x12, 0x1d,
+ 0xe6, 0x25, 0xae, 0x98, 0x12, 0x8e, 0x19, 0x9c,
+ 0x81, 0x68, 0xb1, 0x11, 0xf6, 0x69, 0xda, 0xe3,
+ 0x62, 0x08, 0x18, 0x7a, 0x25, 0x49, 0x28, 0xac,
+ 0xba, 0x71, 0x12, 0x0b, 0xe4, 0xa2, 0xe5, 0xc7,
+ 0x5d, 0x8e, 0xec, 0x49, 0x40, 0x21, 0xbf, 0x5a,
+ 0x98, 0xf3, 0x02, 0x68, 0x55, 0x03, 0x7f, 0x8a,
+ 0xe5, 0x94, 0x0c, 0x32, 0x5c, 0x07, 0x82, 0x63,
+ 0xaf, 0x6f, 0x91, 0x40, 0x84, 0x8e, 0x52, 0x25,
+ 0xd0, 0xb0, 0x29, 0x53, 0x05, 0xe2, 0x50, 0x7a,
+ 0x34, 0xeb, 0xc9, 0x46, 0x20, 0xa8, 0x3d, 0xde,
+ 0x7f, 0x16, 0x5f, 0x36, 0xc5, 0x2e, 0xdc, 0xd1,
+ 0x15, 0x47, 0xc7, 0x50, 0x40, 0x6d, 0x91, 0xc5,
+ 0xe7, 0x93, 0x95, 0x1a, 0xd3, 0x57, 0xbc, 0x52,
+ 0x33, 0xee, 0x14, 0x19, 0x22, 0x52, 0x89, 0xa7,
+ 0x4a, 0x25, 0x56, 0x77, 0x4b, 0xca, 0xcf, 0x0a,
+ 0xe1, 0xf5, 0x35, 0x85, 0x30, 0x7e, 0x59, 0x4a,
+ 0xbd, 0x14, 0x5b, 0xdf, 0xe3, 0x46, 0xcb, 0xac,
+ 0x1f, 0x6c, 0x96, 0x0e, 0xf4, 0x81, 0xd1, 0x99,
+ 0xca, 0x88, 0x63, 0x3d, 0x02, 0x58, 0x6b, 0xa9,
+ 0xe5, 0x9f, 0xb3, 0x00, 0xb2, 0x54, 0xc6, 0x74,
+ 0x1c, 0xbf, 0x46, 0xab, 0x97, 0xcc, 0xf8, 0x54,
+ 0x04, 0x07, 0x08, 0x52, 0xe6, 0xc0, 0xda, 0x93,
+ 0x74, 0x7d, 0x93, 0x99, 0x5d, 0x78, 0x68, 0xa6,
+ 0x2e, 0x6b, 0xd3, 0x6a, 0x69, 0xcc, 0x12, 0x6b,
+ 0xd4, 0xc7, 0xa5, 0xc6, 0xe7, 0xf6, 0x03, 0x04,
+ 0x5d, 0xcd, 0x61, 0x5e, 0x17, 0x40, 0xdc, 0xd1,
+ 0x5c, 0xf5, 0x08, 0xdf, 0x5c, 0x90, 0x85, 0xa4,
+ 0xaf, 0xf6, 0x78, 0xbb, 0x0d, 0xf1, 0xf4, 0xa4,
+ 0x54, 0x26, 0x72, 0x9e, 0x61, 0xfa, 0x86, 0xcf,
+ 0xe8, 0x9e, 0xa1, 0xe0, 0xc7, 0x48, 0x23, 0xae,
+ 0x5a, 0x90, 0xae, 0x75, 0x0a, 0x74, 0x18, 0x89,
+ 0x05, 0xb1, 0x92, 0xb2, 0x7f, 0xd0, 0x1b, 0xa6,
+ 0x62, 0x07, 0x25, 0x01, 0xc7, 0xc2, 0x4f, 0xf9,
+ 0xe8, 0xfe, 0x63, 0x95, 0x80, 0x07, 0xb4, 0x26,
+ 0xcc, 0xd1, 0x26, 0xb6, 0xc4, 0x3f, 0x9e, 0xcb,
+ 0x8e, 0x3b, 0x2e, 0x44, 0x16, 0xd3, 0x10, 0x9a,
+ 0x95, 0x08, 0xeb, 0xc8, 0xcb, 0xeb, 0xbf, 0x6f,
+ 0x0b, 0xcd, 0x1f, 0xc8, 0xca, 0x86, 0xaa, 0xec,
+ 0x33, 0xe6, 0x69, 0xf4, 0x45, 0x25, 0x86, 0x3a,
+ 0x22, 0x94, 0x4f, 0x00, 0x23, 0x6a, 0x44, 0xc2,
+ 0x49, 0x97, 0x33, 0xab, 0x36, 0x14, 0x0a, 0x70,
+ 0x24, 0xc3, 0xbe, 0x04, 0x3b, 0x79, 0xa0, 0xf9,
+ 0xb8, 0xe7, 0x76, 0x29, 0x22, 0x83, 0xd7, 0xf2,
+ 0x94, 0xf4, 0x41, 0x49, 0xba, 0x5f, 0x7b, 0x07,
+ 0xb5, 0xfb, 0xdb, 0x03, 0x1a, 0x9f, 0xb6, 0x4c,
+ 0xc2, 0x2e, 0x37, 0x40, 0x49, 0xc3, 0x38, 0x16,
+ 0xe2, 0x4f, 0x77, 0x82, 0xb0, 0x68, 0x4c, 0x71,
+ 0x1d, 0x57, 0x61, 0x9c, 0xd9, 0x4e, 0x54, 0x99,
+ 0x47, 0x13, 0x28, 0x73, 0x3c, 0xbb, 0x00, 0x90,
+ 0xf3, 0x4d, 0xc9, 0x0e, 0xfd, 0xe7, 0xb1, 0x71,
+ 0xd3, 0x15, 0x79, 0xbf, 0xcc, 0x26, 0x2f, 0xbd,
+ 0xad, 0x6c, 0x50, 0x69, 0x6c, 0x3e, 0x6d, 0x80,
+ 0x9a, 0xea, 0x78, 0xaf, 0x19, 0xb2, 0x0d, 0x4d,
+ 0xad, 0x04, 0x07, 0xae, 0x22, 0x90, 0x4a, 0x93,
+ 0x32, 0x0e, 0x36, 0x9b, 0x1b, 0x46, 0xba, 0x3b,
+ 0xb4, 0xac, 0xc6, 0xd1, 0xa2, 0x31, 0x53, 0x3b,
+ 0x2a, 0x3d, 0x45, 0xfe, 0x03, 0x61, 0x10, 0x85,
+ 0x17, 0x69, 0xa6, 0x78, 0xcc, 0x6c, 0x87, 0x49,
+ 0x53, 0xf9, 0x80, 0x10, 0xde, 0x80, 0xa2, 0x41,
+ 0x6a, 0xc3, 0x32, 0x02, 0xad, 0x6d, 0x3c, 0x56,
+ 0x00, 0x71, 0x51, 0x06, 0xa7, 0xbd, 0xfb, 0xef,
+ 0x3c, 0xb5, 0x9f, 0xfc, 0x48, 0x7d, 0x53, 0x7c,
+ 0x66, 0xb0, 0x49, 0x23, 0xc4, 0x47, 0x10, 0x0e,
+ 0xe5, 0x6c, 0x74, 0x13, 0xe6, 0xc5, 0x3f, 0xaa,
+ 0xde, 0xff, 0x07, 0x44, 0xdd, 0x56, 0x1b, 0xad,
+ 0x09, 0x77, 0xfb, 0x5b, 0x12, 0xb8, 0x0d, 0x38,
+ 0x17, 0x37, 0x35, 0x7b, 0x9b, 0xbc, 0xfe, 0xd4,
+ 0x7e, 0x8b, 0xda, 0x7e, 0x5b, 0x04, 0xa7, 0x22,
+ 0xa7, 0x31, 0xa1, 0x20, 0x86, 0xc7, 0x1b, 0x99,
+ 0xdb, 0xd1, 0x89, 0xf4, 0x94, 0xa3, 0x53, 0x69,
+ 0x8d, 0xe7, 0xe8, 0x74, 0x11, 0x8d, 0x74, 0xd6,
+ 0x07, 0x37, 0x91, 0x9f, 0xfd, 0x67, 0x50, 0x3a,
+ 0xc9, 0xe1, 0xf4, 0x36, 0xd5, 0xa0, 0x47, 0xd1,
+ 0xf9, 0xe5, 0x39, 0xa3, 0x31, 0xac, 0x07, 0x36,
+ 0x23, 0xf8, 0x66, 0x18, 0x14, 0x28, 0x34, 0x0f,
+ 0xb8, 0xd0, 0xe7, 0x29, 0xb3, 0x04, 0x4b, 0x55,
+ 0x01, 0x41, 0xb2, 0x75, 0x8d, 0xcb, 0x96, 0x85,
+ 0x3a, 0xfb, 0xab, 0x2b, 0x9e, 0xfa, 0x58, 0x20,
+ 0x44, 0x1f, 0xc0, 0x14, 0x22, 0x75, 0x61, 0xe8,
+ 0xaa, 0x19, 0xcf, 0xf1, 0x82, 0x56, 0xf4, 0xd7,
+ 0x78, 0x7b, 0x3d, 0x5f, 0xb3, 0x9e, 0x0b, 0x8a,
+ 0x57, 0x50, 0xdb, 0x17, 0x41, 0x65, 0x4d, 0xa3,
+ 0x02, 0xc9, 0x9c, 0x9c, 0x53, 0xfb, 0x39, 0x39,
+ 0x9b, 0x1d, 0x72, 0x24, 0xda, 0xb7, 0x39, 0xbe,
+ 0x13, 0x3b, 0xfa, 0x29, 0xda, 0x9e, 0x54, 0x64,
+ 0x6e, 0xba, 0xd8, 0xa1, 0xcb, 0xb3, 0x36, 0xfa,
+ 0xcb, 0x47, 0x85, 0xe9, 0x61, 0x38, 0xbc, 0xbe,
+ 0xc5, 0x00, 0x38, 0x2a, 0x54, 0xf7, 0xc4, 0xb9,
+ 0xb3, 0xd3, 0x7b, 0xa0, 0xa0, 0xf8, 0x72, 0x7f,
+ 0x8c, 0x8e, 0x82, 0x0e, 0xc6, 0x1c, 0x75, 0x9d,
+ 0xca, 0x8e, 0x61, 0x87, 0xde, 0xad, 0x80, 0xd2,
+ 0xf5, 0xf9, 0x80, 0xef, 0x15, 0x75, 0xaf, 0xf5,
+ 0x80, 0xfb, 0xff, 0x6d, 0x1e, 0x25, 0xb7, 0x40,
+ 0x61, 0x6a, 0x39, 0x5a, 0x6a, 0xb5, 0x31, 0xab,
+ 0x97, 0x8a, 0x19, 0x89, 0x44, 0x40, 0xc0, 0xa6,
+ 0xb4, 0x4e, 0x30, 0x32, 0x7b, 0x13, 0xe7, 0x67,
+ 0xa9, 0x8b, 0x57, 0x04, 0xc2, 0x01, 0xa6, 0xf4,
+ 0x28, 0x99, 0xad, 0x2c, 0x76, 0xa3, 0x78, 0xc2,
+ 0x4a, 0xe6, 0xca, 0x5c, 0x50, 0x6a, 0xc1, 0xb0,
+ 0x62, 0x4b, 0x10, 0x8e, 0x7c, 0x17, 0x43, 0xb3,
+ 0x17, 0x66, 0x1c, 0x3e, 0x8d, 0x69, 0xf0, 0x5a,
+ 0x71, 0xf5, 0x97, 0xdc, 0xd1, 0x45, 0xdd, 0x28,
+ 0xf3, 0x5d, 0xdf, 0x53, 0x7b, 0x11, 0xe5, 0xbc,
+ 0x4c, 0xdb, 0x1b, 0x51, 0x6b, 0xe9, 0xfb, 0x3d,
+ 0xc1, 0xc3, 0x2c, 0xb9, 0x71, 0xf5, 0xb6, 0xb2,
+ 0x13, 0x36, 0x79, 0x80, 0x53, 0xe8, 0xd3, 0xa6,
+ 0x0a, 0xaf, 0xfd, 0x56, 0x97, 0xf7, 0x40, 0x8e,
+ 0x45, 0xce, 0xf8, 0xb0, 0x9e, 0x5c, 0x33, 0x82,
+ 0xb0, 0x44, 0x56, 0xfc, 0x05, 0x09, 0xe9, 0x2a,
+ 0xac, 0x26, 0x80, 0x14, 0x1d, 0xc8, 0x3a, 0x35,
+ 0x4c, 0x82, 0x97, 0xfd, 0x76, 0xb7, 0xa9, 0x0a,
+ 0x35, 0x58, 0x79, 0x8e, 0x0f, 0x66, 0xea, 0xaf,
+ 0x51, 0x6c, 0x09, 0xa9, 0x6e, 0x9b, 0xcb, 0x9a,
+ 0x31, 0x47, 0xa0, 0x2f, 0x7c, 0x71, 0xb4, 0x4a,
+ 0x11, 0xaa, 0x8c, 0x66, 0xc5, 0x64, 0xe6, 0x3a,
+ 0x54, 0xda, 0x24, 0x6a, 0xc4, 0x41, 0x65, 0x46,
+ 0x82, 0xa0, 0x0a, 0x0f, 0x5f, 0xfb, 0x25, 0xd0,
+ 0x2c, 0x91, 0xa7, 0xee, 0xc4, 0x81, 0x07, 0x86,
+ 0x75, 0x5e, 0x33, 0x69, 0x97, 0xe4, 0x2c, 0xa8,
+ 0x9d, 0x9f, 0x0b, 0x6a, 0xbe, 0xad, 0x98, 0xda,
+ 0x6d, 0x94, 0x41, 0xda, 0x2c, 0x1e, 0x89, 0xc4,
+ 0xc2, 0xaf, 0x1e, 0x00, 0x05, 0x0b, 0x83, 0x60,
+ 0xbd, 0x43, 0xea, 0x15, 0x23, 0x7f, 0xb9, 0xac,
+ 0xee, 0x4f, 0x2c, 0xaf, 0x2a, 0xf3, 0xdf, 0xd0,
+ 0xf3, 0x19, 0x31, 0xbb, 0x4a, 0x74, 0x84, 0x17,
+ 0x52, 0x32, 0x2c, 0x7d, 0x61, 0xe4, 0xcb, 0xeb,
+ 0x80, 0x38, 0x15, 0x52, 0xcb, 0x6f, 0xea, 0xe5,
+ 0x73, 0x9c, 0xd9, 0x24, 0x69, 0xc6, 0x95, 0x32,
+ 0x21, 0xc8, 0x11, 0xe4, 0xdc, 0x36, 0xd7, 0x93,
+ 0x38, 0x66, 0xfb, 0xb2, 0x7f, 0x3a, 0xb9, 0xaf,
+ 0x31, 0xdd, 0x93, 0x75, 0x78, 0x8a, 0x2c, 0x94,
+ 0x87, 0x1a, 0x58, 0xec, 0x9e, 0x7d, 0x4d, 0xba,
+ 0xe1, 0xe5, 0x4d, 0xfc, 0xbc, 0xa4, 0x2a, 0x14,
+ 0xef, 0xcc, 0xa7, 0xec, 0xab, 0x43, 0x09, 0x18,
+ 0xd3, 0xab, 0x68, 0xd1, 0x07, 0x99, 0x44, 0x47,
+ 0xd6, 0x83, 0x85, 0x3b, 0x30, 0xea, 0xa9, 0x6b,
+ 0x63, 0xea, 0xc4, 0x07, 0xfb, 0x43, 0x2f, 0xa4,
+ 0xaa, 0xb0, 0xab, 0x03, 0x89, 0xce, 0x3f, 0x8c,
+ 0x02, 0x7c, 0x86, 0x54, 0xbc, 0x88, 0xaf, 0x75,
+ 0xd2, 0xdc, 0x63, 0x17, 0xd3, 0x26, 0xf6, 0x96,
+ 0xa9, 0x3c, 0xf1, 0x61, 0x8c, 0x11, 0x18, 0xcc,
+ 0xd6, 0xea, 0x5b, 0xe2, 0xcd, 0xf0, 0xf1, 0xb2,
+ 0xe5, 0x35, 0x90, 0x1f, 0x85, 0x4c, 0x76, 0x5b,
+ 0x66, 0xce, 0x44, 0xa4, 0x32, 0x9f, 0xe6, 0x7b,
+ 0x71, 0x6e, 0x9f, 0x58, 0x15, 0x67, 0x72, 0x87,
+ 0x64, 0x8e, 0x3a, 0x44, 0x45, 0xd4, 0x76, 0xfa,
+ 0xc2, 0xf6, 0xef, 0x85, 0x05, 0x18, 0x7a, 0x9b,
+ 0xba, 0x41, 0x54, 0xac, 0xf0, 0xfc, 0x59, 0x12,
+ 0x3f, 0xdf, 0xa0, 0xe5, 0x8a, 0x65, 0xfd, 0x3a,
+ 0x62, 0x8d, 0x83, 0x2c, 0x03, 0xbe, 0x05, 0x76,
+ 0x2e, 0x53, 0x49, 0x97, 0x94, 0x33, 0xae, 0x40,
+ 0x81, 0x15, 0xdb, 0x6e, 0xad, 0xaa, 0xf5, 0x4b,
+ 0xe3, 0x98, 0x70, 0xdf, 0xe0, 0x7c, 0xcd, 0xdb,
+ 0x02, 0xd4, 0x7d, 0x2f, 0xc1, 0xe6, 0xb4, 0xf3,
+ 0xd7, 0x0d, 0x7a, 0xd9, 0x23, 0x9e, 0x87, 0x2d,
+ 0xce, 0x87, 0xad, 0xcc, 0x72, 0x05, 0x00, 0x29,
+ 0xdc, 0x73, 0x7f, 0x64, 0xc1, 0x15, 0x0e, 0xc2,
+ 0xdf, 0xa7, 0x5f, 0xeb, 0x41, 0xa1, 0xcd, 0xef,
+ 0x5c, 0x50, 0x79, 0x2a, 0x56, 0x56, 0x71, 0x8c,
+ 0xac, 0xc0, 0x79, 0x50, 0x69, 0xca, 0x59, 0x32,
+ 0x65, 0xf2, 0x54, 0xe4, 0x52, 0x38, 0x76, 0xd1,
+ 0x5e, 0xde, 0x26, 0x9e, 0xfb, 0x75, 0x2e, 0x11,
+ 0xb5, 0x10, 0xf4, 0x17, 0x73, 0xf5, 0x89, 0xc7,
+ 0x4f, 0x43, 0x5c, 0x8e, 0x7c, 0xb9, 0x05, 0x52,
+ 0x24, 0x40, 0x99, 0xfe, 0x9b, 0x85, 0x0b, 0x6c,
+ 0x22, 0x3e, 0x8b, 0xae, 0x86, 0xa1, 0xd2, 0x79,
+ 0x05, 0x68, 0x6b, 0xab, 0xe3, 0x41, 0x49, 0xed,
+ 0x15, 0xa1, 0x8d, 0x40, 0x2d, 0x61, 0xdf, 0x1a,
+ 0x59, 0xc9, 0x26, 0x8b, 0xef, 0x30, 0x4c, 0x88,
+ 0x4b, 0x10, 0xf8, 0x8d, 0xa6, 0x92, 0x9f, 0x4b,
+ 0xf3, 0xc4, 0x53, 0x0b, 0x89, 0x5d, 0x28, 0x92,
+ 0xcf, 0x78, 0xb2, 0xc0, 0x5d, 0xed, 0x7e, 0xfc,
+ 0xc0, 0x12, 0x23, 0x5f, 0x5a, 0x78, 0x86, 0x43,
+ 0x6e, 0x27, 0xf7, 0x5a, 0xa7, 0x6a, 0xed, 0x19,
+ 0x04, 0xf0, 0xb3, 0x12, 0xd1, 0xbd, 0x0e, 0x89,
+ 0x6e, 0xbc, 0x96, 0xa8, 0xd8, 0x49, 0x39, 0x9f,
+ 0x7e, 0x67, 0xf0, 0x2e, 0x3e, 0x01, 0xa9, 0xba,
+ 0xec, 0x8b, 0x62, 0x8e, 0xcb, 0x4a, 0x70, 0x43,
+ 0xc7, 0xc2, 0xc4, 0xca, 0x82, 0x03, 0x73, 0xe9,
+ 0x11, 0xdf, 0xcf, 0x54, 0xea, 0xc9, 0xb0, 0x95,
+ 0x51, 0xc0, 0x13, 0x3d, 0x92, 0x05, 0xfa, 0xf4,
+ 0xa9, 0x34, 0xc8, 0xce, 0x6c, 0x3d, 0x54, 0xcc,
+ 0xc4, 0xaf, 0xf1, 0xdc, 0x11, 0x44, 0x26, 0xa2,
+ 0xaf, 0xf1, 0x85, 0x75, 0x7d, 0x03, 0x61, 0x68,
+ 0x4e, 0x78, 0xc6, 0x92, 0x7d, 0x86, 0x7d, 0x77,
+ 0xdc, 0x71, 0x72, 0xdb, 0xc6, 0xae, 0xa1, 0xcb,
+ 0x70, 0x9a, 0x0b, 0x19, 0xbe, 0x4a, 0x6c, 0x2a,
+ 0xe2, 0xba, 0x6c, 0x64, 0x9a, 0x13, 0x28, 0xdf,
+ 0x85, 0x75, 0xe6, 0x43, 0xf6, 0x87, 0x08, 0x68,
+ 0x6e, 0xba, 0x6e, 0x79, 0x9f, 0x04, 0xbc, 0x23,
+ 0x50, 0xf6, 0x33, 0x5c, 0x1f, 0x24, 0x25, 0xbe,
+ 0x33, 0x47, 0x80, 0x45, 0x56, 0xa3, 0xa7, 0xd7,
+ 0x7a, 0xb1, 0x34, 0x0b, 0x90, 0x3c, 0x9c, 0xad,
+ 0x44, 0x5f, 0x9e, 0x0e, 0x9d, 0xd4, 0xbd, 0x93,
+ 0x5e, 0xfa, 0x3c, 0xe0, 0xb0, 0xd9, 0xed, 0xf3,
+ 0xd6, 0x2e, 0xff, 0x24, 0xd8, 0x71, 0x6c, 0xed,
+ 0xaf, 0x55, 0xeb, 0x22, 0xac, 0x93, 0x68, 0x32,
+ 0x05, 0x5b, 0x47, 0xdd, 0xc6, 0x4a, 0xcb, 0xc7,
+ 0x10, 0xe1, 0x3c, 0x92, 0x1a, 0xf3, 0x23, 0x78,
+ 0x2b, 0xa1, 0xd2, 0x80, 0xf4, 0x12, 0xb1, 0x20,
+ 0x8f, 0xff, 0x26, 0x35, 0xdd, 0xfb, 0xc7, 0x4e,
+ 0x78, 0xf1, 0x2d, 0x50, 0x12, 0x77, 0xa8, 0x60,
+ 0x7c, 0x0f, 0xf5, 0x16, 0x2f, 0x63, 0x70, 0x2a,
+ 0xc0, 0x96, 0x80, 0x4e, 0x0a, 0xb4, 0x93, 0x35,
+ 0x5d, 0x1d, 0x3f, 0x56, 0xf7, 0x2f, 0xbb, 0x90,
+ 0x11, 0x16, 0x8f, 0xa2, 0xec, 0x47, 0xbe, 0xac,
+ 0x56, 0x01, 0x26, 0x56, 0xb1, 0x8c, 0xb2, 0x10,
+ 0xf9, 0x1a, 0xca, 0xf5, 0xd1, 0xb7, 0x39, 0x20,
+ 0x63, 0xf1, 0x69, 0x20, 0x4f, 0x13, 0x12, 0x1f,
+ 0x5b, 0x65, 0xfc, 0x98, 0xf7, 0xc4, 0x7a, 0xbe,
+ 0xf7, 0x26, 0x4d, 0x2b, 0x84, 0x7b, 0x42, 0xad,
+ 0xd8, 0x7a, 0x0a, 0xb4, 0xd8, 0x74, 0xbf, 0xc1,
+ 0xf0, 0x6e, 0xb4, 0x29, 0xa3, 0xbb, 0xca, 0x46,
+ 0x67, 0x70, 0x6a, 0x2d, 0xce, 0x0e, 0xa2, 0x8a,
+ 0xa9, 0x87, 0xbf, 0x05, 0xc4, 0xc1, 0x04, 0xa3,
+ 0xab, 0xd4, 0x45, 0x43, 0x8c, 0xb6, 0x02, 0xb0,
+ 0x41, 0xc8, 0xfc, 0x44, 0x3d, 0x59, 0xaa, 0x2e,
+ 0x44, 0x21, 0x2a, 0x8d, 0x88, 0x9d, 0x57, 0xf4,
+ 0xa0, 0x02, 0x77, 0xb8, 0xa6, 0xa0, 0xe6, 0x75,
+ 0x5c, 0x82, 0x65, 0x3e, 0x03, 0x5c, 0x29, 0x8f,
+ 0x38, 0x55, 0xab, 0x33, 0x26, 0xef, 0x9f, 0x43,
+ 0x52, 0xfd, 0x68, 0xaf, 0x36, 0xb4, 0xbb, 0x9a,
+ 0x58, 0x09, 0x09, 0x1b, 0xc3, 0x65, 0x46, 0x46,
+ 0x1d, 0xa7, 0x94, 0x18, 0x23, 0x50, 0x2c, 0xca,
+ 0x2c, 0x55, 0x19, 0x97, 0x01, 0x9d, 0x93, 0x3b,
+ 0x63, 0x86, 0xf2, 0x03, 0x67, 0x45, 0xd2, 0x72,
+ 0x28, 0x52, 0x6c, 0xf4, 0xe3, 0x1c, 0xb5, 0x11,
+ 0x13, 0xf1, 0xeb, 0x21, 0xc7, 0xd9, 0x56, 0x82,
+ 0x2b, 0x82, 0x39, 0xbd, 0x69, 0x54, 0xed, 0x62,
+ 0xc3, 0xe2, 0xde, 0x73, 0xd4, 0x6a, 0x12, 0xae,
+ 0x13, 0x21, 0x7f, 0x4b, 0x5b, 0xfc, 0xbf, 0xe8,
+ 0x2b, 0xbe, 0x56, 0xba, 0x68, 0x8b, 0x9a, 0xb1,
+ 0x6e, 0xfa, 0xbf, 0x7e, 0x5a, 0x4b, 0xf1, 0xac,
+ 0x98, 0x65, 0x85, 0xd1, 0x93, 0x53, 0xd3, 0x7b,
+ 0x09, 0xdd, 0x4b, 0x10, 0x6d, 0x84, 0xb0, 0x13,
+ 0x65, 0xbd, 0xcf, 0x52, 0x09, 0xc4, 0x85, 0xe2,
+ 0x84, 0x74, 0x15, 0x65, 0xb7, 0xf7, 0x51, 0xaf,
+ 0x55, 0xad, 0xa4, 0xd1, 0x22, 0x54, 0x70, 0x94,
+ 0xa0, 0x1c, 0x90, 0x41, 0xfd, 0x99, 0xd7, 0x5a,
+ 0x31, 0xef, 0xaa, 0x25, 0xd0, 0x7f, 0x4f, 0xea,
+ 0x1d, 0x55, 0x42, 0xe5, 0x49, 0xb0, 0xd0, 0x46,
+ 0x62, 0x36, 0x43, 0xb2, 0x82, 0x15, 0x75, 0x50,
+ 0xa4, 0x72, 0xeb, 0x54, 0x27, 0x1f, 0x8a, 0xe4,
+ 0x7d, 0xe9, 0x66, 0xc5, 0xf1, 0x53, 0xa4, 0xd1,
+ 0x0c, 0xeb, 0xb8, 0xf8, 0xbc, 0xd4, 0xe2, 0xe7,
+ 0xe1, 0xf8, 0x4b, 0xcb, 0xa9, 0xa1, 0xaf, 0x15,
+ 0x83, 0xcb, 0x72, 0xd0, 0x33, 0x79, 0x00, 0x2d,
+ 0x9f, 0xd7, 0xf1, 0x2e, 0x1e, 0x10, 0xe4, 0x45,
+ 0xc0, 0x75, 0x3a, 0x39, 0xea, 0x68, 0xf7, 0x5d,
+ 0x1b, 0x73, 0x8f, 0xe9, 0x8e, 0x0f, 0x72, 0x47,
+ 0xae, 0x35, 0x0a, 0x31, 0x7a, 0x14, 0x4d, 0x4a,
+ 0x6f, 0x47, 0xf7, 0x7e, 0x91, 0x6e, 0x74, 0x8b,
+ 0x26, 0x47, 0xf9, 0xc3, 0xf9, 0xde, 0x70, 0xf5,
+ 0x61, 0xab, 0xa9, 0x27, 0x9f, 0x82, 0xe4, 0x9c,
+ 0x89, 0x91, 0x3f, 0x2e, 0x6a, 0xfd, 0xb5, 0x49,
+ 0xe9, 0xfd, 0x59, 0x14, 0x36, 0x49, 0x40, 0x6d,
+ 0x32, 0xd8, 0x85, 0x42, 0xf3, 0xa5, 0xdf, 0x0c,
+ 0xa8, 0x27, 0xd7, 0x54, 0xe2, 0x63, 0x2f, 0xf2,
+ 0x7e, 0x8b, 0x8b, 0xe7, 0xf1, 0x9a, 0x95, 0x35,
+ 0x43, 0xdc, 0x3a, 0xe4, 0xb6, 0xf4, 0xd0, 0xdf,
+ 0x9c, 0xcb, 0x94, 0xf3, 0x21, 0xa0, 0x77, 0x50,
+ 0xe2, 0xc6, 0xc4, 0xc6, 0x5f, 0x09, 0x64, 0x5b,
+ 0x92, 0x90, 0xd8, 0xe1, 0xd1, 0xed, 0x4b, 0x42,
+ 0xd7, 0x37, 0xaf, 0x65, 0x3d, 0x11, 0x39, 0xb6,
+ 0x24, 0x8a, 0x60, 0xae, 0xd6, 0x1e, 0xbf, 0x0e,
+ 0x0d, 0xd7, 0xdc, 0x96, 0x0e, 0x65, 0x75, 0x4e,
+ 0x29, 0x06, 0x9d, 0xa4, 0x51, 0x3a, 0x10, 0x63,
+ 0x8f, 0x17, 0x07, 0xd5, 0x8e, 0x3c, 0xf4, 0x28,
+ 0x00, 0x5a, 0x5b, 0x05, 0x19, 0xd8, 0xc0, 0x6c,
+ 0xe5, 0x15, 0xe4, 0x9c, 0x9d, 0x71, 0x9d, 0x5e,
+ 0x94, 0x29, 0x1a, 0xa7, 0x80, 0xfa, 0x0e, 0x33,
+ 0x03, 0xdd, 0xb7, 0x3e, 0x9a, 0xa9, 0x26, 0x18,
+ 0x37, 0xa9, 0x64, 0x08, 0x4d, 0x94, 0x5a, 0x88,
+ 0xca, 0x35, 0xce, 0x81, 0x02, 0xe3, 0x1f, 0x1b,
+ 0x89, 0x1a, 0x77, 0x85, 0xe3, 0x41, 0x6d, 0x32,
+ 0x42, 0x19, 0x23, 0x7d, 0xc8, 0x73, 0xee, 0x25,
+ 0x85, 0x0d, 0xf8, 0x31, 0x25, 0x79, 0x1b, 0x6f,
+ 0x79, 0x25, 0xd2, 0xd8, 0xd4, 0x23, 0xfd, 0xf7,
+ 0x82, 0x36, 0x6a, 0x0c, 0x46, 0x22, 0x15, 0xe9,
+ 0xff, 0x72, 0x41, 0x91, 0x91, 0x7d, 0x3a, 0xb7,
+ 0xdd, 0x65, 0x99, 0x70, 0xf6, 0x8d, 0x84, 0xf8,
+ 0x67, 0x15, 0x20, 0x11, 0xd6, 0xb2, 0x55, 0x7b,
+ 0xdb, 0x87, 0xee, 0xef, 0x55, 0x89, 0x2a, 0x59,
+ 0x2b, 0x07, 0x8f, 0x43, 0x8a, 0x59, 0x3c, 0x01,
+ 0x8b, 0x65, 0x54, 0xa1, 0x66, 0xd5, 0x38, 0xbd,
+ 0xc6, 0x30, 0xa9, 0xcc, 0x49, 0xb6, 0xa8, 0x1b,
+ 0xb8, 0xc0, 0x0e, 0xe3, 0x45, 0x28, 0xe2, 0xff,
+ 0x41, 0x9f, 0x7e, 0x7c, 0xd1, 0xae, 0x9e, 0x25,
+ 0x3f, 0x4c, 0x7c, 0x7c, 0xf4, 0xa8, 0x26, 0x4d,
+ 0x5c, 0xfd, 0x4b, 0x27, 0x18, 0xf9, 0x61, 0x76,
+ 0x48, 0xba, 0x0c, 0x6b, 0xa9, 0x4d, 0xfc, 0xf5,
+ 0x3b, 0x35, 0x7e, 0x2f, 0x4a, 0xa9, 0xc2, 0x9a,
+ 0xae, 0xab, 0x86, 0x09, 0x89, 0xc9, 0xc2, 0x40,
+ 0x39, 0x2c, 0x81, 0xb3, 0xb8, 0x17, 0x67, 0xc2,
+ 0x0d, 0x32, 0x4a, 0x3a, 0x67, 0x81, 0xd7, 0x1a,
+ 0x34, 0x52, 0xc5, 0xdb, 0x0a, 0xf5, 0x63, 0x39,
+ 0xea, 0x1f, 0xe1, 0x7c, 0xa1, 0x9e, 0xc1, 0x35,
+ 0xe3, 0xb1, 0x18, 0x45, 0x67, 0xf9, 0x22, 0x38,
+ 0x95, 0xd9, 0x34, 0x34, 0x86, 0xc6, 0x41, 0x94,
+ 0x15, 0xf9, 0x5b, 0x41, 0xa6, 0x87, 0x8b, 0xf8,
+ 0xd5, 0xe1, 0x1b, 0xe2, 0x5b, 0xf3, 0x86, 0x10,
+ 0xff, 0xe6, 0xae, 0x69, 0x76, 0xbc, 0x0d, 0xb4,
+ 0x09, 0x90, 0x0c, 0xa2, 0x65, 0x0c, 0xad, 0x74,
+ 0xf5, 0xd7, 0xff, 0xda, 0xc1, 0xce, 0x85, 0xbe,
+ 0x00, 0xa7, 0xff, 0x4d, 0x2f, 0x65, 0xd3, 0x8c,
+ 0x86, 0x2d, 0x05, 0xe8, 0xed, 0x3e, 0x6b, 0x8b,
+ 0x0f, 0x3d, 0x83, 0x8c, 0xf1, 0x1d, 0x5b, 0x96,
+ 0x2e, 0xb1, 0x9c, 0xc2, 0x98, 0xe1, 0x70, 0xb9,
+ 0xba, 0x5c, 0x8a, 0x43, 0xd6, 0x34, 0xa7, 0x2d,
+ 0xc9, 0x92, 0xae, 0xf2, 0xa5, 0x7b, 0x05, 0x49,
+ 0xa7, 0x33, 0x34, 0x86, 0xca, 0xe4, 0x96, 0x23,
+ 0x76, 0x5b, 0xf2, 0xc6, 0xf1, 0x51, 0x28, 0x42,
+ 0x7b, 0xcc, 0x76, 0x8f, 0xfa, 0xa2, 0xad, 0x31,
+ 0xd4, 0xd6, 0x7a, 0x6d, 0x25, 0x25, 0x54, 0xe4,
+ 0x3f, 0x50, 0x59, 0xe1, 0x5c, 0x05, 0xb7, 0x27,
+ 0x48, 0xbf, 0x07, 0xec, 0x1b, 0x13, 0xbe, 0x2b,
+ 0xa1, 0x57, 0x2b, 0xd5, 0xab, 0xd7, 0xd0, 0x4c,
+ 0x1e, 0xcb, 0x71, 0x9b, 0xc5, 0x90, 0x85, 0xd3,
+ 0xde, 0x59, 0xec, 0x71, 0xeb, 0x89, 0xbb, 0xd0,
+ 0x09, 0x50, 0xe1, 0x16, 0x3f, 0xfd, 0x1c, 0x34,
+ 0xc3, 0x1c, 0xa1, 0x10, 0x77, 0x53, 0x98, 0xef,
+ 0xf2, 0xfd, 0xa5, 0x01, 0x59, 0xc2, 0x9b, 0x26,
+ 0xc7, 0x42, 0xd9, 0x49, 0xda, 0x58, 0x2b, 0x6e,
+ 0x9f, 0x53, 0x19, 0x76, 0x7e, 0xd9, 0xc9, 0x0e,
+ 0x68, 0xc8, 0x7f, 0x51, 0x22, 0x42, 0xef, 0x49,
+ 0xa4, 0x55, 0xb6, 0x36, 0xac, 0x09, 0xc7, 0x31,
+ 0x88, 0x15, 0x4b, 0x2e, 0x8f, 0x3a, 0x08, 0xf7,
+ 0xd8, 0xf7, 0xa8, 0xc5, 0xa9, 0x33, 0xa6, 0x45,
+ 0xe4, 0xc4, 0x94, 0x76, 0xf3, 0x0d, 0x8f, 0x7e,
+ 0xc8, 0xf6, 0xbc, 0x23, 0x0a, 0xb6, 0x4c, 0xd3,
+ 0x6a, 0xcd, 0x36, 0xc2, 0x90, 0x5c, 0x5c, 0x3c,
+ 0x65, 0x7b, 0xc2, 0xd6, 0xcc, 0xe6, 0x0d, 0x87,
+ 0x73, 0x2e, 0x71, 0x79, 0x16, 0x06, 0x63, 0x28,
+ 0x09, 0x15, 0xd8, 0x89, 0x38, 0x38, 0x3d, 0xb5,
+ 0x42, 0x1c, 0x08, 0x24, 0xf7, 0x2a, 0xd2, 0x9d,
+ 0xc8, 0xca, 0xef, 0xf9, 0x27, 0xd8, 0x07, 0x86,
+ 0xf7, 0x43, 0x0b, 0x55, 0x15, 0x3f, 0x9f, 0x83,
+ 0xef, 0xdc, 0x49, 0x9d, 0x2a, 0xc1, 0x54, 0x62,
+ 0xbd, 0x9b, 0x66, 0x55, 0x9f, 0xb7, 0x12, 0xf3,
+ 0x1b, 0x4d, 0x9d, 0x2a, 0x5c, 0xed, 0x87, 0x75,
+ 0x87, 0x26, 0xec, 0x61, 0x2c, 0xb4, 0x0f, 0x89,
+ 0xb0, 0xfb, 0x2e, 0x68, 0x5d, 0x15, 0xc7, 0x8d,
+ 0x2e, 0xc0, 0xd9, 0xec, 0xaf, 0x4f, 0xd2, 0x25,
+ 0x29, 0xe8, 0xd2, 0x26, 0x2b, 0x67, 0xe9, 0xfc,
+ 0x2b, 0xa8, 0x67, 0x96, 0x12, 0x1f, 0x5b, 0x96,
+ 0xc6, 0x14, 0x53, 0xaf, 0x44, 0xea, 0xd6, 0xe2,
+ 0x94, 0x98, 0xe4, 0x12, 0x93, 0x4c, 0x92, 0xe0,
+ 0x18, 0xa5, 0x8d, 0x2d, 0xe4, 0x71, 0x3c, 0x47,
+ 0x4c, 0xf7, 0xe6, 0x47, 0x9e, 0xc0, 0x68, 0xdf,
+ 0xd4, 0xf5, 0x5a, 0x74, 0xb1, 0x2b, 0x29, 0x03,
+ 0x19, 0x07, 0xaf, 0x90, 0x62, 0x5c, 0x68, 0x98,
+ 0x48, 0x16, 0x11, 0x02, 0x9d, 0xee, 0xb4, 0x9b,
+ 0xe5, 0x42, 0x7f, 0x08, 0xfd, 0x16, 0x32, 0x0b,
+ 0xd0, 0xb3, 0xfa, 0x2b, 0xb7, 0x99, 0xf9, 0x29,
+ 0xcd, 0x20, 0x45, 0x9f, 0xb3, 0x1a, 0x5d, 0xa2,
+ 0xaf, 0x4d, 0xe0, 0xbd, 0x42, 0x0d, 0xbc, 0x74,
+ 0x99, 0x9c, 0x8e, 0x53, 0x1a, 0xb4, 0x3e, 0xbd,
+ 0xa2, 0x9a, 0x2d, 0xf7, 0xf8, 0x39, 0x0f, 0x67,
+ 0x63, 0xfc, 0x6b, 0xc0, 0xaf, 0xb3, 0x4b, 0x4f,
+ 0x55, 0xc4, 0xcf, 0xa7, 0xc8, 0x04, 0x11, 0x3e,
+ 0x14, 0x32, 0xbb, 0x1b, 0x38, 0x77, 0xd6, 0x7f,
+ 0x54, 0x4c, 0xdf, 0x75, 0xf3, 0x07, 0x2d, 0x33,
+ 0x9b, 0xa8, 0x20, 0xe1, 0x7b, 0x12, 0xb5, 0xf3,
+ 0xef, 0x2f, 0xce, 0x72, 0xe5, 0x24, 0x60, 0xc1,
+ 0x30, 0xe2, 0xab, 0xa1, 0x8e, 0x11, 0x09, 0xa8,
+ 0x21, 0x33, 0x44, 0xfe, 0x7f, 0x35, 0x32, 0x93,
+ 0x39, 0xa7, 0xad, 0x8b, 0x79, 0x06, 0xb2, 0xcb,
+ 0x4e, 0xa9, 0x5f, 0xc7, 0xba, 0x74, 0x29, 0xec,
+ 0x93, 0xa0, 0x4e, 0x54, 0x93, 0xc0, 0xbc, 0x55,
+ 0x64, 0xf0, 0x48, 0xe5, 0x57, 0x99, 0xee, 0x75,
+ 0xd6, 0x79, 0x0f, 0x66, 0xb7, 0xc6, 0x57, 0x76,
+ 0xf7, 0xb7, 0xf3, 0x9c, 0xc5, 0x60, 0xe8, 0x7f,
+ 0x83, 0x76, 0xd6, 0x0e, 0xaa, 0xe6, 0x90, 0x39,
+ 0x1d, 0xa6, 0x32, 0x6a, 0x34, 0xe3, 0x55, 0xf8,
+ 0x58, 0xa0, 0x58, 0x7d, 0x33, 0xe0, 0x22, 0x39,
+ 0x44, 0x64, 0x87, 0x86, 0x5a, 0x2f, 0xa7, 0x7e,
+ 0x0f, 0x38, 0xea, 0xb0, 0x30, 0xcc, 0x61, 0xa5,
+ 0x6a, 0x32, 0xae, 0x1e, 0xf7, 0xe9, 0xd0, 0xa9,
+ 0x0c, 0x32, 0x4b, 0xb5, 0x49, 0x28, 0xab, 0x85,
+ 0x2f, 0x8e, 0x01, 0x36, 0x38, 0x52, 0xd0, 0xba,
+ 0xd6, 0x02, 0x78, 0xf8, 0x0e, 0x3e, 0x9c, 0x8b,
+ 0x6b, 0x45, 0x99, 0x3f, 0x5c, 0xfe, 0x58, 0xf1,
+ 0x5c, 0x94, 0x04, 0xe1, 0xf5, 0x18, 0x6d, 0x51,
+ 0xb2, 0x5d, 0x18, 0x20, 0xb6, 0xc2, 0x9a, 0x42,
+ 0x1d, 0xb3, 0xab, 0x3c, 0xb6, 0x3a, 0x13, 0x03,
+ 0xb2, 0x46, 0x82, 0x4f, 0xfc, 0x64, 0xbc, 0x4f,
+ 0xca, 0xfa, 0x9c, 0xc0, 0xd5, 0xa7, 0xbd, 0x11,
+ 0xb7, 0xe4, 0x5a, 0xf6, 0x6f, 0x4d, 0x4d, 0x54,
+ 0xea, 0xa4, 0x98, 0x66, 0xd4, 0x22, 0x3b, 0xd3,
+ 0x8f, 0x34, 0x47, 0xd9, 0x7c, 0xf4, 0x72, 0x3b,
+ 0x4d, 0x02, 0x77, 0xf6, 0xd6, 0xdd, 0x08, 0x0a,
+ 0x81, 0xe1, 0x86, 0x89, 0x3e, 0x56, 0x10, 0x3c,
+ 0xba, 0xd7, 0x81, 0x8c, 0x08, 0xbc, 0x8b, 0xe2,
+ 0x53, 0xec, 0xa7, 0x89, 0xee, 0xc8, 0x56, 0xb5,
+ 0x36, 0x2c, 0xb2, 0x03, 0xba, 0x99, 0xdd, 0x7c,
+ 0x48, 0xa0, 0xb0, 0xbc, 0x91, 0x33, 0xe9, 0xa8,
+ 0xcb, 0xcd, 0xcf, 0x59, 0x5f, 0x1f, 0x15, 0xe2,
+ 0x56, 0xf5, 0x4e, 0x01, 0x35, 0x27, 0x45, 0x77,
+ 0x47, 0xc8, 0xbc, 0xcb, 0x7e, 0x39, 0xc1, 0x97,
+ 0x28, 0xd3, 0x84, 0xfc, 0x2c, 0x3e, 0xc8, 0xad,
+ 0x9c, 0xf8, 0x8a, 0x61, 0x9c, 0x28, 0xaa, 0xc5,
+ 0x99, 0x20, 0x43, 0x85, 0x9d, 0xa5, 0xe2, 0x8b,
+ 0xb8, 0xae, 0xeb, 0xd0, 0x32, 0x0d, 0x52, 0x78,
+ 0x09, 0x56, 0x3f, 0xc7, 0xd8, 0x7e, 0x26, 0xfc,
+ 0x37, 0xfb, 0x6f, 0x04, 0xfc, 0xfa, 0x92, 0x10,
+ 0xac, 0xf8, 0x3e, 0x21, 0xdc, 0x8c, 0x21, 0x16,
+ 0x7d, 0x67, 0x6e, 0xf6, 0xcd, 0xda, 0xb6, 0x98,
+ 0x23, 0xab, 0x23, 0x3c, 0xb2, 0x10, 0xa0, 0x53,
+ 0x5a, 0x56, 0x9f, 0xc5, 0xd0, 0xff, 0xbb, 0xe4,
+ 0x98, 0x3c, 0x69, 0x1e, 0xdb, 0x38, 0x8f, 0x7e,
+ 0x0f, 0xd2, 0x98, 0x88, 0x81, 0x8b, 0x45, 0x67,
+ 0xea, 0x33, 0xf1, 0xeb, 0xe9, 0x97, 0x55, 0x2e,
+ 0xd9, 0xaa, 0xeb, 0x5a, 0xec, 0xda, 0xe1, 0x68,
+ 0xa8, 0x9d, 0x3c, 0x84, 0x7c, 0x05, 0x3d, 0x62,
+ 0x87, 0x8f, 0x03, 0x21, 0x28, 0x95, 0x0c, 0x89,
+ 0x25, 0x22, 0x4a, 0xb0, 0x93, 0xa9, 0x50, 0xa2,
+ 0x2f, 0x57, 0x6e, 0x18, 0x42, 0x19, 0x54, 0x0c,
+ 0x55, 0x67, 0xc6, 0x11, 0x49, 0xf4, 0x5c, 0xd2,
+ 0xe9, 0x3d, 0xdd, 0x8b, 0x48, 0x71, 0x21, 0x00,
+ 0xc3, 0x9a, 0x6c, 0x85, 0x74, 0x28, 0x83, 0x4a,
+ 0x1b, 0x31, 0x05, 0xe1, 0x06, 0x92, 0xe7, 0xda,
+ 0x85, 0x73, 0x78, 0x45, 0x20, 0x7f, 0xae, 0x13,
+ 0x7c, 0x33, 0x06, 0x22, 0xf4, 0x83, 0xf9, 0x35,
+ 0x3f, 0x6c, 0x71, 0xa8, 0x4e, 0x48, 0xbe, 0x9b,
+ 0xce, 0x8a, 0xba, 0xda, 0xbe, 0x28, 0x08, 0xf7,
+ 0xe2, 0x14, 0x8c, 0x71, 0xea, 0x72, 0xf9, 0x33,
+ 0xf2, 0x88, 0x3f, 0xd7, 0xbb, 0x69, 0x6c, 0x29,
+ 0x19, 0xdc, 0x84, 0xce, 0x1f, 0x12, 0x4f, 0xc8,
+ 0xaf, 0xa5, 0x04, 0xba, 0x5a, 0xab, 0xb0, 0xd9,
+ 0x14, 0x1f, 0x6c, 0x68, 0x98, 0x39, 0x89, 0x7a,
+ 0xd9, 0xd8, 0x2f, 0xdf, 0xa8, 0x47, 0x4a, 0x25,
+ 0xe2, 0xfb, 0x33, 0xf4, 0x59, 0x78, 0xe1, 0x68,
+ 0x85, 0xcf, 0xfe, 0x59, 0x20, 0xd4, 0x05, 0x1d,
+ 0x80, 0x99, 0xae, 0xbc, 0xca, 0xae, 0x0f, 0x2f,
+ 0x65, 0x43, 0x34, 0x8e, 0x7e, 0xac, 0xd3, 0x93,
+ 0x2f, 0xac, 0x6d, 0x14, 0x3d, 0x02, 0x07, 0x70,
+ 0x9d, 0xa4, 0xf3, 0x1b, 0x5c, 0x36, 0xfc, 0x01,
+ 0x73, 0x34, 0x85, 0x0c, 0x6c, 0xd6, 0xf1, 0xbd,
+ 0x3f, 0xdf, 0xee, 0xf5, 0xd9, 0xba, 0x56, 0xef,
+ 0xf4, 0x9b, 0x6b, 0xee, 0x9f, 0x5a, 0x78, 0x6d,
+ 0x32, 0x19, 0xf4, 0xf7, 0xf8, 0x4c, 0x69, 0x0b,
+ 0x4b, 0xbc, 0xbb, 0xb7, 0xf2, 0x85, 0xaf, 0x70,
+ 0x75, 0x24, 0x6c, 0x54, 0xa7, 0x0e, 0x4d, 0x1d,
+ 0x01, 0xbf, 0x08, 0xac, 0xcf, 0x7f, 0x2c, 0xe3,
+ 0x14, 0x89, 0x5e, 0x70, 0x5a, 0x99, 0x92, 0xcd,
+ 0x01, 0x84, 0xc8, 0xd2, 0xab, 0xe5, 0x4f, 0x58,
+ 0xe7, 0x0f, 0x2f, 0x0e, 0xff, 0x68, 0xea, 0xfd,
+ 0x15, 0xb3, 0x17, 0xe6, 0xb0, 0xe7, 0x85, 0xd8,
+ 0x23, 0x2e, 0x05, 0xc7, 0xc9, 0xc4, 0x46, 0x1f,
+ 0xe1, 0x9e, 0x49, 0x20, 0x23, 0x24, 0x4d, 0x7e,
+ 0x29, 0x65, 0xff, 0xf4, 0xb6, 0xfd, 0x1a, 0x85,
+ 0xc4, 0x16, 0xec, 0xfc, 0xea, 0x7b, 0xd6, 0x2c,
+ 0x43, 0xf8, 0xb7, 0xbf, 0x79, 0xc0, 0x85, 0xcd,
+ 0xef, 0xe1, 0x98, 0xd3, 0xa5, 0xf7, 0x90, 0x8c,
+ 0xe9, 0x7f, 0x80, 0x6b, 0xd2, 0xac, 0x4c, 0x30,
+ 0xa7, 0xc6, 0x61, 0x6c, 0xd2, 0xf9, 0x2c, 0xff,
+ 0x30, 0xbc, 0x22, 0x81, 0x7d, 0x93, 0x12, 0xe4,
+ 0x0a, 0xcd, 0xaf, 0xdd, 0xe8, 0xab, 0x0a, 0x1e,
+ 0x13, 0xa4, 0x27, 0xc3, 0x5f, 0xf7, 0x4b, 0xbb,
+ 0x37, 0x09, 0x4b, 0x91, 0x6f, 0x92, 0x4f, 0xaf,
+ 0x52, 0xee, 0xdf, 0xef, 0x09, 0x6f, 0xf7, 0x5c,
+ 0x6e, 0x12, 0x17, 0x72, 0x63, 0x57, 0xc7, 0xba,
+ 0x3b, 0x6b, 0x38, 0x32, 0x73, 0x1b, 0x9c, 0x80,
+ 0xc1, 0x7a, 0xc6, 0xcf, 0xcd, 0x35, 0xc0, 0x6b,
+ 0x31, 0x1a, 0x6b, 0xe9, 0xd8, 0x2c, 0x29, 0x3f,
+ 0x96, 0xfb, 0xb6, 0xcd, 0x13, 0x91, 0x3b, 0xc2,
+ 0xd2, 0xa3, 0x31, 0x8d, 0xa4, 0xcd, 0x57, 0xcd,
+ 0x13, 0x3d, 0x64, 0xfd, 0x06, 0xce, 0xe6, 0xdc,
+ 0x0c, 0x24, 0x43, 0x31, 0x40, 0x57, 0xf1, 0x72,
+ 0x17, 0xe3, 0x3a, 0x63, 0x6d, 0x35, 0xcf, 0x5d,
+ 0x97, 0x40, 0x59, 0xdd, 0xf7, 0x3c, 0x02, 0xf7,
+ 0x1c, 0x7e, 0x05, 0xbb, 0xa9, 0x0d, 0x01, 0xb1,
+ 0x8e, 0xc0, 0x30, 0xa9, 0x53, 0x24, 0xc9, 0x89,
+ 0x84, 0x6d, 0xaa, 0xd0, 0xcd, 0x91, 0xc2, 0x4d,
+ 0x91, 0xb0, 0x89, 0xe2, 0xbf, 0x83, 0x44, 0xaa,
+ 0x28, 0x72, 0x23, 0xa0, 0xc2, 0xad, 0xad, 0x1c,
+ 0xfc, 0x3f, 0x09, 0x7a, 0x0b, 0xdc, 0xc5, 0x1b,
+ 0x87, 0x13, 0xc6, 0x5b, 0x59, 0x8d, 0xf2, 0xc8,
+ 0xaf, 0xdf, 0x11, 0x95,
+ },
+ .rlen = 4100,
+ },
+};
+
/*
* Compression stuff.
*/
@@ -4408,6 +7721,88 @@
};
/*
+ * LZO test vectors (null-terminated strings).
+ */
+#define LZO_COMP_TEST_VECTORS 2
+#define LZO_DECOMP_TEST_VECTORS 2
+
+static struct comp_testvec lzo_comp_tv_template[] = {
+ {
+ .inlen = 70,
+ .outlen = 46,
+ .input = "Join us now and share the software "
+ "Join us now and share the software ",
+ .output = { 0x00, 0x0d, 0x4a, 0x6f, 0x69, 0x6e, 0x20, 0x75,
+ 0x73, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x73, 0x68, 0x61, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x66, 0x74,
+ 0x77, 0x70, 0x01, 0x01, 0x4a, 0x6f, 0x69, 0x6e,
+ 0x3d, 0x88, 0x00, 0x11, 0x00, 0x00 },
+ }, {
+ .inlen = 159,
+ .outlen = 133,
+ .input = "This document describes a compression method based on the LZO "
+ "compression algorithm. This document defines the application of "
+ "the LZO algorithm used in UBIFS.",
+ .output = { 0x00, 0x2b, 0x54, 0x68, 0x69, 0x73, 0x20, 0x64,
+ 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20,
+ 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65,
+ 0x73, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x70,
+ 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20,
+ 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x20, 0x62,
+ 0x61, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x4c, 0x5a, 0x4f, 0x2b,
+ 0x8c, 0x00, 0x0d, 0x61, 0x6c, 0x67, 0x6f, 0x72,
+ 0x69, 0x74, 0x68, 0x6d, 0x2e, 0x20, 0x20, 0x54,
+ 0x68, 0x69, 0x73, 0x2a, 0x54, 0x01, 0x02, 0x66,
+ 0x69, 0x6e, 0x65, 0x73, 0x94, 0x06, 0x05, 0x61,
+ 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x76,
+ 0x0a, 0x6f, 0x66, 0x88, 0x02, 0x60, 0x09, 0x27,
+ 0xf0, 0x00, 0x0c, 0x20, 0x75, 0x73, 0x65, 0x64,
+ 0x20, 0x69, 0x6e, 0x20, 0x55, 0x42, 0x49, 0x46,
+ 0x53, 0x2e, 0x11, 0x00, 0x00 },
+ },
+};
+
+static struct comp_testvec lzo_decomp_tv_template[] = {
+ {
+ .inlen = 133,
+ .outlen = 159,
+ .input = { 0x00, 0x2b, 0x54, 0x68, 0x69, 0x73, 0x20, 0x64,
+ 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20,
+ 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65,
+ 0x73, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x70,
+ 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20,
+ 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x20, 0x62,
+ 0x61, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x4c, 0x5a, 0x4f, 0x2b,
+ 0x8c, 0x00, 0x0d, 0x61, 0x6c, 0x67, 0x6f, 0x72,
+ 0x69, 0x74, 0x68, 0x6d, 0x2e, 0x20, 0x20, 0x54,
+ 0x68, 0x69, 0x73, 0x2a, 0x54, 0x01, 0x02, 0x66,
+ 0x69, 0x6e, 0x65, 0x73, 0x94, 0x06, 0x05, 0x61,
+ 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x76,
+ 0x0a, 0x6f, 0x66, 0x88, 0x02, 0x60, 0x09, 0x27,
+ 0xf0, 0x00, 0x0c, 0x20, 0x75, 0x73, 0x65, 0x64,
+ 0x20, 0x69, 0x6e, 0x20, 0x55, 0x42, 0x49, 0x46,
+ 0x53, 0x2e, 0x11, 0x00, 0x00 },
+ .output = "This document describes a compression method based on the LZO "
+ "compression algorithm. This document defines the application of "
+ "the LZO algorithm used in UBIFS.",
+ }, {
+ .inlen = 46,
+ .outlen = 70,
+ .input = { 0x00, 0x0d, 0x4a, 0x6f, 0x69, 0x6e, 0x20, 0x75,
+ 0x73, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x73, 0x68, 0x61, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x66, 0x74,
+ 0x77, 0x70, 0x01, 0x01, 0x4a, 0x6f, 0x69, 0x6e,
+ 0x3d, 0x88, 0x00, 0x11, 0x00, 0x00 },
+ .output = "Join us now and share the software "
+ "Join us now and share the software ",
+ },
+};
+
+/*
* Michael MIC test vectors from IEEE 802.11i
*/
#define MICHAEL_MIC_TEST_VECTORS 6
@@ -4812,4 +8207,20 @@
{ .klen = 0, .blen = 0, }
};
+static struct cipher_speed salsa20_speed_template[] = {
+ { .klen = 16, .blen = 16, },
+ { .klen = 16, .blen = 64, },
+ { .klen = 16, .blen = 256, },
+ { .klen = 16, .blen = 1024, },
+ { .klen = 16, .blen = 8192, },
+ { .klen = 32, .blen = 16, },
+ { .klen = 32, .blen = 64, },
+ { .klen = 32, .blen = 256, },
+ { .klen = 32, .blen = 1024, },
+ { .klen = 32, .blen = 8192, },
+
+ /* End marker */
+ { .klen = 0, .blen = 0, }
+};
+
#endif /* _CRYPTO_TCRYPT_H */
diff --git a/crypto/twofish_common.c b/crypto/twofish_common.c
index b4b9c0c..0af216c 100644
--- a/crypto/twofish_common.c
+++ b/crypto/twofish_common.c
@@ -655,84 +655,48 @@
CALC_SB256_2( i, calc_sb_tbl[j], calc_sb_tbl[k] );
}
- /* Calculate whitening and round subkeys. The constants are
- * indices of subkeys, preprocessed through q0 and q1. */
- CALC_K256 (w, 0, 0xA9, 0x75, 0x67, 0xF3);
- CALC_K256 (w, 2, 0xB3, 0xC6, 0xE8, 0xF4);
- CALC_K256 (w, 4, 0x04, 0xDB, 0xFD, 0x7B);
- CALC_K256 (w, 6, 0xA3, 0xFB, 0x76, 0xC8);
- CALC_K256 (k, 0, 0x9A, 0x4A, 0x92, 0xD3);
- CALC_K256 (k, 2, 0x80, 0xE6, 0x78, 0x6B);
- CALC_K256 (k, 4, 0xE4, 0x45, 0xDD, 0x7D);
- CALC_K256 (k, 6, 0xD1, 0xE8, 0x38, 0x4B);
- CALC_K256 (k, 8, 0x0D, 0xD6, 0xC6, 0x32);
- CALC_K256 (k, 10, 0x35, 0xD8, 0x98, 0xFD);
- CALC_K256 (k, 12, 0x18, 0x37, 0xF7, 0x71);
- CALC_K256 (k, 14, 0xEC, 0xF1, 0x6C, 0xE1);
- CALC_K256 (k, 16, 0x43, 0x30, 0x75, 0x0F);
- CALC_K256 (k, 18, 0x37, 0xF8, 0x26, 0x1B);
- CALC_K256 (k, 20, 0xFA, 0x87, 0x13, 0xFA);
- CALC_K256 (k, 22, 0x94, 0x06, 0x48, 0x3F);
- CALC_K256 (k, 24, 0xF2, 0x5E, 0xD0, 0xBA);
- CALC_K256 (k, 26, 0x8B, 0xAE, 0x30, 0x5B);
- CALC_K256 (k, 28, 0x84, 0x8A, 0x54, 0x00);
- CALC_K256 (k, 30, 0xDF, 0xBC, 0x23, 0x9D);
+ /* CALC_K256/CALC_K192/CALC_K loops were unrolled.
+ * Unrolling produced x2.5 more code (+18k on i386),
+ * and speeded up key setup by 7%:
+ * unrolled: twofish_setkey/sec: 41128
+ * loop: twofish_setkey/sec: 38148
+ * CALC_K256: ~100 insns each
+ * CALC_K192: ~90 insns
+ * CALC_K: ~70 insns
+ */
+ /* Calculate whitening and round subkeys */
+ for ( i = 0; i < 8; i += 2 ) {
+ CALC_K256 (w, i, q0[i], q1[i], q0[i+1], q1[i+1]);
+ }
+ for ( i = 0; i < 32; i += 2 ) {
+ CALC_K256 (k, i, q0[i+8], q1[i+8], q0[i+9], q1[i+9]);
+ }
} else if (key_len == 24) { /* 192-bit key */
/* Compute the S-boxes. */
for ( i = j = 0, k = 1; i < 256; i++, j += 2, k += 2 ) {
CALC_SB192_2( i, calc_sb_tbl[j], calc_sb_tbl[k] );
}
- /* Calculate whitening and round subkeys. The constants are
- * indices of subkeys, preprocessed through q0 and q1. */
- CALC_K192 (w, 0, 0xA9, 0x75, 0x67, 0xF3);
- CALC_K192 (w, 2, 0xB3, 0xC6, 0xE8, 0xF4);
- CALC_K192 (w, 4, 0x04, 0xDB, 0xFD, 0x7B);
- CALC_K192 (w, 6, 0xA3, 0xFB, 0x76, 0xC8);
- CALC_K192 (k, 0, 0x9A, 0x4A, 0x92, 0xD3);
- CALC_K192 (k, 2, 0x80, 0xE6, 0x78, 0x6B);
- CALC_K192 (k, 4, 0xE4, 0x45, 0xDD, 0x7D);
- CALC_K192 (k, 6, 0xD1, 0xE8, 0x38, 0x4B);
- CALC_K192 (k, 8, 0x0D, 0xD6, 0xC6, 0x32);
- CALC_K192 (k, 10, 0x35, 0xD8, 0x98, 0xFD);
- CALC_K192 (k, 12, 0x18, 0x37, 0xF7, 0x71);
- CALC_K192 (k, 14, 0xEC, 0xF1, 0x6C, 0xE1);
- CALC_K192 (k, 16, 0x43, 0x30, 0x75, 0x0F);
- CALC_K192 (k, 18, 0x37, 0xF8, 0x26, 0x1B);
- CALC_K192 (k, 20, 0xFA, 0x87, 0x13, 0xFA);
- CALC_K192 (k, 22, 0x94, 0x06, 0x48, 0x3F);
- CALC_K192 (k, 24, 0xF2, 0x5E, 0xD0, 0xBA);
- CALC_K192 (k, 26, 0x8B, 0xAE, 0x30, 0x5B);
- CALC_K192 (k, 28, 0x84, 0x8A, 0x54, 0x00);
- CALC_K192 (k, 30, 0xDF, 0xBC, 0x23, 0x9D);
+ /* Calculate whitening and round subkeys */
+ for ( i = 0; i < 8; i += 2 ) {
+ CALC_K192 (w, i, q0[i], q1[i], q0[i+1], q1[i+1]);
+ }
+ for ( i = 0; i < 32; i += 2 ) {
+ CALC_K192 (k, i, q0[i+8], q1[i+8], q0[i+9], q1[i+9]);
+ }
} else { /* 128-bit key */
/* Compute the S-boxes. */
for ( i = j = 0, k = 1; i < 256; i++, j += 2, k += 2 ) {
CALC_SB_2( i, calc_sb_tbl[j], calc_sb_tbl[k] );
}
- /* Calculate whitening and round subkeys. The constants are
- * indices of subkeys, preprocessed through q0 and q1. */
- CALC_K (w, 0, 0xA9, 0x75, 0x67, 0xF3);
- CALC_K (w, 2, 0xB3, 0xC6, 0xE8, 0xF4);
- CALC_K (w, 4, 0x04, 0xDB, 0xFD, 0x7B);
- CALC_K (w, 6, 0xA3, 0xFB, 0x76, 0xC8);
- CALC_K (k, 0, 0x9A, 0x4A, 0x92, 0xD3);
- CALC_K (k, 2, 0x80, 0xE6, 0x78, 0x6B);
- CALC_K (k, 4, 0xE4, 0x45, 0xDD, 0x7D);
- CALC_K (k, 6, 0xD1, 0xE8, 0x38, 0x4B);
- CALC_K (k, 8, 0x0D, 0xD6, 0xC6, 0x32);
- CALC_K (k, 10, 0x35, 0xD8, 0x98, 0xFD);
- CALC_K (k, 12, 0x18, 0x37, 0xF7, 0x71);
- CALC_K (k, 14, 0xEC, 0xF1, 0x6C, 0xE1);
- CALC_K (k, 16, 0x43, 0x30, 0x75, 0x0F);
- CALC_K (k, 18, 0x37, 0xF8, 0x26, 0x1B);
- CALC_K (k, 20, 0xFA, 0x87, 0x13, 0xFA);
- CALC_K (k, 22, 0x94, 0x06, 0x48, 0x3F);
- CALC_K (k, 24, 0xF2, 0x5E, 0xD0, 0xBA);
- CALC_K (k, 26, 0x8B, 0xAE, 0x30, 0x5B);
- CALC_K (k, 28, 0x84, 0x8A, 0x54, 0x00);
- CALC_K (k, 30, 0xDF, 0xBC, 0x23, 0x9D);
+ /* Calculate whitening and round subkeys */
+ for ( i = 0; i < 8; i += 2 ) {
+ CALC_K (w, i, q0[i], q1[i], q0[i+1], q1[i+1]);
+ }
+ for ( i = 0; i < 32; i += 2 ) {
+ CALC_K (k, i, q0[i+8], q1[i+8], q0[i+9], q1[i+9]);
+ }
}
return 0;
diff --git a/crypto/xcbc.c b/crypto/xcbc.c
index ac68f3b..a82959d 100644
--- a/crypto/xcbc.c
+++ b/crypto/xcbc.c
@@ -19,6 +19,7 @@
* Kazunori Miyazawa <miyazawa@linux-ipv6.org>
*/
+#include <crypto/scatterwalk.h>
#include <linux/crypto.h>
#include <linux/err.h>
#include <linux/hardirq.h>
@@ -27,7 +28,6 @@
#include <linux/rtnetlink.h>
#include <linux/slab.h>
#include <linux/scatterlist.h>
-#include "internal.h"
static u_int32_t ks[12] = {0x01010101, 0x01010101, 0x01010101, 0x01010101,
0x02020202, 0x02020202, 0x02020202, 0x02020202,
@@ -307,7 +307,8 @@
case 16:
break;
default:
- return ERR_PTR(PTR_ERR(alg));
+ inst = ERR_PTR(-EINVAL);
+ goto out_put_alg;
}
inst = crypto_alloc_instance("xcbc", alg);
@@ -320,10 +321,7 @@
inst->alg.cra_alignmask = alg->cra_alignmask;
inst->alg.cra_type = &crypto_hash_type;
- inst->alg.cra_hash.digestsize =
- (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
- CRYPTO_ALG_TYPE_HASH ? alg->cra_hash.digestsize :
- alg->cra_blocksize;
+ inst->alg.cra_hash.digestsize = alg->cra_blocksize;
inst->alg.cra_ctxsize = sizeof(struct crypto_xcbc_ctx) +
ALIGN(inst->alg.cra_blocksize * 3, sizeof(void *));
inst->alg.cra_init = xcbc_init_tfm;
diff --git a/drivers/char/hw_random/amd-rng.c b/drivers/char/hw_random/amd-rng.c
index 556fd81..c422e87 100644
--- a/drivers/char/hw_random/amd-rng.c
+++ b/drivers/char/hw_random/amd-rng.c
@@ -28,6 +28,7 @@
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/hw_random.h>
+#include <linux/delay.h>
#include <asm/io.h>
@@ -52,11 +53,18 @@
static struct pci_dev *amd_pdev;
-static int amd_rng_data_present(struct hwrng *rng)
+static int amd_rng_data_present(struct hwrng *rng, int wait)
{
u32 pmbase = (u32)rng->priv;
+ int data, i;
- return !!(inl(pmbase + 0xF4) & 1);
+ for (i = 0; i < 20; i++) {
+ data = !!(inl(pmbase + 0xF4) & 1);
+ if (data || !wait)
+ break;
+ udelay(10);
+ }
+ return data;
}
static int amd_rng_data_read(struct hwrng *rng, u32 *data)
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
index 26a860a..0118b98 100644
--- a/drivers/char/hw_random/core.c
+++ b/drivers/char/hw_random/core.c
@@ -66,11 +66,11 @@
rng->cleanup(rng);
}
-static inline int hwrng_data_present(struct hwrng *rng)
+static inline int hwrng_data_present(struct hwrng *rng, int wait)
{
if (!rng->data_present)
return 1;
- return rng->data_present(rng);
+ return rng->data_present(rng, wait);
}
static inline int hwrng_data_read(struct hwrng *rng, u32 *data)
@@ -94,8 +94,7 @@
{
u32 data;
ssize_t ret = 0;
- int i, err = 0;
- int data_present;
+ int err = 0;
int bytes_read;
while (size) {
@@ -107,21 +106,10 @@
err = -ENODEV;
goto out;
}
- if (filp->f_flags & O_NONBLOCK) {
- data_present = hwrng_data_present(current_rng);
- } else {
- /* Some RNG require some time between data_reads to gather
- * new entropy. Poll it.
- */
- for (i = 0; i < 20; i++) {
- data_present = hwrng_data_present(current_rng);
- if (data_present)
- break;
- udelay(10);
- }
- }
+
bytes_read = 0;
- if (data_present)
+ if (hwrng_data_present(current_rng,
+ !(filp->f_flags & O_NONBLOCK)))
bytes_read = hwrng_data_read(current_rng, &data);
mutex_unlock(&rng_mutex);
diff --git a/drivers/char/hw_random/geode-rng.c b/drivers/char/hw_random/geode-rng.c
index 8e8658d..fed4ef5 100644
--- a/drivers/char/hw_random/geode-rng.c
+++ b/drivers/char/hw_random/geode-rng.c
@@ -28,6 +28,7 @@
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/hw_random.h>
+#include <linux/delay.h>
#include <asm/io.h>
@@ -61,11 +62,18 @@
return 4;
}
-static int geode_rng_data_present(struct hwrng *rng)
+static int geode_rng_data_present(struct hwrng *rng, int wait)
{
void __iomem *mem = (void __iomem *)rng->priv;
+ int data, i;
- return !!(readl(mem + GEODE_RNG_STATUS_REG));
+ for (i = 0; i < 20; i++) {
+ data = !!(readl(mem + GEODE_RNG_STATUS_REG));
+ if (data || !wait)
+ break;
+ udelay(10);
+ }
+ return data;
}
diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c
index 753f460..5cc651e 100644
--- a/drivers/char/hw_random/intel-rng.c
+++ b/drivers/char/hw_random/intel-rng.c
@@ -29,6 +29,7 @@
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/stop_machine.h>
+#include <linux/delay.h>
#include <asm/io.h>
@@ -162,11 +163,19 @@
return hwstatus_get(mem);
}
-static int intel_rng_data_present(struct hwrng *rng)
+static int intel_rng_data_present(struct hwrng *rng, int wait)
{
void __iomem *mem = (void __iomem *)rng->priv;
+ int data, i;
- return !!(readb(mem + INTEL_RNG_STATUS) & INTEL_RNG_DATA_PRESENT);
+ for (i = 0; i < 20; i++) {
+ data = !!(readb(mem + INTEL_RNG_STATUS) &
+ INTEL_RNG_DATA_PRESENT);
+ if (data || !wait)
+ break;
+ udelay(10);
+ }
+ return data;
}
static int intel_rng_data_read(struct hwrng *rng, u32 *data)
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
index 3f35a1c..7e31995 100644
--- a/drivers/char/hw_random/omap-rng.c
+++ b/drivers/char/hw_random/omap-rng.c
@@ -29,6 +29,7 @@
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/hw_random.h>
+#include <linux/delay.h>
#include <asm/io.h>
@@ -65,9 +66,17 @@
}
/* REVISIT: Does the status bit really work on 16xx? */
-static int omap_rng_data_present(struct hwrng *rng)
+static int omap_rng_data_present(struct hwrng *rng, int wait)
{
- return omap_rng_read_reg(RNG_STAT_REG) ? 0 : 1;
+ int data, i;
+
+ for (i = 0; i < 20; i++) {
+ data = omap_rng_read_reg(RNG_STAT_REG) ? 0 : 1;
+ if (data || !wait)
+ break;
+ udelay(10);
+ }
+ return data;
}
static int omap_rng_data_read(struct hwrng *rng, u32 *data)
diff --git a/drivers/char/hw_random/pasemi-rng.c b/drivers/char/hw_random/pasemi-rng.c
index fa6040b..e2ea210 100644
--- a/drivers/char/hw_random/pasemi-rng.c
+++ b/drivers/char/hw_random/pasemi-rng.c
@@ -23,6 +23,7 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/hw_random.h>
+#include <linux/delay.h>
#include <asm/of_platform.h>
#include <asm/io.h>
@@ -41,12 +42,19 @@
#define MODULE_NAME "pasemi_rng"
-static int pasemi_rng_data_present(struct hwrng *rng)
+static int pasemi_rng_data_present(struct hwrng *rng, int wait)
{
void __iomem *rng_regs = (void __iomem *)rng->priv;
+ int data, i;
- return (in_le32(rng_regs + SDCRNG_CTL_REG)
- & SDCRNG_CTL_FVLD_M) ? 1 : 0;
+ for (i = 0; i < 20; i++) {
+ data = (in_le32(rng_regs + SDCRNG_CTL_REG)
+ & SDCRNG_CTL_FVLD_M) ? 1 : 0;
+ if (data || !wait)
+ break;
+ udelay(10);
+ }
+ return data;
}
static int pasemi_rng_data_read(struct hwrng *rng, u32 *data)
diff --git a/drivers/char/hw_random/via-rng.c b/drivers/char/hw_random/via-rng.c
index ec435cb..868e39f 100644
--- a/drivers/char/hw_random/via-rng.c
+++ b/drivers/char/hw_random/via-rng.c
@@ -27,6 +27,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/hw_random.h>
+#include <linux/delay.h>
#include <asm/io.h>
#include <asm/msr.h>
#include <asm/cpufeature.h>
@@ -77,10 +78,11 @@
return eax_out;
}
-static int via_rng_data_present(struct hwrng *rng)
+static int via_rng_data_present(struct hwrng *rng, int wait)
{
u32 bytes_out;
u32 *via_rng_datum = (u32 *)(&rng->priv);
+ int i;
/* We choose the recommended 1-byte-per-instruction RNG rate,
* for greater randomness at the expense of speed. Larger
@@ -95,12 +97,15 @@
* completes.
*/
- *via_rng_datum = 0; /* paranoia, not really necessary */
- bytes_out = xstore(via_rng_datum, VIA_RNG_CHUNK_1);
- bytes_out &= VIA_XSTORE_CNT_MASK;
- if (bytes_out == 0)
- return 0;
- return 1;
+ for (i = 0; i < 20; i++) {
+ *via_rng_datum = 0; /* paranoia, not really necessary */
+ bytes_out = xstore(via_rng_datum, VIA_RNG_CHUNK_1);
+ bytes_out &= VIA_XSTORE_CNT_MASK;
+ if (bytes_out || !wait)
+ break;
+ udelay(10);
+ }
+ return bytes_out ? 1 : 0;
}
static int via_rng_data_read(struct hwrng *rng, u32 *data)
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index ddd3a25..74bd599 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -83,4 +83,15 @@
that contains all parts of the crypto device driver (ap bus,
request router and all the card drivers).
+config CRYPTO_DEV_HIFN_795X
+ tristate "Driver HIFN 795x crypto accelerator chips"
+ select CRYPTO_DES
+ select CRYPTO_ALGAPI
+ select CRYPTO_BLKCIPHER
+ depends on PCI
+ help
+ This option allows you to have support for HIFN 795x crypto adapters.
+
+
+
endif # CRYPTO_HW
diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
index d070030..c0327f0 100644
--- a/drivers/crypto/Makefile
+++ b/drivers/crypto/Makefile
@@ -1,3 +1,4 @@
obj-$(CONFIG_CRYPTO_DEV_PADLOCK_AES) += padlock-aes.o
obj-$(CONFIG_CRYPTO_DEV_PADLOCK_SHA) += padlock-sha.o
obj-$(CONFIG_CRYPTO_DEV_GEODE) += geode-aes.o
+obj-$(CONFIG_CRYPTO_DEV_HIFN_795X) += hifn_795x.o
diff --git a/drivers/crypto/geode-aes.c b/drivers/crypto/geode-aes.c
index 711e246..4801162 100644
--- a/drivers/crypto/geode-aes.c
+++ b/drivers/crypto/geode-aes.c
@@ -13,44 +13,13 @@
#include <linux/crypto.h>
#include <linux/spinlock.h>
#include <crypto/algapi.h>
+#include <crypto/aes.h>
#include <asm/io.h>
#include <asm/delay.h>
#include "geode-aes.h"
-/* Register definitions */
-
-#define AES_CTRLA_REG 0x0000
-
-#define AES_CTRL_START 0x01
-#define AES_CTRL_DECRYPT 0x00
-#define AES_CTRL_ENCRYPT 0x02
-#define AES_CTRL_WRKEY 0x04
-#define AES_CTRL_DCA 0x08
-#define AES_CTRL_SCA 0x10
-#define AES_CTRL_CBC 0x20
-
-#define AES_INTR_REG 0x0008
-
-#define AES_INTRA_PENDING (1 << 16)
-#define AES_INTRB_PENDING (1 << 17)
-
-#define AES_INTR_PENDING (AES_INTRA_PENDING | AES_INTRB_PENDING)
-#define AES_INTR_MASK 0x07
-
-#define AES_SOURCEA_REG 0x0010
-#define AES_DSTA_REG 0x0014
-#define AES_LENA_REG 0x0018
-#define AES_WRITEKEY0_REG 0x0030
-#define AES_WRITEIV0_REG 0x0040
-
-/* A very large counter that is used to gracefully bail out of an
- * operation in case of trouble
- */
-
-#define AES_OP_TIMEOUT 0x50000
-
/* Static structures */
static void __iomem * _iobase;
@@ -87,9 +56,10 @@
/* Start the operation */
iowrite32(AES_CTRL_START | flags, _iobase + AES_CTRLA_REG);
- do
+ do {
status = ioread32(_iobase + AES_INTR_REG);
- while(!(status & AES_INTRA_PENDING) && --counter);
+ cpu_relax();
+ } while(!(status & AES_INTRA_PENDING) && --counter);
/* Clear the event */
iowrite32((status & 0xFF) | AES_INTRA_PENDING, _iobase + AES_INTR_REG);
@@ -101,6 +71,7 @@
{
u32 flags = 0;
unsigned long iflags;
+ int ret;
if (op->len == 0)
return 0;
@@ -129,7 +100,8 @@
_writefield(AES_WRITEKEY0_REG, op->key);
}
- do_crypt(op->src, op->dst, op->len, flags);
+ ret = do_crypt(op->src, op->dst, op->len, flags);
+ BUG_ON(ret);
if (op->mode == AES_MODE_CBC)
_readfield(AES_WRITEIV0_REG, op->iv);
@@ -141,18 +113,103 @@
/* CRYPTO-API Functions */
-static int
-geode_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int len)
+static int geode_setkey_cip(struct crypto_tfm *tfm, const u8 *key,
+ unsigned int len)
{
struct geode_aes_op *op = crypto_tfm_ctx(tfm);
+ unsigned int ret;
- if (len != AES_KEY_LENGTH) {
+ op->keylen = len;
+
+ if (len == AES_KEYSIZE_128) {
+ memcpy(op->key, key, len);
+ return 0;
+ }
+
+ if (len != AES_KEYSIZE_192 && len != AES_KEYSIZE_256) {
+ /* not supported at all */
tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
return -EINVAL;
}
- memcpy(op->key, key, len);
- return 0;
+ /*
+ * The requested key size is not supported by HW, do a fallback
+ */
+ op->fallback.blk->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
+ op->fallback.blk->base.crt_flags |= (tfm->crt_flags & CRYPTO_TFM_REQ_MASK);
+
+ ret = crypto_cipher_setkey(op->fallback.cip, key, len);
+ if (ret) {
+ tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK;
+ tfm->crt_flags |= (op->fallback.blk->base.crt_flags & CRYPTO_TFM_RES_MASK);
+ }
+ return ret;
+}
+
+static int geode_setkey_blk(struct crypto_tfm *tfm, const u8 *key,
+ unsigned int len)
+{
+ struct geode_aes_op *op = crypto_tfm_ctx(tfm);
+ unsigned int ret;
+
+ op->keylen = len;
+
+ if (len == AES_KEYSIZE_128) {
+ memcpy(op->key, key, len);
+ return 0;
+ }
+
+ if (len != AES_KEYSIZE_192 && len != AES_KEYSIZE_256) {
+ /* not supported at all */
+ tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+ return -EINVAL;
+ }
+
+ /*
+ * The requested key size is not supported by HW, do a fallback
+ */
+ op->fallback.blk->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
+ op->fallback.blk->base.crt_flags |= (tfm->crt_flags & CRYPTO_TFM_REQ_MASK);
+
+ ret = crypto_blkcipher_setkey(op->fallback.blk, key, len);
+ if (ret) {
+ tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK;
+ tfm->crt_flags |= (op->fallback.blk->base.crt_flags & CRYPTO_TFM_RES_MASK);
+ }
+ return ret;
+}
+
+static int fallback_blk_dec(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ unsigned int ret;
+ struct crypto_blkcipher *tfm;
+ struct geode_aes_op *op = crypto_blkcipher_ctx(desc->tfm);
+
+ tfm = desc->tfm;
+ desc->tfm = op->fallback.blk;
+
+ ret = crypto_blkcipher_decrypt_iv(desc, dst, src, nbytes);
+
+ desc->tfm = tfm;
+ return ret;
+}
+static int fallback_blk_enc(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ unsigned int ret;
+ struct crypto_blkcipher *tfm;
+ struct geode_aes_op *op = crypto_blkcipher_ctx(desc->tfm);
+
+ tfm = desc->tfm;
+ desc->tfm = op->fallback.blk;
+
+ ret = crypto_blkcipher_encrypt_iv(desc, dst, src, nbytes);
+
+ desc->tfm = tfm;
+ return ret;
}
static void
@@ -160,8 +217,10 @@
{
struct geode_aes_op *op = crypto_tfm_ctx(tfm);
- if ((out == NULL) || (in == NULL))
+ if (unlikely(op->keylen != AES_KEYSIZE_128)) {
+ crypto_cipher_encrypt_one(op->fallback.cip, out, in);
return;
+ }
op->src = (void *) in;
op->dst = (void *) out;
@@ -179,8 +238,10 @@
{
struct geode_aes_op *op = crypto_tfm_ctx(tfm);
- if ((out == NULL) || (in == NULL))
+ if (unlikely(op->keylen != AES_KEYSIZE_128)) {
+ crypto_cipher_decrypt_one(op->fallback.cip, out, in);
return;
+ }
op->src = (void *) in;
op->dst = (void *) out;
@@ -192,24 +253,50 @@
geode_aes_crypt(op);
}
+static int fallback_init_cip(struct crypto_tfm *tfm)
+{
+ const char *name = tfm->__crt_alg->cra_name;
+ struct geode_aes_op *op = crypto_tfm_ctx(tfm);
+
+ op->fallback.cip = crypto_alloc_cipher(name, 0,
+ CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK);
+
+ if (IS_ERR(op->fallback.cip)) {
+ printk(KERN_ERR "Error allocating fallback algo %s\n", name);
+ return PTR_ERR(op->fallback.blk);
+ }
+
+ return 0;
+}
+
+static void fallback_exit_cip(struct crypto_tfm *tfm)
+{
+ struct geode_aes_op *op = crypto_tfm_ctx(tfm);
+
+ crypto_free_cipher(op->fallback.cip);
+ op->fallback.cip = NULL;
+}
static struct crypto_alg geode_alg = {
- .cra_name = "aes",
- .cra_driver_name = "geode-aes-128",
- .cra_priority = 300,
- .cra_alignmask = 15,
- .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+ .cra_name = "aes",
+ .cra_driver_name = "geode-aes",
+ .cra_priority = 300,
+ .cra_alignmask = 15,
+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER |
+ CRYPTO_ALG_NEED_FALLBACK,
+ .cra_init = fallback_init_cip,
+ .cra_exit = fallback_exit_cip,
.cra_blocksize = AES_MIN_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct geode_aes_op),
- .cra_module = THIS_MODULE,
- .cra_list = LIST_HEAD_INIT(geode_alg.cra_list),
- .cra_u = {
- .cipher = {
- .cia_min_keysize = AES_KEY_LENGTH,
- .cia_max_keysize = AES_KEY_LENGTH,
- .cia_setkey = geode_setkey,
- .cia_encrypt = geode_encrypt,
- .cia_decrypt = geode_decrypt
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(geode_alg.cra_list),
+ .cra_u = {
+ .cipher = {
+ .cia_min_keysize = AES_MIN_KEY_SIZE,
+ .cia_max_keysize = AES_MAX_KEY_SIZE,
+ .cia_setkey = geode_setkey_cip,
+ .cia_encrypt = geode_encrypt,
+ .cia_decrypt = geode_decrypt
}
}
};
@@ -223,8 +310,12 @@
struct blkcipher_walk walk;
int err, ret;
+ if (unlikely(op->keylen != AES_KEYSIZE_128))
+ return fallback_blk_dec(desc, dst, src, nbytes);
+
blkcipher_walk_init(&walk, dst, src, nbytes);
err = blkcipher_walk_virt(desc, &walk);
+ op->iv = walk.iv;
while((nbytes = walk.nbytes)) {
op->src = walk.src.virt.addr,
@@ -233,13 +324,9 @@
op->len = nbytes - (nbytes % AES_MIN_BLOCK_SIZE);
op->dir = AES_DIR_DECRYPT;
- memcpy(op->iv, walk.iv, AES_IV_LENGTH);
-
ret = geode_aes_crypt(op);
- memcpy(walk.iv, op->iv, AES_IV_LENGTH);
nbytes -= ret;
-
err = blkcipher_walk_done(desc, &walk, nbytes);
}
@@ -255,8 +342,12 @@
struct blkcipher_walk walk;
int err, ret;
+ if (unlikely(op->keylen != AES_KEYSIZE_128))
+ return fallback_blk_enc(desc, dst, src, nbytes);
+
blkcipher_walk_init(&walk, dst, src, nbytes);
err = blkcipher_walk_virt(desc, &walk);
+ op->iv = walk.iv;
while((nbytes = walk.nbytes)) {
op->src = walk.src.virt.addr,
@@ -265,8 +356,6 @@
op->len = nbytes - (nbytes % AES_MIN_BLOCK_SIZE);
op->dir = AES_DIR_ENCRYPT;
- memcpy(op->iv, walk.iv, AES_IV_LENGTH);
-
ret = geode_aes_crypt(op);
nbytes -= ret;
err = blkcipher_walk_done(desc, &walk, nbytes);
@@ -275,22 +364,49 @@
return err;
}
+static int fallback_init_blk(struct crypto_tfm *tfm)
+{
+ const char *name = tfm->__crt_alg->cra_name;
+ struct geode_aes_op *op = crypto_tfm_ctx(tfm);
+
+ op->fallback.blk = crypto_alloc_blkcipher(name, 0,
+ CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK);
+
+ if (IS_ERR(op->fallback.blk)) {
+ printk(KERN_ERR "Error allocating fallback algo %s\n", name);
+ return PTR_ERR(op->fallback.blk);
+ }
+
+ return 0;
+}
+
+static void fallback_exit_blk(struct crypto_tfm *tfm)
+{
+ struct geode_aes_op *op = crypto_tfm_ctx(tfm);
+
+ crypto_free_blkcipher(op->fallback.blk);
+ op->fallback.blk = NULL;
+}
+
static struct crypto_alg geode_cbc_alg = {
.cra_name = "cbc(aes)",
- .cra_driver_name = "cbc-aes-geode-128",
+ .cra_driver_name = "cbc-aes-geode",
.cra_priority = 400,
- .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER |
+ CRYPTO_ALG_NEED_FALLBACK,
+ .cra_init = fallback_init_blk,
+ .cra_exit = fallback_exit_blk,
.cra_blocksize = AES_MIN_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct geode_aes_op),
.cra_alignmask = 15,
- .cra_type = &crypto_blkcipher_type,
- .cra_module = THIS_MODULE,
- .cra_list = LIST_HEAD_INIT(geode_cbc_alg.cra_list),
- .cra_u = {
- .blkcipher = {
- .min_keysize = AES_KEY_LENGTH,
- .max_keysize = AES_KEY_LENGTH,
- .setkey = geode_setkey,
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(geode_cbc_alg.cra_list),
+ .cra_u = {
+ .blkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .setkey = geode_setkey_blk,
.encrypt = geode_cbc_encrypt,
.decrypt = geode_cbc_decrypt,
.ivsize = AES_IV_LENGTH,
@@ -307,6 +423,9 @@
struct blkcipher_walk walk;
int err, ret;
+ if (unlikely(op->keylen != AES_KEYSIZE_128))
+ return fallback_blk_dec(desc, dst, src, nbytes);
+
blkcipher_walk_init(&walk, dst, src, nbytes);
err = blkcipher_walk_virt(desc, &walk);
@@ -334,6 +453,9 @@
struct blkcipher_walk walk;
int err, ret;
+ if (unlikely(op->keylen != AES_KEYSIZE_128))
+ return fallback_blk_enc(desc, dst, src, nbytes);
+
blkcipher_walk_init(&walk, dst, src, nbytes);
err = blkcipher_walk_virt(desc, &walk);
@@ -353,28 +475,31 @@
}
static struct crypto_alg geode_ecb_alg = {
- .cra_name = "ecb(aes)",
- .cra_driver_name = "ecb-aes-geode-128",
+ .cra_name = "ecb(aes)",
+ .cra_driver_name = "ecb-aes-geode",
.cra_priority = 400,
- .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER |
+ CRYPTO_ALG_NEED_FALLBACK,
+ .cra_init = fallback_init_blk,
+ .cra_exit = fallback_exit_blk,
.cra_blocksize = AES_MIN_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct geode_aes_op),
.cra_alignmask = 15,
- .cra_type = &crypto_blkcipher_type,
- .cra_module = THIS_MODULE,
- .cra_list = LIST_HEAD_INIT(geode_ecb_alg.cra_list),
- .cra_u = {
- .blkcipher = {
- .min_keysize = AES_KEY_LENGTH,
- .max_keysize = AES_KEY_LENGTH,
- .setkey = geode_setkey,
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(geode_ecb_alg.cra_list),
+ .cra_u = {
+ .blkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .setkey = geode_setkey_blk,
.encrypt = geode_ecb_encrypt,
.decrypt = geode_ecb_decrypt,
}
}
};
-static void
+static void __devexit
geode_aes_remove(struct pci_dev *dev)
{
crypto_unregister_alg(&geode_alg);
@@ -389,7 +514,7 @@
}
-static int
+static int __devinit
geode_aes_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
int ret;
@@ -397,7 +522,7 @@
if ((ret = pci_enable_device(dev)))
return ret;
- if ((ret = pci_request_regions(dev, "geode-aes-128")))
+ if ((ret = pci_request_regions(dev, "geode-aes")))
goto eenable;
_iobase = pci_iomap(dev, 0, 0);
@@ -472,7 +597,6 @@
MODULE_AUTHOR("Advanced Micro Devices, Inc.");
MODULE_DESCRIPTION("Geode LX Hardware AES driver");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("aes");
module_init(geode_aes_init);
module_exit(geode_aes_exit);
diff --git a/drivers/crypto/geode-aes.h b/drivers/crypto/geode-aes.h
index f479686..f1855b5 100644
--- a/drivers/crypto/geode-aes.h
+++ b/drivers/crypto/geode-aes.h
@@ -9,9 +9,9 @@
#ifndef _GEODE_AES_H_
#define _GEODE_AES_H_
-#define AES_KEY_LENGTH 16
+/* driver logic flags */
#define AES_IV_LENGTH 16
-
+#define AES_KEY_LENGTH 16
#define AES_MIN_BLOCK_SIZE 16
#define AES_MODE_ECB 0
@@ -22,6 +22,38 @@
#define AES_FLAGS_HIDDENKEY (1 << 0)
+/* Register definitions */
+
+#define AES_CTRLA_REG 0x0000
+
+#define AES_CTRL_START 0x01
+#define AES_CTRL_DECRYPT 0x00
+#define AES_CTRL_ENCRYPT 0x02
+#define AES_CTRL_WRKEY 0x04
+#define AES_CTRL_DCA 0x08
+#define AES_CTRL_SCA 0x10
+#define AES_CTRL_CBC 0x20
+
+#define AES_INTR_REG 0x0008
+
+#define AES_INTRA_PENDING (1 << 16)
+#define AES_INTRB_PENDING (1 << 17)
+
+#define AES_INTR_PENDING (AES_INTRA_PENDING | AES_INTRB_PENDING)
+#define AES_INTR_MASK 0x07
+
+#define AES_SOURCEA_REG 0x0010
+#define AES_DSTA_REG 0x0014
+#define AES_LENA_REG 0x0018
+#define AES_WRITEKEY0_REG 0x0030
+#define AES_WRITEIV0_REG 0x0040
+
+/* A very large counter that is used to gracefully bail out of an
+ * operation in case of trouble
+ */
+
+#define AES_OP_TIMEOUT 0x50000
+
struct geode_aes_op {
void *src;
@@ -33,7 +65,13 @@
int len;
u8 key[AES_KEY_LENGTH];
- u8 iv[AES_IV_LENGTH];
+ u8 *iv;
+
+ union {
+ struct crypto_blkcipher *blk;
+ struct crypto_cipher *cip;
+ } fallback;
+ u32 keylen;
};
#endif
diff --git a/drivers/crypto/hifn_795x.c b/drivers/crypto/hifn_795x.c
new file mode 100644
index 0000000..16413e5
--- /dev/null
+++ b/drivers/crypto/hifn_795x.c
@@ -0,0 +1,2838 @@
+/*
+ * 2007+ Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/mod_devicetable.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/highmem.h>
+#include <linux/interrupt.h>
+#include <linux/crypto.h>
+#include <linux/hw_random.h>
+#include <linux/ktime.h>
+
+#include <crypto/algapi.h>
+#include <crypto/des.h>
+
+#include <asm/kmap_types.h>
+
+#undef dprintk
+
+#define HIFN_TEST
+//#define HIFN_DEBUG
+
+#ifdef HIFN_DEBUG
+#define dprintk(f, a...) printk(f, ##a)
+#else
+#define dprintk(f, a...) do {} while (0)
+#endif
+
+static char hifn_pll_ref[sizeof("extNNN")] = "ext";
+module_param_string(hifn_pll_ref, hifn_pll_ref, sizeof(hifn_pll_ref), 0444);
+MODULE_PARM_DESC(hifn_pll_ref,
+ "PLL reference clock (pci[freq] or ext[freq], default ext)");
+
+static atomic_t hifn_dev_number;
+
+#define ACRYPTO_OP_DECRYPT 0
+#define ACRYPTO_OP_ENCRYPT 1
+#define ACRYPTO_OP_HMAC 2
+#define ACRYPTO_OP_RNG 3
+
+#define ACRYPTO_MODE_ECB 0
+#define ACRYPTO_MODE_CBC 1
+#define ACRYPTO_MODE_CFB 2
+#define ACRYPTO_MODE_OFB 3
+
+#define ACRYPTO_TYPE_AES_128 0
+#define ACRYPTO_TYPE_AES_192 1
+#define ACRYPTO_TYPE_AES_256 2
+#define ACRYPTO_TYPE_3DES 3
+#define ACRYPTO_TYPE_DES 4
+
+#define PCI_VENDOR_ID_HIFN 0x13A3
+#define PCI_DEVICE_ID_HIFN_7955 0x0020
+#define PCI_DEVICE_ID_HIFN_7956 0x001d
+
+/* I/O region sizes */
+
+#define HIFN_BAR0_SIZE 0x1000
+#define HIFN_BAR1_SIZE 0x2000
+#define HIFN_BAR2_SIZE 0x8000
+
+/* DMA registres */
+
+#define HIFN_DMA_CRA 0x0C /* DMA Command Ring Address */
+#define HIFN_DMA_SDRA 0x1C /* DMA Source Data Ring Address */
+#define HIFN_DMA_RRA 0x2C /* DMA Result Ring Address */
+#define HIFN_DMA_DDRA 0x3C /* DMA Destination Data Ring Address */
+#define HIFN_DMA_STCTL 0x40 /* DMA Status and Control */
+#define HIFN_DMA_INTREN 0x44 /* DMA Interrupt Enable */
+#define HIFN_DMA_CFG1 0x48 /* DMA Configuration #1 */
+#define HIFN_DMA_CFG2 0x6C /* DMA Configuration #2 */
+#define HIFN_CHIP_ID 0x98 /* Chip ID */
+
+/*
+ * Processing Unit Registers (offset from BASEREG0)
+ */
+#define HIFN_0_PUDATA 0x00 /* Processing Unit Data */
+#define HIFN_0_PUCTRL 0x04 /* Processing Unit Control */
+#define HIFN_0_PUISR 0x08 /* Processing Unit Interrupt Status */
+#define HIFN_0_PUCNFG 0x0c /* Processing Unit Configuration */
+#define HIFN_0_PUIER 0x10 /* Processing Unit Interrupt Enable */
+#define HIFN_0_PUSTAT 0x14 /* Processing Unit Status/Chip ID */
+#define HIFN_0_FIFOSTAT 0x18 /* FIFO Status */
+#define HIFN_0_FIFOCNFG 0x1c /* FIFO Configuration */
+#define HIFN_0_SPACESIZE 0x20 /* Register space size */
+
+/* Processing Unit Control Register (HIFN_0_PUCTRL) */
+#define HIFN_PUCTRL_CLRSRCFIFO 0x0010 /* clear source fifo */
+#define HIFN_PUCTRL_STOP 0x0008 /* stop pu */
+#define HIFN_PUCTRL_LOCKRAM 0x0004 /* lock ram */
+#define HIFN_PUCTRL_DMAENA 0x0002 /* enable dma */
+#define HIFN_PUCTRL_RESET 0x0001 /* Reset processing unit */
+
+/* Processing Unit Interrupt Status Register (HIFN_0_PUISR) */
+#define HIFN_PUISR_CMDINVAL 0x8000 /* Invalid command interrupt */
+#define HIFN_PUISR_DATAERR 0x4000 /* Data error interrupt */
+#define HIFN_PUISR_SRCFIFO 0x2000 /* Source FIFO ready interrupt */
+#define HIFN_PUISR_DSTFIFO 0x1000 /* Destination FIFO ready interrupt */
+#define HIFN_PUISR_DSTOVER 0x0200 /* Destination overrun interrupt */
+#define HIFN_PUISR_SRCCMD 0x0080 /* Source command interrupt */
+#define HIFN_PUISR_SRCCTX 0x0040 /* Source context interrupt */
+#define HIFN_PUISR_SRCDATA 0x0020 /* Source data interrupt */
+#define HIFN_PUISR_DSTDATA 0x0010 /* Destination data interrupt */
+#define HIFN_PUISR_DSTRESULT 0x0004 /* Destination result interrupt */
+
+/* Processing Unit Configuration Register (HIFN_0_PUCNFG) */
+#define HIFN_PUCNFG_DRAMMASK 0xe000 /* DRAM size mask */
+#define HIFN_PUCNFG_DSZ_256K 0x0000 /* 256k dram */
+#define HIFN_PUCNFG_DSZ_512K 0x2000 /* 512k dram */
+#define HIFN_PUCNFG_DSZ_1M 0x4000 /* 1m dram */
+#define HIFN_PUCNFG_DSZ_2M 0x6000 /* 2m dram */
+#define HIFN_PUCNFG_DSZ_4M 0x8000 /* 4m dram */
+#define HIFN_PUCNFG_DSZ_8M 0xa000 /* 8m dram */
+#define HIFN_PUNCFG_DSZ_16M 0xc000 /* 16m dram */
+#define HIFN_PUCNFG_DSZ_32M 0xe000 /* 32m dram */
+#define HIFN_PUCNFG_DRAMREFRESH 0x1800 /* DRAM refresh rate mask */
+#define HIFN_PUCNFG_DRFR_512 0x0000 /* 512 divisor of ECLK */
+#define HIFN_PUCNFG_DRFR_256 0x0800 /* 256 divisor of ECLK */
+#define HIFN_PUCNFG_DRFR_128 0x1000 /* 128 divisor of ECLK */
+#define HIFN_PUCNFG_TCALLPHASES 0x0200 /* your guess is as good as mine... */
+#define HIFN_PUCNFG_TCDRVTOTEM 0x0100 /* your guess is as good as mine... */
+#define HIFN_PUCNFG_BIGENDIAN 0x0080 /* DMA big endian mode */
+#define HIFN_PUCNFG_BUS32 0x0040 /* Bus width 32bits */
+#define HIFN_PUCNFG_BUS16 0x0000 /* Bus width 16 bits */
+#define HIFN_PUCNFG_CHIPID 0x0020 /* Allow chipid from PUSTAT */
+#define HIFN_PUCNFG_DRAM 0x0010 /* Context RAM is DRAM */
+#define HIFN_PUCNFG_SRAM 0x0000 /* Context RAM is SRAM */
+#define HIFN_PUCNFG_COMPSING 0x0004 /* Enable single compression context */
+#define HIFN_PUCNFG_ENCCNFG 0x0002 /* Encryption configuration */
+
+/* Processing Unit Interrupt Enable Register (HIFN_0_PUIER) */
+#define HIFN_PUIER_CMDINVAL 0x8000 /* Invalid command interrupt */
+#define HIFN_PUIER_DATAERR 0x4000 /* Data error interrupt */
+#define HIFN_PUIER_SRCFIFO 0x2000 /* Source FIFO ready interrupt */
+#define HIFN_PUIER_DSTFIFO 0x1000 /* Destination FIFO ready interrupt */
+#define HIFN_PUIER_DSTOVER 0x0200 /* Destination overrun interrupt */
+#define HIFN_PUIER_SRCCMD 0x0080 /* Source command interrupt */
+#define HIFN_PUIER_SRCCTX 0x0040 /* Source context interrupt */
+#define HIFN_PUIER_SRCDATA 0x0020 /* Source data interrupt */
+#define HIFN_PUIER_DSTDATA 0x0010 /* Destination data interrupt */
+#define HIFN_PUIER_DSTRESULT 0x0004 /* Destination result interrupt */
+
+/* Processing Unit Status Register/Chip ID (HIFN_0_PUSTAT) */
+#define HIFN_PUSTAT_CMDINVAL 0x8000 /* Invalid command interrupt */
+#define HIFN_PUSTAT_DATAERR 0x4000 /* Data error interrupt */
+#define HIFN_PUSTAT_SRCFIFO 0x2000 /* Source FIFO ready interrupt */
+#define HIFN_PUSTAT_DSTFIFO 0x1000 /* Destination FIFO ready interrupt */
+#define HIFN_PUSTAT_DSTOVER 0x0200 /* Destination overrun interrupt */
+#define HIFN_PUSTAT_SRCCMD 0x0080 /* Source command interrupt */
+#define HIFN_PUSTAT_SRCCTX 0x0040 /* Source context interrupt */
+#define HIFN_PUSTAT_SRCDATA 0x0020 /* Source data interrupt */
+#define HIFN_PUSTAT_DSTDATA 0x0010 /* Destination data interrupt */
+#define HIFN_PUSTAT_DSTRESULT 0x0004 /* Destination result interrupt */
+#define HIFN_PUSTAT_CHIPREV 0x00ff /* Chip revision mask */
+#define HIFN_PUSTAT_CHIPENA 0xff00 /* Chip enabled mask */
+#define HIFN_PUSTAT_ENA_2 0x1100 /* Level 2 enabled */
+#define HIFN_PUSTAT_ENA_1 0x1000 /* Level 1 enabled */
+#define HIFN_PUSTAT_ENA_0 0x3000 /* Level 0 enabled */
+#define HIFN_PUSTAT_REV_2 0x0020 /* 7751 PT6/2 */
+#define HIFN_PUSTAT_REV_3 0x0030 /* 7751 PT6/3 */
+
+/* FIFO Status Register (HIFN_0_FIFOSTAT) */
+#define HIFN_FIFOSTAT_SRC 0x7f00 /* Source FIFO available */
+#define HIFN_FIFOSTAT_DST 0x007f /* Destination FIFO available */
+
+/* FIFO Configuration Register (HIFN_0_FIFOCNFG) */
+#define HIFN_FIFOCNFG_THRESHOLD 0x0400 /* must be written as 1 */
+
+/*
+ * DMA Interface Registers (offset from BASEREG1)
+ */
+#define HIFN_1_DMA_CRAR 0x0c /* DMA Command Ring Address */
+#define HIFN_1_DMA_SRAR 0x1c /* DMA Source Ring Address */
+#define HIFN_1_DMA_RRAR 0x2c /* DMA Result Ring Address */
+#define HIFN_1_DMA_DRAR 0x3c /* DMA Destination Ring Address */
+#define HIFN_1_DMA_CSR 0x40 /* DMA Status and Control */
+#define HIFN_1_DMA_IER 0x44 /* DMA Interrupt Enable */
+#define HIFN_1_DMA_CNFG 0x48 /* DMA Configuration */
+#define HIFN_1_PLL 0x4c /* 795x: PLL config */
+#define HIFN_1_7811_RNGENA 0x60 /* 7811: rng enable */
+#define HIFN_1_7811_RNGCFG 0x64 /* 7811: rng config */
+#define HIFN_1_7811_RNGDAT 0x68 /* 7811: rng data */
+#define HIFN_1_7811_RNGSTS 0x6c /* 7811: rng status */
+#define HIFN_1_7811_MIPSRST 0x94 /* 7811: MIPS reset */
+#define HIFN_1_REVID 0x98 /* Revision ID */
+#define HIFN_1_UNLOCK_SECRET1 0xf4
+#define HIFN_1_UNLOCK_SECRET2 0xfc
+#define HIFN_1_PUB_RESET 0x204 /* Public/RNG Reset */
+#define HIFN_1_PUB_BASE 0x300 /* Public Base Address */
+#define HIFN_1_PUB_OPLEN 0x304 /* Public Operand Length */
+#define HIFN_1_PUB_OP 0x308 /* Public Operand */
+#define HIFN_1_PUB_STATUS 0x30c /* Public Status */
+#define HIFN_1_PUB_IEN 0x310 /* Public Interrupt enable */
+#define HIFN_1_RNG_CONFIG 0x314 /* RNG config */
+#define HIFN_1_RNG_DATA 0x318 /* RNG data */
+#define HIFN_1_PUB_MEM 0x400 /* start of Public key memory */
+#define HIFN_1_PUB_MEMEND 0xbff /* end of Public key memory */
+
+/* DMA Status and Control Register (HIFN_1_DMA_CSR) */
+#define HIFN_DMACSR_D_CTRLMASK 0xc0000000 /* Destinition Ring Control */
+#define HIFN_DMACSR_D_CTRL_NOP 0x00000000 /* Dest. Control: no-op */
+#define HIFN_DMACSR_D_CTRL_DIS 0x40000000 /* Dest. Control: disable */
+#define HIFN_DMACSR_D_CTRL_ENA 0x80000000 /* Dest. Control: enable */
+#define HIFN_DMACSR_D_ABORT 0x20000000 /* Destinition Ring PCIAbort */
+#define HIFN_DMACSR_D_DONE 0x10000000 /* Destinition Ring Done */
+#define HIFN_DMACSR_D_LAST 0x08000000 /* Destinition Ring Last */
+#define HIFN_DMACSR_D_WAIT 0x04000000 /* Destinition Ring Waiting */
+#define HIFN_DMACSR_D_OVER 0x02000000 /* Destinition Ring Overflow */
+#define HIFN_DMACSR_R_CTRL 0x00c00000 /* Result Ring Control */
+#define HIFN_DMACSR_R_CTRL_NOP 0x00000000 /* Result Control: no-op */
+#define HIFN_DMACSR_R_CTRL_DIS 0x00400000 /* Result Control: disable */
+#define HIFN_DMACSR_R_CTRL_ENA 0x00800000 /* Result Control: enable */
+#define HIFN_DMACSR_R_ABORT 0x00200000 /* Result Ring PCI Abort */
+#define HIFN_DMACSR_R_DONE 0x00100000 /* Result Ring Done */
+#define HIFN_DMACSR_R_LAST 0x00080000 /* Result Ring Last */
+#define HIFN_DMACSR_R_WAIT 0x00040000 /* Result Ring Waiting */
+#define HIFN_DMACSR_R_OVER 0x00020000 /* Result Ring Overflow */
+#define HIFN_DMACSR_S_CTRL 0x0000c000 /* Source Ring Control */
+#define HIFN_DMACSR_S_CTRL_NOP 0x00000000 /* Source Control: no-op */
+#define HIFN_DMACSR_S_CTRL_DIS 0x00004000 /* Source Control: disable */
+#define HIFN_DMACSR_S_CTRL_ENA 0x00008000 /* Source Control: enable */
+#define HIFN_DMACSR_S_ABORT 0x00002000 /* Source Ring PCI Abort */
+#define HIFN_DMACSR_S_DONE 0x00001000 /* Source Ring Done */
+#define HIFN_DMACSR_S_LAST 0x00000800 /* Source Ring Last */
+#define HIFN_DMACSR_S_WAIT 0x00000400 /* Source Ring Waiting */
+#define HIFN_DMACSR_ILLW 0x00000200 /* Illegal write (7811 only) */
+#define HIFN_DMACSR_ILLR 0x00000100 /* Illegal read (7811 only) */
+#define HIFN_DMACSR_C_CTRL 0x000000c0 /* Command Ring Control */
+#define HIFN_DMACSR_C_CTRL_NOP 0x00000000 /* Command Control: no-op */
+#define HIFN_DMACSR_C_CTRL_DIS 0x00000040 /* Command Control: disable */
+#define HIFN_DMACSR_C_CTRL_ENA 0x00000080 /* Command Control: enable */
+#define HIFN_DMACSR_C_ABORT 0x00000020 /* Command Ring PCI Abort */
+#define HIFN_DMACSR_C_DONE 0x00000010 /* Command Ring Done */
+#define HIFN_DMACSR_C_LAST 0x00000008 /* Command Ring Last */
+#define HIFN_DMACSR_C_WAIT 0x00000004 /* Command Ring Waiting */
+#define HIFN_DMACSR_PUBDONE 0x00000002 /* Public op done (7951 only) */
+#define HIFN_DMACSR_ENGINE 0x00000001 /* Command Ring Engine IRQ */
+
+/* DMA Interrupt Enable Register (HIFN_1_DMA_IER) */
+#define HIFN_DMAIER_D_ABORT 0x20000000 /* Destination Ring PCIAbort */
+#define HIFN_DMAIER_D_DONE 0x10000000 /* Destination Ring Done */
+#define HIFN_DMAIER_D_LAST 0x08000000 /* Destination Ring Last */
+#define HIFN_DMAIER_D_WAIT 0x04000000 /* Destination Ring Waiting */
+#define HIFN_DMAIER_D_OVER 0x02000000 /* Destination Ring Overflow */
+#define HIFN_DMAIER_R_ABORT 0x00200000 /* Result Ring PCI Abort */
+#define HIFN_DMAIER_R_DONE 0x00100000 /* Result Ring Done */
+#define HIFN_DMAIER_R_LAST 0x00080000 /* Result Ring Last */
+#define HIFN_DMAIER_R_WAIT 0x00040000 /* Result Ring Waiting */
+#define HIFN_DMAIER_R_OVER 0x00020000 /* Result Ring Overflow */
+#define HIFN_DMAIER_S_ABORT 0x00002000 /* Source Ring PCI Abort */
+#define HIFN_DMAIER_S_DONE 0x00001000 /* Source Ring Done */
+#define HIFN_DMAIER_S_LAST 0x00000800 /* Source Ring Last */
+#define HIFN_DMAIER_S_WAIT 0x00000400 /* Source Ring Waiting */
+#define HIFN_DMAIER_ILLW 0x00000200 /* Illegal write (7811 only) */
+#define HIFN_DMAIER_ILLR 0x00000100 /* Illegal read (7811 only) */
+#define HIFN_DMAIER_C_ABORT 0x00000020 /* Command Ring PCI Abort */
+#define HIFN_DMAIER_C_DONE 0x00000010 /* Command Ring Done */
+#define HIFN_DMAIER_C_LAST 0x00000008 /* Command Ring Last */
+#define HIFN_DMAIER_C_WAIT 0x00000004 /* Command Ring Waiting */
+#define HIFN_DMAIER_PUBDONE 0x00000002 /* public op done (7951 only) */
+#define HIFN_DMAIER_ENGINE 0x00000001 /* Engine IRQ */
+
+/* DMA Configuration Register (HIFN_1_DMA_CNFG) */
+#define HIFN_DMACNFG_BIGENDIAN 0x10000000 /* big endian mode */
+#define HIFN_DMACNFG_POLLFREQ 0x00ff0000 /* Poll frequency mask */
+#define HIFN_DMACNFG_UNLOCK 0x00000800
+#define HIFN_DMACNFG_POLLINVAL 0x00000700 /* Invalid Poll Scalar */
+#define HIFN_DMACNFG_LAST 0x00000010 /* Host control LAST bit */
+#define HIFN_DMACNFG_MODE 0x00000004 /* DMA mode */
+#define HIFN_DMACNFG_DMARESET 0x00000002 /* DMA Reset # */
+#define HIFN_DMACNFG_MSTRESET 0x00000001 /* Master Reset # */
+
+/* PLL configuration register */
+#define HIFN_PLL_REF_CLK_HBI 0x00000000 /* HBI reference clock */
+#define HIFN_PLL_REF_CLK_PLL 0x00000001 /* PLL reference clock */
+#define HIFN_PLL_BP 0x00000002 /* Reference clock bypass */
+#define HIFN_PLL_PK_CLK_HBI 0x00000000 /* PK engine HBI clock */
+#define HIFN_PLL_PK_CLK_PLL 0x00000008 /* PK engine PLL clock */
+#define HIFN_PLL_PE_CLK_HBI 0x00000000 /* PE engine HBI clock */
+#define HIFN_PLL_PE_CLK_PLL 0x00000010 /* PE engine PLL clock */
+#define HIFN_PLL_RESERVED_1 0x00000400 /* Reserved bit, must be 1 */
+#define HIFN_PLL_ND_SHIFT 11 /* Clock multiplier shift */
+#define HIFN_PLL_ND_MULT_2 0x00000000 /* PLL clock multiplier 2 */
+#define HIFN_PLL_ND_MULT_4 0x00000800 /* PLL clock multiplier 4 */
+#define HIFN_PLL_ND_MULT_6 0x00001000 /* PLL clock multiplier 6 */
+#define HIFN_PLL_ND_MULT_8 0x00001800 /* PLL clock multiplier 8 */
+#define HIFN_PLL_ND_MULT_10 0x00002000 /* PLL clock multiplier 10 */
+#define HIFN_PLL_ND_MULT_12 0x00002800 /* PLL clock multiplier 12 */
+#define HIFN_PLL_IS_1_8 0x00000000 /* charge pump (mult. 1-8) */
+#define HIFN_PLL_IS_9_12 0x00010000 /* charge pump (mult. 9-12) */
+
+#define HIFN_PLL_FCK_MAX 266 /* Maximum PLL frequency */
+
+/* Public key reset register (HIFN_1_PUB_RESET) */
+#define HIFN_PUBRST_RESET 0x00000001 /* reset public/rng unit */
+
+/* Public base address register (HIFN_1_PUB_BASE) */
+#define HIFN_PUBBASE_ADDR 0x00003fff /* base address */
+
+/* Public operand length register (HIFN_1_PUB_OPLEN) */
+#define HIFN_PUBOPLEN_MOD_M 0x0000007f /* modulus length mask */
+#define HIFN_PUBOPLEN_MOD_S 0 /* modulus length shift */
+#define HIFN_PUBOPLEN_EXP_M 0x0003ff80 /* exponent length mask */
+#define HIFN_PUBOPLEN_EXP_S 7 /* exponent lenght shift */
+#define HIFN_PUBOPLEN_RED_M 0x003c0000 /* reducend length mask */
+#define HIFN_PUBOPLEN_RED_S 18 /* reducend length shift */
+
+/* Public operation register (HIFN_1_PUB_OP) */
+#define HIFN_PUBOP_AOFFSET_M 0x0000007f /* A offset mask */
+#define HIFN_PUBOP_AOFFSET_S 0 /* A offset shift */
+#define HIFN_PUBOP_BOFFSET_M 0x00000f80 /* B offset mask */
+#define HIFN_PUBOP_BOFFSET_S 7 /* B offset shift */
+#define HIFN_PUBOP_MOFFSET_M 0x0003f000 /* M offset mask */
+#define HIFN_PUBOP_MOFFSET_S 12 /* M offset shift */
+#define HIFN_PUBOP_OP_MASK 0x003c0000 /* Opcode: */
+#define HIFN_PUBOP_OP_NOP 0x00000000 /* NOP */
+#define HIFN_PUBOP_OP_ADD 0x00040000 /* ADD */
+#define HIFN_PUBOP_OP_ADDC 0x00080000 /* ADD w/carry */
+#define HIFN_PUBOP_OP_SUB 0x000c0000 /* SUB */
+#define HIFN_PUBOP_OP_SUBC 0x00100000 /* SUB w/carry */
+#define HIFN_PUBOP_OP_MODADD 0x00140000 /* Modular ADD */
+#define HIFN_PUBOP_OP_MODSUB 0x00180000 /* Modular SUB */
+#define HIFN_PUBOP_OP_INCA 0x001c0000 /* INC A */
+#define HIFN_PUBOP_OP_DECA 0x00200000 /* DEC A */
+#define HIFN_PUBOP_OP_MULT 0x00240000 /* MULT */
+#define HIFN_PUBOP_OP_MODMULT 0x00280000 /* Modular MULT */
+#define HIFN_PUBOP_OP_MODRED 0x002c0000 /* Modular RED */
+#define HIFN_PUBOP_OP_MODEXP 0x00300000 /* Modular EXP */
+
+/* Public status register (HIFN_1_PUB_STATUS) */
+#define HIFN_PUBSTS_DONE 0x00000001 /* operation done */
+#define HIFN_PUBSTS_CARRY 0x00000002 /* carry */
+
+/* Public interrupt enable register (HIFN_1_PUB_IEN) */
+#define HIFN_PUBIEN_DONE 0x00000001 /* operation done interrupt */
+
+/* Random number generator config register (HIFN_1_RNG_CONFIG) */
+#define HIFN_RNGCFG_ENA 0x00000001 /* enable rng */
+
+#define HIFN_NAMESIZE 32
+#define HIFN_MAX_RESULT_ORDER 5
+
+#define HIFN_D_CMD_RSIZE 24*4
+#define HIFN_D_SRC_RSIZE 80*4
+#define HIFN_D_DST_RSIZE 80*4
+#define HIFN_D_RES_RSIZE 24*4
+
+#define HIFN_QUEUE_LENGTH HIFN_D_CMD_RSIZE-5
+
+#define AES_MIN_KEY_SIZE 16
+#define AES_MAX_KEY_SIZE 32
+
+#define HIFN_DES_KEY_LENGTH 8
+#define HIFN_3DES_KEY_LENGTH 24
+#define HIFN_MAX_CRYPT_KEY_LENGTH AES_MAX_KEY_SIZE
+#define HIFN_IV_LENGTH 8
+#define HIFN_AES_IV_LENGTH 16
+#define HIFN_MAX_IV_LENGTH HIFN_AES_IV_LENGTH
+
+#define HIFN_MAC_KEY_LENGTH 64
+#define HIFN_MD5_LENGTH 16
+#define HIFN_SHA1_LENGTH 20
+#define HIFN_MAC_TRUNC_LENGTH 12
+
+#define HIFN_MAX_COMMAND (8 + 8 + 8 + 64 + 260)
+#define HIFN_MAX_RESULT (8 + 4 + 4 + 20 + 4)
+#define HIFN_USED_RESULT 12
+
+struct hifn_desc
+{
+ volatile u32 l;
+ volatile u32 p;
+};
+
+struct hifn_dma {
+ struct hifn_desc cmdr[HIFN_D_CMD_RSIZE+1];
+ struct hifn_desc srcr[HIFN_D_SRC_RSIZE+1];
+ struct hifn_desc dstr[HIFN_D_DST_RSIZE+1];
+ struct hifn_desc resr[HIFN_D_RES_RSIZE+1];
+
+ u8 command_bufs[HIFN_D_CMD_RSIZE][HIFN_MAX_COMMAND];
+ u8 result_bufs[HIFN_D_CMD_RSIZE][HIFN_MAX_RESULT];
+
+ u64 test_src, test_dst;
+
+ /*
+ * Our current positions for insertion and removal from the descriptor
+ * rings.
+ */
+ volatile int cmdi, srci, dsti, resi;
+ volatile int cmdu, srcu, dstu, resu;
+ int cmdk, srck, dstk, resk;
+};
+
+#define HIFN_FLAG_CMD_BUSY (1<<0)
+#define HIFN_FLAG_SRC_BUSY (1<<1)
+#define HIFN_FLAG_DST_BUSY (1<<2)
+#define HIFN_FLAG_RES_BUSY (1<<3)
+#define HIFN_FLAG_OLD_KEY (1<<4)
+
+#define HIFN_DEFAULT_ACTIVE_NUM 5
+
+struct hifn_device
+{
+ char name[HIFN_NAMESIZE];
+
+ int irq;
+
+ struct pci_dev *pdev;
+ void __iomem *bar[3];
+
+ unsigned long result_mem;
+ dma_addr_t dst;
+
+ void *desc_virt;
+ dma_addr_t desc_dma;
+
+ u32 dmareg;
+
+ void *sa[HIFN_D_RES_RSIZE];
+
+ spinlock_t lock;
+
+ void *priv;
+
+ u32 flags;
+ int active, started;
+ struct delayed_work work;
+ unsigned long reset;
+ unsigned long success;
+ unsigned long prev_success;
+
+ u8 snum;
+
+ struct tasklet_struct tasklet;
+
+ struct crypto_queue queue;
+ struct list_head alg_list;
+
+ unsigned int pk_clk_freq;
+
+#if defined(CONFIG_HW_RANDOM) || defined(CONFIG_HW_RANDOM_MODULE)
+ unsigned int rng_wait_time;
+ ktime_t rngtime;
+ struct hwrng rng;
+#endif
+};
+
+#define HIFN_D_LENGTH 0x0000ffff
+#define HIFN_D_NOINVALID 0x01000000
+#define HIFN_D_MASKDONEIRQ 0x02000000
+#define HIFN_D_DESTOVER 0x04000000
+#define HIFN_D_OVER 0x08000000
+#define HIFN_D_LAST 0x20000000
+#define HIFN_D_JUMP 0x40000000
+#define HIFN_D_VALID 0x80000000
+
+struct hifn_base_command
+{
+ volatile u16 masks;
+ volatile u16 session_num;
+ volatile u16 total_source_count;
+ volatile u16 total_dest_count;
+};
+
+#define HIFN_BASE_CMD_COMP 0x0100 /* enable compression engine */
+#define HIFN_BASE_CMD_PAD 0x0200 /* enable padding engine */
+#define HIFN_BASE_CMD_MAC 0x0400 /* enable MAC engine */
+#define HIFN_BASE_CMD_CRYPT 0x0800 /* enable crypt engine */
+#define HIFN_BASE_CMD_DECODE 0x2000
+#define HIFN_BASE_CMD_SRCLEN_M 0xc000
+#define HIFN_BASE_CMD_SRCLEN_S 14
+#define HIFN_BASE_CMD_DSTLEN_M 0x3000
+#define HIFN_BASE_CMD_DSTLEN_S 12
+#define HIFN_BASE_CMD_LENMASK_HI 0x30000
+#define HIFN_BASE_CMD_LENMASK_LO 0x0ffff
+
+/*
+ * Structure to help build up the command data structure.
+ */
+struct hifn_crypt_command
+{
+ volatile u16 masks;
+ volatile u16 header_skip;
+ volatile u16 source_count;
+ volatile u16 reserved;
+};
+
+#define HIFN_CRYPT_CMD_ALG_MASK 0x0003 /* algorithm: */
+#define HIFN_CRYPT_CMD_ALG_DES 0x0000 /* DES */
+#define HIFN_CRYPT_CMD_ALG_3DES 0x0001 /* 3DES */
+#define HIFN_CRYPT_CMD_ALG_RC4 0x0002 /* RC4 */
+#define HIFN_CRYPT_CMD_ALG_AES 0x0003 /* AES */
+#define HIFN_CRYPT_CMD_MODE_MASK 0x0018 /* Encrypt mode: */
+#define HIFN_CRYPT_CMD_MODE_ECB 0x0000 /* ECB */
+#define HIFN_CRYPT_CMD_MODE_CBC 0x0008 /* CBC */
+#define HIFN_CRYPT_CMD_MODE_CFB 0x0010 /* CFB */
+#define HIFN_CRYPT_CMD_MODE_OFB 0x0018 /* OFB */
+#define HIFN_CRYPT_CMD_CLR_CTX 0x0040 /* clear context */
+#define HIFN_CRYPT_CMD_KSZ_MASK 0x0600 /* AES key size: */
+#define HIFN_CRYPT_CMD_KSZ_128 0x0000 /* 128 bit */
+#define HIFN_CRYPT_CMD_KSZ_192 0x0200 /* 192 bit */
+#define HIFN_CRYPT_CMD_KSZ_256 0x0400 /* 256 bit */
+#define HIFN_CRYPT_CMD_NEW_KEY 0x0800 /* expect new key */
+#define HIFN_CRYPT_CMD_NEW_IV 0x1000 /* expect new iv */
+#define HIFN_CRYPT_CMD_SRCLEN_M 0xc000
+#define HIFN_CRYPT_CMD_SRCLEN_S 14
+
+/*
+ * Structure to help build up the command data structure.
+ */
+struct hifn_mac_command
+{
+ volatile u16 masks;
+ volatile u16 header_skip;
+ volatile u16 source_count;
+ volatile u16 reserved;
+};
+
+#define HIFN_MAC_CMD_ALG_MASK 0x0001
+#define HIFN_MAC_CMD_ALG_SHA1 0x0000
+#define HIFN_MAC_CMD_ALG_MD5 0x0001
+#define HIFN_MAC_CMD_MODE_MASK 0x000c
+#define HIFN_MAC_CMD_MODE_HMAC 0x0000
+#define HIFN_MAC_CMD_MODE_SSL_MAC 0x0004
+#define HIFN_MAC_CMD_MODE_HASH 0x0008
+#define HIFN_MAC_CMD_MODE_FULL 0x0004
+#define HIFN_MAC_CMD_TRUNC 0x0010
+#define HIFN_MAC_CMD_RESULT 0x0020
+#define HIFN_MAC_CMD_APPEND 0x0040
+#define HIFN_MAC_CMD_SRCLEN_M 0xc000
+#define HIFN_MAC_CMD_SRCLEN_S 14
+
+/*
+ * MAC POS IPsec initiates authentication after encryption on encodes
+ * and before decryption on decodes.
+ */
+#define HIFN_MAC_CMD_POS_IPSEC 0x0200
+#define HIFN_MAC_CMD_NEW_KEY 0x0800
+
+struct hifn_comp_command
+{
+ volatile u16 masks;
+ volatile u16 header_skip;
+ volatile u16 source_count;
+ volatile u16 reserved;
+};
+
+#define HIFN_COMP_CMD_SRCLEN_M 0xc000
+#define HIFN_COMP_CMD_SRCLEN_S 14
+#define HIFN_COMP_CMD_ONE 0x0100 /* must be one */
+#define HIFN_COMP_CMD_CLEARHIST 0x0010 /* clear history */
+#define HIFN_COMP_CMD_UPDATEHIST 0x0008 /* update history */
+#define HIFN_COMP_CMD_LZS_STRIP0 0x0004 /* LZS: strip zero */
+#define HIFN_COMP_CMD_MPPC_RESTART 0x0004 /* MPPC: restart */
+#define HIFN_COMP_CMD_ALG_MASK 0x0001 /* compression mode: */
+#define HIFN_COMP_CMD_ALG_MPPC 0x0001 /* MPPC */
+#define HIFN_COMP_CMD_ALG_LZS 0x0000 /* LZS */
+
+struct hifn_base_result
+{
+ volatile u16 flags;
+ volatile u16 session;
+ volatile u16 src_cnt; /* 15:0 of source count */
+ volatile u16 dst_cnt; /* 15:0 of dest count */
+};
+
+#define HIFN_BASE_RES_DSTOVERRUN 0x0200 /* destination overrun */
+#define HIFN_BASE_RES_SRCLEN_M 0xc000 /* 17:16 of source count */
+#define HIFN_BASE_RES_SRCLEN_S 14
+#define HIFN_BASE_RES_DSTLEN_M 0x3000 /* 17:16 of dest count */
+#define HIFN_BASE_RES_DSTLEN_S 12
+
+struct hifn_comp_result
+{
+ volatile u16 flags;
+ volatile u16 crc;
+};
+
+#define HIFN_COMP_RES_LCB_M 0xff00 /* longitudinal check byte */
+#define HIFN_COMP_RES_LCB_S 8
+#define HIFN_COMP_RES_RESTART 0x0004 /* MPPC: restart */
+#define HIFN_COMP_RES_ENDMARKER 0x0002 /* LZS: end marker seen */
+#define HIFN_COMP_RES_SRC_NOTZERO 0x0001 /* source expired */
+
+struct hifn_mac_result
+{
+ volatile u16 flags;
+ volatile u16 reserved;
+ /* followed by 0, 6, 8, or 10 u16's of the MAC, then crypt */
+};
+
+#define HIFN_MAC_RES_MISCOMPARE 0x0002 /* compare failed */
+#define HIFN_MAC_RES_SRC_NOTZERO 0x0001 /* source expired */
+
+struct hifn_crypt_result
+{
+ volatile u16 flags;
+ volatile u16 reserved;
+};
+
+#define HIFN_CRYPT_RES_SRC_NOTZERO 0x0001 /* source expired */
+
+#ifndef HIFN_POLL_FREQUENCY
+#define HIFN_POLL_FREQUENCY 0x1
+#endif
+
+#ifndef HIFN_POLL_SCALAR
+#define HIFN_POLL_SCALAR 0x0
+#endif
+
+#define HIFN_MAX_SEGLEN 0xffff /* maximum dma segment len */
+#define HIFN_MAX_DMALEN 0x3ffff /* maximum dma length */
+
+struct hifn_crypto_alg
+{
+ struct list_head entry;
+ struct crypto_alg alg;
+ struct hifn_device *dev;
+};
+
+#define ASYNC_SCATTERLIST_CACHE 16
+
+#define ASYNC_FLAGS_MISALIGNED (1<<0)
+
+struct ablkcipher_walk
+{
+ struct scatterlist cache[ASYNC_SCATTERLIST_CACHE];
+ u32 flags;
+ int num;
+};
+
+struct hifn_context
+{
+ u8 key[HIFN_MAX_CRYPT_KEY_LENGTH], *iv;
+ struct hifn_device *dev;
+ unsigned int keysize, ivsize;
+ u8 op, type, mode, unused;
+ struct ablkcipher_walk walk;
+ atomic_t sg_num;
+};
+
+#define crypto_alg_to_hifn(a) container_of(a, struct hifn_crypto_alg, alg)
+
+static inline u32 hifn_read_0(struct hifn_device *dev, u32 reg)
+{
+ u32 ret;
+
+ ret = readl((char *)(dev->bar[0]) + reg);
+
+ return ret;
+}
+
+static inline u32 hifn_read_1(struct hifn_device *dev, u32 reg)
+{
+ u32 ret;
+
+ ret = readl((char *)(dev->bar[1]) + reg);
+
+ return ret;
+}
+
+static inline void hifn_write_0(struct hifn_device *dev, u32 reg, u32 val)
+{
+ writel(val, (char *)(dev->bar[0]) + reg);
+}
+
+static inline void hifn_write_1(struct hifn_device *dev, u32 reg, u32 val)
+{
+ writel(val, (char *)(dev->bar[1]) + reg);
+}
+
+static void hifn_wait_puc(struct hifn_device *dev)
+{
+ int i;
+ u32 ret;
+
+ for (i=10000; i > 0; --i) {
+ ret = hifn_read_0(dev, HIFN_0_PUCTRL);
+ if (!(ret & HIFN_PUCTRL_RESET))
+ break;
+
+ udelay(1);
+ }
+
+ if (!i)
+ dprintk("%s: Failed to reset PUC unit.\n", dev->name);
+}
+
+static void hifn_reset_puc(struct hifn_device *dev)
+{
+ hifn_write_0(dev, HIFN_0_PUCTRL, HIFN_PUCTRL_DMAENA);
+ hifn_wait_puc(dev);
+}
+
+static void hifn_stop_device(struct hifn_device *dev)
+{
+ hifn_write_1(dev, HIFN_1_DMA_CSR,
+ HIFN_DMACSR_D_CTRL_DIS | HIFN_DMACSR_R_CTRL_DIS |
+ HIFN_DMACSR_S_CTRL_DIS | HIFN_DMACSR_C_CTRL_DIS);
+ hifn_write_0(dev, HIFN_0_PUIER, 0);
+ hifn_write_1(dev, HIFN_1_DMA_IER, 0);
+}
+
+static void hifn_reset_dma(struct hifn_device *dev, int full)
+{
+ hifn_stop_device(dev);
+
+ /*
+ * Setting poll frequency and others to 0.
+ */
+ hifn_write_1(dev, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
+ HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
+ mdelay(1);
+
+ /*
+ * Reset DMA.
+ */
+ if (full) {
+ hifn_write_1(dev, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MODE);
+ mdelay(1);
+ } else {
+ hifn_write_1(dev, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MODE |
+ HIFN_DMACNFG_MSTRESET);
+ hifn_reset_puc(dev);
+ }
+
+ hifn_write_1(dev, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
+ HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
+
+ hifn_reset_puc(dev);
+}
+
+static u32 hifn_next_signature(u_int32_t a, u_int cnt)
+{
+ int i;
+ u32 v;
+
+ for (i = 0; i < cnt; i++) {
+
+ /* get the parity */
+ v = a & 0x80080125;
+ v ^= v >> 16;
+ v ^= v >> 8;
+ v ^= v >> 4;
+ v ^= v >> 2;
+ v ^= v >> 1;
+
+ a = (v & 1) ^ (a << 1);
+ }
+
+ return a;
+}
+
+static struct pci2id {
+ u_short pci_vendor;
+ u_short pci_prod;
+ char card_id[13];
+} pci2id[] = {
+ {
+ PCI_VENDOR_ID_HIFN,
+ PCI_DEVICE_ID_HIFN_7955,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00 }
+ },
+ {
+ PCI_VENDOR_ID_HIFN,
+ PCI_DEVICE_ID_HIFN_7956,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00 }
+ }
+};
+
+#if defined(CONFIG_HW_RANDOM) || defined(CONFIG_HW_RANDOM_MODULE)
+static int hifn_rng_data_present(struct hwrng *rng, int wait)
+{
+ struct hifn_device *dev = (struct hifn_device *)rng->priv;
+ s64 nsec;
+
+ nsec = ktime_to_ns(ktime_sub(ktime_get(), dev->rngtime));
+ nsec -= dev->rng_wait_time;
+ if (nsec <= 0)
+ return 1;
+ if (!wait)
+ return 0;
+ ndelay(nsec);
+ return 1;
+}
+
+static int hifn_rng_data_read(struct hwrng *rng, u32 *data)
+{
+ struct hifn_device *dev = (struct hifn_device *)rng->priv;
+
+ *data = hifn_read_1(dev, HIFN_1_RNG_DATA);
+ dev->rngtime = ktime_get();
+ return 4;
+}
+
+static int hifn_register_rng(struct hifn_device *dev)
+{
+ /*
+ * We must wait at least 256 Pk_clk cycles between two reads of the rng.
+ */
+ dev->rng_wait_time = DIV_ROUND_UP(NSEC_PER_SEC, dev->pk_clk_freq) *
+ 256;
+
+ dev->rng.name = dev->name;
+ dev->rng.data_present = hifn_rng_data_present,
+ dev->rng.data_read = hifn_rng_data_read,
+ dev->rng.priv = (unsigned long)dev;
+
+ return hwrng_register(&dev->rng);
+}
+
+static void hifn_unregister_rng(struct hifn_device *dev)
+{
+ hwrng_unregister(&dev->rng);
+}
+#else
+#define hifn_register_rng(dev) 0
+#define hifn_unregister_rng(dev)
+#endif
+
+static int hifn_init_pubrng(struct hifn_device *dev)
+{
+ int i;
+
+ hifn_write_1(dev, HIFN_1_PUB_RESET, hifn_read_1(dev, HIFN_1_PUB_RESET) |
+ HIFN_PUBRST_RESET);
+
+ for (i=100; i > 0; --i) {
+ mdelay(1);
+
+ if ((hifn_read_1(dev, HIFN_1_PUB_RESET) & HIFN_PUBRST_RESET) == 0)
+ break;
+ }
+
+ if (!i)
+ dprintk("Chip %s: Failed to initialise public key engine.\n",
+ dev->name);
+ else {
+ hifn_write_1(dev, HIFN_1_PUB_IEN, HIFN_PUBIEN_DONE);
+ dev->dmareg |= HIFN_DMAIER_PUBDONE;
+ hifn_write_1(dev, HIFN_1_DMA_IER, dev->dmareg);
+
+ dprintk("Chip %s: Public key engine has been sucessfully "
+ "initialised.\n", dev->name);
+ }
+
+ /*
+ * Enable RNG engine.
+ */
+
+ hifn_write_1(dev, HIFN_1_RNG_CONFIG,
+ hifn_read_1(dev, HIFN_1_RNG_CONFIG) | HIFN_RNGCFG_ENA);
+ dprintk("Chip %s: RNG engine has been successfully initialised.\n",
+ dev->name);
+
+#if defined(CONFIG_HW_RANDOM) || defined(CONFIG_HW_RANDOM_MODULE)
+ /* First value must be discarded */
+ hifn_read_1(dev, HIFN_1_RNG_DATA);
+ dev->rngtime = ktime_get();
+#endif
+ return 0;
+}
+
+static int hifn_enable_crypto(struct hifn_device *dev)
+{
+ u32 dmacfg, addr;
+ char *offtbl = NULL;
+ int i;
+
+ for (i = 0; i < sizeof(pci2id)/sizeof(pci2id[0]); i++) {
+ if (pci2id[i].pci_vendor == dev->pdev->vendor &&
+ pci2id[i].pci_prod == dev->pdev->device) {
+ offtbl = pci2id[i].card_id;
+ break;
+ }
+ }
+
+ if (offtbl == NULL) {
+ dprintk("Chip %s: Unknown card!\n", dev->name);
+ return -ENODEV;
+ }
+
+ dmacfg = hifn_read_1(dev, HIFN_1_DMA_CNFG);
+
+ hifn_write_1(dev, HIFN_1_DMA_CNFG,
+ HIFN_DMACNFG_UNLOCK | HIFN_DMACNFG_MSTRESET |
+ HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
+ mdelay(1);
+ addr = hifn_read_1(dev, HIFN_1_UNLOCK_SECRET1);
+ mdelay(1);
+ hifn_write_1(dev, HIFN_1_UNLOCK_SECRET2, 0);
+ mdelay(1);
+
+ for (i=0; i<12; ++i) {
+ addr = hifn_next_signature(addr, offtbl[i] + 0x101);
+ hifn_write_1(dev, HIFN_1_UNLOCK_SECRET2, addr);
+
+ mdelay(1);
+ }
+ hifn_write_1(dev, HIFN_1_DMA_CNFG, dmacfg);
+
+ dprintk("Chip %s: %s.\n", dev->name, pci_name(dev->pdev));
+
+ return 0;
+}
+
+static void hifn_init_dma(struct hifn_device *dev)
+{
+ struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt;
+ u32 dptr = dev->desc_dma;
+ int i;
+
+ for (i=0; i<HIFN_D_CMD_RSIZE; ++i)
+ dma->cmdr[i].p = __cpu_to_le32(dptr +
+ offsetof(struct hifn_dma, command_bufs[i][0]));
+ for (i=0; i<HIFN_D_RES_RSIZE; ++i)
+ dma->resr[i].p = __cpu_to_le32(dptr +
+ offsetof(struct hifn_dma, result_bufs[i][0]));
+
+ /*
+ * Setup LAST descriptors.
+ */
+ dma->cmdr[HIFN_D_CMD_RSIZE].p = __cpu_to_le32(dptr +
+ offsetof(struct hifn_dma, cmdr[0]));
+ dma->srcr[HIFN_D_SRC_RSIZE].p = __cpu_to_le32(dptr +
+ offsetof(struct hifn_dma, srcr[0]));
+ dma->dstr[HIFN_D_DST_RSIZE].p = __cpu_to_le32(dptr +
+ offsetof(struct hifn_dma, dstr[0]));
+ dma->resr[HIFN_D_RES_RSIZE].p = __cpu_to_le32(dptr +
+ offsetof(struct hifn_dma, resr[0]));
+
+ dma->cmdu = dma->srcu = dma->dstu = dma->resu = 0;
+ dma->cmdi = dma->srci = dma->dsti = dma->resi = 0;
+ dma->cmdk = dma->srck = dma->dstk = dma->resk = 0;
+}
+
+/*
+ * Initialize the PLL. We need to know the frequency of the reference clock
+ * to calculate the optimal multiplier. For PCI we assume 66MHz, since that
+ * allows us to operate without the risk of overclocking the chip. If it
+ * actually uses 33MHz, the chip will operate at half the speed, this can be
+ * overriden by specifying the frequency as module parameter (pci33).
+ *
+ * Unfortunately the PCI clock is not very suitable since the HIFN needs a
+ * stable clock and the PCI clock frequency may vary, so the default is the
+ * external clock. There is no way to find out its frequency, we default to
+ * 66MHz since according to Mike Ham of HiFn, almost every board in existence
+ * has an external crystal populated at 66MHz.
+ */
+static void hifn_init_pll(struct hifn_device *dev)
+{
+ unsigned int freq, m;
+ u32 pllcfg;
+
+ pllcfg = HIFN_1_PLL | HIFN_PLL_RESERVED_1;
+
+ if (strncmp(hifn_pll_ref, "ext", 3) == 0)
+ pllcfg |= HIFN_PLL_REF_CLK_PLL;
+ else
+ pllcfg |= HIFN_PLL_REF_CLK_HBI;
+
+ if (hifn_pll_ref[3] != '\0')
+ freq = simple_strtoul(hifn_pll_ref + 3, NULL, 10);
+ else {
+ freq = 66;
+ printk(KERN_INFO "hifn795x: assuming %uMHz clock speed, "
+ "override with hifn_pll_ref=%.3s<frequency>\n",
+ freq, hifn_pll_ref);
+ }
+
+ m = HIFN_PLL_FCK_MAX / freq;
+
+ pllcfg |= (m / 2 - 1) << HIFN_PLL_ND_SHIFT;
+ if (m <= 8)
+ pllcfg |= HIFN_PLL_IS_1_8;
+ else
+ pllcfg |= HIFN_PLL_IS_9_12;
+
+ /* Select clock source and enable clock bypass */
+ hifn_write_1(dev, HIFN_1_PLL, pllcfg |
+ HIFN_PLL_PK_CLK_HBI | HIFN_PLL_PE_CLK_HBI | HIFN_PLL_BP);
+
+ /* Let the chip lock to the input clock */
+ mdelay(10);
+
+ /* Disable clock bypass */
+ hifn_write_1(dev, HIFN_1_PLL, pllcfg |
+ HIFN_PLL_PK_CLK_HBI | HIFN_PLL_PE_CLK_HBI);
+
+ /* Switch the engines to the PLL */
+ hifn_write_1(dev, HIFN_1_PLL, pllcfg |
+ HIFN_PLL_PK_CLK_PLL | HIFN_PLL_PE_CLK_PLL);
+
+ /*
+ * The Fpk_clk runs at half the total speed. Its frequency is needed to
+ * calculate the minimum time between two reads of the rng. Since 33MHz
+ * is actually 33.333... we overestimate the frequency here, resulting
+ * in slightly larger intervals.
+ */
+ dev->pk_clk_freq = 1000000 * (freq + 1) * m / 2;
+}
+
+static void hifn_init_registers(struct hifn_device *dev)
+{
+ u32 dptr = dev->desc_dma;
+
+ /* Initialization magic... */
+ hifn_write_0(dev, HIFN_0_PUCTRL, HIFN_PUCTRL_DMAENA);
+ hifn_write_0(dev, HIFN_0_FIFOCNFG, HIFN_FIFOCNFG_THRESHOLD);
+ hifn_write_0(dev, HIFN_0_PUIER, HIFN_PUIER_DSTOVER);
+
+ /* write all 4 ring address registers */
+ hifn_write_1(dev, HIFN_1_DMA_CRAR, __cpu_to_le32(dptr +
+ offsetof(struct hifn_dma, cmdr[0])));
+ hifn_write_1(dev, HIFN_1_DMA_SRAR, __cpu_to_le32(dptr +
+ offsetof(struct hifn_dma, srcr[0])));
+ hifn_write_1(dev, HIFN_1_DMA_DRAR, __cpu_to_le32(dptr +
+ offsetof(struct hifn_dma, dstr[0])));
+ hifn_write_1(dev, HIFN_1_DMA_RRAR, __cpu_to_le32(dptr +
+ offsetof(struct hifn_dma, resr[0])));
+
+ mdelay(2);
+#if 0
+ hifn_write_1(dev, HIFN_1_DMA_CSR,
+ HIFN_DMACSR_D_CTRL_DIS | HIFN_DMACSR_R_CTRL_DIS |
+ HIFN_DMACSR_S_CTRL_DIS | HIFN_DMACSR_C_CTRL_DIS |
+ HIFN_DMACSR_D_ABORT | HIFN_DMACSR_D_DONE | HIFN_DMACSR_D_LAST |
+ HIFN_DMACSR_D_WAIT | HIFN_DMACSR_D_OVER |
+ HIFN_DMACSR_R_ABORT | HIFN_DMACSR_R_DONE | HIFN_DMACSR_R_LAST |
+ HIFN_DMACSR_R_WAIT | HIFN_DMACSR_R_OVER |
+ HIFN_DMACSR_S_ABORT | HIFN_DMACSR_S_DONE | HIFN_DMACSR_S_LAST |
+ HIFN_DMACSR_S_WAIT |
+ HIFN_DMACSR_C_ABORT | HIFN_DMACSR_C_DONE | HIFN_DMACSR_C_LAST |
+ HIFN_DMACSR_C_WAIT |
+ HIFN_DMACSR_ENGINE |
+ HIFN_DMACSR_PUBDONE);
+#else
+ hifn_write_1(dev, HIFN_1_DMA_CSR,
+ HIFN_DMACSR_C_CTRL_ENA | HIFN_DMACSR_S_CTRL_ENA |
+ HIFN_DMACSR_D_CTRL_ENA | HIFN_DMACSR_R_CTRL_ENA |
+ HIFN_DMACSR_D_ABORT | HIFN_DMACSR_D_DONE | HIFN_DMACSR_D_LAST |
+ HIFN_DMACSR_D_WAIT | HIFN_DMACSR_D_OVER |
+ HIFN_DMACSR_R_ABORT | HIFN_DMACSR_R_DONE | HIFN_DMACSR_R_LAST |
+ HIFN_DMACSR_R_WAIT | HIFN_DMACSR_R_OVER |
+ HIFN_DMACSR_S_ABORT | HIFN_DMACSR_S_DONE | HIFN_DMACSR_S_LAST |
+ HIFN_DMACSR_S_WAIT |
+ HIFN_DMACSR_C_ABORT | HIFN_DMACSR_C_DONE | HIFN_DMACSR_C_LAST |
+ HIFN_DMACSR_C_WAIT |
+ HIFN_DMACSR_ENGINE |
+ HIFN_DMACSR_PUBDONE);
+#endif
+ hifn_read_1(dev, HIFN_1_DMA_CSR);
+
+ dev->dmareg |= HIFN_DMAIER_R_DONE | HIFN_DMAIER_C_ABORT |
+ HIFN_DMAIER_D_OVER | HIFN_DMAIER_R_OVER |
+ HIFN_DMAIER_S_ABORT | HIFN_DMAIER_D_ABORT | HIFN_DMAIER_R_ABORT |
+ HIFN_DMAIER_ENGINE;
+ dev->dmareg &= ~HIFN_DMAIER_C_WAIT;
+
+ hifn_write_1(dev, HIFN_1_DMA_IER, dev->dmareg);
+ hifn_read_1(dev, HIFN_1_DMA_IER);
+#if 0
+ hifn_write_0(dev, HIFN_0_PUCNFG, HIFN_PUCNFG_ENCCNFG |
+ HIFN_PUCNFG_DRFR_128 | HIFN_PUCNFG_TCALLPHASES |
+ HIFN_PUCNFG_TCDRVTOTEM | HIFN_PUCNFG_BUS32 |
+ HIFN_PUCNFG_DRAM);
+#else
+ hifn_write_0(dev, HIFN_0_PUCNFG, 0x10342);
+#endif
+ hifn_init_pll(dev);
+
+ hifn_write_0(dev, HIFN_0_PUISR, HIFN_PUISR_DSTOVER);
+ hifn_write_1(dev, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
+ HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE | HIFN_DMACNFG_LAST |
+ ((HIFN_POLL_FREQUENCY << 16 ) & HIFN_DMACNFG_POLLFREQ) |
+ ((HIFN_POLL_SCALAR << 8) & HIFN_DMACNFG_POLLINVAL));
+}
+
+static int hifn_setup_base_command(struct hifn_device *dev, u8 *buf,
+ unsigned dlen, unsigned slen, u16 mask, u8 snum)
+{
+ struct hifn_base_command *base_cmd;
+ u8 *buf_pos = buf;
+
+ base_cmd = (struct hifn_base_command *)buf_pos;
+ base_cmd->masks = __cpu_to_le16(mask);
+ base_cmd->total_source_count =
+ __cpu_to_le16(slen & HIFN_BASE_CMD_LENMASK_LO);
+ base_cmd->total_dest_count =
+ __cpu_to_le16(dlen & HIFN_BASE_CMD_LENMASK_LO);
+
+ dlen >>= 16;
+ slen >>= 16;
+ base_cmd->session_num = __cpu_to_le16(snum |
+ ((slen << HIFN_BASE_CMD_SRCLEN_S) & HIFN_BASE_CMD_SRCLEN_M) |
+ ((dlen << HIFN_BASE_CMD_DSTLEN_S) & HIFN_BASE_CMD_DSTLEN_M));
+
+ return sizeof(struct hifn_base_command);
+}
+
+static int hifn_setup_crypto_command(struct hifn_device *dev,
+ u8 *buf, unsigned dlen, unsigned slen,
+ u8 *key, int keylen, u8 *iv, int ivsize, u16 mode)
+{
+ struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt;
+ struct hifn_crypt_command *cry_cmd;
+ u8 *buf_pos = buf;
+ u16 cmd_len;
+
+ cry_cmd = (struct hifn_crypt_command *)buf_pos;
+
+ cry_cmd->source_count = __cpu_to_le16(dlen & 0xffff);
+ dlen >>= 16;
+ cry_cmd->masks = __cpu_to_le16(mode |
+ ((dlen << HIFN_CRYPT_CMD_SRCLEN_S) &
+ HIFN_CRYPT_CMD_SRCLEN_M));
+ cry_cmd->header_skip = 0;
+ cry_cmd->reserved = 0;
+
+ buf_pos += sizeof(struct hifn_crypt_command);
+
+ dma->cmdu++;
+ if (dma->cmdu > 1) {
+ dev->dmareg |= HIFN_DMAIER_C_WAIT;
+ hifn_write_1(dev, HIFN_1_DMA_IER, dev->dmareg);
+ }
+
+ if (keylen) {
+ memcpy(buf_pos, key, keylen);
+ buf_pos += keylen;
+ }
+ if (ivsize) {
+ memcpy(buf_pos, iv, ivsize);
+ buf_pos += ivsize;
+ }
+
+ cmd_len = buf_pos - buf;
+
+ return cmd_len;
+}
+
+static int hifn_setup_src_desc(struct hifn_device *dev, struct page *page,
+ unsigned int offset, unsigned int size)
+{
+ struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt;
+ int idx;
+ dma_addr_t addr;
+
+ addr = pci_map_page(dev->pdev, page, offset, size, PCI_DMA_TODEVICE);
+
+ idx = dma->srci;
+
+ dma->srcr[idx].p = __cpu_to_le32(addr);
+ dma->srcr[idx].l = __cpu_to_le32(size) | HIFN_D_VALID |
+ HIFN_D_MASKDONEIRQ | HIFN_D_NOINVALID | HIFN_D_LAST;
+
+ if (++idx == HIFN_D_SRC_RSIZE) {
+ dma->srcr[idx].l = __cpu_to_le32(HIFN_D_VALID |
+ HIFN_D_JUMP |
+ HIFN_D_MASKDONEIRQ | HIFN_D_LAST);
+ idx = 0;
+ }
+
+ dma->srci = idx;
+ dma->srcu++;
+
+ if (!(dev->flags & HIFN_FLAG_SRC_BUSY)) {
+ hifn_write_1(dev, HIFN_1_DMA_CSR, HIFN_DMACSR_S_CTRL_ENA);
+ dev->flags |= HIFN_FLAG_SRC_BUSY;
+ }
+
+ return size;
+}
+
+static void hifn_setup_res_desc(struct hifn_device *dev)
+{
+ struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt;
+
+ dma->resr[dma->resi].l = __cpu_to_le32(HIFN_USED_RESULT |
+ HIFN_D_VALID | HIFN_D_LAST);
+ /*
+ * dma->resr[dma->resi].l = __cpu_to_le32(HIFN_MAX_RESULT | HIFN_D_VALID |
+ * HIFN_D_LAST | HIFN_D_NOINVALID);
+ */
+
+ if (++dma->resi == HIFN_D_RES_RSIZE) {
+ dma->resr[HIFN_D_RES_RSIZE].l = __cpu_to_le32(HIFN_D_VALID |
+ HIFN_D_JUMP | HIFN_D_MASKDONEIRQ | HIFN_D_LAST);
+ dma->resi = 0;
+ }
+
+ dma->resu++;
+
+ if (!(dev->flags & HIFN_FLAG_RES_BUSY)) {
+ hifn_write_1(dev, HIFN_1_DMA_CSR, HIFN_DMACSR_R_CTRL_ENA);
+ dev->flags |= HIFN_FLAG_RES_BUSY;
+ }
+}
+
+static void hifn_setup_dst_desc(struct hifn_device *dev, struct page *page,
+ unsigned offset, unsigned size)
+{
+ struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt;
+ int idx;
+ dma_addr_t addr;
+
+ addr = pci_map_page(dev->pdev, page, offset, size, PCI_DMA_FROMDEVICE);
+
+ idx = dma->dsti;
+ dma->dstr[idx].p = __cpu_to_le32(addr);
+ dma->dstr[idx].l = __cpu_to_le32(size | HIFN_D_VALID |
+ HIFN_D_MASKDONEIRQ | HIFN_D_NOINVALID | HIFN_D_LAST);
+
+ if (++idx == HIFN_D_DST_RSIZE) {
+ dma->dstr[idx].l = __cpu_to_le32(HIFN_D_VALID |
+ HIFN_D_JUMP | HIFN_D_MASKDONEIRQ |
+ HIFN_D_LAST | HIFN_D_NOINVALID);
+ idx = 0;
+ }
+ dma->dsti = idx;
+ dma->dstu++;
+
+ if (!(dev->flags & HIFN_FLAG_DST_BUSY)) {
+ hifn_write_1(dev, HIFN_1_DMA_CSR, HIFN_DMACSR_D_CTRL_ENA);
+ dev->flags |= HIFN_FLAG_DST_BUSY;
+ }
+}
+
+static int hifn_setup_dma(struct hifn_device *dev, struct page *spage, unsigned int soff,
+ struct page *dpage, unsigned int doff, unsigned int nbytes, void *priv,
+ struct hifn_context *ctx)
+{
+ struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt;
+ int cmd_len, sa_idx;
+ u8 *buf, *buf_pos;
+ u16 mask;
+
+ dprintk("%s: spage: %p, soffset: %u, dpage: %p, doffset: %u, nbytes: %u, priv: %p, ctx: %p.\n",
+ dev->name, spage, soff, dpage, doff, nbytes, priv, ctx);
+
+ sa_idx = dma->resi;
+
+ hifn_setup_src_desc(dev, spage, soff, nbytes);
+
+ buf_pos = buf = dma->command_bufs[dma->cmdi];
+
+ mask = 0;
+ switch (ctx->op) {
+ case ACRYPTO_OP_DECRYPT:
+ mask = HIFN_BASE_CMD_CRYPT | HIFN_BASE_CMD_DECODE;
+ break;
+ case ACRYPTO_OP_ENCRYPT:
+ mask = HIFN_BASE_CMD_CRYPT;
+ break;
+ case ACRYPTO_OP_HMAC:
+ mask = HIFN_BASE_CMD_MAC;
+ break;
+ default:
+ goto err_out;
+ }
+
+ buf_pos += hifn_setup_base_command(dev, buf_pos, nbytes,
+ nbytes, mask, dev->snum);
+
+ if (ctx->op == ACRYPTO_OP_ENCRYPT || ctx->op == ACRYPTO_OP_DECRYPT) {
+ u16 md = 0;
+
+ if (ctx->keysize)
+ md |= HIFN_CRYPT_CMD_NEW_KEY;
+ if (ctx->iv && ctx->mode != ACRYPTO_MODE_ECB)
+ md |= HIFN_CRYPT_CMD_NEW_IV;
+
+ switch (ctx->mode) {
+ case ACRYPTO_MODE_ECB:
+ md |= HIFN_CRYPT_CMD_MODE_ECB;
+ break;
+ case ACRYPTO_MODE_CBC:
+ md |= HIFN_CRYPT_CMD_MODE_CBC;
+ break;
+ case ACRYPTO_MODE_CFB:
+ md |= HIFN_CRYPT_CMD_MODE_CFB;
+ break;
+ case ACRYPTO_MODE_OFB:
+ md |= HIFN_CRYPT_CMD_MODE_OFB;
+ break;
+ default:
+ goto err_out;
+ }
+
+ switch (ctx->type) {
+ case ACRYPTO_TYPE_AES_128:
+ if (ctx->keysize != 16)
+ goto err_out;
+ md |= HIFN_CRYPT_CMD_KSZ_128 |
+ HIFN_CRYPT_CMD_ALG_AES;
+ break;
+ case ACRYPTO_TYPE_AES_192:
+ if (ctx->keysize != 24)
+ goto err_out;
+ md |= HIFN_CRYPT_CMD_KSZ_192 |
+ HIFN_CRYPT_CMD_ALG_AES;
+ break;
+ case ACRYPTO_TYPE_AES_256:
+ if (ctx->keysize != 32)
+ goto err_out;
+ md |= HIFN_CRYPT_CMD_KSZ_256 |
+ HIFN_CRYPT_CMD_ALG_AES;
+ break;
+ case ACRYPTO_TYPE_3DES:
+ if (ctx->keysize != 24)
+ goto err_out;
+ md |= HIFN_CRYPT_CMD_ALG_3DES;
+ break;
+ case ACRYPTO_TYPE_DES:
+ if (ctx->keysize != 8)
+ goto err_out;
+ md |= HIFN_CRYPT_CMD_ALG_DES;
+ break;
+ default:
+ goto err_out;
+ }
+
+ buf_pos += hifn_setup_crypto_command(dev, buf_pos,
+ nbytes, nbytes, ctx->key, ctx->keysize,
+ ctx->iv, ctx->ivsize, md);
+ }
+
+ dev->sa[sa_idx] = priv;
+
+ cmd_len = buf_pos - buf;
+ dma->cmdr[dma->cmdi].l = __cpu_to_le32(cmd_len | HIFN_D_VALID |
+ HIFN_D_LAST | HIFN_D_MASKDONEIRQ);
+
+ if (++dma->cmdi == HIFN_D_CMD_RSIZE) {
+ dma->cmdr[dma->cmdi].l = __cpu_to_le32(HIFN_MAX_COMMAND |
+ HIFN_D_VALID | HIFN_D_LAST |
+ HIFN_D_MASKDONEIRQ | HIFN_D_JUMP);
+ dma->cmdi = 0;
+ } else
+ dma->cmdr[dma->cmdi-1].l |= __cpu_to_le32(HIFN_D_VALID);
+
+ if (!(dev->flags & HIFN_FLAG_CMD_BUSY)) {
+ hifn_write_1(dev, HIFN_1_DMA_CSR, HIFN_DMACSR_C_CTRL_ENA);
+ dev->flags |= HIFN_FLAG_CMD_BUSY;
+ }
+
+ hifn_setup_dst_desc(dev, dpage, doff, nbytes);
+ hifn_setup_res_desc(dev);
+
+ return 0;
+
+err_out:
+ return -EINVAL;
+}
+
+static int ablkcipher_walk_init(struct ablkcipher_walk *w,
+ int num, gfp_t gfp_flags)
+{
+ int i;
+
+ num = min(ASYNC_SCATTERLIST_CACHE, num);
+ sg_init_table(w->cache, num);
+
+ w->num = 0;
+ for (i=0; i<num; ++i) {
+ struct page *page = alloc_page(gfp_flags);
+ struct scatterlist *s;
+
+ if (!page)
+ break;
+
+ s = &w->cache[i];
+
+ sg_set_page(s, page, PAGE_SIZE, 0);
+ w->num++;
+ }
+
+ return i;
+}
+
+static void ablkcipher_walk_exit(struct ablkcipher_walk *w)
+{
+ int i;
+
+ for (i=0; i<w->num; ++i) {
+ struct scatterlist *s = &w->cache[i];
+
+ __free_page(sg_page(s));
+
+ s->length = 0;
+ }
+
+ w->num = 0;
+}
+
+static int ablkcipher_add(void *daddr, unsigned int *drestp, struct scatterlist *src,
+ unsigned int size, unsigned int *nbytesp)
+{
+ unsigned int copy, drest = *drestp, nbytes = *nbytesp;
+ int idx = 0;
+ void *saddr;
+
+ if (drest < size || size > nbytes)
+ return -EINVAL;
+
+ while (size) {
+ copy = min(drest, src->length);
+
+ saddr = kmap_atomic(sg_page(src), KM_SOFTIRQ1);
+ memcpy(daddr, saddr + src->offset, copy);
+ kunmap_atomic(saddr, KM_SOFTIRQ1);
+
+ size -= copy;
+ drest -= copy;
+ nbytes -= copy;
+ daddr += copy;
+
+ dprintk("%s: copy: %u, size: %u, drest: %u, nbytes: %u.\n",
+ __func__, copy, size, drest, nbytes);
+
+ src++;
+ idx++;
+ }
+
+ *nbytesp = nbytes;
+ *drestp = drest;
+
+ return idx;
+}
+
+static int ablkcipher_walk(struct ablkcipher_request *req,
+ struct ablkcipher_walk *w)
+{
+ unsigned blocksize =
+ crypto_ablkcipher_blocksize(crypto_ablkcipher_reqtfm(req));
+ unsigned alignmask =
+ crypto_ablkcipher_alignmask(crypto_ablkcipher_reqtfm(req));
+ struct scatterlist *src, *dst, *t;
+ void *daddr;
+ unsigned int nbytes = req->nbytes, offset, copy, diff;
+ int idx, tidx, err;
+
+ tidx = idx = 0;
+ offset = 0;
+ while (nbytes) {
+ if (idx >= w->num && (w->flags & ASYNC_FLAGS_MISALIGNED))
+ return -EINVAL;
+
+ src = &req->src[idx];
+ dst = &req->dst[idx];
+
+ dprintk("\n%s: slen: %u, dlen: %u, soff: %u, doff: %u, offset: %u, "
+ "blocksize: %u, nbytes: %u.\n",
+ __func__, src->length, dst->length, src->offset,
+ dst->offset, offset, blocksize, nbytes);
+
+ if (src->length & (blocksize - 1) ||
+ src->offset & (alignmask - 1) ||
+ dst->length & (blocksize - 1) ||
+ dst->offset & (alignmask - 1) ||
+ offset) {
+ unsigned slen = src->length - offset;
+ unsigned dlen = PAGE_SIZE;
+
+ t = &w->cache[idx];
+
+ daddr = kmap_atomic(sg_page(t), KM_SOFTIRQ0);
+ err = ablkcipher_add(daddr, &dlen, src, slen, &nbytes);
+ if (err < 0)
+ goto err_out_unmap;
+
+ idx += err;
+
+ copy = slen & ~(blocksize - 1);
+ diff = slen & (blocksize - 1);
+
+ if (dlen < nbytes) {
+ /*
+ * Destination page does not have enough space
+ * to put there additional blocksized chunk,
+ * so we mark that page as containing only
+ * blocksize aligned chunks:
+ * t->length = (slen & ~(blocksize - 1));
+ * and increase number of bytes to be processed
+ * in next chunk:
+ * nbytes += diff;
+ */
+ nbytes += diff;
+
+ /*
+ * Temporary of course...
+ * Kick author if you will catch this one.
+ */
+ printk(KERN_ERR "%s: dlen: %u, nbytes: %u,"
+ "slen: %u, offset: %u.\n",
+ __func__, dlen, nbytes, slen, offset);
+ printk(KERN_ERR "%s: please contact author to fix this "
+ "issue, generally you should not catch "
+ "this path under any condition but who "
+ "knows how did you use crypto code.\n"
+ "Thank you.\n", __func__);
+ BUG();
+ } else {
+ copy += diff + nbytes;
+
+ src = &req->src[idx];
+
+ err = ablkcipher_add(daddr + slen, &dlen, src, nbytes, &nbytes);
+ if (err < 0)
+ goto err_out_unmap;
+
+ idx += err;
+ }
+
+ t->length = copy;
+ t->offset = offset;
+
+ kunmap_atomic(daddr, KM_SOFTIRQ0);
+ } else {
+ nbytes -= src->length;
+ idx++;
+ }
+
+ tidx++;
+ }
+
+ return tidx;
+
+err_out_unmap:
+ kunmap_atomic(daddr, KM_SOFTIRQ0);
+ return err;
+}
+
+static int hifn_setup_session(struct ablkcipher_request *req)
+{
+ struct hifn_context *ctx = crypto_tfm_ctx(req->base.tfm);
+ struct hifn_device *dev = ctx->dev;
+ struct page *spage, *dpage;
+ unsigned long soff, doff, flags;
+ unsigned int nbytes = req->nbytes, idx = 0, len;
+ int err = -EINVAL, sg_num;
+ struct scatterlist *src, *dst, *t;
+ unsigned blocksize =
+ crypto_ablkcipher_blocksize(crypto_ablkcipher_reqtfm(req));
+ unsigned alignmask =
+ crypto_ablkcipher_alignmask(crypto_ablkcipher_reqtfm(req));
+
+ if (ctx->iv && !ctx->ivsize && ctx->mode != ACRYPTO_MODE_ECB)
+ goto err_out_exit;
+
+ ctx->walk.flags = 0;
+
+ while (nbytes) {
+ src = &req->src[idx];
+ dst = &req->dst[idx];
+
+ if (src->length & (blocksize - 1) ||
+ src->offset & (alignmask - 1) ||
+ dst->length & (blocksize - 1) ||
+ dst->offset & (alignmask - 1)) {
+ ctx->walk.flags |= ASYNC_FLAGS_MISALIGNED;
+ }
+
+ nbytes -= src->length;
+ idx++;
+ }
+
+ if (ctx->walk.flags & ASYNC_FLAGS_MISALIGNED) {
+ err = ablkcipher_walk_init(&ctx->walk, idx, GFP_ATOMIC);
+ if (err < 0)
+ return err;
+ }
+
+ nbytes = req->nbytes;
+ idx = 0;
+
+ sg_num = ablkcipher_walk(req, &ctx->walk);
+
+ atomic_set(&ctx->sg_num, sg_num);
+
+ spin_lock_irqsave(&dev->lock, flags);
+ if (dev->started + sg_num > HIFN_QUEUE_LENGTH) {
+ err = -EAGAIN;
+ goto err_out;
+ }
+
+ dev->snum++;
+ dev->started += sg_num;
+
+ while (nbytes) {
+ src = &req->src[idx];
+ dst = &req->dst[idx];
+ t = &ctx->walk.cache[idx];
+
+ if (t->length) {
+ spage = dpage = sg_page(t);
+ soff = doff = 0;
+ len = t->length;
+ } else {
+ spage = sg_page(src);
+ soff = src->offset;
+
+ dpage = sg_page(dst);
+ doff = dst->offset;
+
+ len = dst->length;
+ }
+
+ idx++;
+
+ err = hifn_setup_dma(dev, spage, soff, dpage, doff, nbytes,
+ req, ctx);
+ if (err)
+ goto err_out;
+
+ nbytes -= len;
+ }
+
+ dev->active = HIFN_DEFAULT_ACTIVE_NUM;
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ return 0;
+
+err_out:
+ spin_unlock_irqrestore(&dev->lock, flags);
+err_out_exit:
+ if (err && printk_ratelimit())
+ dprintk("%s: iv: %p [%d], key: %p [%d], mode: %u, op: %u, "
+ "type: %u, err: %d.\n",
+ dev->name, ctx->iv, ctx->ivsize,
+ ctx->key, ctx->keysize,
+ ctx->mode, ctx->op, ctx->type, err);
+
+ return err;
+}
+
+static int hifn_test(struct hifn_device *dev, int encdec, u8 snum)
+{
+ int n, err;
+ u8 src[16];
+ struct hifn_context ctx;
+ u8 fips_aes_ecb_from_zero[16] = {
+ 0x66, 0xE9, 0x4B, 0xD4,
+ 0xEF, 0x8A, 0x2C, 0x3B,
+ 0x88, 0x4C, 0xFA, 0x59,
+ 0xCA, 0x34, 0x2B, 0x2E};
+
+ memset(src, 0, sizeof(src));
+ memset(ctx.key, 0, sizeof(ctx.key));
+
+ ctx.dev = dev;
+ ctx.keysize = 16;
+ ctx.ivsize = 0;
+ ctx.iv = NULL;
+ ctx.op = (encdec)?ACRYPTO_OP_ENCRYPT:ACRYPTO_OP_DECRYPT;
+ ctx.mode = ACRYPTO_MODE_ECB;
+ ctx.type = ACRYPTO_TYPE_AES_128;
+ atomic_set(&ctx.sg_num, 1);
+
+ err = hifn_setup_dma(dev,
+ virt_to_page(src), offset_in_page(src),
+ virt_to_page(src), offset_in_page(src),
+ sizeof(src), NULL, &ctx);
+ if (err)
+ goto err_out;
+
+ msleep(200);
+
+ dprintk("%s: decoded: ", dev->name);
+ for (n=0; n<sizeof(src); ++n)
+ dprintk("%02x ", src[n]);
+ dprintk("\n");
+ dprintk("%s: FIPS : ", dev->name);
+ for (n=0; n<sizeof(fips_aes_ecb_from_zero); ++n)
+ dprintk("%02x ", fips_aes_ecb_from_zero[n]);
+ dprintk("\n");
+
+ if (!memcmp(src, fips_aes_ecb_from_zero, sizeof(fips_aes_ecb_from_zero))) {
+ printk(KERN_INFO "%s: AES 128 ECB test has been successfully "
+ "passed.\n", dev->name);
+ return 0;
+ }
+
+err_out:
+ printk(KERN_INFO "%s: AES 128 ECB test has been failed.\n", dev->name);
+ return -1;
+}
+
+static int hifn_start_device(struct hifn_device *dev)
+{
+ int err;
+
+ hifn_reset_dma(dev, 1);
+
+ err = hifn_enable_crypto(dev);
+ if (err)
+ return err;
+
+ hifn_reset_puc(dev);
+
+ hifn_init_dma(dev);
+
+ hifn_init_registers(dev);
+
+ hifn_init_pubrng(dev);
+
+ return 0;
+}
+
+static int ablkcipher_get(void *saddr, unsigned int *srestp, unsigned int offset,
+ struct scatterlist *dst, unsigned int size, unsigned int *nbytesp)
+{
+ unsigned int srest = *srestp, nbytes = *nbytesp, copy;
+ void *daddr;
+ int idx = 0;
+
+ if (srest < size || size > nbytes)
+ return -EINVAL;
+
+ while (size) {
+
+ copy = min(dst->length, srest);
+
+ daddr = kmap_atomic(sg_page(dst), KM_IRQ0);
+ memcpy(daddr + dst->offset + offset, saddr, copy);
+ kunmap_atomic(daddr, KM_IRQ0);
+
+ nbytes -= copy;
+ size -= copy;
+ srest -= copy;
+ saddr += copy;
+ offset = 0;
+
+ dprintk("%s: copy: %u, size: %u, srest: %u, nbytes: %u.\n",
+ __func__, copy, size, srest, nbytes);
+
+ dst++;
+ idx++;
+ }
+
+ *nbytesp = nbytes;
+ *srestp = srest;
+
+ return idx;
+}
+
+static void hifn_process_ready(struct ablkcipher_request *req, int error)
+{
+ struct hifn_context *ctx = crypto_tfm_ctx(req->base.tfm);
+ struct hifn_device *dev;
+
+ dprintk("%s: req: %p, ctx: %p.\n", __func__, req, ctx);
+
+ dev = ctx->dev;
+ dprintk("%s: req: %p, started: %d, sg_num: %d.\n",
+ __func__, req, dev->started, atomic_read(&ctx->sg_num));
+
+ if (--dev->started < 0)
+ BUG();
+
+ if (atomic_dec_and_test(&ctx->sg_num)) {
+ unsigned int nbytes = req->nbytes;
+ int idx = 0, err;
+ struct scatterlist *dst, *t;
+ void *saddr;
+
+ if (ctx->walk.flags & ASYNC_FLAGS_MISALIGNED) {
+ while (nbytes) {
+ t = &ctx->walk.cache[idx];
+ dst = &req->dst[idx];
+
+ dprintk("\n%s: sg_page(t): %p, t->length: %u, "
+ "sg_page(dst): %p, dst->length: %u, "
+ "nbytes: %u.\n",
+ __func__, sg_page(t), t->length,
+ sg_page(dst), dst->length, nbytes);
+
+ if (!t->length) {
+ nbytes -= dst->length;
+ idx++;
+ continue;
+ }
+
+ saddr = kmap_atomic(sg_page(t), KM_IRQ1);
+
+ err = ablkcipher_get(saddr, &t->length, t->offset,
+ dst, nbytes, &nbytes);
+ if (err < 0) {
+ kunmap_atomic(saddr, KM_IRQ1);
+ break;
+ }
+
+ idx += err;
+ kunmap_atomic(saddr, KM_IRQ1);
+ }
+
+ ablkcipher_walk_exit(&ctx->walk);
+ }
+
+ req->base.complete(&req->base, error);
+ }
+}
+
+static void hifn_check_for_completion(struct hifn_device *dev, int error)
+{
+ int i;
+ struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt;
+
+ for (i=0; i<HIFN_D_RES_RSIZE; ++i) {
+ struct hifn_desc *d = &dma->resr[i];
+
+ if (!(d->l & __cpu_to_le32(HIFN_D_VALID)) && dev->sa[i]) {
+ dev->success++;
+ dev->reset = 0;
+ hifn_process_ready(dev->sa[i], error);
+ dev->sa[i] = NULL;
+ }
+
+ if (d->l & __cpu_to_le32(HIFN_D_DESTOVER | HIFN_D_OVER))
+ if (printk_ratelimit())
+ printk("%s: overflow detected [d: %u, o: %u] "
+ "at %d resr: l: %08x, p: %08x.\n",
+ dev->name,
+ !!(d->l & __cpu_to_le32(HIFN_D_DESTOVER)),
+ !!(d->l & __cpu_to_le32(HIFN_D_OVER)),
+ i, d->l, d->p);
+ }
+}
+
+static void hifn_clear_rings(struct hifn_device *dev)
+{
+ struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt;
+ int i, u;
+
+ dprintk("%s: ring cleanup 1: i: %d.%d.%d.%d, u: %d.%d.%d.%d, "
+ "k: %d.%d.%d.%d.\n",
+ dev->name,
+ dma->cmdi, dma->srci, dma->dsti, dma->resi,
+ dma->cmdu, dma->srcu, dma->dstu, dma->resu,
+ dma->cmdk, dma->srck, dma->dstk, dma->resk);
+
+ i = dma->resk; u = dma->resu;
+ while (u != 0) {
+ if (dma->resr[i].l & __cpu_to_le32(HIFN_D_VALID))
+ break;
+
+ if (i != HIFN_D_RES_RSIZE)
+ u--;
+
+ if (++i == (HIFN_D_RES_RSIZE + 1))
+ i = 0;
+ }
+ dma->resk = i; dma->resu = u;
+
+ i = dma->srck; u = dma->srcu;
+ while (u != 0) {
+ if (i == HIFN_D_SRC_RSIZE)
+ i = 0;
+ if (dma->srcr[i].l & __cpu_to_le32(HIFN_D_VALID))
+ break;
+ i++, u--;
+ }
+ dma->srck = i; dma->srcu = u;
+
+ i = dma->cmdk; u = dma->cmdu;
+ while (u != 0) {
+ if (dma->cmdr[i].l & __cpu_to_le32(HIFN_D_VALID))
+ break;
+ if (i != HIFN_D_CMD_RSIZE)
+ u--;
+ if (++i == (HIFN_D_CMD_RSIZE + 1))
+ i = 0;
+ }
+ dma->cmdk = i; dma->cmdu = u;
+
+ i = dma->dstk; u = dma->dstu;
+ while (u != 0) {
+ if (i == HIFN_D_DST_RSIZE)
+ i = 0;
+ if (dma->dstr[i].l & __cpu_to_le32(HIFN_D_VALID))
+ break;
+ i++, u--;
+ }
+ dma->dstk = i; dma->dstu = u;
+
+ dprintk("%s: ring cleanup 2: i: %d.%d.%d.%d, u: %d.%d.%d.%d, "
+ "k: %d.%d.%d.%d.\n",
+ dev->name,
+ dma->cmdi, dma->srci, dma->dsti, dma->resi,
+ dma->cmdu, dma->srcu, dma->dstu, dma->resu,
+ dma->cmdk, dma->srck, dma->dstk, dma->resk);
+}
+
+static void hifn_work(struct work_struct *work)
+{
+ struct delayed_work *dw = container_of(work, struct delayed_work, work);
+ struct hifn_device *dev = container_of(dw, struct hifn_device, work);
+ unsigned long flags;
+ int reset = 0;
+ u32 r = 0;
+
+ spin_lock_irqsave(&dev->lock, flags);
+ if (dev->active == 0) {
+ struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt;
+
+ if (dma->cmdu == 0 && (dev->flags & HIFN_FLAG_CMD_BUSY)) {
+ dev->flags &= ~HIFN_FLAG_CMD_BUSY;
+ r |= HIFN_DMACSR_C_CTRL_DIS;
+ }
+ if (dma->srcu == 0 && (dev->flags & HIFN_FLAG_SRC_BUSY)) {
+ dev->flags &= ~HIFN_FLAG_SRC_BUSY;
+ r |= HIFN_DMACSR_S_CTRL_DIS;
+ }
+ if (dma->dstu == 0 && (dev->flags & HIFN_FLAG_DST_BUSY)) {
+ dev->flags &= ~HIFN_FLAG_DST_BUSY;
+ r |= HIFN_DMACSR_D_CTRL_DIS;
+ }
+ if (dma->resu == 0 && (dev->flags & HIFN_FLAG_RES_BUSY)) {
+ dev->flags &= ~HIFN_FLAG_RES_BUSY;
+ r |= HIFN_DMACSR_R_CTRL_DIS;
+ }
+ if (r)
+ hifn_write_1(dev, HIFN_1_DMA_CSR, r);
+ } else
+ dev->active--;
+
+ if (dev->prev_success == dev->success && dev->started)
+ reset = 1;
+ dev->prev_success = dev->success;
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ if (reset) {
+ dprintk("%s: r: %08x, active: %d, started: %d, "
+ "success: %lu: reset: %d.\n",
+ dev->name, r, dev->active, dev->started,
+ dev->success, reset);
+
+ if (++dev->reset >= 5) {
+ dprintk("%s: really hard reset.\n", dev->name);
+ hifn_reset_dma(dev, 1);
+ hifn_stop_device(dev);
+ hifn_start_device(dev);
+ dev->reset = 0;
+ }
+
+ spin_lock_irqsave(&dev->lock, flags);
+ hifn_check_for_completion(dev, -EBUSY);
+ hifn_clear_rings(dev);
+ dev->started = 0;
+ spin_unlock_irqrestore(&dev->lock, flags);
+ }
+
+ schedule_delayed_work(&dev->work, HZ);
+}
+
+static irqreturn_t hifn_interrupt(int irq, void *data)
+{
+ struct hifn_device *dev = (struct hifn_device *)data;
+ struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt;
+ u32 dmacsr, restart;
+
+ dmacsr = hifn_read_1(dev, HIFN_1_DMA_CSR);
+
+ dprintk("%s: 1 dmacsr: %08x, dmareg: %08x, res: %08x [%d], "
+ "i: %d.%d.%d.%d, u: %d.%d.%d.%d.\n",
+ dev->name, dmacsr, dev->dmareg, dmacsr & dev->dmareg, dma->cmdi,
+ dma->cmdu, dma->srcu, dma->dstu, dma->resu,
+ dma->cmdi, dma->srci, dma->dsti, dma->resi);
+
+ if ((dmacsr & dev->dmareg) == 0)
+ return IRQ_NONE;
+
+ hifn_write_1(dev, HIFN_1_DMA_CSR, dmacsr & dev->dmareg);
+
+ if (dmacsr & HIFN_DMACSR_ENGINE)
+ hifn_write_0(dev, HIFN_0_PUISR, hifn_read_0(dev, HIFN_0_PUISR));
+ if (dmacsr & HIFN_DMACSR_PUBDONE)
+ hifn_write_1(dev, HIFN_1_PUB_STATUS,
+ hifn_read_1(dev, HIFN_1_PUB_STATUS) | HIFN_PUBSTS_DONE);
+
+ restart = dmacsr & (HIFN_DMACSR_R_OVER | HIFN_DMACSR_D_OVER);
+ if (restart) {
+ u32 puisr = hifn_read_0(dev, HIFN_0_PUISR);
+
+ if (printk_ratelimit())
+ printk("%s: overflow: r: %d, d: %d, puisr: %08x, d: %u.\n",
+ dev->name, !!(dmacsr & HIFN_DMACSR_R_OVER),
+ !!(dmacsr & HIFN_DMACSR_D_OVER),
+ puisr, !!(puisr & HIFN_PUISR_DSTOVER));
+ if (!!(puisr & HIFN_PUISR_DSTOVER))
+ hifn_write_0(dev, HIFN_0_PUISR, HIFN_PUISR_DSTOVER);
+ hifn_write_1(dev, HIFN_1_DMA_CSR, dmacsr & (HIFN_DMACSR_R_OVER |
+ HIFN_DMACSR_D_OVER));
+ }
+
+ restart = dmacsr & (HIFN_DMACSR_C_ABORT | HIFN_DMACSR_S_ABORT |
+ HIFN_DMACSR_D_ABORT | HIFN_DMACSR_R_ABORT);
+ if (restart) {
+ if (printk_ratelimit())
+ printk("%s: abort: c: %d, s: %d, d: %d, r: %d.\n",
+ dev->name, !!(dmacsr & HIFN_DMACSR_C_ABORT),
+ !!(dmacsr & HIFN_DMACSR_S_ABORT),
+ !!(dmacsr & HIFN_DMACSR_D_ABORT),
+ !!(dmacsr & HIFN_DMACSR_R_ABORT));
+ hifn_reset_dma(dev, 1);
+ hifn_init_dma(dev);
+ hifn_init_registers(dev);
+ }
+
+ if ((dmacsr & HIFN_DMACSR_C_WAIT) && (dma->cmdu == 0)) {
+ dprintk("%s: wait on command.\n", dev->name);
+ dev->dmareg &= ~(HIFN_DMAIER_C_WAIT);
+ hifn_write_1(dev, HIFN_1_DMA_IER, dev->dmareg);
+ }
+
+ tasklet_schedule(&dev->tasklet);
+ hifn_clear_rings(dev);
+
+ return IRQ_HANDLED;
+}
+
+static void hifn_flush(struct hifn_device *dev)
+{
+ unsigned long flags;
+ struct crypto_async_request *async_req;
+ struct hifn_context *ctx;
+ struct ablkcipher_request *req;
+ struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt;
+ int i;
+
+ spin_lock_irqsave(&dev->lock, flags);
+ for (i=0; i<HIFN_D_RES_RSIZE; ++i) {
+ struct hifn_desc *d = &dma->resr[i];
+
+ if (dev->sa[i]) {
+ hifn_process_ready(dev->sa[i],
+ (d->l & __cpu_to_le32(HIFN_D_VALID))?-ENODEV:0);
+ }
+ }
+
+ while ((async_req = crypto_dequeue_request(&dev->queue))) {
+ ctx = crypto_tfm_ctx(async_req->tfm);
+ req = container_of(async_req, struct ablkcipher_request, base);
+
+ hifn_process_ready(req, -ENODEV);
+ }
+ spin_unlock_irqrestore(&dev->lock, flags);
+}
+
+static int hifn_setkey(struct crypto_ablkcipher *cipher, const u8 *key,
+ unsigned int len)
+{
+ struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher);
+ struct hifn_context *ctx = crypto_tfm_ctx(tfm);
+ struct hifn_device *dev = ctx->dev;
+
+ if (len > HIFN_MAX_CRYPT_KEY_LENGTH) {
+ crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
+ return -1;
+ }
+
+ if (len == HIFN_DES_KEY_LENGTH) {
+ u32 tmp[DES_EXPKEY_WORDS];
+ int ret = des_ekey(tmp, key);
+
+ if (unlikely(ret == 0) && (tfm->crt_flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
+ tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY;
+ return -EINVAL;
+ }
+ }
+
+ dev->flags &= ~HIFN_FLAG_OLD_KEY;
+
+ memcpy(ctx->key, key, len);
+ ctx->keysize = len;
+
+ return 0;
+}
+
+static int hifn_handle_req(struct ablkcipher_request *req)
+{
+ struct hifn_context *ctx = crypto_tfm_ctx(req->base.tfm);
+ struct hifn_device *dev = ctx->dev;
+ int err = -EAGAIN;
+
+ if (dev->started + DIV_ROUND_UP(req->nbytes, PAGE_SIZE) <= HIFN_QUEUE_LENGTH)
+ err = hifn_setup_session(req);
+
+ if (err == -EAGAIN) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&dev->lock, flags);
+ err = ablkcipher_enqueue_request(&dev->queue, req);
+ spin_unlock_irqrestore(&dev->lock, flags);
+ }
+
+ return err;
+}
+
+static int hifn_setup_crypto_req(struct ablkcipher_request *req, u8 op,
+ u8 type, u8 mode)
+{
+ struct hifn_context *ctx = crypto_tfm_ctx(req->base.tfm);
+ unsigned ivsize;
+
+ ivsize = crypto_ablkcipher_ivsize(crypto_ablkcipher_reqtfm(req));
+
+ if (req->info && mode != ACRYPTO_MODE_ECB) {
+ if (type == ACRYPTO_TYPE_AES_128)
+ ivsize = HIFN_AES_IV_LENGTH;
+ else if (type == ACRYPTO_TYPE_DES)
+ ivsize = HIFN_DES_KEY_LENGTH;
+ else if (type == ACRYPTO_TYPE_3DES)
+ ivsize = HIFN_3DES_KEY_LENGTH;
+ }
+
+ if (ctx->keysize != 16 && type == ACRYPTO_TYPE_AES_128) {
+ if (ctx->keysize == 24)
+ type = ACRYPTO_TYPE_AES_192;
+ else if (ctx->keysize == 32)
+ type = ACRYPTO_TYPE_AES_256;
+ }
+
+ ctx->op = op;
+ ctx->mode = mode;
+ ctx->type = type;
+ ctx->iv = req->info;
+ ctx->ivsize = ivsize;
+
+ /*
+ * HEAVY TODO: needs to kick Herbert XU to write documentation.
+ * HEAVY TODO: needs to kick Herbert XU to write documentation.
+ * HEAVY TODO: needs to kick Herbert XU to write documentation.
+ */
+
+ return hifn_handle_req(req);
+}
+
+static int hifn_process_queue(struct hifn_device *dev)
+{
+ struct crypto_async_request *async_req;
+ struct hifn_context *ctx;
+ struct ablkcipher_request *req;
+ unsigned long flags;
+ int err = 0;
+
+ while (dev->started < HIFN_QUEUE_LENGTH) {
+ spin_lock_irqsave(&dev->lock, flags);
+ async_req = crypto_dequeue_request(&dev->queue);
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ if (!async_req)
+ break;
+
+ ctx = crypto_tfm_ctx(async_req->tfm);
+ req = container_of(async_req, struct ablkcipher_request, base);
+
+ err = hifn_handle_req(req);
+ if (err)
+ break;
+ }
+
+ return err;
+}
+
+static int hifn_setup_crypto(struct ablkcipher_request *req, u8 op,
+ u8 type, u8 mode)
+{
+ int err;
+ struct hifn_context *ctx = crypto_tfm_ctx(req->base.tfm);
+ struct hifn_device *dev = ctx->dev;
+
+ err = hifn_setup_crypto_req(req, op, type, mode);
+ if (err)
+ return err;
+
+ if (dev->started < HIFN_QUEUE_LENGTH && dev->queue.qlen)
+ err = hifn_process_queue(dev);
+
+ return err;
+}
+
+/*
+ * AES ecryption functions.
+ */
+static inline int hifn_encrypt_aes_ecb(struct ablkcipher_request *req)
+{
+ return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
+ ACRYPTO_TYPE_AES_128, ACRYPTO_MODE_ECB);
+}
+static inline int hifn_encrypt_aes_cbc(struct ablkcipher_request *req)
+{
+ return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
+ ACRYPTO_TYPE_AES_128, ACRYPTO_MODE_CBC);
+}
+static inline int hifn_encrypt_aes_cfb(struct ablkcipher_request *req)
+{
+ return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
+ ACRYPTO_TYPE_AES_128, ACRYPTO_MODE_CFB);
+}
+static inline int hifn_encrypt_aes_ofb(struct ablkcipher_request *req)
+{
+ return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
+ ACRYPTO_TYPE_AES_128, ACRYPTO_MODE_OFB);
+}
+
+/*
+ * AES decryption functions.
+ */
+static inline int hifn_decrypt_aes_ecb(struct ablkcipher_request *req)
+{
+ return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
+ ACRYPTO_TYPE_AES_128, ACRYPTO_MODE_ECB);
+}
+static inline int hifn_decrypt_aes_cbc(struct ablkcipher_request *req)
+{
+ return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
+ ACRYPTO_TYPE_AES_128, ACRYPTO_MODE_CBC);
+}
+static inline int hifn_decrypt_aes_cfb(struct ablkcipher_request *req)
+{
+ return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
+ ACRYPTO_TYPE_AES_128, ACRYPTO_MODE_CFB);
+}
+static inline int hifn_decrypt_aes_ofb(struct ablkcipher_request *req)
+{
+ return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
+ ACRYPTO_TYPE_AES_128, ACRYPTO_MODE_OFB);
+}
+
+/*
+ * DES ecryption functions.
+ */
+static inline int hifn_encrypt_des_ecb(struct ablkcipher_request *req)
+{
+ return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
+ ACRYPTO_TYPE_DES, ACRYPTO_MODE_ECB);
+}
+static inline int hifn_encrypt_des_cbc(struct ablkcipher_request *req)
+{
+ return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
+ ACRYPTO_TYPE_DES, ACRYPTO_MODE_CBC);
+}
+static inline int hifn_encrypt_des_cfb(struct ablkcipher_request *req)
+{
+ return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
+ ACRYPTO_TYPE_DES, ACRYPTO_MODE_CFB);
+}
+static inline int hifn_encrypt_des_ofb(struct ablkcipher_request *req)
+{
+ return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
+ ACRYPTO_TYPE_DES, ACRYPTO_MODE_OFB);
+}
+
+/*
+ * DES decryption functions.
+ */
+static inline int hifn_decrypt_des_ecb(struct ablkcipher_request *req)
+{
+ return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
+ ACRYPTO_TYPE_DES, ACRYPTO_MODE_ECB);
+}
+static inline int hifn_decrypt_des_cbc(struct ablkcipher_request *req)
+{
+ return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
+ ACRYPTO_TYPE_DES, ACRYPTO_MODE_CBC);
+}
+static inline int hifn_decrypt_des_cfb(struct ablkcipher_request *req)
+{
+ return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
+ ACRYPTO_TYPE_DES, ACRYPTO_MODE_CFB);
+}
+static inline int hifn_decrypt_des_ofb(struct ablkcipher_request *req)
+{
+ return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
+ ACRYPTO_TYPE_DES, ACRYPTO_MODE_OFB);
+}
+
+/*
+ * 3DES ecryption functions.
+ */
+static inline int hifn_encrypt_3des_ecb(struct ablkcipher_request *req)
+{
+ return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
+ ACRYPTO_TYPE_3DES, ACRYPTO_MODE_ECB);
+}
+static inline int hifn_encrypt_3des_cbc(struct ablkcipher_request *req)
+{
+ return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
+ ACRYPTO_TYPE_3DES, ACRYPTO_MODE_CBC);
+}
+static inline int hifn_encrypt_3des_cfb(struct ablkcipher_request *req)
+{
+ return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
+ ACRYPTO_TYPE_3DES, ACRYPTO_MODE_CFB);
+}
+static inline int hifn_encrypt_3des_ofb(struct ablkcipher_request *req)
+{
+ return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
+ ACRYPTO_TYPE_3DES, ACRYPTO_MODE_OFB);
+}
+
+/*
+ * 3DES decryption functions.
+ */
+static inline int hifn_decrypt_3des_ecb(struct ablkcipher_request *req)
+{
+ return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
+ ACRYPTO_TYPE_3DES, ACRYPTO_MODE_ECB);
+}
+static inline int hifn_decrypt_3des_cbc(struct ablkcipher_request *req)
+{
+ return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
+ ACRYPTO_TYPE_3DES, ACRYPTO_MODE_CBC);
+}
+static inline int hifn_decrypt_3des_cfb(struct ablkcipher_request *req)
+{
+ return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
+ ACRYPTO_TYPE_3DES, ACRYPTO_MODE_CFB);
+}
+static inline int hifn_decrypt_3des_ofb(struct ablkcipher_request *req)
+{
+ return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
+ ACRYPTO_TYPE_3DES, ACRYPTO_MODE_OFB);
+}
+
+struct hifn_alg_template
+{
+ char name[CRYPTO_MAX_ALG_NAME];
+ char drv_name[CRYPTO_MAX_ALG_NAME];
+ unsigned int bsize;
+ struct ablkcipher_alg ablkcipher;
+};
+
+static struct hifn_alg_template hifn_alg_templates[] = {
+ /*
+ * 3DES ECB, CBC, CFB and OFB modes.
+ */
+ {
+ .name = "cfb(des3_ede)", .drv_name = "hifn-3des", .bsize = 8,
+ .ablkcipher = {
+ .min_keysize = HIFN_3DES_KEY_LENGTH,
+ .max_keysize = HIFN_3DES_KEY_LENGTH,
+ .setkey = hifn_setkey,
+ .encrypt = hifn_encrypt_3des_cfb,
+ .decrypt = hifn_decrypt_3des_cfb,
+ },
+ },
+ {
+ .name = "ofb(des3_ede)", .drv_name = "hifn-3des", .bsize = 8,
+ .ablkcipher = {
+ .min_keysize = HIFN_3DES_KEY_LENGTH,
+ .max_keysize = HIFN_3DES_KEY_LENGTH,
+ .setkey = hifn_setkey,
+ .encrypt = hifn_encrypt_3des_ofb,
+ .decrypt = hifn_decrypt_3des_ofb,
+ },
+ },
+ {
+ .name = "cbc(des3_ede)", .drv_name = "hifn-3des", .bsize = 8,
+ .ablkcipher = {
+ .min_keysize = HIFN_3DES_KEY_LENGTH,
+ .max_keysize = HIFN_3DES_KEY_LENGTH,
+ .setkey = hifn_setkey,
+ .encrypt = hifn_encrypt_3des_cbc,
+ .decrypt = hifn_decrypt_3des_cbc,
+ },
+ },
+ {
+ .name = "ecb(des3_ede)", .drv_name = "hifn-3des", .bsize = 8,
+ .ablkcipher = {
+ .min_keysize = HIFN_3DES_KEY_LENGTH,
+ .max_keysize = HIFN_3DES_KEY_LENGTH,
+ .setkey = hifn_setkey,
+ .encrypt = hifn_encrypt_3des_ecb,
+ .decrypt = hifn_decrypt_3des_ecb,
+ },
+ },
+
+ /*
+ * DES ECB, CBC, CFB and OFB modes.
+ */
+ {
+ .name = "cfb(des)", .drv_name = "hifn-des", .bsize = 8,
+ .ablkcipher = {
+ .min_keysize = HIFN_DES_KEY_LENGTH,
+ .max_keysize = HIFN_DES_KEY_LENGTH,
+ .setkey = hifn_setkey,
+ .encrypt = hifn_encrypt_des_cfb,
+ .decrypt = hifn_decrypt_des_cfb,
+ },
+ },
+ {
+ .name = "ofb(des)", .drv_name = "hifn-des", .bsize = 8,
+ .ablkcipher = {
+ .min_keysize = HIFN_DES_KEY_LENGTH,
+ .max_keysize = HIFN_DES_KEY_LENGTH,
+ .setkey = hifn_setkey,
+ .encrypt = hifn_encrypt_des_ofb,
+ .decrypt = hifn_decrypt_des_ofb,
+ },
+ },
+ {
+ .name = "cbc(des)", .drv_name = "hifn-des", .bsize = 8,
+ .ablkcipher = {
+ .min_keysize = HIFN_DES_KEY_LENGTH,
+ .max_keysize = HIFN_DES_KEY_LENGTH,
+ .setkey = hifn_setkey,
+ .encrypt = hifn_encrypt_des_cbc,
+ .decrypt = hifn_decrypt_des_cbc,
+ },
+ },
+ {
+ .name = "ecb(des)", .drv_name = "hifn-des", .bsize = 8,
+ .ablkcipher = {
+ .min_keysize = HIFN_DES_KEY_LENGTH,
+ .max_keysize = HIFN_DES_KEY_LENGTH,
+ .setkey = hifn_setkey,
+ .encrypt = hifn_encrypt_des_ecb,
+ .decrypt = hifn_decrypt_des_ecb,
+ },
+ },
+
+ /*
+ * AES ECB, CBC, CFB and OFB modes.
+ */
+ {
+ .name = "ecb(aes)", .drv_name = "hifn-aes", .bsize = 16,
+ .ablkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .setkey = hifn_setkey,
+ .encrypt = hifn_encrypt_aes_ecb,
+ .decrypt = hifn_decrypt_aes_ecb,
+ },
+ },
+ {
+ .name = "cbc(aes)", .drv_name = "hifn-aes", .bsize = 16,
+ .ablkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .setkey = hifn_setkey,
+ .encrypt = hifn_encrypt_aes_cbc,
+ .decrypt = hifn_decrypt_aes_cbc,
+ },
+ },
+ {
+ .name = "cfb(aes)", .drv_name = "hifn-aes", .bsize = 16,
+ .ablkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .setkey = hifn_setkey,
+ .encrypt = hifn_encrypt_aes_cfb,
+ .decrypt = hifn_decrypt_aes_cfb,
+ },
+ },
+ {
+ .name = "ofb(aes)", .drv_name = "hifn-aes", .bsize = 16,
+ .ablkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .setkey = hifn_setkey,
+ .encrypt = hifn_encrypt_aes_ofb,
+ .decrypt = hifn_decrypt_aes_ofb,
+ },
+ },
+};
+
+static int hifn_cra_init(struct crypto_tfm *tfm)
+{
+ struct crypto_alg *alg = tfm->__crt_alg;
+ struct hifn_crypto_alg *ha = crypto_alg_to_hifn(alg);
+ struct hifn_context *ctx = crypto_tfm_ctx(tfm);
+
+ ctx->dev = ha->dev;
+
+ return 0;
+}
+
+static int hifn_alg_alloc(struct hifn_device *dev, struct hifn_alg_template *t)
+{
+ struct hifn_crypto_alg *alg;
+ int err;
+
+ alg = kzalloc(sizeof(struct hifn_crypto_alg), GFP_KERNEL);
+ if (!alg)
+ return -ENOMEM;
+
+ snprintf(alg->alg.cra_name, CRYPTO_MAX_ALG_NAME, "%s", t->name);
+ snprintf(alg->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", t->drv_name);
+
+ alg->alg.cra_priority = 300;
+ alg->alg.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC;
+ alg->alg.cra_blocksize = t->bsize;
+ alg->alg.cra_ctxsize = sizeof(struct hifn_context);
+ alg->alg.cra_alignmask = 15;
+ if (t->bsize == 8)
+ alg->alg.cra_alignmask = 3;
+ alg->alg.cra_type = &crypto_ablkcipher_type;
+ alg->alg.cra_module = THIS_MODULE;
+ alg->alg.cra_u.ablkcipher = t->ablkcipher;
+ alg->alg.cra_init = hifn_cra_init;
+
+ alg->dev = dev;
+
+ list_add_tail(&alg->entry, &dev->alg_list);
+
+ err = crypto_register_alg(&alg->alg);
+ if (err) {
+ list_del(&alg->entry);
+ kfree(alg);
+ }
+
+ return err;
+}
+
+static void hifn_unregister_alg(struct hifn_device *dev)
+{
+ struct hifn_crypto_alg *a, *n;
+
+ list_for_each_entry_safe(a, n, &dev->alg_list, entry) {
+ list_del(&a->entry);
+ crypto_unregister_alg(&a->alg);
+ kfree(a);
+ }
+}
+
+static int hifn_register_alg(struct hifn_device *dev)
+{
+ int i, err;
+
+ for (i=0; i<ARRAY_SIZE(hifn_alg_templates); ++i) {
+ err = hifn_alg_alloc(dev, &hifn_alg_templates[i]);
+ if (err)
+ goto err_out_exit;
+ }
+
+ return 0;
+
+err_out_exit:
+ hifn_unregister_alg(dev);
+ return err;
+}
+
+static void hifn_tasklet_callback(unsigned long data)
+{
+ struct hifn_device *dev = (struct hifn_device *)data;
+
+ /*
+ * This is ok to call this without lock being held,
+ * althogh it modifies some parameters used in parallel,
+ * (like dev->success), but they are used in process
+ * context or update is atomic (like setting dev->sa[i] to NULL).
+ */
+ hifn_check_for_completion(dev, 0);
+}
+
+static int hifn_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ int err, i;
+ struct hifn_device *dev;
+ char name[8];
+
+ err = pci_enable_device(pdev);
+ if (err)
+ return err;
+ pci_set_master(pdev);
+
+ err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (err)
+ goto err_out_disable_pci_device;
+
+ snprintf(name, sizeof(name), "hifn%d",
+ atomic_inc_return(&hifn_dev_number)-1);
+
+ err = pci_request_regions(pdev, name);
+ if (err)
+ goto err_out_disable_pci_device;
+
+ if (pci_resource_len(pdev, 0) < HIFN_BAR0_SIZE ||
+ pci_resource_len(pdev, 1) < HIFN_BAR1_SIZE ||
+ pci_resource_len(pdev, 2) < HIFN_BAR2_SIZE) {
+ dprintk("%s: Broken hardware - I/O regions are too small.\n",
+ pci_name(pdev));
+ err = -ENODEV;
+ goto err_out_free_regions;
+ }
+
+ dev = kzalloc(sizeof(struct hifn_device) + sizeof(struct crypto_alg),
+ GFP_KERNEL);
+ if (!dev) {
+ err = -ENOMEM;
+ goto err_out_free_regions;
+ }
+
+ INIT_LIST_HEAD(&dev->alg_list);
+
+ snprintf(dev->name, sizeof(dev->name), "%s", name);
+ spin_lock_init(&dev->lock);
+
+ for (i=0; i<3; ++i) {
+ unsigned long addr, size;
+
+ addr = pci_resource_start(pdev, i);
+ size = pci_resource_len(pdev, i);
+
+ dev->bar[i] = ioremap_nocache(addr, size);
+ if (!dev->bar[i])
+ goto err_out_unmap_bars;
+ }
+
+ dev->result_mem = __get_free_pages(GFP_KERNEL, HIFN_MAX_RESULT_ORDER);
+ if (!dev->result_mem) {
+ dprintk("Failed to allocate %d pages for result_mem.\n",
+ HIFN_MAX_RESULT_ORDER);
+ goto err_out_unmap_bars;
+ }
+ memset((void *)dev->result_mem, 0, PAGE_SIZE*(1<<HIFN_MAX_RESULT_ORDER));
+
+ dev->dst = pci_map_single(pdev, (void *)dev->result_mem,
+ PAGE_SIZE << HIFN_MAX_RESULT_ORDER, PCI_DMA_FROMDEVICE);
+
+ dev->desc_virt = pci_alloc_consistent(pdev, sizeof(struct hifn_dma),
+ &dev->desc_dma);
+ if (!dev->desc_virt) {
+ dprintk("Failed to allocate descriptor rings.\n");
+ goto err_out_free_result_pages;
+ }
+ memset(dev->desc_virt, 0, sizeof(struct hifn_dma));
+
+ dev->pdev = pdev;
+ dev->irq = pdev->irq;
+
+ for (i=0; i<HIFN_D_RES_RSIZE; ++i)
+ dev->sa[i] = NULL;
+
+ pci_set_drvdata(pdev, dev);
+
+ tasklet_init(&dev->tasklet, hifn_tasklet_callback, (unsigned long)dev);
+
+ crypto_init_queue(&dev->queue, 1);
+
+ err = request_irq(dev->irq, hifn_interrupt, IRQF_SHARED, dev->name, dev);
+ if (err) {
+ dprintk("Failed to request IRQ%d: err: %d.\n", dev->irq, err);
+ dev->irq = 0;
+ goto err_out_free_desc;
+ }
+
+ err = hifn_start_device(dev);
+ if (err)
+ goto err_out_free_irq;
+
+ err = hifn_test(dev, 1, 0);
+ if (err)
+ goto err_out_stop_device;
+
+ err = hifn_register_rng(dev);
+ if (err)
+ goto err_out_stop_device;
+
+ err = hifn_register_alg(dev);
+ if (err)
+ goto err_out_unregister_rng;
+
+ INIT_DELAYED_WORK(&dev->work, hifn_work);
+ schedule_delayed_work(&dev->work, HZ);
+
+ dprintk("HIFN crypto accelerator card at %s has been "
+ "successfully registered as %s.\n",
+ pci_name(pdev), dev->name);
+
+ return 0;
+
+err_out_unregister_rng:
+ hifn_unregister_rng(dev);
+err_out_stop_device:
+ hifn_reset_dma(dev, 1);
+ hifn_stop_device(dev);
+err_out_free_irq:
+ free_irq(dev->irq, dev->name);
+ tasklet_kill(&dev->tasklet);
+err_out_free_desc:
+ pci_free_consistent(pdev, sizeof(struct hifn_dma),
+ dev->desc_virt, dev->desc_dma);
+
+err_out_free_result_pages:
+ pci_unmap_single(pdev, dev->dst, PAGE_SIZE << HIFN_MAX_RESULT_ORDER,
+ PCI_DMA_FROMDEVICE);
+ free_pages(dev->result_mem, HIFN_MAX_RESULT_ORDER);
+
+err_out_unmap_bars:
+ for (i=0; i<3; ++i)
+ if (dev->bar[i])
+ iounmap(dev->bar[i]);
+
+err_out_free_regions:
+ pci_release_regions(pdev);
+
+err_out_disable_pci_device:
+ pci_disable_device(pdev);
+
+ return err;
+}
+
+static void hifn_remove(struct pci_dev *pdev)
+{
+ int i;
+ struct hifn_device *dev;
+
+ dev = pci_get_drvdata(pdev);
+
+ if (dev) {
+ cancel_delayed_work(&dev->work);
+ flush_scheduled_work();
+
+ hifn_unregister_rng(dev);
+ hifn_unregister_alg(dev);
+ hifn_reset_dma(dev, 1);
+ hifn_stop_device(dev);
+
+ free_irq(dev->irq, dev->name);
+ tasklet_kill(&dev->tasklet);
+
+ hifn_flush(dev);
+
+ pci_free_consistent(pdev, sizeof(struct hifn_dma),
+ dev->desc_virt, dev->desc_dma);
+ pci_unmap_single(pdev, dev->dst,
+ PAGE_SIZE << HIFN_MAX_RESULT_ORDER,
+ PCI_DMA_FROMDEVICE);
+ free_pages(dev->result_mem, HIFN_MAX_RESULT_ORDER);
+ for (i=0; i<3; ++i)
+ if (dev->bar[i])
+ iounmap(dev->bar[i]);
+
+ kfree(dev);
+ }
+
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+}
+
+static struct pci_device_id hifn_pci_tbl[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_HIFN, PCI_DEVICE_ID_HIFN_7955) },
+ { PCI_DEVICE(PCI_VENDOR_ID_HIFN, PCI_DEVICE_ID_HIFN_7956) },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, hifn_pci_tbl);
+
+static struct pci_driver hifn_pci_driver = {
+ .name = "hifn795x",
+ .id_table = hifn_pci_tbl,
+ .probe = hifn_probe,
+ .remove = __devexit_p(hifn_remove),
+};
+
+static int __devinit hifn_init(void)
+{
+ unsigned int freq;
+ int err;
+
+ if (strncmp(hifn_pll_ref, "ext", 3) &&
+ strncmp(hifn_pll_ref, "pci", 3)) {
+ printk(KERN_ERR "hifn795x: invalid hifn_pll_ref clock, "
+ "must be pci or ext");
+ return -EINVAL;
+ }
+
+ /*
+ * For the 7955/7956 the reference clock frequency must be in the
+ * range of 20MHz-100MHz. For the 7954 the upper bound is 66.67MHz,
+ * but this chip is currently not supported.
+ */
+ if (hifn_pll_ref[3] != '\0') {
+ freq = simple_strtoul(hifn_pll_ref + 3, NULL, 10);
+ if (freq < 20 || freq > 100) {
+ printk(KERN_ERR "hifn795x: invalid hifn_pll_ref "
+ "frequency, must be in the range "
+ "of 20-100");
+ return -EINVAL;
+ }
+ }
+
+ err = pci_register_driver(&hifn_pci_driver);
+ if (err < 0) {
+ dprintk("Failed to register PCI driver for %s device.\n",
+ hifn_pci_driver.name);
+ return -ENODEV;
+ }
+
+ printk(KERN_INFO "Driver for HIFN 795x crypto accelerator chip "
+ "has been successfully registered.\n");
+
+ return 0;
+}
+
+static void __devexit hifn_fini(void)
+{
+ pci_unregister_driver(&hifn_pci_driver);
+
+ printk(KERN_INFO "Driver for HIFN 795x crypto accelerator chip "
+ "has been successfully unregistered.\n");
+}
+
+module_init(hifn_init);
+module_exit(hifn_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+MODULE_DESCRIPTION("Driver for HIFN 795x crypto accelerator chip.");
diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c
index 5f7e718..2f3ad3f 100644
--- a/drivers/crypto/padlock-aes.c
+++ b/drivers/crypto/padlock-aes.c
@@ -44,6 +44,7 @@
*/
#include <crypto/algapi.h>
+#include <crypto/aes.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
@@ -53,9 +54,6 @@
#include <asm/byteorder.h>
#include "padlock.h"
-#define AES_MIN_KEY_SIZE 16 /* in uint8_t units */
-#define AES_MAX_KEY_SIZE 32 /* ditto */
-#define AES_BLOCK_SIZE 16 /* ditto */
#define AES_EXTENDED_KEY_SIZE 64 /* in uint32_t units */
#define AES_EXTENDED_KEY_SIZE_B (AES_EXTENDED_KEY_SIZE * sizeof(uint32_t))
@@ -419,6 +417,11 @@
/* ====== Encryption/decryption routines ====== */
/* These are the real call to PadLock. */
+static inline void padlock_reset_key(void)
+{
+ asm volatile ("pushfl; popfl");
+}
+
static inline void padlock_xcrypt(const u8 *input, u8 *output, void *key,
void *control_word)
{
@@ -439,8 +442,6 @@
static inline void aes_crypt(const u8 *in, u8 *out, u32 *key,
struct cword *cword)
{
- asm volatile ("pushfl; popfl");
-
/* padlock_xcrypt requires at least two blocks of data. */
if (unlikely(!(((unsigned long)in ^ (PAGE_SIZE - AES_BLOCK_SIZE)) &
(PAGE_SIZE - 1)))) {
@@ -459,7 +460,6 @@
return;
}
- asm volatile ("pushfl; popfl"); /* enforce key reload. */
asm volatile ("test $1, %%cl;"
"je 1f;"
"lea -1(%%ecx), %%eax;"
@@ -476,8 +476,6 @@
static inline u8 *padlock_xcrypt_cbc(const u8 *input, u8 *output, void *key,
u8 *iv, void *control_word, u32 count)
{
- /* Enforce key reload. */
- asm volatile ("pushfl; popfl");
/* rep xcryptcbc */
asm volatile (".byte 0xf3,0x0f,0xa7,0xd0"
: "+S" (input), "+D" (output), "+a" (iv)
@@ -488,12 +486,14 @@
static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
{
struct aes_ctx *ctx = aes_ctx(tfm);
+ padlock_reset_key();
aes_crypt(in, out, ctx->E, &ctx->cword.encrypt);
}
static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
{
struct aes_ctx *ctx = aes_ctx(tfm);
+ padlock_reset_key();
aes_crypt(in, out, ctx->D, &ctx->cword.decrypt);
}
@@ -526,6 +526,8 @@
struct blkcipher_walk walk;
int err;
+ padlock_reset_key();
+
blkcipher_walk_init(&walk, dst, src, nbytes);
err = blkcipher_walk_virt(desc, &walk);
@@ -548,6 +550,8 @@
struct blkcipher_walk walk;
int err;
+ padlock_reset_key();
+
blkcipher_walk_init(&walk, dst, src, nbytes);
err = blkcipher_walk_virt(desc, &walk);
@@ -592,6 +596,8 @@
struct blkcipher_walk walk;
int err;
+ padlock_reset_key();
+
blkcipher_walk_init(&walk, dst, src, nbytes);
err = blkcipher_walk_virt(desc, &walk);
@@ -616,6 +622,8 @@
struct blkcipher_walk walk;
int err;
+ padlock_reset_key();
+
blkcipher_walk_init(&walk, dst, src, nbytes);
err = blkcipher_walk_virt(desc, &walk);
diff --git a/include/crypto/aead.h b/include/crypto/aead.h
new file mode 100644
index 0000000..0edf949
--- /dev/null
+++ b/include/crypto/aead.h
@@ -0,0 +1,105 @@
+/*
+ * AEAD: Authenticated Encryption with Associated Data
+ *
+ * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+#ifndef _CRYPTO_AEAD_H
+#define _CRYPTO_AEAD_H
+
+#include <linux/crypto.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+/**
+ * struct aead_givcrypt_request - AEAD request with IV generation
+ * @seq: Sequence number for IV generation
+ * @giv: Space for generated IV
+ * @areq: The AEAD request itself
+ */
+struct aead_givcrypt_request {
+ u64 seq;
+ u8 *giv;
+
+ struct aead_request areq;
+};
+
+static inline struct crypto_aead *aead_givcrypt_reqtfm(
+ struct aead_givcrypt_request *req)
+{
+ return crypto_aead_reqtfm(&req->areq);
+}
+
+static inline int crypto_aead_givencrypt(struct aead_givcrypt_request *req)
+{
+ struct aead_tfm *crt = crypto_aead_crt(aead_givcrypt_reqtfm(req));
+ return crt->givencrypt(req);
+};
+
+static inline int crypto_aead_givdecrypt(struct aead_givcrypt_request *req)
+{
+ struct aead_tfm *crt = crypto_aead_crt(aead_givcrypt_reqtfm(req));
+ return crt->givdecrypt(req);
+};
+
+static inline void aead_givcrypt_set_tfm(struct aead_givcrypt_request *req,
+ struct crypto_aead *tfm)
+{
+ req->areq.base.tfm = crypto_aead_tfm(tfm);
+}
+
+static inline struct aead_givcrypt_request *aead_givcrypt_alloc(
+ struct crypto_aead *tfm, gfp_t gfp)
+{
+ struct aead_givcrypt_request *req;
+
+ req = kmalloc(sizeof(struct aead_givcrypt_request) +
+ crypto_aead_reqsize(tfm), gfp);
+
+ if (likely(req))
+ aead_givcrypt_set_tfm(req, tfm);
+
+ return req;
+}
+
+static inline void aead_givcrypt_free(struct aead_givcrypt_request *req)
+{
+ kfree(req);
+}
+
+static inline void aead_givcrypt_set_callback(
+ struct aead_givcrypt_request *req, u32 flags,
+ crypto_completion_t complete, void *data)
+{
+ aead_request_set_callback(&req->areq, flags, complete, data);
+}
+
+static inline void aead_givcrypt_set_crypt(struct aead_givcrypt_request *req,
+ struct scatterlist *src,
+ struct scatterlist *dst,
+ unsigned int nbytes, void *iv)
+{
+ aead_request_set_crypt(&req->areq, src, dst, nbytes, iv);
+}
+
+static inline void aead_givcrypt_set_assoc(struct aead_givcrypt_request *req,
+ struct scatterlist *assoc,
+ unsigned int assoclen)
+{
+ aead_request_set_assoc(&req->areq, assoc, assoclen);
+}
+
+static inline void aead_givcrypt_set_giv(struct aead_givcrypt_request *req,
+ u8 *giv, u64 seq)
+{
+ req->giv = giv;
+ req->seq = seq;
+}
+
+#endif /* _CRYPTO_AEAD_H */
diff --git a/include/crypto/aes.h b/include/crypto/aes.h
new file mode 100644
index 0000000..d480b76
--- /dev/null
+++ b/include/crypto/aes.h
@@ -0,0 +1,31 @@
+/*
+ * Common values for AES algorithms
+ */
+
+#ifndef _CRYPTO_AES_H
+#define _CRYPTO_AES_H
+
+#include <linux/types.h>
+#include <linux/crypto.h>
+
+#define AES_MIN_KEY_SIZE 16
+#define AES_MAX_KEY_SIZE 32
+#define AES_KEYSIZE_128 16
+#define AES_KEYSIZE_192 24
+#define AES_KEYSIZE_256 32
+#define AES_BLOCK_SIZE 16
+
+struct crypto_aes_ctx {
+ u32 key_length;
+ u32 key_enc[60];
+ u32 key_dec[60];
+};
+
+extern u32 crypto_ft_tab[4][256];
+extern u32 crypto_fl_tab[4][256];
+extern u32 crypto_it_tab[4][256];
+extern u32 crypto_il_tab[4][256];
+
+int crypto_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+ unsigned int key_len);
+#endif
diff --git a/include/crypto/algapi.h b/include/crypto/algapi.h
index b9b05d3..60d06e7 100644
--- a/include/crypto/algapi.h
+++ b/include/crypto/algapi.h
@@ -111,8 +111,15 @@
struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn, u32 type,
u32 mask);
+static inline void crypto_set_spawn(struct crypto_spawn *spawn,
+ struct crypto_instance *inst)
+{
+ spawn->inst = inst;
+}
+
struct crypto_attr_type *crypto_get_attr_type(struct rtattr **tb);
int crypto_check_attr_type(struct rtattr **tb, u32 type);
+const char *crypto_attr_alg_name(struct rtattr *rta);
struct crypto_alg *crypto_attr_alg(struct rtattr *rta, u32 type, u32 mask);
int crypto_attr_u32(struct rtattr *rta, u32 *num);
struct crypto_instance *crypto_alloc_instance(const char *name,
@@ -124,6 +131,10 @@
struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue);
int crypto_tfm_in_queue(struct crypto_queue *queue, struct crypto_tfm *tfm);
+/* These functions require the input/output to be aligned as u32. */
+void crypto_inc(u8 *a, unsigned int size);
+void crypto_xor(u8 *dst, const u8 *src, unsigned int size);
+
int blkcipher_walk_done(struct blkcipher_desc *desc,
struct blkcipher_walk *walk, int err);
int blkcipher_walk_virt(struct blkcipher_desc *desc,
@@ -187,20 +198,11 @@
return crypto_tfm_alg_instance(&aead->base);
}
-static inline struct crypto_ablkcipher *crypto_spawn_ablkcipher(
- struct crypto_spawn *spawn)
-{
- u32 type = CRYPTO_ALG_TYPE_BLKCIPHER;
- u32 mask = CRYPTO_ALG_TYPE_MASK;
-
- return __crypto_ablkcipher_cast(crypto_spawn_tfm(spawn, type, mask));
-}
-
static inline struct crypto_blkcipher *crypto_spawn_blkcipher(
struct crypto_spawn *spawn)
{
u32 type = CRYPTO_ALG_TYPE_BLKCIPHER;
- u32 mask = CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC;
+ u32 mask = CRYPTO_ALG_TYPE_MASK;
return __crypto_blkcipher_cast(crypto_spawn_tfm(spawn, type, mask));
}
@@ -303,5 +305,14 @@
return crypto_attr_alg(tb[1], type, mask);
}
+/*
+ * Returns CRYPTO_ALG_ASYNC if type/mask requires the use of sync algorithms.
+ * Otherwise returns zero.
+ */
+static inline int crypto_requires_sync(u32 type, u32 mask)
+{
+ return (type ^ CRYPTO_ALG_ASYNC) & mask & CRYPTO_ALG_ASYNC;
+}
+
#endif /* _CRYPTO_ALGAPI_H */
diff --git a/include/crypto/authenc.h b/include/crypto/authenc.h
new file mode 100644
index 0000000..e47b044
--- /dev/null
+++ b/include/crypto/authenc.h
@@ -0,0 +1,27 @@
+/*
+ * Authenc: Simple AEAD wrapper for IPsec
+ *
+ * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+#ifndef _CRYPTO_AUTHENC_H
+#define _CRYPTO_AUTHENC_H
+
+#include <linux/types.h>
+
+enum {
+ CRYPTO_AUTHENC_KEYA_UNSPEC,
+ CRYPTO_AUTHENC_KEYA_PARAM,
+};
+
+struct crypto_authenc_key_param {
+ __be32 enckeylen;
+};
+
+#endif /* _CRYPTO_AUTHENC_H */
+
diff --git a/include/crypto/ctr.h b/include/crypto/ctr.h
new file mode 100644
index 0000000..4180fc0
--- /dev/null
+++ b/include/crypto/ctr.h
@@ -0,0 +1,20 @@
+/*
+ * CTR: Counter mode
+ *
+ * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+#ifndef _CRYPTO_CTR_H
+#define _CRYPTO_CTR_H
+
+#define CTR_RFC3686_NONCE_SIZE 4
+#define CTR_RFC3686_IV_SIZE 8
+#define CTR_RFC3686_BLOCK_SIZE 16
+
+#endif /* _CRYPTO_CTR_H */
diff --git a/include/crypto/des.h b/include/crypto/des.h
new file mode 100644
index 0000000..2971c63
--- /dev/null
+++ b/include/crypto/des.h
@@ -0,0 +1,19 @@
+/*
+ * DES & Triple DES EDE Cipher Algorithms.
+ */
+
+#ifndef __CRYPTO_DES_H
+#define __CRYPTO_DES_H
+
+#define DES_KEY_SIZE 8
+#define DES_EXPKEY_WORDS 32
+#define DES_BLOCK_SIZE 8
+
+#define DES3_EDE_KEY_SIZE (3 * DES_KEY_SIZE)
+#define DES3_EDE_EXPKEY_WORDS (3 * DES_EXPKEY_WORDS)
+#define DES3_EDE_BLOCK_SIZE DES_BLOCK_SIZE
+
+
+extern unsigned long des_ekey(u32 *pe, const u8 *k);
+
+#endif /* __CRYPTO_DES_H */
diff --git a/include/crypto/internal/aead.h b/include/crypto/internal/aead.h
new file mode 100644
index 0000000..d838c94
--- /dev/null
+++ b/include/crypto/internal/aead.h
@@ -0,0 +1,80 @@
+/*
+ * AEAD: Authenticated Encryption with Associated Data
+ *
+ * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+#ifndef _CRYPTO_INTERNAL_AEAD_H
+#define _CRYPTO_INTERNAL_AEAD_H
+
+#include <crypto/aead.h>
+#include <crypto/algapi.h>
+#include <linux/types.h>
+
+struct rtattr;
+
+struct crypto_aead_spawn {
+ struct crypto_spawn base;
+};
+
+extern const struct crypto_type crypto_nivaead_type;
+
+static inline void crypto_set_aead_spawn(
+ struct crypto_aead_spawn *spawn, struct crypto_instance *inst)
+{
+ crypto_set_spawn(&spawn->base, inst);
+}
+
+int crypto_grab_aead(struct crypto_aead_spawn *spawn, const char *name,
+ u32 type, u32 mask);
+
+static inline void crypto_drop_aead(struct crypto_aead_spawn *spawn)
+{
+ crypto_drop_spawn(&spawn->base);
+}
+
+static inline struct crypto_alg *crypto_aead_spawn_alg(
+ struct crypto_aead_spawn *spawn)
+{
+ return spawn->base.alg;
+}
+
+static inline struct crypto_aead *crypto_spawn_aead(
+ struct crypto_aead_spawn *spawn)
+{
+ return __crypto_aead_cast(
+ crypto_spawn_tfm(&spawn->base, CRYPTO_ALG_TYPE_AEAD,
+ CRYPTO_ALG_TYPE_MASK));
+}
+
+struct crypto_instance *aead_geniv_alloc(struct crypto_template *tmpl,
+ struct rtattr **tb, u32 type,
+ u32 mask);
+void aead_geniv_free(struct crypto_instance *inst);
+int aead_geniv_init(struct crypto_tfm *tfm);
+void aead_geniv_exit(struct crypto_tfm *tfm);
+
+static inline struct crypto_aead *aead_geniv_base(struct crypto_aead *geniv)
+{
+ return crypto_aead_crt(geniv)->base;
+}
+
+static inline void *aead_givcrypt_reqctx(struct aead_givcrypt_request *req)
+{
+ return aead_request_ctx(&req->areq);
+}
+
+static inline void aead_givcrypt_complete(struct aead_givcrypt_request *req,
+ int err)
+{
+ aead_request_complete(&req->areq, err);
+}
+
+#endif /* _CRYPTO_INTERNAL_AEAD_H */
+
diff --git a/include/crypto/internal/skcipher.h b/include/crypto/internal/skcipher.h
new file mode 100644
index 0000000..2ba42cd
--- /dev/null
+++ b/include/crypto/internal/skcipher.h
@@ -0,0 +1,110 @@
+/*
+ * Symmetric key ciphers.
+ *
+ * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+#ifndef _CRYPTO_INTERNAL_SKCIPHER_H
+#define _CRYPTO_INTERNAL_SKCIPHER_H
+
+#include <crypto/algapi.h>
+#include <crypto/skcipher.h>
+#include <linux/types.h>
+
+struct rtattr;
+
+struct crypto_skcipher_spawn {
+ struct crypto_spawn base;
+};
+
+extern const struct crypto_type crypto_givcipher_type;
+
+static inline void crypto_set_skcipher_spawn(
+ struct crypto_skcipher_spawn *spawn, struct crypto_instance *inst)
+{
+ crypto_set_spawn(&spawn->base, inst);
+}
+
+int crypto_grab_skcipher(struct crypto_skcipher_spawn *spawn, const char *name,
+ u32 type, u32 mask);
+
+static inline void crypto_drop_skcipher(struct crypto_skcipher_spawn *spawn)
+{
+ crypto_drop_spawn(&spawn->base);
+}
+
+static inline struct crypto_alg *crypto_skcipher_spawn_alg(
+ struct crypto_skcipher_spawn *spawn)
+{
+ return spawn->base.alg;
+}
+
+static inline struct crypto_ablkcipher *crypto_spawn_skcipher(
+ struct crypto_skcipher_spawn *spawn)
+{
+ return __crypto_ablkcipher_cast(
+ crypto_spawn_tfm(&spawn->base, crypto_skcipher_type(0),
+ crypto_skcipher_mask(0)));
+}
+
+int skcipher_null_givencrypt(struct skcipher_givcrypt_request *req);
+int skcipher_null_givdecrypt(struct skcipher_givcrypt_request *req);
+const char *crypto_default_geniv(const struct crypto_alg *alg);
+
+struct crypto_instance *skcipher_geniv_alloc(struct crypto_template *tmpl,
+ struct rtattr **tb, u32 type,
+ u32 mask);
+void skcipher_geniv_free(struct crypto_instance *inst);
+int skcipher_geniv_init(struct crypto_tfm *tfm);
+void skcipher_geniv_exit(struct crypto_tfm *tfm);
+
+static inline struct crypto_ablkcipher *skcipher_geniv_cipher(
+ struct crypto_ablkcipher *geniv)
+{
+ return crypto_ablkcipher_crt(geniv)->base;
+}
+
+static inline int skcipher_enqueue_givcrypt(
+ struct crypto_queue *queue, struct skcipher_givcrypt_request *request)
+{
+ return ablkcipher_enqueue_request(queue, &request->creq);
+}
+
+static inline struct skcipher_givcrypt_request *skcipher_dequeue_givcrypt(
+ struct crypto_queue *queue)
+{
+ return container_of(ablkcipher_dequeue_request(queue),
+ struct skcipher_givcrypt_request, creq);
+}
+
+static inline void *skcipher_givcrypt_reqctx(
+ struct skcipher_givcrypt_request *req)
+{
+ return ablkcipher_request_ctx(&req->creq);
+}
+
+static inline void ablkcipher_request_complete(struct ablkcipher_request *req,
+ int err)
+{
+ req->base.complete(&req->base, err);
+}
+
+static inline void skcipher_givcrypt_complete(
+ struct skcipher_givcrypt_request *req, int err)
+{
+ ablkcipher_request_complete(&req->creq, err);
+}
+
+static inline u32 ablkcipher_request_flags(struct ablkcipher_request *req)
+{
+ return req->base.flags;
+}
+
+#endif /* _CRYPTO_INTERNAL_SKCIPHER_H */
+
diff --git a/crypto/scatterwalk.h b/include/crypto/scatterwalk.h
similarity index 69%
rename from crypto/scatterwalk.h
rename to include/crypto/scatterwalk.h
index 87ed681..224658b 100644
--- a/crypto/scatterwalk.h
+++ b/include/crypto/scatterwalk.h
@@ -1,9 +1,10 @@
/*
- * Cryptographic API.
+ * Cryptographic scatter and gather helpers.
*
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
* Copyright (c) 2002 Adam J. Richter <adam@yggdrasil.com>
* Copyright (c) 2004 Jean-Luc Cooke <jlcooke@certainkey.com>
+ * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -15,14 +16,52 @@
#ifndef _CRYPTO_SCATTERWALK_H
#define _CRYPTO_SCATTERWALK_H
+#include <asm/kmap_types.h>
+#include <crypto/algapi.h>
+#include <linux/hardirq.h>
+#include <linux/highmem.h>
+#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/scatterlist.h>
+#include <linux/sched.h>
-#include "internal.h"
+static inline enum km_type crypto_kmap_type(int out)
+{
+ enum km_type type;
+
+ if (in_softirq())
+ type = out * (KM_SOFTIRQ1 - KM_SOFTIRQ0) + KM_SOFTIRQ0;
+ else
+ type = out * (KM_USER1 - KM_USER0) + KM_USER0;
+
+ return type;
+}
+
+static inline void *crypto_kmap(struct page *page, int out)
+{
+ return kmap_atomic(page, crypto_kmap_type(out));
+}
+
+static inline void crypto_kunmap(void *vaddr, int out)
+{
+ kunmap_atomic(vaddr, crypto_kmap_type(out));
+}
+
+static inline void crypto_yield(u32 flags)
+{
+ if (flags & CRYPTO_TFM_REQ_MAY_SLEEP)
+ cond_resched();
+}
+
+static inline void scatterwalk_sg_chain(struct scatterlist *sg1, int num,
+ struct scatterlist *sg2)
+{
+ sg_set_page(&sg1[num - 1], (void *)sg2, 0, 0);
+}
static inline struct scatterlist *scatterwalk_sg_next(struct scatterlist *sg)
{
- return (++sg)->length ? sg : (void *) sg_page(sg);
+ return (++sg)->length ? sg : (void *)sg_page(sg);
}
static inline unsigned long scatterwalk_samebuf(struct scatter_walk *walk_in,
diff --git a/include/crypto/sha.h b/include/crypto/sha.h
index 0686e1f..c0ccc2b 100644
--- a/include/crypto/sha.h
+++ b/include/crypto/sha.h
@@ -8,6 +8,9 @@
#define SHA1_DIGEST_SIZE 20
#define SHA1_BLOCK_SIZE 64
+#define SHA224_DIGEST_SIZE 28
+#define SHA224_BLOCK_SIZE 64
+
#define SHA256_DIGEST_SIZE 32
#define SHA256_BLOCK_SIZE 64
@@ -23,6 +26,15 @@
#define SHA1_H3 0x10325476UL
#define SHA1_H4 0xc3d2e1f0UL
+#define SHA224_H0 0xc1059ed8UL
+#define SHA224_H1 0x367cd507UL
+#define SHA224_H2 0x3070dd17UL
+#define SHA224_H3 0xf70e5939UL
+#define SHA224_H4 0xffc00b31UL
+#define SHA224_H5 0x68581511UL
+#define SHA224_H6 0x64f98fa7UL
+#define SHA224_H7 0xbefa4fa4UL
+
#define SHA256_H0 0x6a09e667UL
#define SHA256_H1 0xbb67ae85UL
#define SHA256_H2 0x3c6ef372UL
diff --git a/include/crypto/skcipher.h b/include/crypto/skcipher.h
new file mode 100644
index 0000000..25fd612
--- /dev/null
+++ b/include/crypto/skcipher.h
@@ -0,0 +1,110 @@
+/*
+ * Symmetric key ciphers.
+ *
+ * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+#ifndef _CRYPTO_SKCIPHER_H
+#define _CRYPTO_SKCIPHER_H
+
+#include <linux/crypto.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+/**
+ * struct skcipher_givcrypt_request - Crypto request with IV generation
+ * @seq: Sequence number for IV generation
+ * @giv: Space for generated IV
+ * @creq: The crypto request itself
+ */
+struct skcipher_givcrypt_request {
+ u64 seq;
+ u8 *giv;
+
+ struct ablkcipher_request creq;
+};
+
+static inline struct crypto_ablkcipher *skcipher_givcrypt_reqtfm(
+ struct skcipher_givcrypt_request *req)
+{
+ return crypto_ablkcipher_reqtfm(&req->creq);
+}
+
+static inline int crypto_skcipher_givencrypt(
+ struct skcipher_givcrypt_request *req)
+{
+ struct ablkcipher_tfm *crt =
+ crypto_ablkcipher_crt(skcipher_givcrypt_reqtfm(req));
+ return crt->givencrypt(req);
+};
+
+static inline int crypto_skcipher_givdecrypt(
+ struct skcipher_givcrypt_request *req)
+{
+ struct ablkcipher_tfm *crt =
+ crypto_ablkcipher_crt(skcipher_givcrypt_reqtfm(req));
+ return crt->givdecrypt(req);
+};
+
+static inline void skcipher_givcrypt_set_tfm(
+ struct skcipher_givcrypt_request *req, struct crypto_ablkcipher *tfm)
+{
+ req->creq.base.tfm = crypto_ablkcipher_tfm(tfm);
+}
+
+static inline struct skcipher_givcrypt_request *skcipher_givcrypt_cast(
+ struct crypto_async_request *req)
+{
+ return container_of(ablkcipher_request_cast(req),
+ struct skcipher_givcrypt_request, creq);
+}
+
+static inline struct skcipher_givcrypt_request *skcipher_givcrypt_alloc(
+ struct crypto_ablkcipher *tfm, gfp_t gfp)
+{
+ struct skcipher_givcrypt_request *req;
+
+ req = kmalloc(sizeof(struct skcipher_givcrypt_request) +
+ crypto_ablkcipher_reqsize(tfm), gfp);
+
+ if (likely(req))
+ skcipher_givcrypt_set_tfm(req, tfm);
+
+ return req;
+}
+
+static inline void skcipher_givcrypt_free(struct skcipher_givcrypt_request *req)
+{
+ kfree(req);
+}
+
+static inline void skcipher_givcrypt_set_callback(
+ struct skcipher_givcrypt_request *req, u32 flags,
+ crypto_completion_t complete, void *data)
+{
+ ablkcipher_request_set_callback(&req->creq, flags, complete, data);
+}
+
+static inline void skcipher_givcrypt_set_crypt(
+ struct skcipher_givcrypt_request *req,
+ struct scatterlist *src, struct scatterlist *dst,
+ unsigned int nbytes, void *iv)
+{
+ ablkcipher_request_set_crypt(&req->creq, src, dst, nbytes, iv);
+}
+
+static inline void skcipher_givcrypt_set_giv(
+ struct skcipher_givcrypt_request *req, u8 *giv, u64 seq)
+{
+ req->giv = giv;
+ req->seq = seq;
+}
+
+#endif /* _CRYPTO_SKCIPHER_H */
+
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index f3110eb..5e02d1b 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -33,10 +33,13 @@
#define CRYPTO_ALG_TYPE_DIGEST 0x00000002
#define CRYPTO_ALG_TYPE_HASH 0x00000003
#define CRYPTO_ALG_TYPE_BLKCIPHER 0x00000004
-#define CRYPTO_ALG_TYPE_COMPRESS 0x00000005
-#define CRYPTO_ALG_TYPE_AEAD 0x00000006
+#define CRYPTO_ALG_TYPE_ABLKCIPHER 0x00000005
+#define CRYPTO_ALG_TYPE_GIVCIPHER 0x00000006
+#define CRYPTO_ALG_TYPE_COMPRESS 0x00000008
+#define CRYPTO_ALG_TYPE_AEAD 0x00000009
#define CRYPTO_ALG_TYPE_HASH_MASK 0x0000000e
+#define CRYPTO_ALG_TYPE_BLKCIPHER_MASK 0x0000000c
#define CRYPTO_ALG_LARVAL 0x00000010
#define CRYPTO_ALG_DEAD 0x00000020
@@ -50,6 +53,12 @@
#define CRYPTO_ALG_NEED_FALLBACK 0x00000100
/*
+ * This bit is set for symmetric key ciphers that have already been wrapped
+ * with a generic IV generator to prevent them from being wrapped again.
+ */
+#define CRYPTO_ALG_GENIV 0x00000200
+
+/*
* Transform masks and values (for crt_flags).
*/
#define CRYPTO_TFM_REQ_MASK 0x000fff00
@@ -81,13 +90,11 @@
#define CRYPTO_MINALIGN ARCH_KMALLOC_MINALIGN
#elif defined(ARCH_SLAB_MINALIGN)
#define CRYPTO_MINALIGN ARCH_SLAB_MINALIGN
+#else
+#define CRYPTO_MINALIGN __alignof__(unsigned long long)
#endif
-#ifdef CRYPTO_MINALIGN
#define CRYPTO_MINALIGN_ATTR __attribute__ ((__aligned__(CRYPTO_MINALIGN)))
-#else
-#define CRYPTO_MINALIGN_ATTR
-#endif
struct scatterlist;
struct crypto_ablkcipher;
@@ -97,6 +104,8 @@
struct crypto_hash;
struct crypto_tfm;
struct crypto_type;
+struct aead_givcrypt_request;
+struct skcipher_givcrypt_request;
typedef void (*crypto_completion_t)(struct crypto_async_request *req, int err);
@@ -176,6 +185,10 @@
unsigned int keylen);
int (*encrypt)(struct ablkcipher_request *req);
int (*decrypt)(struct ablkcipher_request *req);
+ int (*givencrypt)(struct skcipher_givcrypt_request *req);
+ int (*givdecrypt)(struct skcipher_givcrypt_request *req);
+
+ const char *geniv;
unsigned int min_keysize;
unsigned int max_keysize;
@@ -185,11 +198,16 @@
struct aead_alg {
int (*setkey)(struct crypto_aead *tfm, const u8 *key,
unsigned int keylen);
+ int (*setauthsize)(struct crypto_aead *tfm, unsigned int authsize);
int (*encrypt)(struct aead_request *req);
int (*decrypt)(struct aead_request *req);
+ int (*givencrypt)(struct aead_givcrypt_request *req);
+ int (*givdecrypt)(struct aead_givcrypt_request *req);
+
+ const char *geniv;
unsigned int ivsize;
- unsigned int authsize;
+ unsigned int maxauthsize;
};
struct blkcipher_alg {
@@ -202,6 +220,8 @@
struct scatterlist *dst, struct scatterlist *src,
unsigned int nbytes);
+ const char *geniv;
+
unsigned int min_keysize;
unsigned int max_keysize;
unsigned int ivsize;
@@ -317,6 +337,11 @@
unsigned int keylen);
int (*encrypt)(struct ablkcipher_request *req);
int (*decrypt)(struct ablkcipher_request *req);
+ int (*givencrypt)(struct skcipher_givcrypt_request *req);
+ int (*givdecrypt)(struct skcipher_givcrypt_request *req);
+
+ struct crypto_ablkcipher *base;
+
unsigned int ivsize;
unsigned int reqsize;
};
@@ -326,6 +351,11 @@
unsigned int keylen);
int (*encrypt)(struct aead_request *req);
int (*decrypt)(struct aead_request *req);
+ int (*givencrypt)(struct aead_givcrypt_request *req);
+ int (*givdecrypt)(struct aead_givcrypt_request *req);
+
+ struct crypto_aead *base;
+
unsigned int ivsize;
unsigned int authsize;
unsigned int reqsize;
@@ -525,17 +555,23 @@
return (struct crypto_ablkcipher *)tfm;
}
-static inline struct crypto_ablkcipher *crypto_alloc_ablkcipher(
- const char *alg_name, u32 type, u32 mask)
+static inline u32 crypto_skcipher_type(u32 type)
{
- type &= ~CRYPTO_ALG_TYPE_MASK;
+ type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
type |= CRYPTO_ALG_TYPE_BLKCIPHER;
- mask |= CRYPTO_ALG_TYPE_MASK;
-
- return __crypto_ablkcipher_cast(
- crypto_alloc_base(alg_name, type, mask));
+ return type;
}
+static inline u32 crypto_skcipher_mask(u32 mask)
+{
+ mask &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
+ mask |= CRYPTO_ALG_TYPE_BLKCIPHER_MASK;
+ return mask;
+}
+
+struct crypto_ablkcipher *crypto_alloc_ablkcipher(const char *alg_name,
+ u32 type, u32 mask);
+
static inline struct crypto_tfm *crypto_ablkcipher_tfm(
struct crypto_ablkcipher *tfm)
{
@@ -550,11 +586,8 @@
static inline int crypto_has_ablkcipher(const char *alg_name, u32 type,
u32 mask)
{
- type &= ~CRYPTO_ALG_TYPE_MASK;
- type |= CRYPTO_ALG_TYPE_BLKCIPHER;
- mask |= CRYPTO_ALG_TYPE_MASK;
-
- return crypto_has_alg(alg_name, type, mask);
+ return crypto_has_alg(alg_name, crypto_skcipher_type(type),
+ crypto_skcipher_mask(mask));
}
static inline struct ablkcipher_tfm *crypto_ablkcipher_crt(
@@ -601,7 +634,9 @@
static inline int crypto_ablkcipher_setkey(struct crypto_ablkcipher *tfm,
const u8 *key, unsigned int keylen)
{
- return crypto_ablkcipher_crt(tfm)->setkey(tfm, key, keylen);
+ struct ablkcipher_tfm *crt = crypto_ablkcipher_crt(tfm);
+
+ return crt->setkey(crt->base, key, keylen);
}
static inline struct crypto_ablkcipher *crypto_ablkcipher_reqtfm(
@@ -633,7 +668,7 @@
static inline void ablkcipher_request_set_tfm(
struct ablkcipher_request *req, struct crypto_ablkcipher *tfm)
{
- req->base.tfm = crypto_ablkcipher_tfm(tfm);
+ req->base.tfm = crypto_ablkcipher_tfm(crypto_ablkcipher_crt(tfm)->base);
}
static inline struct ablkcipher_request *ablkcipher_request_cast(
@@ -686,15 +721,7 @@
return (struct crypto_aead *)tfm;
}
-static inline struct crypto_aead *crypto_alloc_aead(const char *alg_name,
- u32 type, u32 mask)
-{
- type &= ~CRYPTO_ALG_TYPE_MASK;
- type |= CRYPTO_ALG_TYPE_AEAD;
- mask |= CRYPTO_ALG_TYPE_MASK;
-
- return __crypto_aead_cast(crypto_alloc_base(alg_name, type, mask));
-}
+struct crypto_aead *crypto_alloc_aead(const char *alg_name, u32 type, u32 mask);
static inline struct crypto_tfm *crypto_aead_tfm(struct crypto_aead *tfm)
{
@@ -749,9 +776,13 @@
static inline int crypto_aead_setkey(struct crypto_aead *tfm, const u8 *key,
unsigned int keylen)
{
- return crypto_aead_crt(tfm)->setkey(tfm, key, keylen);
+ struct aead_tfm *crt = crypto_aead_crt(tfm);
+
+ return crt->setkey(crt->base, key, keylen);
}
+int crypto_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize);
+
static inline struct crypto_aead *crypto_aead_reqtfm(struct aead_request *req)
{
return __crypto_aead_cast(req->base.tfm);
@@ -775,7 +806,7 @@
static inline void aead_request_set_tfm(struct aead_request *req,
struct crypto_aead *tfm)
{
- req->base.tfm = crypto_aead_tfm(tfm);
+ req->base.tfm = crypto_aead_tfm(crypto_aead_crt(tfm)->base);
}
static inline struct aead_request *aead_request_alloc(struct crypto_aead *tfm,
@@ -841,9 +872,9 @@
static inline struct crypto_blkcipher *crypto_alloc_blkcipher(
const char *alg_name, u32 type, u32 mask)
{
- type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
+ type &= ~CRYPTO_ALG_TYPE_MASK;
type |= CRYPTO_ALG_TYPE_BLKCIPHER;
- mask |= CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC;
+ mask |= CRYPTO_ALG_TYPE_MASK;
return __crypto_blkcipher_cast(crypto_alloc_base(alg_name, type, mask));
}
@@ -861,9 +892,9 @@
static inline int crypto_has_blkcipher(const char *alg_name, u32 type, u32 mask)
{
- type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
+ type &= ~CRYPTO_ALG_TYPE_MASK;
type |= CRYPTO_ALG_TYPE_BLKCIPHER;
- mask |= CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC;
+ mask |= CRYPTO_ALG_TYPE_MASK;
return crypto_has_alg(alg_name, type, mask);
}
@@ -1081,6 +1112,7 @@
u32 type, u32 mask)
{
type &= ~CRYPTO_ALG_TYPE_MASK;
+ mask &= ~CRYPTO_ALG_TYPE_MASK;
type |= CRYPTO_ALG_TYPE_HASH;
mask |= CRYPTO_ALG_TYPE_HASH_MASK;
@@ -1100,6 +1132,7 @@
static inline int crypto_has_hash(const char *alg_name, u32 type, u32 mask)
{
type &= ~CRYPTO_ALG_TYPE_MASK;
+ mask &= ~CRYPTO_ALG_TYPE_MASK;
type |= CRYPTO_ALG_TYPE_HASH;
mask |= CRYPTO_ALG_TYPE_HASH_MASK;
diff --git a/include/linux/hw_random.h b/include/linux/hw_random.h
index 21ea761..85d1191 100644
--- a/include/linux/hw_random.h
+++ b/include/linux/hw_random.h
@@ -33,7 +33,7 @@
const char *name;
int (*init)(struct hwrng *rng);
void (*cleanup)(struct hwrng *rng);
- int (*data_present)(struct hwrng *rng);
+ int (*data_present)(struct hwrng *rng, int wait);
int (*data_read)(struct hwrng *rng, u32 *data);
unsigned long priv;