Commit b99b66de authored by James Morris's avatar James Morris

[CRYPTO]: Add initial crypto api subsystem.

parent ecf2c214
......@@ -209,7 +209,7 @@ endif
include arch/$(ARCH)/Makefile
core-y += kernel/ mm/ fs/ ipc/ security/
core-y += kernel/ mm/ fs/ ipc/ security/ crypto/
SUBDIRS += $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
$(core-y) $(core-m) $(drivers-y) $(drivers-m) \
......
......@@ -398,4 +398,5 @@ fi
endmenu
source security/Config.in
source crypto/Config.in
source lib/Config.in
......@@ -553,4 +553,5 @@ dep_bool ' Kernel low-level debugging messages via UART2' CONFIG_DEBUG_CLPS71
endmenu
source security/Config.in
source crypto/Config.in
source lib/Config.in
......@@ -229,4 +229,5 @@ fi
endmenu
source security/Config.in
source crypto/Config.in
source lib/Config.in
......@@ -477,6 +477,7 @@ fi
endmenu
source security/Config.in
source crypto/Config.in
source lib/Config.in
if [ "$CONFIG_SMP" = "y" ]; then
......
......@@ -288,3 +288,4 @@ fi
endmenu
source security/Config.in
source crypto/Config.in
......@@ -547,4 +547,5 @@ fi
endmenu
source security/Config.in
source crypto/Config.in
source lib/Config.in
......@@ -497,4 +497,5 @@ fi
endmenu
source security/Config.in
source crypto/Config.in
source lib/Config.in
......@@ -251,4 +251,5 @@ fi
endmenu
source security/Config.in
source crypto/Config.in
source lib/Config.in
......@@ -195,4 +195,5 @@ bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
endmenu
source security/Config.in
source crypto/Config.in
source lib/Config.in
......@@ -625,4 +625,5 @@ fi
endmenu
source security/Config.in
source crypto/Config.in
......@@ -207,4 +207,5 @@ fi
endmenu
source security/Config.in
source crypto/Config.in
source lib/Config.in
......@@ -76,4 +76,5 @@ bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
endmenu
source security/Config.in
source crypto/Config.in
source lib/Config.in
......@@ -80,4 +80,5 @@ bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
endmenu
source security/Config.in
source crypto/Config.in
source lib/Config.in
......@@ -369,4 +369,5 @@ fi
endmenu
source security/Config.in
source crypto/Config.in
source lib/Config.in
......@@ -252,4 +252,5 @@ bool 'Spinlock debugging' CONFIG_DEBUG_SPINLOCK
endmenu
source security/Config.in
source crypto/Config.in
source lib/Config.in
......@@ -295,4 +295,5 @@ fi
endmenu
source security/Config.in
source crypto/Config.in
source lib/Config.in
......@@ -237,4 +237,5 @@ fi
endmenu
source security/Config.in
source crypto/Config.in
source lib/Config.in
#
# 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.
#
# 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
#
# 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
/*
* 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 Mller.
*
* 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);
/*
* 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();
}
}
/*
* 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;
}
/*
* 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 Slensminde <gisle@ii.uib.no>
* Copyright (C) 2001 Niels Mller.
* 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
/*
* 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;
}
/*
* 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 */
/*
* 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");
/*
* 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");
/*
* 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>");
/*
* 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 */
......@@ -14,16 +14,17 @@
enum km_type {
D(0) KM_BOUNCE_READ,
D(1) KM_SKB_SUNRPC_DATA,
D(2) KM_SKB_DATA_SOFTIRQ,
D(3) KM_USER0,
D(4) KM_USER1,
D(5) KM_BIO_SRC_IRQ,
D(6) KM_BIO_DST_IRQ,
D(7) KM_PTE0,
D(8) KM_PTE1,
D(9) KM_IRQ0,
D(10) KM_IRQ1,
D(11) KM_TYPE_NR
D(2) KM_CRYPTO,
D(3) KM_SKB_DATA_SOFTIRQ,
D(4) KM_USER0,
D(5) KM_USER1,
D(6) KM_BIO_SRC_IRQ,
D(7) KM_BIO_DST_IRQ,
D(8) KM_PTE0,
D(9) KM_PTE1,
D(10) KM_IRQ0,
D(11) KM_IRQ1,
D(12) KM_TYPE_NR
};
#undef D
......
......@@ -12,17 +12,18 @@
enum km_type {
D(0) KM_BOUNCE_READ,
D(1) KM_SKB_SUNRPC_DATA,
D(2) KM_SKB_DATA_SOFTIRQ,
D(3) KM_USER0,
D(4) KM_USER1,
D(5) KM_BIO_SRC_IRQ,
D(6) KM_BIO_DST_IRQ,
D(7) KM_PTE0,
D(8) KM_PTE1,
D(9) KM_PTE2,
D(10) KM_IRQ0,
D(11) KM_IRQ1,
D(12) KM_TYPE_NR
D(2) KM_CRYPTO,
D(3) KM_SKB_DATA_SOFTIRQ,
D(4) KM_USER0,
D(5) KM_USER1,
D(6) KM_BIO_SRC_IRQ,
D(7) KM_BIO_DST_IRQ,
D(8) KM_PTE0,
D(9) KM_PTE1,
D(10) KM_PTE2,
D(11) KM_IRQ0,
D(12) KM_IRQ1,
D(13) KM_TYPE_NR
};
#undef D
......
......@@ -12,16 +12,17 @@
enum km_type {
D(0) KM_BOUNCE_READ,
D(1) KM_SKB_SUNRPC_DATA,
D(2) KM_SKB_DATA_SOFTIRQ,
D(3) KM_USER0,
D(4) KM_USER1,
D(5) KM_BIO_SRC_IRQ,
D(6) KM_BIO_DST_IRQ,
D(7) KM_PTE0,
D(8) KM_PTE1,
D(9) KM_IRQ0,
D(10) KM_IRQ1,
D(11) KM_TYPE_NR
D(2) KM_CRYPTO,
D(3) KM_SKB_DATA_SOFTIRQ,
D(4) KM_USER0,
D(5) KM_USER1,
D(6) KM_BIO_SRC_IRQ,
D(7) KM_BIO_DST_IRQ,
D(8) KM_PTE0,
D(9) KM_PTE1,
D(10) KM_IRQ0,
D(11) KM_IRQ1,
D(12) KM_TYPE_NR
};
#undef D
......
......@@ -5,6 +5,7 @@
enum km_type {
KM_BOUNCE_READ,
KM_SKB_SUNRPC_DATA,
KM_CRYPTO,
KM_SKB_DATA_SOFTIRQ,
KM_USER0,
KM_USER1,
......
......@@ -5,6 +5,7 @@
enum km_type {
KM_BOUNCE_READ,
KM_SKB_SUNRPC_DATA,
KM_CRYPTO,
KM_SKB_DATA_SOFTIRQ,
KM_USER0,
KM_USER1,
......
......@@ -5,6 +5,7 @@
enum km_type {
KM_BOUNCE_READ,
KM_SKB_SUNRPC_DATA,
KM_CRYPTO,
KM_SKB_DATA_SOFTIRQ,
KM_USER0,
KM_USER1,
......
......@@ -4,6 +4,7 @@
enum km_type {
KM_BOUNCE_READ,
KM_SKB_SUNRPC_DATA,
KM_CRYPTO,
KM_SKB_DATA_SOFTIRQ,
KM_USER0,
KM_USER1,
......
......@@ -8,6 +8,7 @@
enum km_type {
KM_BOUNCE_READ,
KM_SKB_SUNRPC_DATA,
KM_CRYPTO,
KM_SKB_DATA_SOFTIRQ,
KM_USER0,
KM_USER1,
......
......@@ -4,6 +4,7 @@
enum km_type {
KM_BOUNCE_READ,
KM_SKB_SUNRPC_DATA,
KM_CRYPTO,
KM_SKB_DATA_SOFTIRQ,
KM_USER0,
KM_USER1,
......
/*
* 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 Mller.
*
* 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 _LINUX_CRYPTO_H
#define _LINUX_CRYPTO_H
/*
* Crypto context flags.
*/
#define CRYPTO_WEAK_KEY_CHECK 0x0001
#define CRYPTO_WEAK_KEY 0x0008
#define CRYPTO_BAD_KEY_LEN 0x0010
#define CRYPTO_BAD_BLOCK_LEN 0x0020
#define CRYPTO_ATOMIC 0x1000
/*
* Algorithm identifiers. These may be expanded later to 64 bits
* and include vendor id info, so we can have multiple versions
* (e.g. asm, various hardware versions etc).
*
* Todo: sadb translation.
*/
#define CRYPTO_TYPE_MASK 0xf0000000
#define CRYPTO_MODE_MASK 0x0ff00000
#define CRYPTO_ALG_MASK 0x000fffff
#define CRYPTO_TYPE_CIPHER 0x00000000
#define CRYPTO_TYPE_DIGEST 0x10000000
#define CRYPTO_TYPE_COMP 0x20000000
#define CRYPTO_MODE_ECB 0x00000000
#define CRYPTO_MODE_CBC 0x00100000
#define CRYPTO_MODE_CFB 0x00200000
#define CRYPTO_MODE_CTR 0x00400000
#define CRYPTO_ALG_NULL 0x00000000
#define CRYPTO_ALG_DES (0x00000001|CRYPTO_TYPE_CIPHER)
#define CRYPTO_ALG_DES_ECB (CRYPTO_ALG_DES|CRYPTO_MODE_ECB)
#define CRYPTO_ALG_DES_CBC (CRYPTO_ALG_DES|CRYPTO_MODE_CBC)
#define CRYPTO_ALG_3DES_EDE (0x00000002|CRYPTO_TYPE_CIPHER)
#define CRYPTO_ALG_3DES_EDE_ECB (CRYPTO_ALG_3DES_EDE|CRYPTO_MODE_ECB)
#define CRYPTO_ALG_3DES_EDE_CBC (CRYPTO_ALG_3DES_EDE|CRYPTO_MODE_CBC)
#define CRYPTO_ALG_MD5 (0x00000f00|CRYPTO_TYPE_DIGEST)
#define CRYPTO_ALG_SHA1 (0x00000f01|CRYPTO_TYPE_DIGEST)
#define CRYPTO_MAX_ALG_NAME 64
#define CRYPTO_MAX_BLOCK_SIZE 16
#define cra_cipher cra_u.cipher
#define cra_digest cra_u.digest
#define cra_compress cra_u.compress
struct scatterlist;
struct cipher_alg {
size_t cia_keysize;
size_t cia_ivsize;
int (*cia_setkey)(void *ctx, const __u8 *key, size_t keylen,
int *flags);
void (*cia_encrypt)(void *ctx, __u8 *dst, __u8 *src);
void (*cia_decrypt)(void *ctx, __u8 *dst, __u8 *src);
};
struct digest_alg {
size_t dia_digestsize;
void (*dia_init)(void *ctx);
void (*dia_update)(void *ctx, const __u8 *data, size_t len);
void (*dia_final)(void *ctx, __u8 *out);
};
struct compress_alg {
void (*coa_compress)(void);
void (*coa_decompress)(void);
};
#define cra_cipher cra_u.cipher
#define cra_digest cra_u.digest
#define cra_compress cra_u.compress
struct crypto_alg {
struct list_head cra_list;
__u32 cra_id;
size_t cra_blocksize;
size_t cra_ctxsize;
char cra_name[CRYPTO_MAX_ALG_NAME];
union {
struct cipher_alg cipher;
struct digest_alg digest;
struct compress_alg compress;
} cra_u;
};
/*
* Algorithm registration interface.
*/
int crypto_register_alg(struct crypto_alg *alg);
int crypto_unregister_alg(struct crypto_alg *alg);
struct crypto_tfm;
/*
* Transformations: user-instantiated algorithms.
*/
struct cipher_tfm {
void *cit_iv;
__u32 cit_mode;
int (*cit_setkey)(struct crypto_tfm *tfm, const __u8 *key,
size_t keylen);
int (*cit_encrypt)(struct crypto_tfm *tfm,
struct scatterlist *sg, size_t nsg);
int (*cit_decrypt)(struct crypto_tfm *tfm,
struct scatterlist *sg, size_t nsg);
};
struct digest_tfm {
void (*dit_init)(struct crypto_tfm *tfm);
void (*dit_update)(struct crypto_tfm *tfm,
struct scatterlist *sg, size_t nsg);
void (*dit_final)(struct crypto_tfm *tfm, __u8 *out);
void (*dit_digest)(struct crypto_tfm *tfm, struct scatterlist *sg,
size_t nsg, __u8 *out);
void (*dit_hmac)(struct crypto_tfm *tfm, __u8 *key, size_t keylen,
struct scatterlist *sg, size_t nsg, __u8 *out);
};
struct compress_tfm {
void (*cot_compress)(struct crypto_tfm *tfm);
void (*cot_decompress)(struct crypto_tfm *tfm);
};
#define crt_cipher crt_u.cipher
#define crt_digest crt_u.digest
#define crt_compress crt_u.compress
struct crypto_tfm {
void *crt_ctx;
int crt_flags;
union {
struct cipher_tfm cipher;
struct digest_tfm digest;
struct compress_tfm compress;
} crt_u;
struct crypto_alg *__crt_alg;
};
/*
* Finds specified algorithm, allocates and returns a transform for it.
* Will try an load a module based on the name if not present
* in the kernel. Increments its algorithm refcount.
*/
struct crypto_tfm *crypto_alloc_tfm(__u32 id);
/*
* Frees the transform and decrements its algorithm's recount.
*/
void crypto_free_tfm(struct crypto_tfm *tfm);
/*
* API wrappers.
*/
static inline void crypto_digest_init(struct crypto_tfm *tfm)
{
tfm->crt_digest.dit_init(tfm);
}
static inline void crypto_digest_update(struct crypto_tfm *tfm,
struct scatterlist *sg, size_t nsg)
{
tfm->crt_digest.dit_update(tfm, sg, nsg);
}
static inline void crypto_digest_final(struct crypto_tfm *tfm, __u8 *out)
{
tfm->crt_digest.dit_final(tfm, out);
}
static inline void crypto_digest_digest(struct crypto_tfm *tfm,
struct scatterlist *sg,
size_t nsg, __u8 *out)
{
tfm->crt_digest.dit_digest(tfm, sg, nsg, out);
}
static inline void crypto_digest_hmac(struct crypto_tfm *tfm, __u8 *key,
size_t keylen, struct scatterlist *sg,
size_t nsg, __u8 *out)
{
tfm->crt_digest.dit_hmac(tfm, key, keylen, sg, nsg, out);
}
static inline int crypto_cipher_setkey(struct crypto_tfm *tfm,
const __u8 *key, size_t keylen)
{
return tfm->crt_cipher.cit_setkey(tfm, key, keylen);
}
static inline int crypto_cipher_encrypt(struct crypto_tfm *tfm,
struct scatterlist *sg, size_t nsg)
{
return tfm->crt_cipher.cit_encrypt(tfm, sg, nsg);
}
static inline int crypto_cipher_decrypt(struct crypto_tfm *tfm,
struct scatterlist *sg, size_t nsg)
{
return tfm->crt_cipher.cit_decrypt(tfm, sg, nsg);
}
static inline void crypto_cipher_copy_iv(struct crypto_tfm *tfm,
__u8 *src, size_t len)
{
memcpy(tfm->crt_cipher.cit_iv, src, len);
}
static inline void crypto_comp_compress(struct crypto_tfm *tfm)
{
tfm->crt_compress.cot_compress(tfm);
}
static inline void crypto_comp_decompress(struct crypto_tfm *tfm)
{
tfm->crt_compress.cot_decompress(tfm);
}
/*
* Transform helpers which allow the underlying algorithm to be queried.
*/
static inline int crypto_tfm_id(struct crypto_tfm *tfm)
{
return tfm->__crt_alg->cra_id;
}
static inline int crypto_tfm_alg(struct crypto_tfm *tfm)
{
return tfm->__crt_alg->cra_id & CRYPTO_ALG_MASK;
}
static inline char *crypto_tfm_name(struct crypto_tfm *tfm)
{
return tfm->__crt_alg->cra_name;
}
static inline __u32 crypto_tfm_type(struct crypto_tfm *tfm)
{
return tfm->__crt_alg->cra_id & CRYPTO_TYPE_MASK;
}
static inline size_t crypto_tfm_keysize(struct crypto_tfm *tfm)
{
return tfm->__crt_alg->cra_cipher.cia_keysize;
}
static inline size_t crypto_tfm_ivsize(struct crypto_tfm *tfm)
{
return tfm->__crt_alg->cra_cipher.cia_ivsize;
}
static inline size_t crypto_tfm_blocksize(struct crypto_tfm *tfm)
{
return tfm->__crt_alg->cra_blocksize;
}
static inline size_t crypto_tfm_digestsize(struct crypto_tfm *tfm)
{
return tfm->__crt_alg->cra_digest.dia_digestsize;
}
#endif /* _LINUX_CRYPTO_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment