diff options
author | James Morris <jmorris@intercode.com.au> | 2002-10-23 14:00:40 -0700 |
---|---|---|
committer | James Morris <jmorris@intercode.com.au> | 2002-10-23 14:00:40 -0700 |
commit | b99b66de129f360653bd8f37af0f16e37009899e (patch) | |
tree | 34b29e190822252e7965dcf8a9ec423d5d9d28d4 /crypto | |
parent | ecf2c2143f0865f447020144b2ee6e4181f65814 (diff) | |
download | history-b99b66de129f360653bd8f37af0f16e37009899e.tar.gz |
[CRYPTO]: Add initial crypto api subsystem.
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/Config.help | 18 | ||||
-rw-r--r-- | crypto/Config.in | 15 | ||||
-rw-r--r-- | crypto/Makefile | 15 | ||||
-rw-r--r-- | crypto/api.c | 270 | ||||
-rw-r--r-- | crypto/cipher.c | 249 | ||||
-rw-r--r-- | crypto/compress.c | 41 | ||||
-rw-r--r-- | crypto/des.c | 1215 | ||||
-rw-r--r-- | crypto/digest.c | 126 | ||||
-rw-r--r-- | crypto/internal.h | 53 | ||||
-rw-r--r-- | crypto/md5.c | 242 | ||||
-rw-r--r-- | crypto/sha1.c | 203 | ||||
-rw-r--r-- | crypto/tcrypt.c | 1152 | ||||
-rw-r--r-- | crypto/tcrypt.h | 587 |
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 */ + |