aboutsummaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorJames Morris <jmorris@intercode.com.au>2002-10-23 14:00:40 -0700
committerJames Morris <jmorris@intercode.com.au>2002-10-23 14:00:40 -0700
commitb99b66de129f360653bd8f37af0f16e37009899e (patch)
tree34b29e190822252e7965dcf8a9ec423d5d9d28d4 /crypto
parentecf2c2143f0865f447020144b2ee6e4181f65814 (diff)
downloadhistory-b99b66de129f360653bd8f37af0f16e37009899e.tar.gz
[CRYPTO]: Add initial crypto api subsystem.
Diffstat (limited to 'crypto')
-rw-r--r--crypto/Config.help18
-rw-r--r--crypto/Config.in15
-rw-r--r--crypto/Makefile15
-rw-r--r--crypto/api.c270
-rw-r--r--crypto/cipher.c249
-rw-r--r--crypto/compress.c41
-rw-r--r--crypto/des.c1215
-rw-r--r--crypto/digest.c126
-rw-r--r--crypto/internal.h53
-rw-r--r--crypto/md5.c242
-rw-r--r--crypto/sha1.c203
-rw-r--r--crypto/tcrypt.c1152
-rw-r--r--crypto/tcrypt.h587
13 files changed, 4186 insertions, 0 deletions
diff --git a/crypto/Config.help b/crypto/Config.help
new file mode 100644
index 00000000000000..5ed0e427a51cca
--- /dev/null
+++ b/crypto/Config.help
@@ -0,0 +1,18 @@
+#
+# Cryptographic API Components
+#
+CONFIG_CRYPTO
+ This option provides the core Cryptographic API.
+
+CONFIG_CRYPTO_MD5
+ MD5 message digest algorithm (RFC1321), including HMAC (RFC2104, RFC2403).
+
+CONFIG_CRYPTO_SHA1
+ SHA-1 secure hash standard (FIPS 180-1), including HMAC (RFC2104, RFC2404).
+
+CONFIG_CRYPTO_DES
+ DES cipher algorithm (FIPS 46-2), and 3DES_EDE.
+
+CONFIG_CRYPTO_TEST
+ Quick & dirty crypto test module.
+
diff --git a/crypto/Config.in b/crypto/Config.in
new file mode 100644
index 00000000000000..bcdd5852ead678
--- /dev/null
+++ b/crypto/Config.in
@@ -0,0 +1,15 @@
+#
+# Cryptographic API Configuration
+#
+mainmenu_option next_comment
+comment 'Cryptographic options'
+
+bool 'Cryptographic API' CONFIG_CRYPTO
+if [ "$CONFIG_CRYPTO" = "y" ]; then
+ tristate ' MD5 digest algorithm' CONFIG_CRYPTO_MD5
+ tristate ' SHA-1 digest algorithm' CONFIG_CRYPTO_SHA1
+ tristate ' DES/3DES cipher algorithms' CONFIG_CRYPTO_DES
+ tristate ' Testing module' CONFIG_CRYPTO_TEST
+fi
+
+endmenu
diff --git a/crypto/Makefile b/crypto/Makefile
new file mode 100644
index 00000000000000..6c7f7fb6590e4d
--- /dev/null
+++ b/crypto/Makefile
@@ -0,0 +1,15 @@
+#
+# Cryptographic API
+#
+
+export-objs := api.o
+
+obj-$(CONFIG_CRYPTO) += api.o cipher.o digest.o compress.o
+
+obj-$(CONFIG_CRYPTO_MD5) += md5.o
+obj-$(CONFIG_CRYPTO_SHA1) += sha1.o
+obj-$(CONFIG_CRYPTO_DES) += des.o
+
+obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
+
+include $(TOPDIR)/Rules.make
diff --git a/crypto/api.c b/crypto/api.c
new file mode 100644
index 00000000000000..d0c9fded60813b
--- /dev/null
+++ b/crypto/api.c
@@ -0,0 +1,270 @@
+/*
+ * Scatterlist Cryptographic API.
+ *
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ * Copyright (c) 2002 David S. Miller (davem@redhat.com)
+ *
+ * Portions derived from Cryptoapi, by Alexander Kjeldaas <astor@fast.no>
+ * and Nettle, by Niels Möller.
+ *
+ * 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/spinlock.h>
+#include <linux/list.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/crypto.h>
+#include "internal.h"
+
+static rwlock_t crypto_alg_lock = RW_LOCK_UNLOCKED;
+static LIST_HEAD(crypto_alg_list);
+
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+ struct list_head *v;
+ loff_t n = *pos;
+
+ read_lock(&crypto_alg_lock);
+ list_for_each(v, &crypto_alg_list)
+ if (!n--)
+ return list_entry(v, struct crypto_alg, cra_list);
+ return NULL;
+}
+
+static void *c_next(struct seq_file *m, void *p, loff_t *pos)
+{
+ struct list_head *v = p;
+
+ (*pos)++;
+ v = v->next;
+ return (v == &crypto_alg_list) ?
+ NULL : list_entry(v, struct crypto_alg, cra_list);
+}
+
+static void c_stop(struct seq_file *m, void *p)
+{
+ read_unlock(&crypto_alg_lock);
+}
+
+static int c_show(struct seq_file *m, void *p)
+{
+ struct crypto_alg *alg = (struct crypto_alg *)p;
+
+ seq_printf(m, "name : %s\n", alg->cra_name);
+ seq_printf(m, "id : 0x%08x\n", alg->cra_id);
+ seq_printf(m, "blocksize : %d\n", alg->cra_blocksize);
+
+ switch (alg->cra_id & CRYPTO_TYPE_MASK) {
+ case CRYPTO_TYPE_CIPHER:
+ seq_printf(m, "keysize : %d\n", alg->cra_cipher.cia_keysize);
+ seq_printf(m, "ivsize : %d\n", alg->cra_cipher.cia_ivsize);
+ break;
+
+ case CRYPTO_TYPE_DIGEST:
+ seq_printf(m, "digestsize : %d\n",
+ alg->cra_digest.dia_digestsize);
+ break;
+ }
+
+ seq_putc(m, '\n');
+ return 0;
+}
+
+static struct seq_operations crypto_seq_ops = {
+ .start = c_start,
+ .next = c_next,
+ .stop = c_stop,
+ .show = c_show
+};
+
+static int crypto_info_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &crypto_seq_ops);
+}
+
+struct file_operations proc_crypto_ops = {
+ .open = crypto_info_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release
+};
+
+
+static inline void crypto_alg_get(struct crypto_alg *alg)
+{
+ /* XXX: inc refcount */
+}
+
+static inline void crypto_alg_put(struct crypto_alg *alg)
+{
+ /* XXX: dec refcount */
+}
+
+struct crypto_alg *crypto_alg_lookup(__u32 algid)
+{
+ struct list_head *p;
+ struct crypto_alg *alg = NULL;
+
+ read_lock(&crypto_alg_lock);
+
+ list_for_each(p, &crypto_alg_list) {
+ if ((((struct crypto_alg *)p)->cra_id
+ & CRYPTO_ALG_MASK) == algid) {
+ alg = (struct crypto_alg *)p;
+ crypto_alg_get(alg);
+ break;
+ }
+ }
+
+ read_unlock(&crypto_alg_lock);
+ return alg;
+}
+
+static void crypto_init_ops(struct crypto_tfm *tfm)
+{
+ switch (crypto_tfm_type(tfm) & CRYPTO_TYPE_MASK) {
+ case CRYPTO_TYPE_CIPHER:
+ crypto_init_cipher_ops(tfm);
+ break;
+
+ case CRYPTO_TYPE_DIGEST:
+ crypto_init_digest_ops(tfm);
+ break;
+
+ case CRYPTO_TYPE_COMP:
+ crypto_init_compress_ops(tfm);
+ break;
+
+ default:
+ BUG();
+
+ }
+}
+
+/*
+ * Todo: try and load the module if the lookup fails.
+ */
+struct crypto_tfm *crypto_alloc_tfm(__u32 id)
+{
+ struct crypto_tfm *tfm = NULL;
+ struct crypto_alg *alg;
+
+ alg = crypto_alg_lookup(id & CRYPTO_ALG_MASK);
+ if (alg == NULL)
+ goto out;
+
+ tfm = kmalloc(sizeof(*tfm), GFP_KERNEL);
+ if (tfm == NULL)
+ goto out_put;
+
+ if (alg->cra_ctxsize) {
+ tfm->crt_ctx = kmalloc(alg->cra_ctxsize, GFP_KERNEL);
+ if (tfm->crt_ctx == NULL)
+ goto out_free_tfm;
+ }
+
+ if ((alg->cra_id & CRYPTO_TYPE_MASK) == CRYPTO_TYPE_CIPHER) {
+ if (alg->cra_cipher.cia_ivsize) {
+ tfm->crt_cipher.cit_iv =
+ kmalloc(alg->cra_cipher.cia_ivsize, GFP_KERNEL);
+ if (tfm->crt_cipher.cit_iv == NULL)
+ goto out_free_ctx;
+ }
+ tfm->crt_cipher.cit_mode = id & CRYPTO_MODE_MASK;
+ }
+
+ tfm->__crt_alg = alg;
+ crypto_init_ops(tfm);
+
+ goto out;
+
+out_free_ctx:
+ if (tfm->__crt_alg->cra_ctxsize)
+ kfree(tfm->crt_ctx);
+out_free_tfm:
+ kfree(tfm);
+out_put:
+ crypto_alg_put(alg);
+out:
+ return tfm;
+}
+
+void crypto_free_tfm(struct crypto_tfm *tfm)
+{
+ if (tfm->__crt_alg->cra_ctxsize)
+ kfree(tfm->crt_ctx);
+
+ if (crypto_tfm_type(tfm) == CRYPTO_TYPE_CIPHER)
+ if (tfm->__crt_alg->cra_cipher.cia_ivsize)
+ kfree(tfm->crt_cipher.cit_iv);
+
+ crypto_alg_put(tfm->__crt_alg);
+ kfree(tfm);
+}
+
+int crypto_register_alg(struct crypto_alg *alg)
+{
+ int ret = 0;
+ struct list_head *p;
+
+ write_lock(&crypto_alg_lock);
+
+ list_for_each(p, &crypto_alg_list) {
+ struct crypto_alg *q = (struct crypto_alg *)p;
+
+ if (q->cra_id == alg->cra_id) {
+ ret = -EEXIST;
+ goto out;
+ }
+ }
+ list_add_tail(&alg->cra_list, &crypto_alg_list);
+out:
+ write_unlock(&crypto_alg_lock);
+ return ret;
+}
+
+int crypto_unregister_alg(struct crypto_alg *alg)
+{
+ int ret = -ENOENT;
+ struct list_head *p;
+
+ write_lock(&crypto_alg_lock);
+
+ list_for_each(p, &crypto_alg_list) {
+ if (alg == (struct crypto_alg *)p) {
+ list_del(p);
+ ret = 0;
+ goto out;
+ }
+ }
+out:
+ write_unlock(&crypto_alg_lock);
+ return ret;
+}
+
+
+static int __init init_crypto(void)
+{
+ struct proc_dir_entry *proc;
+
+ printk(KERN_INFO "Initializing Cryptographic API\n");
+ proc = create_proc_entry("crypto", 0, NULL);
+ if (proc)
+ proc->proc_fops = &proc_crypto_ops;
+
+ return 0;
+}
+
+__initcall(init_crypto);
+
+EXPORT_SYMBOL_GPL(crypto_register_alg);
+EXPORT_SYMBOL_GPL(crypto_unregister_alg);
+EXPORT_SYMBOL_GPL(crypto_alloc_tfm);
+EXPORT_SYMBOL_GPL(crypto_free_tfm);
+
diff --git a/crypto/cipher.c b/crypto/cipher.c
new file mode 100644
index 00000000000000..bb466a968a965c
--- /dev/null
+++ b/crypto/cipher.c
@@ -0,0 +1,249 @@
+/*
+ * Cryptographic API.
+ *
+ * Cipher operations.
+ *
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.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 <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <asm/scatterlist.h>
+#include <linux/crypto.h>
+#include "internal.h"
+
+typedef void (cryptfn_t)(void *, __u8 *, __u8 *);
+typedef void (procfn_t)(struct crypto_tfm *, __u8 *, cryptfn_t, int enc);
+
+static inline void xor_64(__u8 *a, const __u8 *b)
+{
+ ((__u32 *)a)[0] ^= ((__u32 *)b)[0];
+ ((__u32 *)a)[1] ^= ((__u32 *)b)[1];
+}
+
+static inline size_t sglen(struct scatterlist *sg, size_t nsg)
+{
+ int i;
+ size_t n;
+
+ for (i = 0, n = 0; i < nsg; i++)
+ n += sg[i].length;
+
+ return n;
+}
+
+/*
+ * Do not call this unless the total length of all of the fragments
+ * has been verified as multiple of the block size.
+ */
+static int copy_chunks(struct crypto_tfm *tfm, __u8 *buf,
+ struct scatterlist *sg, int sgidx,
+ int rlen, int *last, int in)
+{
+ int i, copied, coff, j, aligned;
+ size_t bsize = crypto_tfm_blocksize(tfm);
+
+ for (i = sgidx, j = copied = 0, aligned = 0 ; copied < bsize; i++) {
+ int len = sg[i].length;
+ int clen;
+ char *p;
+
+ if (copied) {
+ coff = 0;
+ clen = min_t(int, len, bsize - copied);
+
+ if (len == bsize - copied)
+ aligned = 1; /* last + right aligned */
+
+ } else {
+ coff = len - rlen;
+ clen = rlen;
+ }
+
+ p = crypto_kmap(tfm, sg[i].page) + sg[i].offset + coff;
+
+ if (in)
+ memcpy(&buf[copied], p, clen);
+ else
+ memcpy(p, &buf[copied], clen);
+
+ crypto_kunmap(tfm, sg[i].page, p);
+ *last = aligned ? 0 : clen;
+ copied += clen;
+ }
+
+ return i - sgidx - 2 + aligned;
+}
+
+static inline int gather_chunks(struct crypto_tfm *tfm, __u8 *buf,
+ struct scatterlist *sg,
+ int sgidx, int rlen, int *last)
+{
+ return copy_chunks(tfm, buf, sg, sgidx, rlen, last, 1);
+}
+
+static inline int scatter_chunks(struct crypto_tfm *tfm, __u8 *buf,
+ struct scatterlist *sg,
+ int sgidx, int rlen, int *last)
+{
+ return copy_chunks(tfm, buf, sg, sgidx, rlen, last, 0);
+}
+
+/*
+ * Generic encrypt/decrypt wrapper for ciphers.
+ *
+ * If we find a a remnant at the end of a frag, we have to encrypt or
+ * decrypt across possibly multiple page boundaries via a temporary
+ * block, then continue processing with a chunk offset until the end
+ * of a frag is block aligned.
+ */
+static int crypt(struct crypto_tfm *tfm, struct scatterlist *sg,
+ size_t nsg, cryptfn_t crfn, procfn_t prfn, int enc)
+{
+ int i, coff;
+ size_t bsize = crypto_tfm_blocksize(tfm);
+ __u8 tmp[CRYPTO_MAX_BLOCK_SIZE];
+
+ if (sglen(sg, nsg) % bsize) {
+ tfm->crt_flags |= CRYPTO_BAD_BLOCK_LEN;
+ return -EINVAL;
+ }
+
+ for (i = 0, coff = 0; i < nsg; i++) {
+ int n = 0;
+ int len = sg[i].length - coff;
+ char *p = crypto_kmap(tfm, sg[i].page) + sg[i].offset + coff;
+
+ while (len) {
+ if (len < bsize) {
+ crypto_kunmap(tfm, sg[i].page, p);
+ n = gather_chunks(tfm, tmp, sg, i, len, &coff);
+ prfn(tfm, tmp, crfn, enc);
+ scatter_chunks(tfm, tmp, sg, i, len, &coff);
+ crypto_yield(tfm);
+ goto unmapped;
+ } else {
+ prfn(tfm, p, crfn, enc);
+ crypto_kunmap(tfm, sg[i].page, p);
+ crypto_yield(tfm);
+ p = crypto_kmap(tfm, sg[i].page) + sg[i].offset + coff;
+ p += bsize;
+ len -= bsize;
+
+ /* End of frag with no remnant? */
+ if (coff && len == 0)
+ coff = 0;
+ }
+ }
+ crypto_kunmap(tfm, sg[i].page, p);
+unmapped:
+ i += n;
+
+ }
+ return 0;
+}
+
+static void cbc_process(struct crypto_tfm *tfm,
+ __u8 *block, cryptfn_t fn, int enc)
+{
+ if (enc) {
+ xor_64(tfm->crt_cipher.cit_iv, block);
+ fn(tfm->crt_ctx, block, tfm->crt_cipher.cit_iv);
+ memcpy(tfm->crt_cipher.cit_iv, block,
+ crypto_tfm_blocksize(tfm));
+ } else {
+ __u8 buf[CRYPTO_MAX_BLOCK_SIZE];
+
+ fn(tfm->crt_ctx, buf, block);
+ xor_64(buf, tfm->crt_cipher.cit_iv);
+ memcpy(tfm->crt_cipher.cit_iv, block,
+ crypto_tfm_blocksize(tfm));
+ memcpy(block, buf, crypto_tfm_blocksize(tfm));
+ }
+}
+
+static void ecb_process(struct crypto_tfm *tfm, __u8 *block,
+ cryptfn_t fn, int enc)
+{
+ fn(tfm->crt_ctx, block, block);
+}
+
+static int setkey(struct crypto_tfm *tfm, const __u8 *key, size_t keylen)
+{
+ return tfm->__crt_alg->cra_cipher.cia_setkey(tfm->crt_ctx, key,
+ keylen, &tfm->crt_flags);
+}
+
+static int ecb_encrypt(struct crypto_tfm *tfm,
+ struct scatterlist *sg, size_t nsg)
+{
+ return crypt(tfm, sg, nsg,
+ tfm->__crt_alg->cra_cipher.cia_encrypt, ecb_process, 1);
+}
+
+static int ecb_decrypt(struct crypto_tfm *tfm,
+ struct scatterlist *sg, size_t nsg)
+{
+ return crypt(tfm, sg, nsg,
+ tfm->__crt_alg->cra_cipher.cia_decrypt, ecb_process, 1);
+}
+
+static int cbc_encrypt(struct crypto_tfm *tfm,
+ struct scatterlist *sg, size_t nsg)
+{
+ return crypt(tfm, sg, nsg,
+ tfm->__crt_alg->cra_cipher.cia_encrypt, cbc_process, 1);
+}
+
+static int cbc_decrypt(struct crypto_tfm *tfm,
+ struct scatterlist *sg, size_t nsg)
+{
+ return crypt(tfm, sg, nsg,
+ tfm->__crt_alg->cra_cipher.cia_decrypt, cbc_process, 0);
+}
+
+static int nocrypt(struct crypto_tfm *tfm, struct scatterlist *sg, size_t nsg)
+{
+ return -ENOSYS;
+}
+
+void crypto_init_cipher_ops(struct crypto_tfm *tfm)
+{
+ struct cipher_tfm *ops = &tfm->crt_cipher;
+
+ ops->cit_setkey = setkey;
+
+ switch (tfm->crt_cipher.cit_mode) {
+ case CRYPTO_MODE_ECB:
+ ops->cit_encrypt = ecb_encrypt;
+ ops->cit_decrypt = ecb_decrypt;
+ break;
+
+ case CRYPTO_MODE_CBC:
+ ops->cit_encrypt = cbc_encrypt;
+ ops->cit_decrypt = cbc_decrypt;
+ break;
+
+ case CRYPTO_MODE_CFB:
+ ops->cit_encrypt = nocrypt;
+ ops->cit_decrypt = nocrypt;
+ break;
+
+ case CRYPTO_MODE_CTR:
+ ops->cit_encrypt = nocrypt;
+ ops->cit_decrypt = nocrypt;
+ break;
+
+ default:
+ BUG();
+ }
+}
diff --git a/crypto/compress.c b/crypto/compress.c
new file mode 100644
index 00000000000000..9a6c2577d75d50
--- /dev/null
+++ b/crypto/compress.c
@@ -0,0 +1,41 @@
+/*
+ * Cryptographic API.
+ *
+ * Compression operations.
+ *
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.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 <linux/types.h>
+#include <linux/list.h>
+#include <asm/scatterlist.h>
+#include <linux/string.h>
+#include <linux/crypto.h>
+#include "internal.h"
+
+/*
+ * This code currently implements blazingly fast and
+ * lossless Quadruple ROT13 compression.
+ */
+static void crypto_compress(struct crypto_tfm *tfm)
+{
+ return;
+}
+
+static void crypto_decompress(struct crypto_tfm *tfm)
+{
+ return;
+}
+
+void crypto_init_compress_ops(struct crypto_tfm *tfm)
+{
+ struct compress_tfm *ops = &tfm->crt_compress;
+
+ ops->cot_compress = crypto_compress;
+ ops->cot_decompress = crypto_decompress;
+}
diff --git a/crypto/des.c b/crypto/des.c
new file mode 100644
index 00000000000000..c7957159f8725f
--- /dev/null
+++ b/crypto/des.c
@@ -0,0 +1,1215 @@
+/*
+ * Cryptographic API.
+ *
+ * DES & 3DES_EDE Cipher Algorithms.
+ *
+ * Originally released as descore by Dana L. How <how@isl.stanford.edu>.
+ * Modified by Raimar Falke <rf13@inf.tu-dresden.de> for the Linux-Kernel.
+ * Derived from Cryptoapi and Nettle implementations, adapted for in-place
+ * scatterlist interface. Changed LGPL to GPL per section 3 of the LGPL.
+ *
+ * Copyright (c) 1992 Dana L. How.
+ * Copyright (c) Raimar Falke <rf13@inf.tu-dresden.de>
+ * Copyright (c) Gisle Sælensminde <gisle@ii.uib.no>
+ * Copyright (C) 2001 Niels Möller.
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.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 <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <asm/scatterlist.h>
+#include <linux/crypto.h>
+
+#define DES_KEY_SIZE 8
+#define DES_KEY_SIZE_WORDS 2
+#define DES_BLOCK_SIZE 8
+
+#define ROR(d,c,o) ((d) = (d) >> (c) | (d) << (o))
+
+const static __u32 des_keymap[] = {
+ 0x02080008, 0x02082000, 0x00002008, 0x00000000,
+ 0x02002000, 0x00080008, 0x02080000, 0x02082008,
+ 0x00000008, 0x02000000, 0x00082000, 0x00002008,
+ 0x00082008, 0x02002008, 0x02000008, 0x02080000,
+ 0x00002000, 0x00082008, 0x00080008, 0x02002000,
+ 0x02082008, 0x02000008, 0x00000000, 0x00082000,
+ 0x02000000, 0x00080000, 0x02002008, 0x02080008,
+ 0x00080000, 0x00002000, 0x02082000, 0x00000008,
+ 0x00080000, 0x00002000, 0x02000008, 0x02082008,
+ 0x00002008, 0x02000000, 0x00000000, 0x00082000,
+ 0x02080008, 0x02002008, 0x02002000, 0x00080008,
+ 0x02082000, 0x00000008, 0x00080008, 0x02002000,
+ 0x02082008, 0x00080000, 0x02080000, 0x02000008,
+ 0x00082000, 0x00002008, 0x02002008, 0x02080000,
+ 0x00000008, 0x02082000, 0x00082008, 0x00000000,
+ 0x02000000, 0x02080008, 0x00002000, 0x00082008,
+
+ 0x08000004, 0x00020004, 0x00000000, 0x08020200,
+ 0x00020004, 0x00000200, 0x08000204, 0x00020000,
+ 0x00000204, 0x08020204, 0x00020200, 0x08000000,
+ 0x08000200, 0x08000004, 0x08020000, 0x00020204,
+ 0x00020000, 0x08000204, 0x08020004, 0x00000000,
+ 0x00000200, 0x00000004, 0x08020200, 0x08020004,
+ 0x08020204, 0x08020000, 0x08000000, 0x00000204,
+ 0x00000004, 0x00020200, 0x00020204, 0x08000200,
+ 0x00000204, 0x08000000, 0x08000200, 0x00020204,
+ 0x08020200, 0x00020004, 0x00000000, 0x08000200,
+ 0x08000000, 0x00000200, 0x08020004, 0x00020000,
+ 0x00020004, 0x08020204, 0x00020200, 0x00000004,
+ 0x08020204, 0x00020200, 0x00020000, 0x08000204,
+ 0x08000004, 0x08020000, 0x00020204, 0x00000000,
+ 0x00000200, 0x08000004, 0x08000204, 0x08020200,
+ 0x08020000, 0x00000204, 0x00000004, 0x08020004,
+
+ 0x80040100, 0x01000100, 0x80000000, 0x81040100,
+ 0x00000000, 0x01040000, 0x81000100, 0x80040000,
+ 0x01040100, 0x81000000, 0x01000000, 0x80000100,
+ 0x81000000, 0x80040100, 0x00040000, 0x01000000,
+ 0x81040000, 0x00040100, 0x00000100, 0x80000000,
+ 0x00040100, 0x81000100, 0x01040000, 0x00000100,
+ 0x80000100, 0x00000000, 0x80040000, 0x01040100,
+ 0x01000100, 0x81040000, 0x81040100, 0x00040000,
+ 0x81040000, 0x80000100, 0x00040000, 0x81000000,
+ 0x00040100, 0x01000100, 0x80000000, 0x01040000,
+ 0x81000100, 0x00000000, 0x00000100, 0x80040000,
+ 0x00000000, 0x81040000, 0x01040100, 0x00000100,
+ 0x01000000, 0x81040100, 0x80040100, 0x00040000,
+ 0x81040100, 0x80000000, 0x01000100, 0x80040100,
+ 0x80040000, 0x00040100, 0x01040000, 0x81000100,
+ 0x80000100, 0x01000000, 0x81000000, 0x01040100,
+
+ 0x04010801, 0x00000000, 0x00010800, 0x04010000,
+ 0x04000001, 0x00000801, 0x04000800, 0x00010800,
+ 0x00000800, 0x04010001, 0x00000001, 0x04000800,
+ 0x00010001, 0x04010800, 0x04010000, 0x00000001,
+ 0x00010000, 0x04000801, 0x04010001, 0x00000800,
+ 0x00010801, 0x04000000, 0x00000000, 0x00010001,
+ 0x04000801, 0x00010801, 0x04010800, 0x04000001,
+ 0x04000000, 0x00010000, 0x00000801, 0x04010801,
+ 0x00010001, 0x04010800, 0x04000800, 0x00010801,
+ 0x04010801, 0x00010001, 0x04000001, 0x00000000,
+ 0x04000000, 0x00000801, 0x00010000, 0x04010001,
+ 0x00000800, 0x04000000, 0x00010801, 0x04000801,
+ 0x04010800, 0x00000800, 0x00000000, 0x04000001,
+ 0x00000001, 0x04010801, 0x00010800, 0x04010000,
+ 0x04010001, 0x00010000, 0x00000801, 0x04000800,
+ 0x04000801, 0x00000001, 0x04010000, 0x00010800,
+
+ 0x00000400, 0x00000020, 0x00100020, 0x40100000,
+ 0x40100420, 0x40000400, 0x00000420, 0x00000000,
+ 0x00100000, 0x40100020, 0x40000020, 0x00100400,
+ 0x40000000, 0x00100420, 0x00100400, 0x40000020,
+ 0x40100020, 0x00000400, 0x40000400, 0x40100420,
+ 0x00000000, 0x00100020, 0x40100000, 0x00000420,
+ 0x40100400, 0x40000420, 0x00100420, 0x40000000,
+ 0x40000420, 0x40100400, 0x00000020, 0x00100000,
+ 0x40000420, 0x00100400, 0x40100400, 0x40000020,
+ 0x00000400, 0x00000020, 0x00100000, 0x40100400,
+ 0x40100020, 0x40000420, 0x00000420, 0x00000000,
+ 0x00000020, 0x40100000, 0x40000000, 0x00100020,
+ 0x00000000, 0x40100020, 0x00100020, 0x00000420,
+ 0x40000020, 0x00000400, 0x40100420, 0x00100000,
+ 0x00100420, 0x40000000, 0x40000400, 0x40100420,
+ 0x40100000, 0x00100420, 0x00100400, 0x40000400,
+
+ 0x00800000, 0x00001000, 0x00000040, 0x00801042,
+ 0x00801002, 0x00800040, 0x00001042, 0x00801000,
+ 0x00001000, 0x00000002, 0x00800002, 0x00001040,
+ 0x00800042, 0x00801002, 0x00801040, 0x00000000,
+ 0x00001040, 0x00800000, 0x00001002, 0x00000042,
+ 0x00800040, 0x00001042, 0x00000000, 0x00800002,
+ 0x00000002, 0x00800042, 0x00801042, 0x00001002,
+ 0x00801000, 0x00000040, 0x00000042, 0x00801040,
+ 0x00801040, 0x00800042, 0x00001002, 0x00801000,
+ 0x00001000, 0x00000002, 0x00800002, 0x00800040,
+ 0x00800000, 0x00001040, 0x00801042, 0x00000000,
+ 0x00001042, 0x00800000, 0x00000040, 0x00001002,
+ 0x00800042, 0x00000040, 0x00000000, 0x00801042,
+ 0x00801002, 0x00801040, 0x00000042, 0x00001000,
+ 0x00001040, 0x00801002, 0x00800040, 0x00000042,
+ 0x00000002, 0x00001042, 0x00801000, 0x00800002,
+
+ 0x10400000, 0x00404010, 0x00000010, 0x10400010,
+ 0x10004000, 0x00400000, 0x10400010, 0x00004010,
+ 0x00400010, 0x00004000, 0x00404000, 0x10000000,
+ 0x10404010, 0x10000010, 0x10000000, 0x10404000,
+ 0x00000000, 0x10004000, 0x00404010, 0x00000010,
+ 0x10000010, 0x10404010, 0x00004000, 0x10400000,
+ 0x10404000, 0x00400010, 0x10004010, 0x00404000,
+ 0x00004010, 0x00000000, 0x00400000, 0x10004010,
+ 0x00404010, 0x00000010, 0x10000000, 0x00004000,
+ 0x10000010, 0x10004000, 0x00404000, 0x10400010,
+ 0x00000000, 0x00404010, 0x00004010, 0x10404000,
+ 0x10004000, 0x00400000, 0x10404010, 0x10000000,
+ 0x10004010, 0x10400000, 0x00400000, 0x10404010,
+ 0x00004000, 0x00400010, 0x10400010, 0x00004010,
+ 0x00400010, 0x00000000, 0x10404000, 0x10000010,
+ 0x10400000, 0x10004010, 0x00000010, 0x00404000,
+
+ 0x00208080, 0x00008000, 0x20200000, 0x20208080,
+ 0x00200000, 0x20008080, 0x20008000, 0x20200000,
+ 0x20008080, 0x00208080, 0x00208000, 0x20000080,
+ 0x20200080, 0x00200000, 0x00000000, 0x20008000,
+ 0x00008000, 0x20000000, 0x00200080, 0x00008080,
+ 0x20208080, 0x00208000, 0x20000080, 0x00200080,
+ 0x20000000, 0x00000080, 0x00008080, 0x20208000,
+ 0x00000080, 0x20200080, 0x20208000, 0x00000000,
+ 0x00000000, 0x20208080, 0x00200080, 0x20008000,
+ 0x00208080, 0x00008000, 0x20000080, 0x00200080,
+ 0x20208000, 0x00000080, 0x00008080, 0x20200000,
+ 0x20008080, 0x20000000, 0x20200000, 0x00208000,
+ 0x20208080, 0x00008080, 0x00208000, 0x20200080,
+ 0x00200000, 0x20000080, 0x20008000, 0x00000000,
+ 0x00008000, 0x00200000, 0x20200080, 0x00208080,
+ 0x20000000, 0x20208000, 0x00000080, 0x20008080,
+};
+
+const static char rotors[] = {
+ 34, 13, 5, 46, 47, 18, 32, 41, 11, 53, 33, 20,
+ 14, 36, 30, 24, 49, 2, 15, 37, 42, 50, 0, 21,
+ 38, 48, 6, 26, 39, 4, 52, 25, 12, 27, 31, 40,
+ 1, 17, 28, 29, 23, 51, 35, 7, 3, 22, 9, 43,
+
+ 41, 20, 12, 53, 54, 25, 39, 48, 18, 31, 40, 27,
+ 21, 43, 37, 0, 1, 9, 22, 44, 49, 2, 7, 28,
+ 45, 55, 13, 33, 46, 11, 6, 32, 19, 34, 38, 47,
+ 8, 24, 35, 36, 30, 3, 42, 14, 10, 29, 16, 50,
+
+ 55, 34, 26, 38, 11, 39, 53, 5, 32, 45, 54, 41,
+ 35, 2, 51, 14, 15, 23, 36, 3, 8, 16, 21, 42,
+ 6, 12, 27, 47, 31, 25, 20, 46, 33, 48, 52, 4,
+ 22, 7, 49, 50, 44, 17, 1, 28, 24, 43, 30, 9,
+
+ 12, 48, 40, 52, 25, 53, 38, 19, 46, 6, 11, 55,
+ 49, 16, 10, 28, 29, 37, 50, 17, 22, 30, 35, 1,
+ 20, 26, 41, 4, 45, 39, 34, 31, 47, 5, 13, 18,
+ 36, 21, 8, 9, 3, 0, 15, 42, 7, 2, 44, 23,
+
+ 26, 5, 54, 13, 39, 38, 52, 33, 31, 20, 25, 12,
+ 8, 30, 24, 42, 43, 51, 9, 0, 36, 44, 49, 15,
+ 34, 40, 55, 18, 6, 53, 48, 45, 4, 19, 27, 32,
+ 50, 35, 22, 23, 17, 14, 29, 1, 21, 16, 3, 37,
+
+ 40, 19, 11, 27, 53, 52, 13, 47, 45, 34, 39, 26,
+ 22, 44, 7, 1, 2, 10, 23, 14, 50, 3, 8, 29,
+ 48, 54, 12, 32, 20, 38, 5, 6, 18, 33, 41, 46,
+ 9, 49, 36, 37, 0, 28, 43, 15, 35, 30, 17, 51,
+
+ 54, 33, 25, 41, 38, 13, 27, 4, 6, 48, 53, 40,
+ 36, 3, 21, 15, 16, 24, 37, 28, 9, 17, 22, 43,
+ 5, 11, 26, 46, 34, 52, 19, 20, 32, 47, 55, 31,
+ 23, 8, 50, 51, 14, 42, 2, 29, 49, 44, 0, 10,
+
+ 11, 47, 39, 55, 52, 27, 41, 18, 20, 5, 38, 54,
+ 50, 17, 35, 29, 30, 7, 51, 42, 23, 0, 36, 2,
+ 19, 25, 40, 31, 48, 13, 33, 34, 46, 4, 12, 45,
+ 37, 22, 9, 10, 28, 1, 16, 43, 8, 3, 14, 24,
+
+ 18, 54, 46, 5, 6, 34, 48, 25, 27, 12, 45, 4,
+ 2, 24, 42, 36, 37, 14, 3, 49, 30, 7, 43, 9,
+ 26, 32, 47, 38, 55, 20, 40, 41, 53, 11, 19, 52,
+ 44, 29, 16, 17, 35, 8, 23, 50, 15, 10, 21, 0,
+
+ 32, 11, 31, 19, 20, 48, 5, 39, 41, 26, 6, 18,
+ 16, 7, 1, 50, 51, 28, 17, 8, 44, 21, 2, 23,
+ 40, 46, 4, 52, 12, 34, 54, 55, 38, 25, 33, 13,
+ 3, 43, 30, 0, 49, 22, 37, 9, 29, 24, 35, 14,
+
+ 46, 25, 45, 33, 34, 5, 19, 53, 55, 40, 20, 32,
+ 30, 21, 15, 9, 10, 42, 0, 22, 3, 35, 16, 37,
+ 54, 31, 18, 13, 26, 48, 11, 12, 52, 39, 47, 27,
+ 17, 2, 44, 14, 8, 36, 51, 23, 43, 7, 49, 28,
+
+ 31, 39, 6, 47, 48, 19, 33, 38, 12, 54, 34, 46,
+ 44, 35, 29, 23, 24, 1, 14, 36, 17, 49, 30, 51,
+ 11, 45, 32, 27, 40, 5, 25, 26, 13, 53, 4, 41,
+ 0, 16, 3, 28, 22, 50, 10, 37, 2, 21, 8, 42,
+
+ 45, 53, 20, 4, 5, 33, 47, 52, 26, 11, 48, 31,
+ 3, 49, 43, 37, 7, 15, 28, 50, 0, 8, 44, 10,
+ 25, 6, 46, 41, 54, 19, 39, 40, 27, 38, 18, 55,
+ 14, 30, 17, 42, 36, 9, 24, 51, 16, 35, 22, 1,
+
+ 6, 38, 34, 18, 19, 47, 4, 13, 40, 25, 5, 45,
+ 17, 8, 2, 51, 21, 29, 42, 9, 14, 22, 3, 24,
+ 39, 20, 31, 55, 11, 33, 53, 54, 41, 52, 32, 12,
+ 28, 44, 0, 1, 50, 23, 7, 10, 30, 49, 36, 15,
+
+ 20, 52, 48, 32, 33, 4, 18, 27, 54, 39, 19, 6,
+ 0, 22, 16, 10, 35, 43, 1, 23, 28, 36, 17, 7,
+ 53, 34, 45, 12, 25, 47, 38, 11, 55, 13, 46, 26,
+ 42, 3, 14, 15, 9, 37, 21, 24, 44, 8, 50, 29,
+
+ 27, 6, 55, 39, 40, 11, 25, 34, 4, 46, 26, 13,
+ 7, 29, 23, 17, 42, 50, 8, 30, 35, 43, 24, 14,
+ 31, 41, 52, 19, 32, 54, 45, 18, 5, 20, 53, 33,
+ 49, 10, 21, 22, 16, 44, 28, 0, 51, 15, 2, 36,
+};
+
+const static char parity[] = {
+ 8,1,0,8,0,8,8,0,0,8,8,0,8,0,2,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,3,
+ 0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,
+ 0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,
+ 8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,
+ 0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,
+ 8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,
+ 8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,
+ 4,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,5,0,8,0,8,8,0,0,8,8,0,8,0,6,8,
+};
+
+struct des_ctx {
+ __u8 iv[DES_BLOCK_SIZE];
+ __u32 keyinfo[32];
+};
+
+static void des_small_fips_encrypt(void *ctx, __u8 *dst, __u8 *src)
+{
+ __u32 *keyinfo = ((struct des_ctx *)ctx)->keyinfo;
+ __u32 x, y, z;
+
+ x = src [7];
+ x <<= 8;
+ x |= src [6];
+ x <<= 8;
+ x |= src [5];
+ x <<= 8;
+ x |= src [4];
+ y = src [3];
+ y <<= 8;
+ y |= src [2];
+ y <<= 8;
+ y |= src [1];
+ y <<= 8;
+ y |= src [0];
+ z = ((x >> 004) ^ y) & 0x0F0F0F0FL;
+ x ^= z << 004;
+ y ^= z;
+ z = ((y >> 020) ^ x) & 0x0000FFFFL;
+ y ^= z << 020;
+ x ^= z;
+ z = ((x >> 002) ^ y) & 0x33333333L;
+ x ^= z << 002;
+ y ^= z;
+ z = ((y >> 010) ^ x) & 0x00FF00FFL;
+ y ^= z << 010;
+ x ^= z;
+ x = x >> 1 | x << 31;
+ z = (x ^ y) & 0x55555555L;
+ y ^= z;
+ x ^= z;
+ y = y >> 1 | y << 31;
+ z = keyinfo [0];
+ z ^= y;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) des_keymap + (0xFC & z));
+ z = keyinfo [1];
+ z ^= y;
+ z = z << 4 | z >> 28;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z));
+ z = keyinfo [2];
+ z ^= x;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) des_keymap + (0xFC & z));
+ z = keyinfo [3];
+ z ^= x;
+ z = z << 4 | z >> 28;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z));
+ z = keyinfo [4];
+ z ^= y;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) des_keymap + (0xFC & z));
+ z = keyinfo [5];
+ z ^= y;
+ z = z << 4 | z >> 28;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z));
+ z = keyinfo [6];
+ z ^= x;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) des_keymap + (0xFC & z));
+ z = keyinfo [7];
+ z ^= x;
+ z = z << 4 | z >> 28;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z));
+ z = keyinfo [8];
+ z ^= y;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) des_keymap + (0xFC & z));
+ z = keyinfo [9];
+ z ^= y;
+ z = z << 4 | z >> 28;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z));
+ z = keyinfo [10];
+ z ^= x;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) des_keymap + (0xFC & z));
+ z = keyinfo [11];
+ z ^= x;
+ z = z << 4 | z >> 28;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z));
+ z = keyinfo [12];
+ z ^= y;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) des_keymap + (0xFC & z));
+ z = keyinfo [13];
+ z ^= y;
+ z = z << 4 | z >> 28;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z));
+ z = keyinfo [14];
+ z ^= x;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) des_keymap + (0xFC & z));
+ z = keyinfo [15];
+ z ^= x;
+ z = z << 4 | z >> 28;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z));
+ z = keyinfo [16];
+ z ^= y;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) des_keymap + (0xFC & z));
+ z = keyinfo [17];
+ z ^= y;
+ z = z << 4 | z >> 28;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z));
+ z = keyinfo [18];
+ z ^= x;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) des_keymap + (0xFC & z));
+ z = keyinfo [19];
+ z ^= x;
+ z = z << 4 | z >> 28;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z));
+ z = keyinfo [20];
+ z ^= y;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) des_keymap + (0xFC & z));
+ z = keyinfo [21];
+ z ^= y;
+ z = z << 4 | z >> 28;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z));
+ z = keyinfo [22];
+ z ^= x;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) des_keymap + (0xFC & z));
+ z = keyinfo [23];
+ z ^= x;
+ z = z << 4 | z >> 28;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z));
+ z = keyinfo [24];
+ z ^= y;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) des_keymap + (0xFC & z));
+ z = keyinfo [25];
+ z ^= y;
+ z = z << 4 | z >> 28;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z));
+ z = keyinfo [26];
+ z ^= x;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) des_keymap + (0xFC & z));
+ z = keyinfo [27];
+ z ^= x;
+ z = z << 4 | z >> 28;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z));
+ z = keyinfo [28];
+ z ^= y;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) des_keymap + (0xFC & z));
+ z = keyinfo [29];
+ z ^= y;
+ z = z << 4 | z >> 28;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z));
+ z = keyinfo [30];
+ z ^= x;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) des_keymap + (0xFC & z));
+ z = keyinfo [31];
+ z ^= x;
+ z = z << 4 | z >> 28;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z));
+ x = x << 1 | x >> 31;
+ z = (x ^ y) & 0x55555555L;
+ y ^= z;
+ x ^= z;
+ y = y << 1 | y >> 31;
+ z = ((x >> 010) ^ y) & 0x00FF00FFL;
+ x ^= z << 010;
+ y ^= z;
+ z = ((y >> 002) ^ x) & 0x33333333L;
+ y ^= z << 002;
+ x ^= z;
+ z = ((x >> 020) ^ y) & 0x0000FFFFL;
+ x ^= z << 020;
+ y ^= z;
+ z = ((y >> 004) ^ x) & 0x0F0F0F0FL;
+ y ^= z << 004;
+ x ^= z;
+ dst [0] = x;
+ x >>= 8;
+ dst [1] = x;
+ x >>= 8;
+ dst [2] = x;
+ x >>= 8;
+ dst [3] = x;
+ dst [4] = y;
+ y >>= 8;
+ dst [5] = y;
+ y >>= 8;
+ dst [6] = y;
+ y >>= 8;
+ dst [7] = y;
+ return;
+}
+
+static void des_small_fips_decrypt(void *ctx, __u8 *dst, __u8 *src)
+{
+ __u32 *keyinfo = ((struct des_ctx *)ctx)->keyinfo;
+ __u32 x, y, z;
+
+ x = src [7];
+ x <<= 8;
+ x |= src [6];
+ x <<= 8;
+ x |= src [5];
+ x <<= 8;
+ x |= src [4];
+ y = src [3];
+ y <<= 8;
+ y |= src [2];
+ y <<= 8;
+ y |= src [1];
+ y <<= 8;
+ y |= src [0];
+ z = ((x >> 004) ^ y) & 0x0F0F0F0FL;
+ x ^= z << 004;
+ y ^= z;
+ z = ((y >> 020) ^ x) & 0x0000FFFFL;
+ y ^= z << 020;
+ x ^= z;
+ z = ((x >> 002) ^ y) & 0x33333333L;
+ x ^= z << 002;
+ y ^= z;
+ z = ((y >> 010) ^ x) & 0x00FF00FFL;
+ y ^= z << 010;
+ x ^= z;
+ x = x >> 1 | x << 31;
+ z = (x ^ y) & 0x55555555L;
+ y ^= z;
+ x ^= z;
+ y = y >> 1 | y << 31;
+ z = keyinfo [31];
+ z ^= y;
+ z = z << 4 | z >> 28;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z));
+ z = keyinfo [30];
+ z ^= y;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) des_keymap + (0xFC & z));
+ z = keyinfo [29];
+ z ^= x;
+ z = z << 4 | z >> 28;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z));
+ z = keyinfo [28];
+ z ^= x;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) des_keymap + (0xFC & z));
+ z = keyinfo [27];
+ z ^= y;
+ z = z << 4 | z >> 28;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z));
+ z = keyinfo [26];
+ z ^= y;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) des_keymap + (0xFC & z));
+ z = keyinfo [25];
+ z ^= x;
+ z = z << 4 | z >> 28;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z));
+ z = keyinfo [24];
+ z ^= x;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) des_keymap + (0xFC & z));
+ z = keyinfo [23];
+ z ^= y;
+ z = z << 4 | z >> 28;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z));
+ z = keyinfo [22];
+ z ^= y;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) des_keymap + (0xFC & z));
+ z = keyinfo [21];
+ z ^= x;
+ z = z << 4 | z >> 28;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z));
+ z = keyinfo [20];
+ z ^= x;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) des_keymap + (0xFC & z));
+ z = keyinfo [19];
+ z ^= y;
+ z = z << 4 | z >> 28;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z));
+ z = keyinfo [18];
+ z ^= y;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) des_keymap + (0xFC & z));
+ z = keyinfo [17];
+ z ^= x;
+ z = z << 4 | z >> 28;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z));
+ z = keyinfo [16];
+ z ^= x;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) des_keymap + (0xFC & z));
+ z = keyinfo [15];
+ z ^= y;
+ z = z << 4 | z >> 28;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z));
+ z = keyinfo [14];
+ z ^= y;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) des_keymap + (0xFC & z));
+ z = keyinfo [13];
+ z ^= x;
+ z = z << 4 | z >> 28;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z));
+ z = keyinfo [12];
+ z ^= x;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) des_keymap + (0xFC & z));
+ z = keyinfo [11];
+ z ^= y;
+ z = z << 4 | z >> 28;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z));
+ z = keyinfo [10];
+ z ^= y;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) des_keymap + (0xFC & z));
+ z = keyinfo [9];
+ z ^= x;
+ z = z << 4 | z >> 28;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z));
+ z = keyinfo [8];
+ z ^= x;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) des_keymap + (0xFC & z));
+ z = keyinfo [7];
+ z ^= y;
+ z = z << 4 | z >> 28;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z));
+ z = keyinfo [6];
+ z ^= y;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) des_keymap + (0xFC & z));
+ z = keyinfo [5];
+ z ^= x;
+ z = z << 4 | z >> 28;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z));
+ z = keyinfo [4];
+ z ^= x;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) des_keymap + (0xFC & z));
+ z = keyinfo [3];
+ z ^= y;
+ z = z << 4 | z >> 28;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z));
+ z = keyinfo [2];
+ z ^= y;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z));
+ z >>= 8;
+ x ^= * (__u32 *) ((u8 *) des_keymap + (0xFC & z));
+ z = keyinfo [1];
+ z ^= x;
+ z = z << 4 | z >> 28;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 448) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 384) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 320) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 256) + (0xFC & z));
+ z = keyinfo [0];
+ z ^= x;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 192) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 128) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) (des_keymap + 64) + (0xFC & z));
+ z >>= 8;
+ y ^= * (__u32 *) ((u8 *) des_keymap + (0xFC & z));
+ x = x << 1 | x >> 31;
+ z = (x ^ y) & 0x55555555L;
+ y ^= z;
+ x ^= z;
+ y = y << 1 | y >> 31;
+ z = ((x >> 010) ^ y) & 0x00FF00FFL;
+ x ^= z << 010;
+ y ^= z;
+ z = ((y >> 002) ^ x) & 0x33333333L;
+ y ^= z << 002;
+ x ^= z;
+ z = ((x >> 020) ^ y) & 0x0000FFFFL;
+ x ^= z << 020;
+ y ^= z;
+ z = ((y >> 004) ^ x) & 0x0F0F0F0FL;
+ y ^= z << 004;
+ x ^= z;
+ dst [0] = x;
+ x >>= 8;
+ dst [1] = x;
+ x >>= 8;
+ dst [2] = x;
+ x >>= 8;
+ dst [3] = x;
+ dst [4] = y;
+ y >>= 8;
+ dst [5] = y;
+ y >>= 8;
+ dst [6] = y;
+ y >>= 8;
+ dst [7] = y;
+ return;
+}
+
+/*
+ * RFC2451: Weak key checks SHOULD be performed.
+ */
+static int des_setkey(void *ctx, const __u8 *key, size_t keylen, int *flags)
+{
+ struct des_ctx *dctx = ctx;
+ const __u8 *k;
+ __u8 *b0, *b1;
+ __u32 n, w;
+ __u32 *method;
+ __u8 bits0[56], bits1[56];
+
+ if (keylen != DES_KEY_SIZE) {
+ *flags |= CRYPTO_BAD_KEY_LEN;
+ return -EINVAL;
+ }
+
+ n = parity[key[0]]; n <<= 4;
+ n |= parity[key[1]]; n <<= 4;
+ n |= parity[key[2]]; n <<= 4;
+ n |= parity[key[3]]; n <<= 4;
+ n |= parity[key[4]]; n <<= 4;
+ n |= parity[key[5]]; n <<= 4;
+ n |= parity[key[6]]; n <<= 4;
+ n |= parity[key[7]];
+ w = 0x88888888L;
+
+ if ((*flags & CRYPTO_WEAK_KEY_CHECK)
+ && !((n - (w >> 3)) & w)) { /* 1 in 10^10 keys passes this test */
+ if (n < 0x41415151) {
+ if (n < 0x31312121) {
+ if (n < 0x14141515) {
+ /* 01 01 01 01 01 01 01 01 */
+ if (n == 0x11111111) goto weak;
+ /* 01 1F 01 1F 01 0E 01 0E */
+ if (n == 0x13131212) goto weak;
+ } else {
+ /* 01 E0 01 E0 01 F1 01 F1 */
+ if (n == 0x14141515) goto weak;
+ /* 01 FE 01 FE 01 FE 01 FE */
+ if (n == 0x16161616) goto weak;
+ }
+ } else {
+ if (n < 0x34342525) {
+ /* 1F 01 1F 01 0E 01 0E 01 */
+ if (n == 0x31312121) goto weak;
+ /* 1F 1F 1F 1F 0E 0E 0E 0E (?) */
+ if (n == 0x33332222) goto weak;
+ } else {
+ /* 1F E0 1F E0 0E F1 0E F1 */
+ if (n == 0x34342525) goto weak;
+ /* 1F FE 1F FE 0E FE 0E FE */
+ if (n == 0x36362626) goto weak;
+ }
+ }
+ } else {
+ if (n < 0x61616161) {
+ if (n < 0x44445555) {
+ /* E0 01 E0 01 F1 01 F1 01 */
+ if (n == 0x41415151) goto weak;
+ /* E0 1F E0 1F F1 0E F1 0E */
+ if (n == 0x43435252) goto weak;
+ } else {
+ /* E0 E0 E0 E0 F1 F1 F1 F1 (?) */
+ if (n == 0x44445555) goto weak;
+ /* E0 FE E0 FE F1 FE F1 FE */
+ if (n == 0x46465656) goto weak;
+ }
+ } else {
+ if (n < 0x64646565) {
+ /* FE 01 FE 01 FE 01 FE 01 */
+ if (n == 0x61616161) goto weak;
+ /* FE 1F FE 1F FE 0E FE 0E */
+ if (n == 0x63636262) goto weak;
+ } else {
+ /* FE E0 FE E0 FE F1 FE F1 */
+ if (n == 0x64646565) goto weak;
+ /* FE FE FE FE FE FE FE FE */
+ if (n == 0x66666666) goto weak;
+ }
+ }
+ }
+
+ goto not_weak;
+weak:
+ *flags |= CRYPTO_WEAK_KEY;
+ return -EINVAL;
+ }
+
+not_weak:
+
+ /* explode the bits */
+ n = 56;
+ b0 = bits0;
+ b1 = bits1;
+
+ do {
+ w = (256 | *key++) << 2;
+ do {
+ --n;
+ b1[n] = 8 & w;
+ w >>= 1;
+ b0[n] = 4 & w;
+ } while ( w >= 16 );
+ } while ( n );
+
+ /* put the bits in the correct places */
+ n = 16;
+ k = rotors;
+ method = dctx->keyinfo;
+
+ do {
+ w = (b1[k[ 0 ]] | b0[k[ 1 ]]) << 4;
+ w |= (b1[k[ 2 ]] | b0[k[ 3 ]]) << 2;
+ w |= b1[k[ 4 ]] | b0[k[ 5 ]];
+ w <<= 8;
+ w |= (b1[k[ 6 ]] | b0[k[ 7 ]]) << 4;
+ w |= (b1[k[ 8 ]] | b0[k[ 9 ]]) << 2;
+ w |= b1[k[10 ]] | b0[k[11 ]];
+ w <<= 8;
+ w |= (b1[k[12 ]] | b0[k[13 ]]) << 4;
+ w |= (b1[k[14 ]] | b0[k[15 ]]) << 2;
+ w |= b1[k[16 ]] | b0[k[17 ]];
+ w <<= 8;
+ w |= (b1[k[18 ]] | b0[k[19 ]]) << 4;
+ w |= (b1[k[20 ]] | b0[k[21 ]]) << 2;
+ w |= b1[k[22 ]] | b0[k[23 ]];
+ method[0] = w;
+
+ w = (b1[k[ 0+24]] | b0[k[ 1+24]]) << 4;
+ w |= (b1[k[ 2+24]] | b0[k[ 3+24]]) << 2;
+ w |= b1[k[ 4+24]] | b0[k[ 5+24]];
+ w <<= 8;
+ w |= (b1[k[ 6+24]] | b0[k[ 7+24]]) << 4;
+ w |= (b1[k[ 8+24]] | b0[k[ 9+24]]) << 2;
+ w |= b1[k[10+24]] | b0[k[11+24]];
+ w <<= 8;
+ w |= (b1[k[12+24]] | b0[k[13+24]]) << 4;
+ w |= (b1[k[14+24]] | b0[k[15+24]]) << 2;
+ w |= b1[k[16+24]] | b0[k[17+24]];
+ w <<= 8;
+ w |= (b1[k[18+24]] | b0[k[19+24]]) << 4;
+ w |= (b1[k[20+24]] | b0[k[21+24]]) << 2;
+ w |= b1[k[22+24]] | b0[k[23+24]];
+
+ ROR(w, 4, 28); /* could be eliminated */
+ method[1] = w;
+
+ k += 48;
+ method += 2;
+ } while (--n);
+
+ return 0;
+}
+
+static struct crypto_alg alg = {
+ .cra_id = CRYPTO_ALG_DES,
+ .cra_name = "des",
+ .cra_blocksize = DES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct des_ctx),
+ .cra_u = { .cipher = {
+ .cia_keysize = DES_KEY_SIZE,
+ .cia_ivsize = DES_BLOCK_SIZE,
+ .cia_setkey = des_setkey,
+ .cia_encrypt = des_small_fips_encrypt,
+ .cia_decrypt = des_small_fips_decrypt } }
+};
+
+static int __init init(void)
+{
+ INIT_LIST_HEAD(&alg.cra_list);
+ 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("DES & Triple DES EDE Cipher Algorithms");
+
+#if 0
+/*
+ * RFC2451:
+ *
+ * However, if the first two or last two independent 64-bit keys are
+ * equal (k1 == k2 or k2 == k3), then the 3DES operation is simply the
+ * same as DES. Implementers MUST reject keys that exhibit this
+ * property.
+ */
+
+#endif
+
diff --git a/crypto/digest.c b/crypto/digest.c
new file mode 100644
index 00000000000000..fb1a07b0b01fad
--- /dev/null
+++ b/crypto/digest.c
@@ -0,0 +1,126 @@
+/*
+ * Cryptographic API.
+ *
+ * Digest operations.
+ *
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.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 <linux/types.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <asm/scatterlist.h>
+#include <linux/crypto.h>
+#include "internal.h"
+
+static void init(struct crypto_tfm *tfm)
+{
+ tfm->__crt_alg->cra_digest.dia_init(tfm->crt_ctx);
+ return;
+}
+
+static void update(struct crypto_tfm *tfm, struct scatterlist *sg, size_t nsg)
+{
+ int i;
+
+ for (i = 0; i < nsg; i++) {
+ char *p = crypto_kmap(tfm, sg[i].page) + sg[i].offset;
+ tfm->__crt_alg->cra_digest.dia_update(tfm->crt_ctx,
+ p, sg[i].length);
+ crypto_kunmap(tfm, sg[i].page, p);
+ crypto_yield(tfm);
+ }
+ return;
+}
+
+static void final(struct crypto_tfm *tfm, __u8 *out)
+{
+ tfm->__crt_alg->cra_digest.dia_final(tfm->crt_ctx, out);
+ return;
+}
+
+static void digest(struct crypto_tfm *tfm,
+ struct scatterlist *sg, size_t nsg, __u8 *out)
+{
+ int i;
+
+ tfm->crt_digest.dit_init(tfm);
+
+ for (i = 0; i < nsg; i++) {
+ char *p = crypto_kmap(tfm, sg[i].page) + sg[i].offset;
+ tfm->__crt_alg->cra_digest.dia_update(tfm->crt_ctx,
+ p, sg[i].length);
+ crypto_kunmap(tfm, sg[i].page, p);
+ crypto_yield(tfm);
+ }
+ crypto_digest_final(tfm, out);
+ return;
+}
+
+static void hmac(struct crypto_tfm *tfm, __u8 *key, size_t keylen,
+ struct scatterlist *sg, size_t nsg, __u8 *out)
+{
+ int i;
+ struct scatterlist tmp;
+ char ipad[crypto_tfm_blocksize(tfm) + 1];
+ char opad[crypto_tfm_blocksize(tfm) + 1];
+
+ if (keylen > crypto_tfm_blocksize(tfm)) {
+ tmp.page = virt_to_page(key);
+ tmp.offset = ((long)key & ~PAGE_MASK);
+ tmp.length = keylen;
+ crypto_digest_digest(tfm, &tmp, 1, key);
+ keylen = crypto_tfm_digestsize(tfm);
+ }
+
+ memset(ipad, 0, sizeof(ipad));
+ memset(opad, 0, sizeof(opad));
+ memcpy(ipad, key, keylen);
+ memcpy(opad, key, keylen);
+
+ for (i = 0; i < crypto_tfm_blocksize(tfm); i++) {
+ ipad[i] ^= 0x36;
+ opad[i] ^= 0x5c;
+ }
+
+ tmp.page = virt_to_page(ipad);
+ tmp.offset = ((long)ipad & ~PAGE_MASK);
+ tmp.length = crypto_tfm_blocksize(tfm);
+
+ crypto_digest_init(tfm);
+ crypto_digest_update(tfm, &tmp, 1);
+ crypto_digest_update(tfm, sg, nsg);
+ crypto_digest_final(tfm, out);
+
+ tmp.page = virt_to_page(opad);
+ tmp.offset = ((long)opad & ~PAGE_MASK);
+ tmp.length = crypto_tfm_blocksize(tfm);
+
+ crypto_digest_init(tfm);
+ crypto_digest_update(tfm, &tmp, 1);
+
+ tmp.page = virt_to_page(out);
+ tmp.offset = ((long)out & ~PAGE_MASK);
+ tmp.length = crypto_tfm_digestsize(tfm);
+
+ crypto_digest_update(tfm, &tmp, 1);
+ crypto_digest_final(tfm, out);
+ return;
+}
+
+void crypto_init_digest_ops(struct crypto_tfm *tfm)
+{
+ struct digest_tfm *ops = &tfm->crt_digest;
+
+ ops->dit_init = init;
+ ops->dit_update = update;
+ ops->dit_final = final;
+ ops->dit_digest = digest;
+ ops->dit_hmac = hmac;
+}
diff --git a/crypto/internal.h b/crypto/internal.h
new file mode 100644
index 00000000000000..a194210bcdec92
--- /dev/null
+++ b/crypto/internal.h
@@ -0,0 +1,53 @@
+/*
+ * Cryptographic API.
+ *
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.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_H
+#define _CRYPTO_INTERNAL_H
+
+#include <linux/highmem.h>
+#include <asm/hardirq.h>
+#include <asm/softirq.h>
+
+static inline void *crypto_kmap(struct crypto_tfm *tfm, struct page *page)
+{
+ if (tfm->crt_flags & CRYPTO_ATOMIC) {
+#ifdef CONFIG_HIGHMEM
+ local_bh_disable();
+#endif
+ return kmap_atomic(page, KM_CRYPTO);
+ } else
+ return kmap(page);
+}
+
+static inline void crypto_kunmap(struct crypto_tfm *tfm,
+ struct page *page, void *vaddr)
+{
+ if (tfm->crt_flags & CRYPTO_ATOMIC) {
+ kunmap_atomic(vaddr, KM_CRYPTO);
+#ifdef CONFIG_HIGHMEM
+ local_bh_enable();
+#endif
+ } else
+ kunmap(page);
+}
+
+static inline void crypto_yield(struct crypto_tfm *tfm)
+{
+ if (!(tfm->crt_flags & CRYPTO_ATOMIC))
+ cond_resched();
+}
+
+void crypto_init_digest_ops(struct crypto_tfm *tfm);
+void crypto_init_cipher_ops(struct crypto_tfm *tfm);
+void crypto_init_compress_ops(struct crypto_tfm *tfm);
+
+#endif /* _CRYPTO_INTERNAL_H */
+
diff --git a/crypto/md5.c b/crypto/md5.c
new file mode 100644
index 00000000000000..43d5e1254b932a
--- /dev/null
+++ b/crypto/md5.c
@@ -0,0 +1,242 @@
+/*
+ * Cryptographic API.
+ *
+ * MD5 Message Digest Algorithm (RFC1321).
+ *
+ * Derived from cryptoapi implementation, originally based on the
+ * public domain implementation written by Colin Plumb in 1993.
+ *
+ * Copyright (c) Cryptoapi developers.
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.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 <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/crypto.h>
+
+#define MD5_DIGEST_SIZE 16
+#define MD5_HMAC_BLOCK_SIZE 64
+#define MD5_BLOCK_WORDS 16
+#define MD5_HASH_WORDS 4
+
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+#define MD5STEP(f, w, x, y, z, in, s) \
+ (w += f(x, y, z) + in, w = (w<<s | w>>(32-s)) + x)
+
+struct md5_ctx {
+ __u32 hash[MD5_HASH_WORDS];
+ __u32 block[MD5_BLOCK_WORDS];
+ __u64 byte_count;
+};
+
+static inline void md5_transform(__u32 *hash, __u32 const *in)
+{
+ register __u32 a, b, c, d;
+
+ a = hash[0];
+ b = hash[1];
+ c = hash[2];
+ d = hash[3];
+
+ MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+ hash[0] += a;
+ hash[1] += b;
+ hash[2] += c;
+ hash[3] += d;
+}
+
+/* XXX: this stuff can be optimized */
+static inline void le32_to_cpu_array(__u32 *buf, unsigned words)
+{
+ while (words--) {
+ __le32_to_cpus(buf);
+ buf++;
+ }
+}
+
+static inline void cpu_to_le32_array(__u32 *buf, unsigned words)
+{
+ while (words--) {
+ __cpu_to_le32s(buf);
+ buf++;
+ }
+}
+
+static inline void md5_transform_helper(struct md5_ctx *ctx)
+{
+ le32_to_cpu_array(ctx->block, sizeof(ctx->block) / sizeof(__u32));
+ md5_transform(ctx->hash, ctx->block);
+}
+
+static void md5_init(void *ctx)
+{
+ struct md5_ctx *mctx = ctx;
+
+ mctx->hash[0] = 0x67452301;
+ mctx->hash[1] = 0xefcdab89;
+ mctx->hash[2] = 0x98badcfe;
+ mctx->hash[3] = 0x10325476;
+ mctx->byte_count = 0;
+}
+
+static void md5_update(void *ctx, const __u8 *data, size_t len)
+{
+ struct md5_ctx *mctx = ctx;
+ const __u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f);
+
+ mctx->byte_count += len;
+
+ if (avail > len) {
+ memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
+ data, len);
+ return;
+ }
+
+ memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
+ data, avail);
+
+ md5_transform_helper(mctx);
+ data += avail;
+ len -= avail;
+
+ while (len >= sizeof(mctx->block)) {
+ memcpy(mctx->block, data, sizeof(mctx->block));
+ md5_transform_helper(mctx);
+ data += sizeof(mctx->block);
+ len -= sizeof(mctx->block);
+ }
+
+ memcpy(mctx->block, data, len);
+}
+
+static void md5_final(void *ctx, __u8 *out)
+{
+ struct md5_ctx *mctx = ctx;
+ const int offset = mctx->byte_count & 0x3f;
+ char *p = (char *)mctx->block + offset;
+ int padding = 56 - (offset + 1);
+
+ *p++ = 0x80;
+ if (padding < 0) {
+ memset(p, 0x00, padding + sizeof (__u64));
+ md5_transform_helper(mctx);
+ p = (char *)mctx->block;
+ padding = 56;
+ }
+
+ memset(p, 0, padding);
+ mctx->block[14] = mctx->byte_count << 3;
+ mctx->block[15] = mctx->byte_count >> 29;
+ le32_to_cpu_array(mctx->block, (sizeof(mctx->block) -
+ sizeof(__u64)) / sizeof(__u32));
+ md5_transform(mctx->hash, mctx->block);
+ cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(__u32));
+ memcpy(out, mctx->hash, sizeof(mctx->hash));
+ memset(mctx, 0, sizeof(mctx));
+}
+
+static struct crypto_alg alg = {
+ .cra_id = CRYPTO_ALG_MD5,
+ .cra_name = "md5",
+ .cra_blocksize = MD5_HMAC_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct md5_ctx),
+ .cra_u = { .digest = {
+ .dia_digestsize = MD5_DIGEST_SIZE,
+ .dia_init = md5_init,
+ .dia_update = md5_update,
+ .dia_final = md5_final } }
+};
+
+static int __init init(void)
+{
+ INIT_LIST_HEAD(&alg.cra_list);
+ 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("MD5 Message Digest Algorithm");
diff --git a/crypto/sha1.c b/crypto/sha1.c
new file mode 100644
index 00000000000000..54476823eb2904
--- /dev/null
+++ b/crypto/sha1.c
@@ -0,0 +1,203 @@
+/*
+ * Cryptographic API.
+ *
+ * SHA1 Secure Hash Algorithm.
+ *
+ * Derived from cryptoapi implementation, adapted for in-place
+ * scatterlist interface. Originally based on the public domain
+ * implementation written by Steve Raid.
+ *
+ * Copyright (c) Alan Smithee.
+ * Copyright (c) McDonald <andrew@mcdonald.org.uk>
+ * Copyright (c) Jean-Francois Dive <jef@linuxbe.org>
+ *
+ * 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/mm.h>
+#include <linux/crypto.h>
+#include <asm/scatterlist.h>
+
+#define SHA1_DIGEST_SIZE 20
+#define SHA1_HMAC_BLOCK_SIZE 64
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/* blk0() and blk() perform the initial expand. */
+/* I got the idea of expanding during the round function from SSLeay */
+# define blk0(i) block32[i]
+
+#define blk(i) (block32[i&15] = rol(block32[(i+13)&15]^block32[(i+8)&15] \
+ ^block32[(i+2)&15]^block32[i&15],1))
+
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5); \
+ w=rol(w,30);
+#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5); \
+ w=rol(w,30);
+#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
+#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5); \
+ w=rol(w,30);
+#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
+
+struct sha1_ctx {
+ __u64 count;
+ __u32 state[5];
+ __u8 buffer[64];
+};
+
+/* Hash a single 512-bit block. This is the core of the algorithm. */
+static void sha1_transform(__u32 *state, const char *in)
+{
+ __u32 a, b, c, d, e;
+ __u32 block32[16];
+
+ /* convert/copy data to workspace */
+ for (a = 0; a < sizeof(block32)/sizeof(__u32); a++)
+ block32[a] = be32_to_cpu (((const __u32 *)in)[a]);
+
+ /* Copy context->state[] to working vars */
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+ e = state[4];
+
+ /* 4 rounds of 20 operations each. Loop unrolled. */
+ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+ /* Add the working vars back into context.state[] */
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+ /* Wipe variables */
+ a = b = c = d = e = 0;
+ memset (block32, 0x00, sizeof block32);
+}
+
+static void sha1_init(void *ctx)
+{
+ struct sha1_ctx *sctx = ctx;
+ const static struct sha1_ctx initstate = {
+ 0,
+ { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 },
+ { 0, }
+ };
+
+ *sctx = initstate;
+}
+
+static void sha1_update(void *ctx, const __u8 *data, size_t len)
+{
+ struct sha1_ctx *sctx = ctx;
+ unsigned i, j;
+
+ j = (sctx->count >> 3) & 0x3f;
+ sctx->count += len << 3;
+
+ if ((j + len) > 63) {
+ memcpy(&sctx->buffer[j], data, (i = 64-j));
+ sha1_transform(sctx->state, sctx->buffer);
+ for ( ; i + 63 < len; i += 64) {
+ sha1_transform(sctx->state, &data[i]);
+ }
+ j = 0;
+ }
+ else i = 0;
+ memcpy(&sctx->buffer[j], &data[i], len - i);
+}
+
+
+/* Add padding and return the message digest. */
+static void sha1_final(void* ctx, __u8 *out)
+{
+ struct sha1_ctx *sctx = ctx;
+ __u32 i, j, index, padlen;
+ __u64 t;
+ __u8 bits[8] = { 0, };
+ const static __u8 padding[64] = { 0x80, };
+
+ t = sctx->count;
+ bits[7] = 0xff & t; t>>=8;
+ bits[6] = 0xff & t; t>>=8;
+ bits[5] = 0xff & t; t>>=8;
+ bits[4] = 0xff & t; t>>=8;
+ bits[3] = 0xff & t; t>>=8;
+ bits[2] = 0xff & t; t>>=8;
+ bits[1] = 0xff & t; t>>=8;
+ bits[0] = 0xff & t;
+
+ /* Pad out to 56 mod 64 */
+ index = (sctx->count >> 3) & 0x3f;
+ padlen = (index < 56) ? (56 - index) : ((64+56) - index);
+ sha1_update(sctx, padding, padlen);
+
+ /* Append length */
+ sha1_update(sctx, bits, sizeof bits);
+
+ /* Store state in digest */
+ for (i = j = 0; i < 5; i++, j += 4) {
+ __u32 t2 = sctx->state[i];
+ out[j+3] = t2 & 0xff; t2>>=8;
+ out[j+2] = t2 & 0xff; t2>>=8;
+ out[j+1] = t2 & 0xff; t2>>=8;
+ out[j ] = t2 & 0xff;
+ }
+
+ /* Wipe context */
+ memset(sctx, 0, sizeof *sctx);
+}
+
+static struct crypto_alg alg = {
+ .cra_id = CRYPTO_ALG_SHA1,
+ .cra_name = "sha1",
+ .cra_blocksize = SHA1_HMAC_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct sha1_ctx),
+ .cra_u = { .digest = {
+ .dia_digestsize = SHA1_DIGEST_SIZE,
+ .dia_init = sha1_init,
+ .dia_update = sha1_update,
+ .dia_final = sha1_final } }
+};
+
+static int __init init(void)
+{
+ INIT_LIST_HEAD(&alg.cra_list);
+ 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("SHA1 Secure Hash Algorithm");
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
new file mode 100644
index 00000000000000..10845062d1e046
--- /dev/null
+++ b/crypto/tcrypt.c
@@ -0,0 +1,1152 @@
+/*
+ * Quick & dirty crypto testing module.
+ *
+ * This will only exist until we have a better testing mechanism
+ * (e.g. a char device).
+ *
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ * Copyright (c) 2002 Jean-Francois Dive <jef@linuxbe.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <asm/scatterlist.h>
+#include <linux/string.h>
+#include <linux/crypto.h>
+#include <linux/highmem.h>
+#include "tcrypt.h"
+
+/*
+ * Need to kmalloc() memory for testing kmap().
+ */
+#define TVMEMSIZE 4096
+#define XBUFSIZE 32768
+
+/*
+ * Indexes into the xbuf to simulate cross-page access.
+ */
+#define IDX1 37
+#define IDX2 32400
+#define IDX3 1
+#define IDX4 8193
+#define IDX5 22222
+#define IDX6 17101
+#define IDX7 27333
+#define IDX8 3000
+
+
+static int mode = 0;
+static char *xbuf;
+static char *tvmem;
+
+static void hexdump(unsigned char *buf, size_t len)
+{
+ while (len--)
+ printk("%02x", *buf++);
+
+ printk("\n");
+}
+
+static void test_md5(void)
+{
+ char *p;
+ int i;
+ struct scatterlist sg[2];
+ char result[128];
+ struct crypto_tfm *tfm;
+ struct md5_testvec *md5_tv;
+ struct hmac_md5_testvec *hmac_md5_tv;
+ size_t tsize;
+
+ printk("\ntesting md5\n");
+
+ tsize = sizeof(md5_tv_template);
+ if (tsize > TVMEMSIZE) {
+ printk("template (%d) too big for tvmem (%d)\n", tsize, TVMEMSIZE);
+ return;
+ }
+
+ memcpy(tvmem, md5_tv_template, tsize);
+ md5_tv = (void *)tvmem;
+
+ tfm = crypto_alloc_tfm(CRYPTO_ALG_MD5);
+ if (tfm == NULL) {
+ printk("failed to load transform for CRYPTO_ALG_MD5\n");
+ return;
+ }
+
+ for (i = 0; i < MD5_TEST_VECTORS; i++) {
+ printk("test %d:\n", i + 1);
+ memset(result, 0, sizeof(result));
+
+ p = md5_tv[i].plaintext;
+ sg[0].page = virt_to_page(p);
+ sg[0].offset = ((long)p & ~PAGE_MASK);
+ sg[0].length = strlen(md5_tv[i].plaintext);
+
+ crypto_digest_init(tfm);
+ crypto_digest_update(tfm, sg, 1);
+ crypto_digest_final(tfm, result);
+
+ hexdump(result, crypto_tfm_digestsize(tfm));
+ printk("%s\n", memcmp(result, md5_tv[i].digest, crypto_tfm_digestsize(tfm)) ? "fail" : "pass");
+ }
+
+ printk("\ntesting md5 across pages\n");
+
+ /* setup the dummy buffer first */
+ memset(xbuf, 0, sizeof(xbuf));
+ memcpy(&xbuf[IDX1], "abcdefghijklm", 13);
+ memcpy(&xbuf[IDX2], "nopqrstuvwxyz", 13);
+
+ p = &xbuf[IDX1];
+ sg[0].page = virt_to_page(p);
+ sg[0].offset = ((long)p & ~PAGE_MASK);
+ sg[0].length = 13;
+
+ p = &xbuf[IDX2];
+ sg[1].page = virt_to_page(p);
+ sg[1].offset = ((long)p & ~PAGE_MASK);
+ sg[1].length = 13;
+
+ memset(result, 0, sizeof(result));
+ crypto_digest_digest(tfm, sg, 2, result);
+ hexdump(result, crypto_tfm_digestsize(tfm));
+
+ printk("%s\n", memcmp(result, md5_tv[4].digest, crypto_tfm_digestsize(tfm)) ? "fail" : "pass");
+
+ printk("\ntesting hmac_md5\n");
+
+ tsize = sizeof(hmac_md5_tv_template);
+ if (tsize > TVMEMSIZE) {
+ printk("template (%d) too big for tvmem (%d)\n", tsize, TVMEMSIZE);
+ return;
+ }
+
+ memcpy(tvmem, hmac_md5_tv_template, tsize);
+ hmac_md5_tv = (void *)tvmem;
+
+ for (i = 0; i < HMAC_MD5_TEST_VECTORS; i++) {
+ printk("test %d:\n", i + 1);
+ memset(result, 0, sizeof(result));
+
+ p = hmac_md5_tv[i].plaintext;
+ sg[0].page = virt_to_page(p);
+ sg[0].offset = ((long)p & ~PAGE_MASK);
+ sg[0].length = strlen(hmac_md5_tv[i].plaintext);
+
+ crypto_digest_hmac(tfm, hmac_md5_tv[i].key, strlen(hmac_md5_tv[i].key),sg , 1, result);
+
+ hexdump(result, crypto_tfm_digestsize(tfm));
+ printk("%s\n", memcmp(result, hmac_md5_tv[i].digest, crypto_tfm_digestsize(tfm)) ? "fail" : "pass");
+ }
+
+ printk("\ntesting hmac_md5 across pages\n");
+
+ memset(xbuf, 0, sizeof(xbuf));
+
+ memcpy(&xbuf[IDX1], "what do ya want ", 16);
+ memcpy(&xbuf[IDX2], "for nothing?", 12);
+
+ p = &xbuf[IDX1];
+ sg[0].page = virt_to_page(p);
+ sg[0].offset = ((long)p & ~PAGE_MASK);
+ sg[0].length = 16;
+
+ p = &xbuf[IDX2];
+ sg[1].page = virt_to_page(p);
+ sg[1].offset = ((long)p & ~PAGE_MASK);
+ sg[1].length = 12;
+
+ memset(result, 0, sizeof(result));
+ crypto_digest_hmac(tfm, hmac_md5_tv[1].key, strlen(hmac_md5_tv[1].key), sg, 2, result);
+ hexdump(result, crypto_tfm_digestsize(tfm));
+
+ printk("%s\n", memcmp(result, hmac_md5_tv[1].digest, crypto_tfm_digestsize(tfm)) ? "fail" : "pass");
+
+ crypto_free_tfm(tfm);
+}
+
+static void test_sha1(void)
+{
+ char *p;
+ int i;
+ struct crypto_tfm *tfm;
+ struct sha1_testvec *sha1_tv;
+ struct hmac_sha1_testvec *hmac_sha1_tv;
+ struct scatterlist sg[2];
+ size_t tsize;
+ char result[SHA1_DIGEST_SIZE];
+
+ printk("\ntesting sha1\n");
+
+ tsize = sizeof(sha1_tv_template);
+ if (tsize > TVMEMSIZE) {
+ printk("template (%d) too big for tvmem (%d)\n", tsize, TVMEMSIZE);
+ return;
+ }
+
+ memcpy(tvmem, sha1_tv_template, tsize);
+ sha1_tv = (void *)tvmem;
+
+ tfm = crypto_alloc_tfm(CRYPTO_ALG_SHA1);
+ if (tfm == NULL) {
+ printk("failed to load transform for CRYPTO_ALG_SHA1\n");
+ return;
+ }
+
+ for (i = 0; i < SHA1_TEST_VECTORS; i++) {
+ printk("test %d:\n", i + 1);
+ memset(result, 0, sizeof(result));
+
+ p = sha1_tv[i].plaintext;
+ sg[0].page = virt_to_page(p);
+ sg[0].offset = ((long)p & ~PAGE_MASK);
+ sg[0].length = strlen(sha1_tv[i].plaintext);
+
+ crypto_digest_init(tfm);
+ crypto_digest_update(tfm, sg, 1);
+ crypto_digest_final(tfm, result);
+
+ hexdump(result, crypto_tfm_digestsize(tfm));
+ printk("%s\n", memcmp(result, sha1_tv[i].digest, crypto_tfm_digestsize(tfm)) ? "fail" : "pass");
+ }
+
+ printk("\ntesting sha1 across pages\n");
+
+ /* setup the dummy buffer first */
+ memset(xbuf, 0, sizeof(xbuf));
+ memcpy(&xbuf[IDX1], "abcdbcdecdefdefgefghfghighij", 28);
+ memcpy(&xbuf[IDX2], "hijkijkljklmklmnlmnomnopnopq", 28);
+
+ p = &xbuf[IDX1];
+ sg[0].page = virt_to_page(p);
+ sg[0].offset = ((long)p & ~PAGE_MASK);
+ sg[0].length = 28;
+
+ p = &xbuf[IDX2];
+ sg[1].page = virt_to_page(p);
+ sg[1].offset = ((long)p & ~PAGE_MASK);
+ sg[1].length = 28;
+
+ memset(result, 0, sizeof(result));
+ crypto_digest_digest(tfm, sg, 2, result);
+ hexdump(result, crypto_tfm_digestsize(tfm));
+
+ printk("%s\n", memcmp(result, sha1_tv[1].digest, crypto_tfm_digestsize(tfm)) ? "fail" : "pass");
+
+ printk("\ntesting hmac_sha1\n");
+
+ tsize = sizeof(hmac_sha1_tv_template);
+ if (tsize > TVMEMSIZE) {
+ printk("template (%d) too big for tvmem (%d)\n", tsize, TVMEMSIZE);
+ return;
+ }
+
+ memcpy(tvmem, hmac_sha1_tv_template, tsize);
+ hmac_sha1_tv = (void *)tvmem;
+
+ for (i = 0; i < HMAC_SHA1_TEST_VECTORS; i++) {
+ printk("test %d:\n", i + 1);
+ memset(result, 0, sizeof(result));
+
+ p = hmac_sha1_tv[i].plaintext;
+ sg[0].page = virt_to_page(p);
+ sg[0].offset = ((long)p & ~PAGE_MASK);
+ sg[0].length = strlen(hmac_sha1_tv[i].plaintext);
+
+ crypto_digest_hmac(tfm, hmac_sha1_tv[i].key, strlen(hmac_sha1_tv[i].key),sg , 1, result);
+
+ hexdump(result, sizeof(result));
+ printk("%s\n", memcmp(result, hmac_sha1_tv[i].digest, crypto_tfm_digestsize(tfm)) ? "fail" : "pass");
+ }
+
+ printk("\ntesting hmac_sha1 across pages\n");
+
+ /* setup the dummy buffer first */
+ memset(xbuf, 0, sizeof(xbuf));
+
+ memcpy(&xbuf[IDX1], "what do ya want ", 16);
+ memcpy(&xbuf[IDX2], "for nothing?", 12);
+
+ p = &xbuf[IDX1];
+ sg[0].page = virt_to_page(p);
+ sg[0].offset = ((long)p & ~PAGE_MASK);
+ sg[0].length = 16;
+
+ p = &xbuf[IDX2];
+ sg[1].page = virt_to_page(p);
+ sg[1].offset = ((long)p & ~PAGE_MASK);
+ sg[1].length = 12;
+
+ memset(result, 0, sizeof(result));
+ crypto_digest_hmac(tfm, hmac_sha1_tv[1].key, strlen(hmac_sha1_tv[1].key), sg, 2, result);
+ hexdump(result, crypto_tfm_digestsize(tfm));
+
+ printk("%s\n", memcmp(result, hmac_sha1_tv[1].digest, crypto_tfm_digestsize(tfm)) ? "fail" : "pass");
+ crypto_free_tfm(tfm);
+}
+
+void test_des(void)
+{
+ int ret, i, len;
+ size_t tsize;
+ char *p, *q;
+ struct crypto_tfm *tfm;
+ char *key;
+ char res[8];
+ struct des_tv *des_tv;
+ struct scatterlist sg[8];
+
+ printk("\ntesting des encryption\n");
+
+ tsize = sizeof(des_enc_tv_template);
+ if (tsize > TVMEMSIZE) {
+ printk("template (%d) too big for tvmem (%d)\n", tsize, TVMEMSIZE);
+ return;
+ }
+
+ memcpy(tvmem, des_enc_tv_template, tsize);
+ des_tv = (void *)tvmem;
+
+ tfm = crypto_alloc_tfm(CRYPTO_ALG_DES_ECB);
+ if (tfm == NULL) {
+ printk("failed to load transform for CRYPTO_ALG_DES_ECB\n");
+ return;
+ }
+
+ for (i = 0; i < DES_ENC_TEST_VECTORS; i++) {
+ printk("test %d:\n", i + 1);
+
+ key = des_tv[i].key;
+
+ tfm->crt_flags = CRYPTO_WEAK_KEY_CHECK;
+ ret = crypto_cipher_setkey(tfm, key, 8);
+ if (ret) {
+ printk("setkey() failed flags=%x\n", tfm->crt_flags);
+
+ if (!des_tv[i].fail)
+ goto out;
+ }
+
+ len = des_tv[i].len;
+
+ p = des_tv[i].plaintext;
+ sg[0].page = virt_to_page(p);
+ sg[0].offset = ((long)p & ~PAGE_MASK);
+ sg[0].length = len;
+ ret = crypto_cipher_encrypt(tfm, sg, 1);
+ if (ret) {
+ printk("encrypt() failed flags=%x\n", tfm->crt_flags);
+ goto out;
+ }
+
+ q = kmap(sg[0].page) + sg[0].offset;
+ hexdump(q, len);
+
+ printk("%s\n", memcmp(q, des_tv[i].result, len) ? "fail" : "pass");
+
+ }
+
+ printk("\ntesting des ecb encryption across pages\n");
+
+ i = 5;
+ key = des_tv[i].key;
+ tfm->crt_flags = 0;
+
+ hexdump(key, 8);
+
+ ret = crypto_cipher_setkey(tfm, key, 8);
+ if (ret) {
+ printk("setkey() failed flags=%x\n", tfm->crt_flags);
+ goto out;
+ }
+
+ /* setup the dummy buffer first */
+ memset(xbuf, 0, sizeof(xbuf));
+ memcpy(&xbuf[IDX1], des_tv[i].plaintext, 8);
+ memcpy(&xbuf[IDX2], des_tv[i].plaintext + 8 , 8);
+
+ p = &xbuf[IDX1];
+ sg[0].page = virt_to_page(p);
+ sg[0].offset = ((long)p & ~PAGE_MASK);
+ sg[0].length = 8;
+
+ p = &xbuf[IDX2];
+ sg[1].page = virt_to_page(p);
+ sg[1].offset = ((long)p & ~PAGE_MASK);
+ sg[1].length = 8;
+
+ ret = crypto_cipher_encrypt(tfm, sg, 2);
+ if (ret) {
+ printk("encrypt() failed flags=%x\n", tfm->crt_flags);
+ goto out;
+ }
+
+ printk("page 1\n");
+ q = kmap(sg[0].page) + sg[0].offset;
+ hexdump(q, 8);
+ printk("%s\n", memcmp(q, des_tv[i].result, 8) ? "fail" : "pass");
+
+ printk("page 2\n");
+ q = kmap(sg[1].page) + sg[1].offset;
+ hexdump(q, 8);
+ printk("%s\n", memcmp(q, des_tv[i].result + 8, 8) ? "fail" : "pass");
+
+ printk("\ntesting des ecb encryption chunking scenario A\n");
+
+ /*
+ * Scenario A:
+ *
+ * F1 F2 F3
+ * [8 + 6] [2 + 8] [8]
+ * ^^^^^^ ^
+ * a b c
+ *
+ * Chunking should begin at a, then end with b, and
+ * continue encrypting at an offset of 2 until c.
+ *
+ */
+ i = 7;
+
+ key = des_tv[i].key;
+ tfm->crt_flags = 0;
+
+ ret = crypto_cipher_setkey(tfm, key, 8);
+ if (ret) {
+ printk("setkey() failed flags=%x\n", tfm->crt_flags);
+ goto out;
+ }
+
+ /* setup the dummy buffer first */
+ memset(xbuf, 0, sizeof(xbuf));
+
+ /* Frag 1: 8 + 6 */
+ memcpy(&xbuf[IDX3], des_tv[i].plaintext, 14);
+
+ /* Frag 2: 2 + 8 */
+ memcpy(&xbuf[IDX4], des_tv[i].plaintext + 14, 10);
+
+ /* Frag 3: 8 */
+ memcpy(&xbuf[IDX5], des_tv[i].plaintext + 24, 8);
+
+ p = &xbuf[IDX3];
+ sg[0].page = virt_to_page(p);
+ sg[0].offset = ((long)p & ~PAGE_MASK);
+ sg[0].length = 14;
+
+ p = &xbuf[IDX4];
+ sg[1].page = virt_to_page(p);
+ sg[1].offset = ((long)p & ~PAGE_MASK);
+ sg[1].length = 10;
+
+ p = &xbuf[IDX5];
+ sg[2].page = virt_to_page(p);
+ sg[2].offset = ((long)p & ~PAGE_MASK);
+ sg[2].length = 8;
+
+ ret = crypto_cipher_encrypt(tfm, sg, 3);
+
+ if (ret) {
+ printk("decrypt() failed flags=%x\n", tfm->crt_flags);
+ goto out;
+ }
+
+ printk("page 1\n");
+ q = kmap(sg[0].page) + sg[0].offset;
+ hexdump(q, 14);
+ printk("%s\n", memcmp(q, des_tv[i].result, 14) ? "fail" : "pass");
+
+ printk("page 2\n");
+ q = kmap(sg[1].page) + sg[1].offset;
+ hexdump(q, 10);
+ printk("%s\n", memcmp(q, des_tv[i].result + 14, 10) ? "fail" : "pass");
+
+ printk("page 3\n");
+ q = kmap(sg[2].page) + sg[2].offset;
+ hexdump(q, 8);
+ printk("%s\n", memcmp(q, des_tv[i].result + 24, 8) ? "fail" : "pass");
+
+ printk("\ntesting des ecb encryption chunking scenario B\n");
+
+ /*
+ * Scenario B:
+ *
+ * F1 F2 F3 F4
+ * [2] [1] [3] [2 + 8 + 8]
+ */
+ i = 7;
+
+ key = des_tv[i].key;
+ tfm->crt_flags = 0;
+
+ ret = crypto_cipher_setkey(tfm, key, 8);
+ if (ret) {
+ printk("setkey() failed flags=%x\n", tfm->crt_flags);
+ goto out;
+ }
+
+ /* setup the dummy buffer first */
+ memset(xbuf, 0, sizeof(xbuf));
+
+ /* Frag 1: 2 */
+ memcpy(&xbuf[IDX3], des_tv[i].plaintext, 2);
+
+ /* Frag 2: 1 */
+ memcpy(&xbuf[IDX4], des_tv[i].plaintext + 2, 1);
+
+ /* Frag 3: 3 */
+ memcpy(&xbuf[IDX5], des_tv[i].plaintext + 3, 3);
+
+ /* Frag 4: 2 + 8 + 8 */
+ memcpy(&xbuf[IDX6], des_tv[i].plaintext + 6, 18);
+
+ p = &xbuf[IDX3];
+ sg[0].page = virt_to_page(p);
+ sg[0].offset = ((long)p & ~PAGE_MASK);
+ sg[0].length = 2;
+
+ p = &xbuf[IDX4];
+ sg[1].page = virt_to_page(p);
+ sg[1].offset = ((long)p & ~PAGE_MASK);
+ sg[1].length = 1;
+
+ p = &xbuf[IDX5];
+ sg[2].page = virt_to_page(p);
+ sg[2].offset = ((long)p & ~PAGE_MASK);
+ sg[2].length = 3;
+
+ p = &xbuf[IDX6];
+ sg[3].page = virt_to_page(p);
+ sg[3].offset = ((long)p & ~PAGE_MASK);
+ sg[3].length = 18;
+
+ ret = crypto_cipher_encrypt(tfm, sg, 4);
+
+ if (ret) {
+ printk("encrypt() failed flags=%x\n", tfm->crt_flags);
+ goto out;
+ }
+
+ printk("page 1\n");
+ q = kmap(sg[0].page) + sg[0].offset;
+ hexdump(q, 2);
+ printk("%s\n", memcmp(q, des_tv[i].result, 2) ? "fail" : "pass");
+
+ printk("page 2\n");
+ q = kmap(sg[1].page) + sg[1].offset;
+ hexdump(q, 1);
+ printk("%s\n", memcmp(q, des_tv[i].result + 2, 1) ? "fail" : "pass");
+
+ printk("page 3\n");
+ q = kmap(sg[2].page) + sg[2].offset;
+ hexdump(q, 3);
+ printk("%s\n", memcmp(q, des_tv[i].result + 3, 3) ? "fail" : "pass");
+
+ printk("page 4\n");
+ q = kmap(sg[3].page) + sg[3].offset;
+ hexdump(q, 18);
+ printk("%s\n", memcmp(q, des_tv[i].result + 6, 18) ? "fail" : "pass");
+
+ printk("\ntesting des ecb encryption chunking scenario C\n");
+
+ /*
+ * Scenario B:
+ *
+ * F1 F2 F3 F4 F5
+ * [2] [2] [2] [2] [8]
+ */
+ i = 7;
+
+ key = des_tv[i].key;
+ tfm->crt_flags = 0;
+
+ ret = crypto_cipher_setkey(tfm, key, 8);
+ if (ret) {
+ printk("setkey() failed flags=%x\n", tfm->crt_flags);
+ goto out;
+ }
+
+ /* setup the dummy buffer first */
+ memset(xbuf, 0, sizeof(xbuf));
+
+ /* Frag 1: 2 */
+ memcpy(&xbuf[IDX3], des_tv[i].plaintext, 2);
+
+ /* Frag 2: 2 */
+ memcpy(&xbuf[IDX4], des_tv[i].plaintext + 2, 2);
+
+ /* Frag 3: 2 */
+ memcpy(&xbuf[IDX5], des_tv[i].plaintext + 4, 2);
+
+ /* Frag 4: 2 */
+ memcpy(&xbuf[IDX6], des_tv[i].plaintext + 6, 2);
+
+ /* Frag 5: 8 */
+ memcpy(&xbuf[IDX7], des_tv[i].plaintext + 8, 8);
+
+ p = &xbuf[IDX3];
+ sg[0].page = virt_to_page(p);
+ sg[0].offset = ((long)p & ~PAGE_MASK);
+ sg[0].length = 2;
+
+ p = &xbuf[IDX4];
+ sg[1].page = virt_to_page(p);
+ sg[1].offset = ((long)p & ~PAGE_MASK);
+ sg[1].length = 2;
+
+ p = &xbuf[IDX5];
+ sg[2].page = virt_to_page(p);
+ sg[2].offset = ((long)p & ~PAGE_MASK);
+ sg[2].length = 2;
+
+ p = &xbuf[IDX6];
+ sg[3].page = virt_to_page(p);
+ sg[3].offset = ((long)p & ~PAGE_MASK);
+ sg[3].length = 2;
+
+ p = &xbuf[IDX7];
+ sg[4].page = virt_to_page(p);
+ sg[4].offset = ((long)p & ~PAGE_MASK);
+ sg[4].length = 8;
+
+ ret = crypto_cipher_encrypt(tfm, sg, 5);
+
+ if (ret) {
+ printk("encrypt() failed flags=%x\n", tfm->crt_flags);
+ goto out;
+ }
+
+ printk("page 1\n");
+ q = kmap(sg[0].page) + sg[0].offset;
+ hexdump(q, 2);
+ printk("%s\n", memcmp(q, des_tv[i].result, 2) ? "fail" : "pass");
+
+ printk("page 2\n");
+ q = kmap(sg[1].page) + sg[1].offset;
+ hexdump(q, 2);
+ printk("%s\n", memcmp(q, des_tv[i].result + 2, 2) ? "fail" : "pass");
+
+ printk("page 3\n");
+ q = kmap(sg[2].page) + sg[2].offset;
+ hexdump(q, 2);
+ printk("%s\n", memcmp(q, des_tv[i].result + 4, 2) ? "fail" : "pass");
+
+ printk("page 4\n");
+ q = kmap(sg[3].page) + sg[3].offset;
+ hexdump(q, 2);
+ printk("%s\n", memcmp(q, des_tv[i].result + 6, 2) ? "fail" : "pass");
+
+ printk("page 5\n");
+ q = kmap(sg[4].page) + sg[4].offset;
+ hexdump(q, 8);
+ printk("%s\n", memcmp(q, des_tv[i].result + 8, 8) ? "fail" : "pass");
+
+ printk("\ntesting des ecb encryption chunking scenario D (atomic)\n");
+
+ /*
+ * Scenario D, torture test, one byte per frag.
+ */
+ i = 7;
+ key = des_tv[i].key;
+ tfm->crt_flags = CRYPTO_ATOMIC;
+
+ ret = crypto_cipher_setkey(tfm, key, 8);
+ if (ret) {
+ printk("setkey() failed flags=%x\n", tfm->crt_flags);
+ goto out;
+ }
+
+ /* setup the dummy buffer first */
+ memset(xbuf, 0, sizeof(xbuf));
+
+ xbuf[IDX1] = des_tv[i].plaintext[0];
+ xbuf[IDX2] = des_tv[i].plaintext[1];
+ xbuf[IDX3] = des_tv[i].plaintext[2];
+ xbuf[IDX4] = des_tv[i].plaintext[3];
+ xbuf[IDX5] = des_tv[i].plaintext[4];
+ xbuf[IDX6] = des_tv[i].plaintext[5];
+ xbuf[IDX7] = des_tv[i].plaintext[6];
+ xbuf[IDX8] = des_tv[i].plaintext[7];
+
+ p = &xbuf[IDX1];
+ sg[0].page = virt_to_page(p);
+ sg[0].offset = ((long)p & ~PAGE_MASK);
+ sg[0].length = 1;
+
+ p = &xbuf[IDX2];
+ sg[1].page = virt_to_page(p);
+ sg[1].offset = ((long)p & ~PAGE_MASK);
+ sg[1].length = 1;
+
+ p = &xbuf[IDX3];
+ sg[2].page = virt_to_page(p);
+ sg[2].offset = ((long)p & ~PAGE_MASK);
+ sg[2].length = 1;
+
+ p = &xbuf[IDX4];
+ sg[3].page = virt_to_page(p);
+ sg[3].offset = ((long)p & ~PAGE_MASK);
+ sg[3].length = 1;
+
+ p = &xbuf[IDX5];
+ sg[4].page = virt_to_page(p);
+ sg[4].offset = ((long)p & ~PAGE_MASK);
+ sg[4].length = 1;
+
+ p = &xbuf[IDX6];
+ sg[5].page = virt_to_page(p);
+ sg[5].offset = ((long)p & ~PAGE_MASK);
+ sg[5].length = 1;
+
+ p = &xbuf[IDX7];
+ sg[6].page = virt_to_page(p);
+ sg[6].offset = ((long)p & ~PAGE_MASK);
+ sg[6].length = 1;
+
+ p = &xbuf[IDX8];
+ sg[7].page = virt_to_page(p);
+ sg[7].offset = ((long)p & ~PAGE_MASK);
+ sg[7].length = 1;
+
+ ret = crypto_cipher_encrypt(tfm, sg, 8);
+
+ if (ret) {
+ printk("encrypt() failed flags=%x\n", tfm->crt_flags);
+ goto out;
+ }
+
+ for (i = 0; i < 8; i++)
+ res[i] = *(char *)(kmap(sg[i].page) + sg[i].offset);
+
+ hexdump(res, 8);
+ printk("%s\n", memcmp(res, des_tv[7].result, 8) ? "fail" : "pass");
+
+
+ printk("\ntesting des decryption\n");
+
+ tsize = sizeof(des_dec_tv_template);
+ if (tsize > TVMEMSIZE) {
+ printk("template (%d) too big for tvmem (%d)\n", tsize, TVMEMSIZE);
+ return;
+ }
+ memcpy(tvmem, des_dec_tv_template, tsize);
+ des_tv = (void *)tvmem;
+
+ for (i = 0; i < DES_DEC_TEST_VECTORS; i++) {
+ printk("test %d:\n", i + 1);
+
+ key = des_tv[i].key;
+
+ tfm->crt_flags = 0;
+ ret = crypto_cipher_setkey(tfm, key, 8);
+ if (ret) {
+ printk("setkey() failed flags=%x\n", tfm->crt_flags);
+ goto out;
+ }
+
+ len = des_tv[i].len;
+
+ p = des_tv[i].plaintext;
+ sg[0].page = virt_to_page(p);
+ sg[0].offset = ((long)p & ~PAGE_MASK);
+ sg[0].length = len;
+
+ ret = crypto_cipher_decrypt(tfm, sg, 1);
+ if (ret) {
+ printk("des_decrypt() failed flags=%x\n", tfm->crt_flags);
+ goto out;
+ }
+
+ q = kmap(sg[0].page) + sg[0].offset;
+ hexdump(q, len);
+
+ printk("%s\n", memcmp(q, des_tv[i].result, len) ? "fail" : "pass");
+
+ }
+
+ printk("\ntesting des ecb decryption across pages\n");
+
+ i = 6;
+
+ key = des_tv[i].key;
+ tfm->crt_flags = 0;
+
+ ret = crypto_cipher_setkey(tfm, key, 8);
+ if (ret) {
+ printk("setkey() failed flags=%x\n", tfm->crt_flags);
+ goto out;
+ }
+
+ /* setup the dummy buffer first */
+ memset(xbuf, 0, sizeof(xbuf));
+ memcpy(&xbuf[IDX1], des_tv[i].plaintext, 8);
+ memcpy(&xbuf[IDX2], des_tv[i].plaintext + 8 , 8);
+
+ p = &xbuf[IDX1];
+ sg[0].page = virt_to_page(p);
+ sg[0].offset = ((long)p & ~PAGE_MASK);
+ sg[0].length = 8;
+
+ p = &xbuf[IDX2];
+ sg[1].page = virt_to_page(p);
+ sg[1].offset = ((long)p & ~PAGE_MASK);
+ sg[1].length = 8;
+
+ ret = crypto_cipher_decrypt(tfm, sg, 2);
+ if (ret) {
+ printk("decrypt() failed flags=%x\n", tfm->crt_flags);
+ goto out;
+ }
+
+ printk("page 1\n");
+ q = kmap(sg[0].page) + sg[0].offset;
+ hexdump(q, 8);
+ printk("%s\n", memcmp(q, des_tv[i].result, 8) ? "fail" : "pass");
+
+ printk("page 2\n");
+ q = kmap(sg[1].page) + sg[1].offset;
+ hexdump(q, 8);
+ printk("%s\n", memcmp(q, des_tv[i].result + 8, 8) ? "fail" : "pass");
+
+
+ /*
+ * Scenario E:
+ *
+ * F1 F2 F3
+ * [3] [5 + 7] [1]
+ *
+ */
+ printk("\ntesting des ecb decryption chunking scenario E\n");
+ i = 2;
+
+ key = des_tv[i].key;
+ tfm->crt_flags = 0;
+
+ ret = crypto_cipher_setkey(tfm, key, 8);
+ if (ret) {
+ printk("setkey() failed flags=%x\n", tfm->crt_flags);
+ goto out;
+ }
+
+ /* setup the dummy buffer first */
+ memset(xbuf, 0, sizeof(xbuf));
+
+ memcpy(&xbuf[IDX1], des_tv[i].plaintext, 3);
+ memcpy(&xbuf[IDX2], des_tv[i].plaintext + 3, 12);
+ memcpy(&xbuf[IDX3], des_tv[i].plaintext + 15, 1);
+
+ p = &xbuf[IDX1];
+ sg[0].page = virt_to_page(p);
+ sg[0].offset = ((long)p & ~PAGE_MASK);
+ sg[0].length = 3;
+
+ p = &xbuf[IDX2];
+ sg[1].page = virt_to_page(p);
+ sg[1].offset = ((long)p & ~PAGE_MASK);
+ sg[1].length = 12;
+
+ p = &xbuf[IDX3];
+ sg[2].page = virt_to_page(p);
+ sg[2].offset = ((long)p & ~PAGE_MASK);
+ sg[2].length = 1;
+
+ ret = crypto_cipher_decrypt(tfm, sg, 3);
+
+ if (ret) {
+ printk("decrypt() failed flags=%x\n", tfm->crt_flags);
+ goto out;
+ }
+
+ printk("page 1\n");
+ q = kmap(sg[0].page) + sg[0].offset;
+ hexdump(q, 3);
+ printk("%s\n", memcmp(q, des_tv[i].result, 3) ? "fail" : "pass");
+
+ printk("page 2\n");
+ q = kmap(sg[1].page) + sg[1].offset;
+ hexdump(q, 12);
+ printk("%s\n", memcmp(q, des_tv[i].result + 3, 12) ? "fail" : "pass");
+
+ printk("page 3\n");
+ q = kmap(sg[2].page) + sg[2].offset;
+ hexdump(q, 1);
+ printk("%s\n", memcmp(q, des_tv[i].result + 15, 1) ? "fail" : "pass");
+
+ crypto_free_tfm(tfm);
+
+ tfm = crypto_alloc_tfm(CRYPTO_ALG_DES_CBC);
+ if (tfm == NULL) {
+ printk("failed to load transform for CRYPTO_ALG_DES_CBC\n");
+ return;
+ }
+
+ printk("\ntesting des cbc encryption (atomic)\n");
+
+ tsize = sizeof(des_cbc_enc_tv_template);
+ if (tsize > TVMEMSIZE) {
+ printk("template (%d) too big for tvmem (%d)\n", tsize, TVMEMSIZE);
+ return;
+ }
+ memcpy(tvmem, des_cbc_enc_tv_template, tsize);
+ des_tv = (void *)tvmem;
+
+ for (i = 0; i < DES_CBC_ENC_TEST_VECTORS; i++) {
+ printk("test %d:\n", i + 1);
+
+ tfm->crt_flags = CRYPTO_ATOMIC;
+ key = des_tv[i].key;
+
+ ret = crypto_cipher_setkey(tfm, key, 8);
+ if (ret) {
+ printk("setkey() failed flags=%x\n", tfm->crt_flags);
+ goto out;
+ }
+
+ len = des_tv[i].len;
+ p = des_tv[i].plaintext;
+
+ sg[0].page = virt_to_page(p);
+ sg[0].offset = ((long)p & ~PAGE_MASK);
+ sg[0].length = len;
+
+ crypto_cipher_copy_iv(tfm, des_tv[i].iv, crypto_tfm_ivsize(tfm));
+
+ ret = crypto_cipher_encrypt(tfm, sg, 1);
+ if (ret) {
+ printk("des_cbc_encrypt() failed flags=%x\n", tfm->crt_flags);
+ goto out;
+ }
+
+ q = kmap(sg[0].page) + sg[0].offset;
+ hexdump(q, len);
+
+ printk("%s\n", memcmp(q, des_tv[i].result, len) ? "fail" : "pass");
+ }
+
+ /*
+ * Scenario F:
+ *
+ * F1 F2
+ * [8 + 5] [3 + 8]
+ *
+ */
+ printk("\ntesting des cbc encryption chunking scenario F\n");
+ i = 4;
+
+ tfm = crypto_alloc_tfm(CRYPTO_ALG_DES_CBC);
+ if (tfm == NULL) {
+ printk("failed to load transform for CRYPTO_ALG_DES_CCB\n");
+ return;
+ }
+
+ tfm->crt_flags = 0;
+ key = des_tv[i].key;
+
+ ret = crypto_cipher_setkey(tfm, key, 8);
+ if (ret) {
+ printk("setkey() failed flags=%x\n", tfm->crt_flags);
+ goto out;
+ }
+
+ /* setup the dummy buffer first */
+ memset(xbuf, 0, sizeof(xbuf));
+
+ memcpy(&xbuf[IDX1], des_tv[i].plaintext, 13);
+ memcpy(&xbuf[IDX2], des_tv[i].plaintext + 13, 11);
+
+ p = &xbuf[IDX1];
+ sg[0].page = virt_to_page(p);
+ sg[0].offset = ((long)p & ~PAGE_MASK);
+ sg[0].length = 13;
+
+ p = &xbuf[IDX2];
+ sg[1].page = virt_to_page(p);
+ sg[1].offset = ((long)p & ~PAGE_MASK);
+ sg[1].length = 11;
+
+ crypto_cipher_copy_iv(tfm, des_tv[i].iv, crypto_tfm_ivsize(tfm));
+
+ ret = crypto_cipher_encrypt(tfm, sg, 2);
+ if (ret) {
+ printk("des_cbc_decrypt() failed flags=%x\n", tfm->crt_flags);
+ goto out;
+ }
+
+ printk("page 1\n");
+ q = kmap(sg[0].page) + sg[0].offset;
+ hexdump(q, 13);
+ printk("%s\n", memcmp(q, des_tv[i].result, 13) ? "fail" : "pass");
+
+ printk("page 2\n");
+ q = kmap(sg[1].page) + sg[1].offset;
+ hexdump(q, 11);
+ printk("%s\n", memcmp(q, des_tv[i].result + 13, 11) ? "fail" : "pass");
+
+
+ tsize = sizeof(des_cbc_dec_tv_template);
+ if (tsize > TVMEMSIZE) {
+ printk("template (%d) too big for tvmem (%d)\n", tsize, TVMEMSIZE);
+ return;
+ }
+ memcpy(tvmem, des_cbc_dec_tv_template, tsize);
+ des_tv = (void *)tvmem;
+
+ printk("\ntesting des cbc decryption\n");
+
+ for (i = 0; i < DES_CBC_DEC_TEST_VECTORS; i++) {
+ printk("test %d:\n", i + 1);
+
+ tfm->crt_flags = 0;
+ key = des_tv[i].key;
+
+ ret = crypto_cipher_setkey(tfm, key, 8);
+ if (ret) {
+ printk("setkey() failed flags=%x\n", tfm->crt_flags);
+ goto out;
+ }
+
+ len = des_tv[i].len;
+ p = des_tv[i].plaintext;
+
+ sg[0].page = virt_to_page(p);
+ sg[0].offset = ((long)p & ~PAGE_MASK);
+ sg[0].length = len;
+
+ crypto_cipher_copy_iv(tfm, des_tv[i].iv, crypto_tfm_blocksize(tfm));
+
+ ret = crypto_cipher_decrypt(tfm, sg, 1);
+ if (ret) {
+ printk("des_cbc_decrypt() failed flags=%x\n", tfm->crt_flags);
+ goto out;
+ }
+
+ hexdump(tfm->crt_cipher.cit_iv, 8);
+
+ q = kmap(sg[0].page) + sg[0].offset;
+ hexdump(q, len);
+
+ printk("%s\n", memcmp(q, des_tv[i].result, len) ? "fail" : "pass");
+ }
+
+ /*
+ * Scenario G:
+ *
+ * F1 F2
+ * [4] [4]
+ *
+ */
+ printk("\ntesting des cbc decryption chunking scenario G\n");
+ i = 3;
+
+ tfm->crt_flags = 0;
+ key = des_tv[i].key;
+
+ ret = crypto_cipher_setkey(tfm, key, 8);
+ if (ret) {
+ printk("setkey() failed flags=%x\n", tfm->crt_flags);
+ goto out;
+ }
+
+ /* setup the dummy buffer first */
+ memset(xbuf, 0, sizeof(xbuf));
+ memcpy(&xbuf[IDX1], des_tv[i].plaintext, 4);
+ memcpy(&xbuf[IDX2], des_tv[i].plaintext + 4, 4);
+
+ p = &xbuf[IDX1];
+ sg[0].page = virt_to_page(p);
+ sg[0].offset = ((long)p & ~PAGE_MASK);
+ sg[0].length = 4;
+
+ p = &xbuf[IDX2];
+ sg[1].page = virt_to_page(p);
+ sg[1].offset = ((long)p & ~PAGE_MASK);
+ sg[1].length = 4;
+
+ crypto_cipher_copy_iv(tfm, des_tv[i].iv, crypto_tfm_ivsize(tfm));
+
+ ret = crypto_cipher_decrypt(tfm, sg, 2);
+ if (ret) {
+ printk("des_cbc_decrypt() failed flags=%x\n", tfm->crt_flags);
+ goto out;
+ }
+
+ printk("page 1\n");
+ q = kmap(sg[0].page) + sg[0].offset;
+ hexdump(q, 4);
+ printk("%s\n", memcmp(q, des_tv[i].result, 4) ? "fail" : "pass");
+
+ printk("page 2\n");
+ q = kmap(sg[1].page) + sg[1].offset;
+ hexdump(q, 4);
+ printk("%s\n", memcmp(q, des_tv[i].result + 4, 4) ? "fail" : "pass");
+
+out:
+ crypto_free_tfm(tfm);
+ return;
+}
+
+static void do_test(void)
+{
+ switch (mode) {
+
+ case 0:
+ test_md5();
+ test_sha1();
+ test_des();
+ break;
+
+ case 1:
+ test_md5();
+ break;
+
+ case 2:
+ test_sha1();
+ break;
+
+ case 3:
+ test_des();
+ break;
+
+ default:
+ /* useful for debugging */
+ printk("not testing anything\n");
+ break;
+ }
+}
+
+
+static int __init init(void)
+{
+ tvmem = kmalloc(TVMEMSIZE, GFP_KERNEL);
+ if (tvmem == NULL)
+ return -ENOMEM;
+
+ xbuf = kmalloc(XBUFSIZE, GFP_KERNEL);
+ if (xbuf == NULL) {
+ kfree(tvmem);
+ return -ENOMEM;
+ }
+
+ do_test();
+
+ kfree(xbuf);
+ kfree(tvmem);
+ return 0;
+}
+
+module_init(init);
+
+MODULE_PARM(mode, "i");
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Quick & dirty crypto testing module");
+MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
diff --git a/crypto/tcrypt.h b/crypto/tcrypt.h
new file mode 100644
index 00000000000000..33b37860189c67
--- /dev/null
+++ b/crypto/tcrypt.h
@@ -0,0 +1,587 @@
+/*
+ * Quick & dirty crypto testing module.
+ *
+ * This will only exist until we have a better testing mechanism
+ * (e.g. a char device).
+ *
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ * Copyright (c) 2002 Jean-Francois Dive <jef@linuxbe.org>
+ *
+ * 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_TCRYPT_H
+#define _CRYPTO_TCRYPT_H
+
+#define MD5_DIGEST_SIZE 16
+#define SHA1_DIGEST_SIZE 20
+
+/*
+ * MD5 test vectors from RFC1321
+ */
+#define MD5_TEST_VECTORS 7
+
+struct md5_testvec {
+ char plaintext[128];
+ char digest[MD5_DIGEST_SIZE];
+} md5_tv_template[] = {
+ { "",
+ { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
+ 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e } },
+
+ { "a",
+ { 0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8,
+ 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 } },
+
+ { "abc",
+ { 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0,
+ 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 } },
+
+ { "message digest",
+ { 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d,
+ 0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 } },
+
+ { "abcdefghijklmnopqrstuvwxyz",
+ { 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00,
+ 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b } },
+
+ { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+ { 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5,
+ 0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f } },
+
+ { "12345678901234567890123456789012345678901234567890123456789012"
+ "345678901234567890",
+ { 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55,
+ 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a } }
+};
+
+/*
+ * HMAC-MD5 test vectors from RFC2202
+ * (These need to be fixed to not use strlen).
+ */
+#define HMAC_MD5_TEST_VECTORS 7
+
+struct hmac_md5_testvec {
+ char key[128];
+ char plaintext[128];
+ char digest[MD5_DIGEST_SIZE];
+};
+
+struct hmac_md5_testvec hmac_md5_tv_template[] =
+{
+
+ {
+ { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x00},
+
+ "Hi There",
+
+ { 0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c,
+ 0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d }
+ },
+
+ {
+ { 'J', 'e', 'f', 'e', 0 },
+
+ "what do ya want for nothing?",
+
+ { 0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03,
+ 0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38 }
+ },
+
+ {
+ { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00 },
+
+ { 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x00 },
+
+ { 0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88,
+ 0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6 }
+ },
+
+ {
+ { 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, 0x00 },
+
+ {
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0x00 },
+
+ { 0x69, 0x7e, 0xaf, 0x0a, 0xca, 0x3a, 0x3a, 0xea,
+ 0x3a, 0x75, 0x16, 0x47, 0x46, 0xff, 0xaa, 0x79 }
+ },
+
+ {
+ { 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00 },
+
+ "Test With Truncation",
+
+ { 0x56, 0x46, 0x1e, 0xf2, 0x34, 0x2e, 0xdc, 0x00,
+ 0xf9, 0xba, 0xb9, 0x95, 0x69, 0x0e, 0xfd, 0x4c }
+ },
+
+ {
+ { 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, 0x00 },
+
+ "Test Using Larger Than Block-Size Key - Hash Key First",
+
+ { 0x6b, 0x1a, 0xb7, 0xfe, 0x4b, 0xd7, 0xbf, 0x8f,
+ 0x0b, 0x62, 0xe6, 0xce, 0x61, 0xb9, 0xd0, 0xcd }
+ },
+
+ {
+ { 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, 0x00 },
+
+ "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
+
+ { 0x6f, 0x63, 0x0f, 0xad, 0x67, 0xcd, 0xa0, 0xee,
+ 0x1f, 0xb1, 0xf5, 0x62, 0xdb, 0x3a, 0xa5, 0x3e }
+ }
+};
+
+
+/*
+ * HMAC-SHA1 test vectors from RFC2202
+ */
+
+#define HMAC_SHA1_TEST_VECTORS 7
+
+struct hmac_sha1_testvec {
+ char key[128];
+ char plaintext[128];
+ char digest[SHA1_DIGEST_SIZE];
+} hmac_sha1_tv_template[] = {
+
+ {
+ { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x00},
+
+ "Hi There",
+
+ { 0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64,
+ 0xe2, 0x8b, 0xc0, 0xb6, 0xfb ,0x37, 0x8c, 0x8e, 0xf1,
+ 0x46, 0xbe, 0x00 }
+ },
+
+ {
+ { 'J', 'e', 'f', 'e', 0 },
+
+ "what do ya want for nothing?",
+
+ { 0xef, 0xfc, 0xdf, 0x6a, 0xe5, 0xeb, 0x2f, 0xa2, 0xd2, 0x74,
+ 0x16, 0xd5, 0xf1, 0x84, 0xdf, 0x9c, 0x25, 0x9a, 0x7c, 0x79 }
+
+ },
+
+ {
+ { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00},
+
+
+ { 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0x00 },
+
+ { 0x12, 0x5d, 0x73, 0x42, 0xb9, 0xac, 0x11, 0xcd, 0x91, 0xa3,
+ 0x9a, 0xf4, 0x8a, 0xa1, 0x7b, 0x4f, 0x63, 0xf1, 0x75, 0xd3 }
+
+ },
+
+ {
+ { 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, 0x00 },
+
+ {
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0x00 },
+
+ { 0x4c, 0x90, 0x07, 0xf4, 0x02, 0x62, 0x50, 0xc6, 0xbc, 0x84,
+ 0x14, 0xf9, 0xbf, 0x50, 0xc8, 0x6c, 0x2d, 0x72, 0x35, 0xda }
+
+ },
+
+ {
+ { 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00 },
+
+ "Test With Truncation",
+
+ { 0x4c, 0x1a, 0x03, 0x42, 0x4b, 0x55, 0xe0, 0x7f, 0xe7, 0xf2,
+ 0x7b, 0xe1, 0xd5, 0x8b, 0xb9, 0x32, 0x4a, 0x9a, 0x5a, 0x04 }
+
+ },
+
+ {
+ { 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, 0x00 },
+
+ "Test Using Larger Than Block-Size Key - Hash Key First",
+
+ { 0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72, 0xd0, 0x0e, 0x95, 0x70,
+ 0x56, 0x37, 0xce, 0x8a, 0x3b, 0x55, 0xed, 0x40, 0x21, 0x12 }
+
+ },
+
+ {
+ { 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, 0x00 },
+
+ "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
+
+ { 0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23, 0x7d, 0x78, 0x6d, 0x6b,
+ 0xba, 0xa7, 0x96, 0x5c, 0x78, 0x08, 0xbb, 0xff, 0x1a, 0x91 }
+ }
+};
+
+
+/*
+ * SHA1 test vectors from from FIPS PUB 180-1
+ */
+#define SHA1_TEST_VECTORS 2
+
+struct sha1_testvec {
+ char plaintext[128];
+ char digest[SHA1_DIGEST_SIZE];
+} sha1_tv_template[] = {
+ { "abc",
+ { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E,
+ 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C ,0x9C, 0xD0, 0xD8, 0x9D }
+ },
+
+ { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+
+ { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E ,0xBA, 0xAE,
+ 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 }
+ }
+};
+
+/*
+ * DES test vectors (also need to test for weak keys etc).
+ */
+#define DES_ENC_TEST_VECTORS 5
+#define DES_DEC_TEST_VECTORS 2
+#define DES_CBC_ENC_TEST_VECTORS 4
+#define DES_CBC_DEC_TEST_VECTORS 3
+
+struct des_tv {
+ int len;
+ int fail;
+ char key[8];
+ char iv[8];
+ char plaintext[128];
+ char result[128];
+};
+
+struct des_tv des_enc_tv_template[] = {
+
+ /* From Applied Cryptography */
+ {
+ 8, 0,
+
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+ { 0 },
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7 },
+ { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d }
+ },
+
+ /* Same key, different plaintext block */
+ {
+ 8, 0,
+
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+ { 0 },
+ { 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 },
+ { 0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b }
+ },
+
+ /* Sbox test from NBS */
+ {
+ 8, 0,
+
+ { 0x7C, 0xA1, 0x10, 0x45, 0x4A, 0x1A, 0x6E, 0x57 },
+ { 0 },
+ { 0x01, 0xA1, 0xD6, 0xD0, 0x39, 0x77, 0x67, 0x42 },
+ { 0x69, 0x0F, 0x5B, 0x0D, 0x9A, 0x26, 0x93, 0x9B }
+ },
+
+ /* Three blocks */
+ {
+ 24, 0,
+
+
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+
+ { 0 },
+
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7,
+ 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
+ 0xca, 0xfe, 0xba, 0xbe, 0xfe, 0xed, 0xbe, 0xef },
+
+ { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d,
+ 0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b,
+ 0xb4, 0x99, 0x26, 0xf7, 0x1f, 0xe1, 0xd4, 0x90 },
+ },
+
+ /* Weak key */
+ {
+ 8, 1,
+
+ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0 },
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7 },
+ { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d }
+ },
+
+ /* Two blocks -- for testing encryption across pages */
+ {
+ 16, 0,
+
+
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+
+ { 0 },
+
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7,
+ 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 },
+
+ { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d,
+ 0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b }
+ },
+
+ /* Two blocks -- for testing decryption across pages */
+ {
+ 16, 0,
+
+
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+
+ { 0 },
+
+ { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d,
+ 0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b },
+
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7,
+ 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 },
+ },
+
+ /* Four blocks -- for testing encryption with chunking */
+ {
+ 24, 0,
+
+
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+
+ { 0 },
+
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7,
+ 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
+ 0xca, 0xfe, 0xba, 0xbe, 0xfe, 0xed, 0xbe, 0xef,
+ 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 },
+
+ { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d,
+ 0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b,
+ 0xb4, 0x99, 0x26, 0xf7, 0x1f, 0xe1, 0xd4, 0x90,
+ 0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b },
+ },
+
+};
+
+struct des_tv des_dec_tv_template[] = {
+
+ /* From Applied Cryptography */
+ {
+ 8, 0,
+
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+ { 0 },
+ { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d },
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7 },
+ },
+
+ /* Sbox test from NBS */
+ {
+ 8, 0,
+
+ { 0x7C, 0xA1, 0x10, 0x45, 0x4A, 0x1A, 0x6E, 0x57 },
+ { 0 },
+ { 0x69, 0x0F, 0x5B, 0x0D, 0x9A, 0x26, 0x93, 0x9B },
+ { 0x01, 0xA1, 0xD6, 0xD0, 0x39, 0x77, 0x67, 0x42 }
+ },
+
+ /* Two blocks, for chunking test */
+ {
+ 16, 0,
+
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+ { 0 },
+
+ { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d,
+ 0x69, 0x0F, 0x5B, 0x0D, 0x9A, 0x26, 0x93, 0x9B },
+
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7,
+ 0xa3, 0x99, 0x7b, 0xca, 0xaf, 0x69, 0xa0, 0xf5 }
+ },
+
+};
+
+struct des_tv des_cbc_enc_tv_template[] = {
+ /* From OpenSSL */
+ {
+ 24, 0,
+
+ {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+ {0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+
+ { 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20,
+ 0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x20,
+ 0x66, 0x6F, 0x72, 0x20, 0x00, 0x31, 0x00, 0x00 },
+
+ { 0xcc, 0xd1, 0x73, 0xff, 0xab, 0x20, 0x39, 0xf4,
+ 0xac, 0xd8, 0xae, 0xfd, 0xdf, 0xd8, 0xa1, 0xeb,
+ 0x46, 0x8e, 0x91, 0x15, 0x78, 0x88, 0xba, 0x68,
+ 0x1d, 0x26, 0x93, 0x97, 0xf7, 0xfe, 0x62, 0xb4 }
+ },
+
+ /* FIPS Pub 81 */
+ {
+ 8, 0,
+
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+ { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef },
+ { 0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74 },
+ { 0xe5, 0xc7, 0xcd, 0xde, 0x87, 0x2b, 0xf2, 0x7c },
+
+ },
+
+ {
+ 8, 0,
+
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+ { 0xe5, 0xc7, 0xcd, 0xde, 0x87, 0x2b, 0xf2, 0x7c },
+ { 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20 },
+ { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
+ },
+
+ {
+ 8, 0,
+
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+ { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
+ { 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20 },
+ { 0x68, 0x37, 0x88, 0x49, 0x9a, 0x7c, 0x05, 0xf6 },
+ },
+
+ /* Copy of openssl vector for chunk testing */
+
+ /* From OpenSSL */
+ {
+ 24, 0,
+
+ {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+ {0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+
+ { 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20,
+ 0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x20,
+ 0x66, 0x6F, 0x72, 0x20, 0x00, 0x31, 0x00, 0x00 },
+
+ { 0xcc, 0xd1, 0x73, 0xff, 0xab, 0x20, 0x39, 0xf4,
+ 0xac, 0xd8, 0xae, 0xfd, 0xdf, 0xd8, 0xa1, 0xeb,
+ 0x46, 0x8e, 0x91, 0x15, 0x78, 0x88, 0xba, 0x68,
+ 0x1d, 0x26, 0x93, 0x97, 0xf7, 0xfe, 0x62, 0xb4 }
+ },
+
+
+};
+
+struct des_tv des_cbc_dec_tv_template[] = {
+
+ /* FIPS Pub 81 */
+ {
+ 8, 0,
+
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+ { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef },
+ { 0xe5, 0xc7, 0xcd, 0xde, 0x87, 0x2b, 0xf2, 0x7c },
+ { 0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74 },
+ },
+
+ {
+ 8, 0,
+
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+ { 0xe5, 0xc7, 0xcd, 0xde, 0x87, 0x2b, 0xf2, 0x7c },
+ { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
+ { 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20 },
+ },
+
+ {
+ 8, 0,
+
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+ { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
+ { 0x68, 0x37, 0x88, 0x49, 0x9a, 0x7c, 0x05, 0xf6 },
+ { 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20 },
+ },
+
+ /* Copy of above, for chunk testing */
+
+ {
+ 8, 0,
+
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+ { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
+ { 0x68, 0x37, 0x88, 0x49, 0x9a, 0x7c, 0x05, 0xf6 },
+ { 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20 },
+ },
+};
+
+
+
+#endif /* _CRYPTO_TCRYPT_H */
+