diff options
author | Imre Kaloz <kaloz@openwrt.org> | 2012-05-01 07:00:17 +0000 |
---|---|---|
committer | Imre Kaloz <kaloz@openwrt.org> | 2012-05-01 07:00:17 +0000 |
commit | 880de62f91bcffe7f1c7f16c9463e10853fa2524 (patch) | |
tree | 058bb1c73786a7bf492cc1a554effe4692a9b50e /target/linux/coldfire/patches/011-Add-CAU-driver-for-MCF5445x-and-MCF5441x.patch | |
parent | 7a8d12bafaf8b882d0278156e5f22d0a396687e2 (diff) | |
download | upstream-880de62f91bcffe7f1c7f16c9463e10853fa2524.tar.gz upstream-880de62f91bcffe7f1c7f16c9463e10853fa2524.tar.bz2 upstream-880de62f91bcffe7f1c7f16c9463e10853fa2524.zip |
switch to 2.6.38
SVN-Revision: 31546
Diffstat (limited to 'target/linux/coldfire/patches/011-Add-CAU-driver-for-MCF5445x-and-MCF5441x.patch')
-rw-r--r-- | target/linux/coldfire/patches/011-Add-CAU-driver-for-MCF5445x-and-MCF5441x.patch | 2514 |
1 files changed, 2514 insertions, 0 deletions
diff --git a/target/linux/coldfire/patches/011-Add-CAU-driver-for-MCF5445x-and-MCF5441x.patch b/target/linux/coldfire/patches/011-Add-CAU-driver-for-MCF5445x-and-MCF5441x.patch new file mode 100644 index 0000000000..6608246c37 --- /dev/null +++ b/target/linux/coldfire/patches/011-Add-CAU-driver-for-MCF5445x-and-MCF5441x.patch @@ -0,0 +1,2514 @@ +From 0419eb27af72bd37c3ef926169fe4db90e8690d3 Mon Sep 17 00:00:00 2001 +From: Alison Wang <b18965@freescale.com> +Date: Thu, 4 Aug 2011 09:59:41 +0800 +Subject: [PATCH 11/52] Add CAU driver for MCF5445x and MCF5441x + +Add CAU driver support for MCF5445x and MCF5441x. + +Signed-off-by: Alison Wang <b18965@freescale.com> +--- + crypto/testmgr.c | 13 +- + drivers/crypto/Kconfig | 65 +++ + drivers/crypto/Makefile | 5 + + drivers/crypto/mcfcau-aes.c | 367 ++++++++++++++++ + drivers/crypto/mcfcau-des.c | 525 +++++++++++++++++++++++ + drivers/crypto/mcfcau-md5.c | 972 ++++++++++++++++++++++++++++++++++++++++++ + drivers/crypto/mcfcau-sha1.c | 331 ++++++++++++++ + drivers/crypto/mcfcau.c | 33 ++ + drivers/crypto/mcfcau.h | 101 +++++ + 9 files changed, 2410 insertions(+), 2 deletions(-) + create mode 100644 drivers/crypto/mcfcau-aes.c + create mode 100644 drivers/crypto/mcfcau-des.c + create mode 100644 drivers/crypto/mcfcau-md5.c + create mode 100644 drivers/crypto/mcfcau-sha1.c + create mode 100644 drivers/crypto/mcfcau.c + create mode 100644 drivers/crypto/mcfcau.h + +--- a/crypto/testmgr.c ++++ b/crypto/testmgr.c +@@ -705,6 +705,7 @@ static int test_cipher(struct crypto_cip + else + e = "decryption"; + ++ printk(KERN_INFO "%s testing %s %s\n", __func__, algo, e); + j = 0; + for (i = 0; i < tcount; i++) { + if (template[i].np) +@@ -750,7 +751,9 @@ static int test_cipher(struct crypto_cip + hexdump(q, template[i].rlen); + ret = -EINVAL; + goto out; +- } ++ } else ++ printk(KERN_INFO "alg: cipher: Test %d pass " ++ "on %s for %s\n", j, e, algo); + } + + ret = 0; +@@ -785,6 +788,7 @@ static int test_skcipher(struct crypto_a + else + e = "decryption"; + ++ printk(KERN_INFO "%s testing %s %s\n", __func__, algo, e); + init_completion(&result.completion); + + req = ablkcipher_request_alloc(tfm, GFP_KERNEL); +@@ -863,10 +867,13 @@ static int test_skcipher(struct crypto_a + hexdump(q, template[i].rlen); + ret = -EINVAL; + goto out; +- } ++ } else ++ printk(KERN_INFO "alg: skcipher: Test %d " ++ "pass on %s for %s\n", j, e, algo); + } + } + ++ printk(KERN_INFO "\ntesting %s %s across pages (chunking)\n", algo, e); + j = 0; + for (i = 0; i < tcount; i++) { + +@@ -2514,6 +2521,8 @@ int alg_test(const char *driver, const c + int j; + int rc; + ++ printk(KERN_INFO "\ntesting %s\n", alg); ++ + if ((type & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_CIPHER) { + char nalg[CRYPTO_MAX_ALG_NAME]; + +--- a/drivers/crypto/Kconfig ++++ b/drivers/crypto/Kconfig +@@ -61,6 +61,71 @@ config CRYPTO_DEV_GEODE + To compile this driver as a module, choose M here: the module + will be called geode-aes. + ++config CRYPTO_DEV_MCFCAU ++ bool "Support for Freescale Coldfire Cryptographic Acceleration Unit (CAU)" ++ depends on M5445X || M5441X ++ select CRYPTO_ALGAPI ++ help ++ The cryptographic acceleration unit (CAU) is a ColdFire coprocessor ++ implementing a set of specialized operations in hardware. For example, ++ you can find it on MCF5445X, or M5441X. ++ ++ Say Y here if you want to use CAU. ++ ++config CRYPTO_DEV_MCFCAU_DES ++ tristate "DES and Triple DES cipher algorithms (coldfire)" ++ depends on CRYPTO_DEV_MCFCAU ++ select CRYPTO_ALGAPI ++ select CRYPTO_BLKCIPHER ++ help ++ DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3). ++ ++ Say 'Y' here to use the CAU coprocessor for ++ the CryptoAPI DES and 3DES alogrithms. ++ ++ To compile this driver as a module, choose M here: the module ++ will be called mcfcau-des. ++ ++config CRYPTO_DEV_MCFCAU_AES ++ tristate "AES cipher algorithm (coldfire)" ++ depends on CRYPTO_DEV_MCFCAU ++ select CRYPTO_ALGAPI ++ select CRYPTO_BLKCIPHER ++ help ++ AES cipher algorithm (FIPS 197). ++ ++ Say 'Y' here to use the CAU coprocessor for ++ the CryptoAPI AES alogrithm. ++ ++ To compile this driver as a module, choose M here: the module ++ will be called mcfcau-aes. ++ ++config CRYPTO_DEV_MCFCAU_MD5 ++ tristate "MD5 digest algorithm (coldfire)" ++ depends on CRYPTO_DEV_MCFCAU ++ select CRYPTO_ALGAPI ++ help ++ MD5 message digest algorithm (RFC1321). ++ ++ Say 'Y' here to use the CAU coprocessor for ++ the CryptoAPI MD5 alogrithm. ++ ++ To compile this driver as a module, choose M here: ++ the module will be called mcfcau-md5. ++ ++config CRYPTO_DEV_MCFCAU_SHA1 ++ tristate "SHA1 digest algorithm (coldfire)" ++ depends on CRYPTO_DEV_MCFCAU ++ select CRYPTO_ALGAPI ++ help ++ SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2). ++ ++ Say 'Y' here to use the CAU coprocessor for ++ the CryptoAPI SHA1 alogrithm. ++ ++ To compile this driver as a module, choose M here: the module ++ will be called mcfcau-sha1. ++ + config ZCRYPT + tristate "Support for PCI-attached cryptographic adapters" + depends on S390 +--- a/drivers/crypto/Makefile ++++ b/drivers/crypto/Makefile +@@ -7,6 +7,11 @@ obj-$(CONFIG_CRYPTO_DEV_HIFN_795X) += hi + obj-$(CONFIG_CRYPTO_DEV_MV_CESA) += mv_cesa.o + obj-$(CONFIG_CRYPTO_DEV_TALITOS) += talitos.o + obj-$(CONFIG_CRYPTO_DEV_IXP4XX) += ixp4xx_crypto.o ++obj-$(CONFIG_CRYPTO_DEV_MCFCAU) += mcfcau.o ++obj-$(CONFIG_CRYPTO_DEV_MCFCAU_DES) += mcfcau-des.o ++obj-$(CONFIG_CRYPTO_DEV_MCFCAU_AES) += mcfcau-aes.o ++obj-$(CONFIG_CRYPTO_DEV_MCFCAU_MD5) += mcfcau-md5.o ++obj-$(CONFIG_CRYPTO_DEV_MCFCAU_SHA1) += mcfcau-sha1.o + obj-$(CONFIG_CRYPTO_DEV_PPC4XX) += amcc/ + obj-$(CONFIG_CRYPTO_DEV_OMAP_SHAM) += omap-sham.o + obj-$(CONFIG_CRYPTO_DEV_OMAP_AES) += omap-aes.o +--- /dev/null ++++ b/drivers/crypto/mcfcau-aes.c +@@ -0,0 +1,367 @@ ++/*************************************************************************** ++ * mcfcau-aes.c - Implementation of AES Cipher Algorithm ++ * for Freescale ColdFire Cryptographic Acceleration Unit (CAU). ++ * ++ * Copyright (C) 2007-2011 Freescale Semiconductor Inc. All Rights Reserved. ++ * Author: Andrey Butok ++ * Shrek Wu B16972@freescale.com ++ * ++ * NOTE: You can find the ColdFire CAU module on MCF5445X and MCF52235. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software Foundation, ++ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ *************************************************************************** ++ * Changes: ++ * v0.01 17 September 2007 Andrey Butok ++ * Initial Release - developed on 2.6.20 Linux kernel. ++ */ ++ ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/types.h> ++#include <linux/errno.h> ++#include <linux/crypto.h> ++ ++/* ++#undef DEBUG ++#define DEBUG 1 ++*/ ++ ++#include "mcfcau.h" ++ ++#define MCFCAU_AES_MIN_KEY_SIZE (16) ++#define MCFCAU_AES_MAX_KEY_SIZE (32) ++#define MCFCAU_AES_BLOCK_SIZE (16) ++ ++#define MCFCAU_AES_DRIVER_DESC "AES ColdFire CAU driver" ++#define MCFCAU_AES_DRIVER_VERSION "v0.01" ++ ++struct mcfcau_aes_ctx { ++ int Nr_1; ++ u32 buf[120]; ++ u32 buf_tmp[16]; ++}; ++ ++static u32 mcfcau_rco_tab[10] ++ = { 0x01000000, 0x02000000, 0x04000000, 0x08000000, ++ 0x10000000, 0x20000000, 0x40000000, 0x80000000, ++ 0x1b000000, 0x36000000}; ++ ++int mcfcau_aes_setkey(struct crypto_tfm *tfm, const u8 *in_key, ++ unsigned int key_len) ++{ ++ struct mcfcau_aes_ctx *ctx = crypto_tfm_ctx(tfm); ++ const u32 *key = (const u32 *)in_key; ++ u32 *flags = &tfm->crt_flags; ++ u32 i; ++ u32 *key_sch = (&ctx->buf[0]); ++ u32 *temp_p, *rcon_p; ++ u32 Nx; ++ u32 Nk; ++ unsigned long iflags; ++ ++ DBG("mcfcau_aes_setkey\n"); ++ ++ if (key_len % 8) { ++ *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; ++ return -EINVAL; ++ } ++ ++ Nk = key_len>>2; ++ ++ for (i = 0; i < Nk; i++) ++ key_sch[i] = key[i]; ++ ++ ctx->Nr_1 = Nk+5; ++ ++ /* Key Expansion */ ++ temp_p = &key_sch[Nk-1]; ++ rcon_p = &mcfcau_rco_tab[0]; ++ ++ spin_lock_irqsave(&mcfcau_lock, iflags); ++ ++ asm volatile ("move.l %0, %%a1" ++ : : "m"(temp_p) : "a1"); ++ asm volatile ("move.l %0, %%a3" ++ : : "m"(rcon_p) : "a3"); ++ asm volatile ("move.l %0, %%a4" ++ : : "m"(key_sch) : "a4"); ++ ++ Nx = (Nk+7)<<2; /* (Nr+1)*Nb */ ++ ++ for (i = Nk; i < Nx; i++) { ++ /* temp = key_sch[Nk-1] */ ++ asm volatile ("cp0ld.l (%%a1)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CAA) : "a1"); ++ ++ if (i % Nk == 0) { ++ asm volatile ("moveq #8, %%d0" : : : "d0"); ++ /* CAA=RotWord(temp) */ ++ asm volatile ("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA) : "d0"); ++ /* SubWord(CAA) */ ++ asm volatile ("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_AESS+MCFCAU_CAA)); ++ /* ACC xor rcon[i/Nk] */ ++ asm volatile ("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_XOR+MCFCAU_CAA) : "a3"); ++ ++ } else if ((Nk > 6) && (i % Nk == 4)) { ++ /* SubWord(ACC) */ ++ asm volatile ("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_AESS+MCFCAU_CAA)); ++ } ++ ++ /* key_sch[i]^=key_sch[i-Nk]; store ACC to key_sch[i] */ ++ asm volatile ("cp0ld.l (%%a4)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_XOR+MCFCAU_CAA) : "a4"); ++ asm volatile ("cp0st.l %%d0,(%%a1),#1,%0" ++ : : "n"(MCFCAU_STR+MCFCAU_CAA)); ++ } ++ spin_unlock_irqrestore(&mcfcau_lock, iflags); ++ ++ return 0; ++} ++ ++ ++/* encrypt a block of text */ ++static void mcfcau_aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) ++{ ++ struct mcfcau_aes_ctx *ctx = crypto_tfm_ctx(tfm); ++ const int Nr_1 = ctx->Nr_1; ++ ++ u32 *key_sch = &(ctx->buf[0]); ++ u32 i; ++ unsigned long iflags; ++ ++ DBG("mcfcau_aes_encrypt\n"); ++ ++ spin_lock_irqsave(&mcfcau_lock, iflags); ++ asm("move.l %0, %%a1" : : "m"(in) : "a1"); ++ asm("move.l %0, %%a0" : : "m"(key_sch) : "a0"); ++ /* state=in */ ++ asm("cp0ld.l (%%a1)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA0) : "a1"); ++ asm("cp0ld.l (%%a1)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA1) : "a1"); ++ asm("cp0ld.l (%%a1)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA2) : "a1"); ++ asm("cp0ld.l (%%a1)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA3) : "a1"); ++ /* AddRoundKey() */ ++ asm("cp0ld.l (%%a0)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_XOR+MCFCAU_CA0) : "a0"); ++ asm("cp0ld.l (%%a0)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_XOR+MCFCAU_CA1) : "a0"); ++ asm("cp0ld.l (%%a0)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_XOR+MCFCAU_CA2) : "a0"); ++ asm("cp0ld.l (%%a0)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_XOR+MCFCAU_CA3) : "a0"); ++ ++ for (i = Nr_1; i > 0; i--) { ++ /* SubBytes(state) */ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_AESS+MCFCAU_CA0)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_AESS+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_AESS+MCFCAU_CA2)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_AESS+MCFCAU_CA3)); ++ /* ShiftRows(state) */ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" : : "n"(MCFCAU_AESR)); ++ /* MixColumns(state); AddRoundKey() */ ++ asm("cp0ld.l (%%a0)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_AESC+MCFCAU_CA0) : "a0"); ++ asm("cp0ld.l (%%a0)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_AESC+MCFCAU_CA1) : "a0"); ++ asm("cp0ld.l (%%a0)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_AESC+MCFCAU_CA2) : "a0"); ++ asm("cp0ld.l (%%a0)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_AESC+MCFCAU_CA3) : "a0"); ++ } ++ /* SubBytes(state)*/ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" : : "n"(MCFCAU_AESS+MCFCAU_CA0)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" : : "n"(MCFCAU_AESS+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" : : "n"(MCFCAU_AESS+MCFCAU_CA2)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" : : "n"(MCFCAU_AESS+MCFCAU_CA3)); ++ /* ShiftRows(state) */ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" : : "n"(MCFCAU_AESR)); ++ /* AddRoundKey() */ ++ asm("cp0ld.l (%%a0)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_XOR+MCFCAU_CA0) : "a0"); ++ asm("cp0ld.l (%%a0)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_XOR+MCFCAU_CA1) : "a0"); ++ asm("cp0ld.l (%%a0)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_XOR+MCFCAU_CA2) : "a0"); ++ asm("cp0ld.l (%%a0)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_XOR+MCFCAU_CA3) : "a0"); ++ /* out = state */ ++ asm("move.l %0, %%a1" : : "m"(out) : "a1"); ++ asm("cp0st.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_STR+MCFCAU_CA0) : "d0"); ++ asm("cp0st.l %%d0,%%d1,#1,%0" ++ : : "n"(MCFCAU_STR+MCFCAU_CA1) : "d1"); ++ ++ asm("move.l %%d0,(%%a1)+" : : : "a1"); ++ asm("move.l %%d1,(%%a1)+" : : : "a1"); ++ ++ asm("cp0st.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_STR+MCFCAU_CA2) : "d0"); ++ asm("cp0st.l %%d0,%%d1,#1,%0" ++ : : "n"(MCFCAU_STR+MCFCAU_CA3) : "d1"); ++ ++ asm("move.l %%d0,(%%a1)+" : : : "a1"); ++ asm("move.l %%d1,(%%a1)+" : : : "a1"); ++ spin_unlock_irqrestore(&mcfcau_lock, iflags); ++} ++ ++ ++/* decrypt a block of text */ ++static void mcfcau_aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) ++{ ++ struct mcfcau_aes_ctx *ctx = crypto_tfm_ctx(tfm); ++ u32 *key_sch = &(ctx->buf[0]); ++ u32 i; ++ unsigned long iflags; ++ const int Nr_1 = ctx->Nr_1; ++ key_sch = &key_sch[(Nr_1+2)*4]; ++ ++ DBG("mcfcau_aes_decrypt\n"); ++ ++ spin_lock_irqsave(&mcfcau_lock, iflags); ++ ++ asm("move.l %0, %%a1" : : "m"(in) : "a1"); ++ asm("move.l %0, %%a0" : : "m"(key_sch) : "a0"); ++ /* state=in */ ++ asm("cp0ld.l (%%a1)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA0) : "a1"); ++ asm("cp0ld.l (%%a1)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA1) : "a1"); ++ asm("cp0ld.l (%%a1)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA2) : "a1"); ++ asm("cp0ld.l (%%a1)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA3) : "a1"); ++ /* AddRoundKey() */ ++ asm("cp0ld.l -(%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_XOR+MCFCAU_CA3) : "a0"); ++ asm("cp0ld.l -(%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_XOR+MCFCAU_CA2) : "a0"); ++ asm("cp0ld.l -(%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_XOR+MCFCAU_CA1) : "a0"); ++ asm("cp0ld.l -(%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_XOR+MCFCAU_CA0) : "a0"); ++ ++ for (i = Nr_1; i > 0; i--) { ++ /* InvShiftRows(state) */ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_AESIR)); ++ /* InvSubBytes(state) */ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_AESIS+MCFCAU_CA3)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_AESIS+MCFCAU_CA2)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_AESIS+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_AESIS+MCFCAU_CA0)); ++ /* InvMixColumns(state); AddRoundKey() */ ++ asm("cp0ld.l -(%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_AESIC+MCFCAU_CA3) : "a0"); ++ asm("cp0ld.l -(%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_AESIC+MCFCAU_CA2) : "a0"); ++ asm("cp0ld.l -(%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_AESIC+MCFCAU_CA1) : "a0"); ++ asm("cp0ld.l -(%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_AESIC+MCFCAU_CA0) : "a0"); ++ } ++ /* InvShiftRows(state) */ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" : : "n"(MCFCAU_AESIR)); ++ /* InvSubBytes(state)*/ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" : : "n"(MCFCAU_AESIS+MCFCAU_CA3)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" : : "n"(MCFCAU_AESIS+MCFCAU_CA2)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" : : "n"(MCFCAU_AESIS+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" : : "n"(MCFCAU_AESIS+MCFCAU_CA0)); ++ /* AddRoundKey() */ ++ asm("cp0ld.l -(%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_XOR+MCFCAU_CA3) : "a0"); ++ asm("cp0ld.l -(%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_XOR+MCFCAU_CA2) : "a0"); ++ asm("cp0ld.l -(%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_XOR+MCFCAU_CA1) : "a0"); ++ asm("cp0ld.l -(%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_XOR+MCFCAU_CA0) : "a0"); ++ /* out = state */ ++ asm("move.l %0, %%a1" : : "m"(out) : "a1"); ++ asm("cp0st.l %%d0,%%d0,#1,%0" : : "n"(MCFCAU_STR+MCFCAU_CA0) : "d0"); ++ asm("cp0st.l %%d0,%%d1,#1,%0" : : "n"(MCFCAU_STR+MCFCAU_CA1) : "d1"); ++ ++ asm("move.l %%d0,(%%a1)+" : : : "a1"); ++ asm("move.l %%d1,(%%a1)+" : : : "a1"); ++ ++ asm("cp0st.l %%d0,%%d0,#1,%0" : : "n"(MCFCAU_STR+MCFCAU_CA2) : "d0"); ++ asm("cp0st.l %%d0,%%d1,#1,%0" : : "n"(MCFCAU_STR+MCFCAU_CA3) : "d1"); ++ ++ asm("move.l %%d0,(%%a1)+" : : : "a1"); ++ asm("move.l %%d1,(%%a1)+" : : : "a1"); ++ spin_unlock_irqrestore(&mcfcau_lock, iflags); ++ ++} ++ ++ ++static struct crypto_alg mcfcau_aes_alg = { ++ .cra_name = "aes", ++ .cra_driver_name = "aes-mcfcau", ++ .cra_priority = MCFCAU_CRA_PRIORITY, ++ .cra_flags = CRYPTO_ALG_TYPE_CIPHER, ++ .cra_blocksize = MCFCAU_AES_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct mcfcau_aes_ctx), ++ .cra_alignmask = 3, ++ .cra_module = THIS_MODULE, ++ .cra_list = LIST_HEAD_INIT(mcfcau_aes_alg.cra_list), ++ .cra_u = { ++ .cipher = { ++ .cia_min_keysize = MCFCAU_AES_MIN_KEY_SIZE, ++ .cia_max_keysize = MCFCAU_AES_MAX_KEY_SIZE, ++ .cia_setkey = mcfcau_aes_setkey, ++ .cia_encrypt = mcfcau_aes_encrypt, ++ .cia_decrypt = mcfcau_aes_decrypt ++ } ++ } ++}; ++ ++static int __init mcfcau_aes_init(void) ++{ ++ int ret = crypto_register_alg(&mcfcau_aes_alg); ++ ++ printk(KERN_INFO MCFCAU_AES_DRIVER_DESC " " ++ MCFCAU_AES_DRIVER_VERSION " %s.\n", ++ ret ? "failed" : "registered"); ++ return ret; ++} ++ ++static void __exit mcfcau_aes_fini(void) ++{ ++ crypto_unregister_alg(&mcfcau_aes_alg); ++ printk(KERN_INFO MCFCAU_AES_DRIVER_DESC " " ++ MCFCAU_AES_DRIVER_VERSION " unregistered.\n"); ++} ++ ++module_init(mcfcau_aes_init); ++module_exit(mcfcau_aes_fini); ++ ++MODULE_DESCRIPTION(MCFCAU_AES_DRIVER_DESC); ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_AUTHOR("Andrey Butok"); +--- /dev/null ++++ b/drivers/crypto/mcfcau-des.c +@@ -0,0 +1,525 @@ ++/*************************************************************************** ++ * mcfcau-des.c - Implementation of DES & Triple DES EDE Cipher Algorithms ++ * for Freescale ColdFire Cryptographic Acceleration Unit (CAU). ++ * ++ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved. ++ * Author: Andrey Butok ++ * Shrek Wu B16972@freescale.com ++ * ++ * NOTE: You can find the ColdFire CAU module on MCF5445X and MCF52235. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software Foundation, ++ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ *************************************************************************** ++ * Changes: ++ * v0.01 14 August 2007 Andrey Butok ++ * Initial Release - developed on 2.6.20 Linux kernel. ++ */ ++ ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/errno.h> ++#include <linux/crypto.h> ++#include <linux/types.h> ++ ++/* ++#undef DEBUG ++#define DEBUG 1 ++*/ ++ ++#include "mcfcau.h" ++ ++#define MCFCAU_DES_KEY_SIZE (8) ++#define MCFCAU_DES_EXPKEY_WORDS (32) ++#define MCFCAU_DES_BLOCK_SIZE (8) ++ ++#define MCFCAU_DES3_EDE_KEY_SIZE (3 * MCFCAU_DES_KEY_SIZE) ++#define MCFCAU_DES3_EDE_EXPKEY_WORDS (3 * MCFCAU_DES_EXPKEY_WORDS) ++#define MCFCAU_DES3_EDE_BLOCK_SIZE (MCFCAU_DES_BLOCK_SIZE) ++ ++#define MCFCAU_DES_DRIVER_DESC "DES & 3DES ColdFire CAU driver" ++#define MCFCAU_DES_DRIVER_VERSION "v0.01" ++ ++struct mcfcau_des_ctx { ++ u32 expkey[MCFCAU_DES_EXPKEY_WORDS]; ++}; ++ ++struct mcfcau_des3_ede_ctx { ++ u32 expkey[MCFCAU_DES3_EDE_EXPKEY_WORDS]; ++}; ++ ++/* DES round operations */ ++static inline void mcfcau_des_encipher(void) ++{ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_DESK)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_DESR+MCFCAU_IP+MCFCAU_KSL1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_DESR+MCFCAU_KSL2)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_DESR+MCFCAU_KSL2)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_DESR+MCFCAU_KSL2)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_DESR+MCFCAU_KSL2)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_DESR+MCFCAU_KSL2)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_DESR+MCFCAU_KSL2)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_DESR+MCFCAU_KSL1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_DESR+MCFCAU_KSL2)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_DESR+MCFCAU_KSL2)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_DESR+MCFCAU_KSL2)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_DESR+MCFCAU_KSL2)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_DESR+MCFCAU_KSL2)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_DESR+MCFCAU_KSL2)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_DESR+MCFCAU_KSL1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_DESR+MCFCAU_FP+MCFCAU_KSL1)); ++} ++ ++static inline void mcfcau_des_decipher(void) ++{ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_DESK+MCFCAU_DC)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_DESR+MCFCAU_IP+MCFCAU_KSR1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_DESR+MCFCAU_KSR2)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_DESR+MCFCAU_KSR2)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_DESR+MCFCAU_KSR2)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_DESR+MCFCAU_KSR2)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_DESR+MCFCAU_KSR2)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_DESR+MCFCAU_KSR2)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_DESR+MCFCAU_KSR1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_DESR+MCFCAU_KSR2)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_DESR+MCFCAU_KSR2)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_DESR+MCFCAU_KSR2)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_DESR+MCFCAU_KSR2)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_DESR+MCFCAU_KSR2)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_DESR+MCFCAU_KSR2)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_DESR+MCFCAU_KSR1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_DESR+MCFCAU_FP+MCFCAU_KSL1)); ++} ++ ++ ++static int mcfcau_des_setkey(struct crypto_tfm *tfm, const u8 *key_p, ++ unsigned int keylen) ++{ ++ struct mcfcau_des_ctx *dctx = crypto_tfm_ctx(tfm); ++ u32 *flags = &tfm->crt_flags; ++ u32 * key = (u32 *) key_p; ++ ++ DBG("mcfcau_des_setkey\n"); ++ ++ /* ++ * RFC2451: Weak key checks SHOULD be performed. ++ * ++ * FIPS 74: ++ * Keys having duals are keys which produce all zeros, all ones, or ++ * alternating zero-one patterns in the C and D registers ++ * after Permuted ++ * Choice 1 has operated on the key. ++ * ++ */ ++ if (*flags & CRYPTO_TFM_REQ_WEAK_KEY) { /* FIPS 74 */ ++ if (key[0] < 0xE001E00l) { ++ if (key[0] < 0x1FE01FE0) { ++ if (key[0] < 0x01E001E0) { ++ if (((key[0] == 0x01010101) && ++ (key[1] == 0x01010101)) || ++ ((key[0] == 0x011F011F) && ++ (key[1] == 0x010E010E))) ++ goto WEAK_KEY; ++ } else { ++ if (((key[0] == 0x01E001E0) && ++ (key[1] == 0x01F101F1)) || ++ ((key[0] == 0x01FE01FE) && ++ (key[1] == 0x01FE01FE))) ++ goto WEAK_KEY; ++ } ++ } else { ++ if (key[0] < 0x1F1F1F1F) { ++ if (((key[0] == 0x1FE01FE0) && ++ (key[1] == 0x0EF10EF1)) || ++ ((key[0] == 0x1F011F0l) && ++ (key[1] == 0x0E010E01))) ++ goto WEAK_KEY; ++ } else{ ++ if (((key[0] == 0x1F1F1F1F) && ++ (key[1] == 0x0E0E0E0E)) || ++ ((key[0] == 0x1FFE1FFE) && ++ (key[1] == 0x0EFE0EFE))) ++ goto WEAK_KEY; ++ } ++ } ++ } else { ++ if (key[0] < 0xFE01FE01) { ++ if (key[0] < 0xE0E0E0E0) { ++ if (((key[0] == 0xE001E00l) && ++ (key[1] == 0xF101F101)) || ++ ((key[0] == 0xE01FE01F) && ++ (key[1] == 0xF10EF10E))) ++ goto WEAK_KEY; ++ } else { ++ if (((key[0] == 0xE0E0E0E0) && ++ (key[1] == 0xF1F1F1F1)) || ++ ((key[0] == 0xE0FEE0FE) && ++ (key[1] == 0xF1FEF1FE))) ++ goto WEAK_KEY; ++ } ++ } else { ++ if (key[0] < 0xFEE0FEE0) { ++ if (((key[0] == 0xFE01FE01) && ++ (key[1] == 0xFE01FE01)) || ++ ((key[0] == 0xFE1FFE1F) && ++ (key[1] == 0xFE0EFE0E))) ++ goto WEAK_KEY; ++ } else { ++ if (((key[0] == 0xFEE0FEE0) && ++ (key[1] == 0xFEF1FEF1)) || ++ ((key[0] == 0xFEFEFEFE) ++ && (key[1] == 0xFEFEFEFE))) ++ goto WEAK_KEY; ++ } ++ } ++ } ++ } ++ memcpy(dctx->expkey, key_p, keylen); ++ return 0; ++WEAK_KEY: ++ *flags |= CRYPTO_TFM_RES_WEAK_KEY; ++ return -EINVAL; ++} ++ ++ ++void mcfcau_des_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) ++{ ++ struct mcfcau_des_ctx *ctx = crypto_tfm_ctx(tfm); ++ u32 *des_key_tmp = ctx->expkey; ++ unsigned long iflags; ++ ++ DBG("mcfcau_des_encrypt\n"); ++ ++ spin_lock_irqsave(&mcfcau_lock, iflags); ++ ++ asm("move.l %0, %%a0" : : "m"(src) : "a0"); ++ asm("move.l %0, %%a1" : : "m"(des_key_tmp) : "a1"); ++ ++ asm("cp0ld.l (%%a0)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA2) : "a0"); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA3)); ++ asm("cp0ld.l (%%a1)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA0) : "a1"); ++ asm("cp0ld.l (%%a1),%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA1)); ++ ++ mcfcau_des_encipher(); ++ ++ asm("cp0st.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_STR+MCFCAU_CA2) : "d0"); ++ asm("cp0st.l %%d0,%%d1,#1,%0" ++ : : "n"(MCFCAU_STR+MCFCAU_CA3) : "d1"); ++ asm("move.l %0, %%a1" : : "m"(dst) : "a1"); ++ asm("move.l %d0,(%a1)+"); ++ asm("move.l %d1,(%a1)"); ++ ++ spin_unlock_irqrestore(&mcfcau_lock, iflags); ++} ++ ++ ++void mcfcau_des_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) ++{ ++ struct mcfcau_des_ctx *ctx = crypto_tfm_ctx(tfm); ++ u32 *des_key_tmp = ctx->expkey; ++ unsigned long iflags; ++ ++ DBG("mcfcau_des_decrypt\n"); ++ ++ spin_lock_irqsave(&mcfcau_lock, iflags); ++ ++ asm("move.l %0, %%a0" : : "m"(src) : "a0"); ++ asm("move.l %0, %%a1" : : "m"(des_key_tmp) : "a1"); ++ ++ asm("cp0ld.l (%%a0)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA2) : "a0"); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA3)); ++ asm("cp0ld.l (%%a1)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA0) : "a1"); ++ asm("cp0ld.l (%%a1),%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA1)); ++ ++ mcfcau_des_decipher(); ++ ++ asm("move.l %0, %%a1" : : "m"(dst) : "a1"); ++ asm("cp0st.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_STR+MCFCAU_CA2) : "d0"); ++ asm("cp0st.l %%d0,%%d1,#1,%0" ++ : : "n"(MCFCAU_STR+MCFCAU_CA3) : "d1"); ++ asm("move.l %d0,(%a1)+"); ++ asm("move.l %d1,(%a1)"); ++ ++ spin_unlock_irqrestore(&mcfcau_lock, iflags); ++} ++ ++ ++/* ++ * RFC2451: ++ * ++ * For DES-EDE3, there is no known need to reject weak or ++ * complementation keys. Any weakness is obviated by the use of ++ * multiple keys. ++ * ++ * However, if the first two or last two independent 64-bit keys are ++ * equal (k1 == k2 or k2 == k3), then the DES3 operation is simply the ++ * same as DES. Implementers MUST reject keys that exhibit this ++ * property. ++ * ++ */ ++ ++static int mcfcau_des3_ede_setkey( ++ struct crypto_tfm *tfm, const u8 *key_p, unsigned int keylen) ++{ ++ const u32 *key = (const u32 *)key_p; ++ struct mcfcau_des3_ede_ctx *dctx = crypto_tfm_ctx(tfm); ++ u32 *flags = &tfm->crt_flags; ++ ++ DBG("mcfcau_des3_ede_setkey\n"); ++ ++ if (unlikely(!((key[0] ^ key[2]) | (key[1] ^ key[3])) || ++ !((key[2] ^ key[4]) | (key[3] ^ key[5])))) { ++ *flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED; ++ return -EINVAL; ++ } ++ ++ memcpy(dctx->expkey, key_p, keylen); ++ ++ return 0; ++} ++ ++static void mcfcau_des3_ede_encrypt( ++ struct crypto_tfm *tfm, u8 *dst, const u8 *src) ++{ ++ struct mcfcau_des3_ede_ctx *dctx = crypto_tfm_ctx(tfm); ++ const u32 *des_key_tmp = dctx->expkey; ++ unsigned long iflags; ++ ++ DBG("mcfcau_des3_ede_encrypt\n"); ++ ++ spin_lock_irqsave(&mcfcau_lock, iflags); ++ ++ /*EK1*/ ++ asm("move.l %0, %%a0" ++ : : "m"(src) : "a0"); ++ asm("move.l %0, %%a1" ++ : : "m"(des_key_tmp) : "a1"); ++ ++ asm("cp0ld.l (%%a0)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA2) : "a0"); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA3)); ++ asm("cp0ld.l (%%a1)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA0) : "a1"); ++ asm("cp0ld.l (%%a1)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA1) : "a1"); ++ ++ mcfcau_des_encipher(); ++ ++ /*DK2*/ ++ asm("cp0ld.l (%%a1)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA0) : "a1"); ++ asm("cp0ld.l (%%a1)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA1) : "a1"); ++ ++ mcfcau_des_decipher(); ++ ++ /*EK3*/ ++ asm("cp0ld.l (%%a1)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA0) : "a1"); ++ asm("cp0ld.l (%%a1),%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA1)); ++ ++ mcfcau_des_encipher(); ++ ++ asm("move.l %0, %%a1" ++ : : "m"(dst) : "a1"); ++ asm("cp0st.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_STR+MCFCAU_CA2) : "d0"); ++ asm("cp0st.l %%d0,%%d1,#1,%0" ++ : : "n"(MCFCAU_STR+MCFCAU_CA3) : "d1"); ++ asm("move.l %d0,(%a1)+"); ++ asm("move.l %d1,(%a1)"); ++ ++ spin_unlock_irqrestore(&mcfcau_lock, iflags); ++} ++ ++static void mcfcau_des3_ede_decrypt( ++ struct crypto_tfm *tfm, u8 *dst, const u8 *src) ++{ ++ struct mcfcau_des3_ede_ctx *dctx = crypto_tfm_ctx(tfm); ++ const u32 *des_key_tmp = dctx->expkey + 6 - 2; ++ unsigned long iflags; ++ ++ DBG("mcfcau_des3_ede_decrypt\n"); ++ ++ spin_lock_irqsave(&mcfcau_lock, iflags); ++ ++ /*DK3*/ ++ asm("move.l %0, %%a0" ++ : : "m"(src) : "a0"); ++ asm("move.l %0, %%a1" ++ : : "m"(des_key_tmp) : "a1"); ++ ++ asm("cp0ld.l (%%a0)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA2) : "a0"); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA3)); ++ asm("cp0ld.l (%%a1)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA0) : "a1"); ++ asm("cp0ld.l (%%a1),%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA1)); ++ ++ mcfcau_des_decipher(); ++ ++ /*EK2*/ ++ asm("suba.l #12,%a1"); /*dec key pointer*/ ++ ++ asm("cp0ld.l (%%a1)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA0) : "a1"); ++ asm("cp0ld.l (%%a1),%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA1)); ++ ++ mcfcau_des_encipher(); ++ ++ /*DK1*/ ++ asm("suba.l #12,%a1"); /*dec key pointer*/ ++ ++ asm("cp0ld.l (%%a1)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA0) : "a1"); ++ asm("cp0ld.l (%%a1),%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA1)); ++ ++ mcfcau_des_decipher(); ++ ++ asm("move.l %0, %%a1" ++ : : "m"(dst) : "a1"); ++ asm("cp0st.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_STR+MCFCAU_CA2) : "d0"); ++ asm("cp0st.l %%d0,%%d1,#1,%0" ++ : : "n"(MCFCAU_STR+MCFCAU_CA3) : "d1"); ++ asm("move.l %d0,(%a1)+"); ++ asm("move.l %d1,(%a1)"); ++ ++ spin_unlock_irqrestore(&mcfcau_lock, iflags); ++} ++ ++ ++static struct crypto_alg mcfcau_des_alg = { ++ .cra_name = "des", ++ .cra_driver_name = "des-mcfcau", ++ .cra_priority = MCFCAU_CRA_PRIORITY, ++ .cra_flags = CRYPTO_ALG_TYPE_CIPHER, ++ .cra_blocksize = MCFCAU_DES_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct mcfcau_des_ctx), ++ .cra_module = THIS_MODULE, ++ .cra_alignmask = 3, ++ .cra_list = LIST_HEAD_INIT(mcfcau_des_alg.cra_list), ++ .cra_u = { .cipher = { ++ .cia_min_keysize = MCFCAU_DES_KEY_SIZE, ++ .cia_max_keysize = MCFCAU_DES_KEY_SIZE, ++ .cia_setkey = mcfcau_des_setkey, ++ .cia_encrypt = mcfcau_des_encrypt, ++ .cia_decrypt = mcfcau_des_decrypt } } ++}; ++ ++static struct crypto_alg mcfcau_des3_ede_alg = { ++ .cra_name = "des3_ede", ++ .cra_driver_name = "des3_ede-mcfcau", ++ .cra_priority = MCFCAU_CRA_PRIORITY, ++ .cra_flags = CRYPTO_ALG_TYPE_CIPHER, ++ .cra_blocksize = MCFCAU_DES3_EDE_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct mcfcau_des3_ede_ctx), ++ .cra_module = THIS_MODULE, ++ .cra_alignmask = 3, ++ .cra_list = ++ LIST_HEAD_INIT(mcfcau_des3_ede_alg.cra_list), ++ .cra_u = { .cipher = { ++ .cia_min_keysize = MCFCAU_DES3_EDE_KEY_SIZE, ++ .cia_max_keysize = MCFCAU_DES3_EDE_KEY_SIZE, ++ .cia_setkey = mcfcau_des3_ede_setkey, ++ .cia_encrypt = mcfcau_des3_ede_encrypt, ++ .cia_decrypt = mcfcau_des3_ede_decrypt } } ++}; ++ ++MODULE_ALIAS("mcfcau_des3_ede"); ++ ++static int __init mcfcau_des_init(void) ++{ ++ int ret; ++ ++ ret = crypto_register_alg(&mcfcau_des_alg); ++ if (ret < 0) ++ goto out; ++ ++ ret = crypto_register_alg(&mcfcau_des3_ede_alg); ++ if (ret < 0) ++ crypto_unregister_alg(&mcfcau_des_alg); ++out: ++ printk(KERN_INFO MCFCAU_DES_DRIVER_DESC " " ++ MCFCAU_DES_DRIVER_VERSION " %s.\n", ++ ret ? "failed" : "registered"); ++ return ret; ++} ++ ++static void __exit mcfcau_des_exit(void) ++{ ++ crypto_unregister_alg(&mcfcau_des3_ede_alg); ++ crypto_unregister_alg(&mcfcau_des_alg); ++ ++ printk(KERN_INFO MCFCAU_DES_DRIVER_DESC " " ++ MCFCAU_DES_DRIVER_VERSION " unregistered.\n"); ++} ++ ++module_init(mcfcau_des_init); ++module_exit(mcfcau_des_exit); ++ ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms for ColdFire CAU"); ++MODULE_AUTHOR("Andrey Butok"); +--- /dev/null ++++ b/drivers/crypto/mcfcau-md5.c +@@ -0,0 +1,972 @@ ++/*************************************************************************** ++ * mcfcau-md5.c - Implementation of MD5 Message Digest Algorithm (RFC1321) ++ * for Freescale ColdFire Cryptographic Acceleration Unit (CAU). ++ * ++ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved. ++ * Author: Andrey Butok ++ * Shrek Wu B16972@freescale.com ++ * Alison Wang b18965@freescale.com ++ * ++ * NOTE: You can find the ColdFire CAU module on MCF5445X and MCF52235. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software Foundation, ++ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ *************************************************************************** ++ * Changes: ++ * v0.01 30 September 2007 Andrey Butok ++ * Initial Release - developed on 2.6.20 Linux kernel. ++ */ ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/string.h> ++#include <linux/crypto.h> ++#include <linux/types.h> ++#include <crypto/algapi.h> ++#include <crypto/hash.h> ++#include <crypto/internal/hash.h> ++#include <asm/byteorder.h> ++ ++#include "mcfcau.h" ++ ++#define MCFCAU_MD5_DIGEST_SIZE (16) ++#define MCFCAU_MD5_HMAC_BLOCK_SIZE (64) ++#define MCFCAU_MD5_BLOCK_WORDS (16) ++#define MCFCAU_MD5_HASH_WORDS (4) ++ ++#define MCFCAU_MD5_DRIVER_DESC "MD5 ColdFire CAU driver" ++#define MCFCAU_MD5_DRIVER_VERSION "v0.01" ++ ++ ++struct mcfcau_md5_ctx { ++ u32 hash[MCFCAU_MD5_HASH_WORDS]; ++ u32 block[MCFCAU_MD5_BLOCK_WORDS]; ++ u64 byte_count; ++}; ++ ++u32 mcfcau_md5_t[64] = {0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, ++ 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, ++ 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, ++ 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, ++ 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, ++ 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, ++ 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, ++ 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, ++ 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, ++ 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, ++ 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, ++ 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, ++ 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, ++ 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, ++ 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, ++ 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391}; ++ ++ ++ ++static void mcfcau_md5_transform(u32 *hash, u32 const *in) ++{ ++ int i; ++ u32 *md5_t_p = &mcfcau_md5_t[0]; ++ unsigned long iflags; ++ ++ spin_lock_irqsave(&mcfcau_lock, iflags); ++ asm("move.l %0, %%a1" : : "m"(hash) : "a1"); ++ asm("cp0ld.l (%%a1)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CAA) : "a1");/*a*/ ++ asm("cp0ld.l (%%a1)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA1) : "a1");/*b*/ ++ asm("cp0ld.l (%%a1)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA2) : "a1");/*c*/ ++ asm("cp0ld.l (%%a1)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA3) : "a1");/*d*/ ++ asm("move.l %0, %%a0" : : "m"(in) : "a0"); /* X[] */ ++ asm("move.l %0, %%a3" : : "m"(md5_t_p) : "a3"); /* T[] */ ++ ++ /* Round 1 */ ++ asm("moveq.l #7, %%d4" : : : "d4"); /* for rotating by 7 */ ++ asm("moveq.l #12, %%d5" : : : "d5"); /* for rotating by 12 */ ++ asm("moveq.l #17, %%d6" : : : "d6"); /* for rotating by 17 */ ++ asm("moveq.l #22, %%d7" : : : "d7"); /* for rotating by 22 */ ++ ++ for (i = 0; i < 4; i++) { ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFF)); ++ /* a+F(b,c,d) */ ++ asm("cp0ld.l (%%a0)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ /* add byterev x[i] */ ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ /* add t[i] */ ++ asm("cp0ld.l %%d4,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ /* rotate by 7 */ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ /* add b */ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ /* register to register shift */ ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFF)); ++ asm("cp0ld.l (%%a0)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d5,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFF)); ++ asm("cp0ld.l (%%a0)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d6,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFF)); ++ asm("cp0ld.l (%%a0)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d7,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ }; ++ ++ ++ /* Round 2 */ ++ asm("moveq.l #5, %%d4" : : : "d4"); /* for rotating by 5 */ ++ asm("moveq.l #9, %%d5" : : : "d5"); /* for rotating by 9 */ ++ asm("moveq.l #14, %%d6" : : : "d6"); /* for rotating by 14 */ ++ asm("moveq.l #20, %%d7" : : : "d7"); /* for rotating by 20 */ ++ ++ asm("lea -60(%%a0),%%a0" : : : "a0"); ++ ++ for (i = 0; i < 2; i++) { ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFG)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea 20(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d4,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFG)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea 20(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d5,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFG)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea -44(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d6,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFG)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea 20(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d7,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ }; ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFG)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea 20(%%a0),%%a0" ++ : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d4,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFG)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea -44(%%a0),%%a0" ++ : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d5,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFG)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea 20(%%a0),%%a0" ++ : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d6,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFG)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea 20(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d7,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFG)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea -44(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d4,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFG)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea 20(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d5,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFG)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea 20(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d6,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFG)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea -28(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d7,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ ++ /* Round 3 */ ++ asm("moveq.l #4, %%d4" : : : "d4"); /* for rotating by 5 */ ++ asm("moveq.l #11, %%d5" : : : "d5"); /* for rotating by 9 */ ++ asm("moveq.l #16, %%d6" : : : "d6"); /* for rotating by 14 */ ++ asm("moveq.l #23, %%d7" : : : "d7"); /* for rotating by 20 */ ++ ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFH)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea 12(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d4,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFH)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea 12(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d5,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFH)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea 12(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d6,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFH)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea -52(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d7,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFH)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea 12(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d4,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFH)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea 12(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d5,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFH)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea 12(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d6,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFH)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea 12(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d7,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFH)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea -52(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d4,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFH)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea 12(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d5,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFH)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea 12(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d6,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFH)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea 12(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d7,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFH)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea 12(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d4,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFH)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea 12(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d5,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFH)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea -52(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d6,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFH)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea -8(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d7,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ /* Round 4 */ ++ asm("moveq.l #6, %%d4" : : : "d4"); /* for rotating by 6 */ ++ asm("moveq.l #10, %%d5" : : : "d5"); /* for rotating by 10 */ ++ asm("moveq.l #15, %%d6" : : : "d6"); /* for rotating by 15 */ ++ asm("moveq.l #21, %%d7" : : : "d7"); /* for rotating by 21 */ ++ ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFI)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea 28(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d4,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFI)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea 28(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d5,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFI)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea -36(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d6,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFI)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea 28(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d7,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFI)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea -36(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d4,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFI)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea 28(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d5,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFI)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea -36(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d6,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFI)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea 28(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d7,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFI)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea 28(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d4,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFI)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea -36(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d5,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFI)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea 28(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d6,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFI)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea -36(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d7,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFI)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea 28(%%a0),%%a0" ++ : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d4,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFI)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea -36(%%a0),%%a0" ++ : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d5,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFI)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea 28(%%a0),%%a0" ++ : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d6,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFI)); ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_RADR+MCFCAU_CAA) : "a0"); ++ asm("lea 28(%%a0),%%a0" : : : "a0"); ++ asm("cp0ld.l (%%a3)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a3"); ++ asm("cp0ld.l %%d7,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA1)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MDS)); ++ ++ ++ asm("move.l %0, %%a1" : : "m"(hash) : "a1"); ++ ++ asm("cp0ld.l (%%a1)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a1");/*a*/ ++ asm("cp0ld.l (%%a1)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CA1) : "a1");/*b*/ ++ asm("cp0ld.l (%%a1)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CA2) : "a1");/*c*/ ++ asm("cp0ld.l (%%a1)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CA3) : "a1");/*d*/ ++ ++ asm("cp0st.l %%d0,-(%%a1),#1,%0" ++ : : "n"(MCFCAU_STR+MCFCAU_CA3) : "a1");/*d*/ ++ asm("cp0st.l %%d0,-(%%a1),#1,%0" ++ : : "n"(MCFCAU_STR+MCFCAU_CA2) : "a1");/*c*/ ++ asm("cp0st.l %%d0,-(%%a1),#1,%0" ++ : : "n"(MCFCAU_STR+MCFCAU_CA1) : "a1");/*b*/ ++ asm("cp0st.l %%d0,-(%%a1),#1,%0" ++ : : "n"(MCFCAU_STR+MCFCAU_CAA) : "a1");/*a*/ ++ spin_unlock_irqrestore(&mcfcau_lock, iflags); ++} ++ ++static inline void le32_to_cpu_array(u32 *buf, unsigned int words) ++{ ++ while (words--) { ++ __le32_to_cpus(buf); ++ buf++; ++ } ++} ++ ++static inline void cpu_to_le32_array(u32 *buf, unsigned int words) ++{ ++ while (words--) { ++ __cpu_to_le32s(buf); ++ buf++; ++ } ++} ++ ++static int mcfcau_md5_initialization(struct shash_desc *desc) ++{ ++ struct mcfcau_md5_ctx *mctx = shash_desc_ctx(desc); ++ ++ DBG("mcfcau_md5_initialization\n"); ++ mctx->hash[0] = 0x67452301; ++ mctx->hash[1] = 0xefcdab89; ++ mctx->hash[2] = 0x98badcfe; ++ mctx->hash[3] = 0x10325476; ++ mctx->byte_count = 0; ++ ++ return 0; ++} ++ ++static int mcfcau_md5_update(struct shash_desc *desc, ++ const u8 *data, unsigned int len) ++{ ++ struct mcfcau_md5_ctx *mctx = shash_desc_ctx(desc); ++ const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f); ++ ++ DBG("mcfcau_md5_update\n"); ++ mctx->byte_count += len; ++ ++ if (avail > len) { ++ memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), ++ data, len); ++ } else { ++ memcpy((char *)mctx->block + ++ (sizeof(mctx->block) - avail), data, avail); ++ ++ mcfcau_md5_transform(mctx->hash, mctx->block); ++ data += avail; ++ len -= avail; ++ ++ while (len >= sizeof(mctx->block)) { ++ memcpy(mctx->block, data, sizeof(mctx->block)); ++ mcfcau_md5_transform(mctx->hash, mctx->block); ++ data += sizeof(mctx->block); ++ len -= sizeof(mctx->block); ++ } ++ ++ memcpy(mctx->block, data, len); ++ } ++ ++ return 0; ++} ++ ++static int mcfcau_md5_final(struct shash_desc *desc, u8 *out) ++{ ++ struct mcfcau_md5_ctx *mctx = shash_desc_ctx(desc); ++ const unsigned int offset = mctx->byte_count & 0x3f; ++ char *p = (char *)mctx->block + offset; ++ int padding = 56 - (offset + 1); ++ ++ DBG("mcfcau_md5_final\n"); ++ ++ *p++ = 0x80; ++ if (padding < 0) { ++ memset(p, 0x00, padding + sizeof(u64)); ++ mcfcau_md5_transform(mctx->hash, mctx->block); ++ 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[14], 2); ++ ++ mcfcau_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)); ++ ++ return 0; ++} ++ ++static struct shash_alg mcfcau_md5_alg = { ++ .init = mcfcau_md5_initialization, ++ .update = mcfcau_md5_update, ++ .final = mcfcau_md5_final, ++ .digestsize = MCFCAU_MD5_DIGEST_SIZE, ++ .descsize = sizeof(struct mcfcau_md5_ctx), ++ .statesize = sizeof(struct mcfcau_md5_ctx), ++ .base = { ++ .cra_name = "md5", ++ .cra_driver_name = "md5-mcfcau", ++ .cra_blocksize = MCFCAU_MD5_HMAC_BLOCK_SIZE, ++ .cra_flags = CRYPTO_ALG_TYPE_SHASH, ++ .cra_priority = MCFCAU_CRA_PRIORITY, ++ .cra_module = THIS_MODULE ++ } ++}; ++ ++static int __init mcfcau_md5_init(void) ++{ ++ int ret = 0; ++ ++ ret = crypto_register_shash(&mcfcau_md5_alg); ++ printk(KERN_INFO MCFCAU_MD5_DRIVER_DESC " " ++ MCFCAU_MD5_DRIVER_VERSION " %s.\n", ++ ret ? "failed" : "registered"); ++ return ret; ++} ++ ++static void __exit mcfcau_md5_exit(void) ++{ ++ crypto_unregister_shash(&mcfcau_md5_alg); ++ printk(KERN_INFO MCFCAU_MD5_DRIVER_DESC " " ++ MCFCAU_MD5_DRIVER_VERSION " unregistered.\n"); ++} ++ ++module_init(mcfcau_md5_init); ++module_exit(mcfcau_md5_exit); ++ ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION(MCFCAU_MD5_DRIVER_DESC); ++MODULE_AUTHOR("Andrey Butok"); +--- /dev/null ++++ b/drivers/crypto/mcfcau-sha1.c +@@ -0,0 +1,331 @@ ++/*************************************************************************** ++ * mcfcau-sha1.c - Implementation of SHA1 Secure Hash Algorithm ++ * for Freescale ColdFire Cryptographic Acceleration Unit (CAU). ++ * ++ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved. ++ * Author: Andrey Butok ++ * Shrek Wu B16972@freescale.com ++ * Alison Wang b18965@freescale.com ++ * ++ * NOTE: You can find the ColdFire CAU module on MCF5445X and MCF52235. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software Foundation, ++ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ *************************************************************************** ++ * Changes: ++ * v0.01 15 October 2007 Andrey Butok ++ * Initial Release - developed on 2.6.20 Linux kernel. ++ */ ++ ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/mm.h> ++#include <linux/crypto.h> ++#include <linux/types.h> ++#include <crypto/algapi.h> ++#include <crypto/hash.h> ++#include <crypto/internal/hash.h> ++ ++#include "mcfcau.h" ++ ++#define MCFCAU_SHA1_DIGEST_WORDS (5) ++#define MCFCAU_SHA1_WORKSPACE_WORDS (80) ++ ++#define MCFCAU_SHA1_DIGEST_SIZE (20) ++#define MCFCAU_SHA1_HMAC_BLOCK_SIZE (64) ++ ++#define MCFCAU_SHA1_DRIVER_DESC "SHA1 ColdFire CAU driver" ++#define MCFCAU_SHA1_DRIVER_VERSION "v0.01" ++ ++static const u32 K[4] = {0x5A827999L, /* Rounds 0-19: sqrt(2) * 2^30 */ ++ 0x6ED9EBA1L, /* Rounds 20-39: sqrt(3) * 2^30 */ ++ 0x8F1BBCDCL, /* Rounds 40-59: sqrt(5) * 2^30 */ ++ 0xCA62C1D6L}; /* Rounds 60-79: sqrt(10) * 2^30 */ ++ ++struct mcfcau_sha1_ctx { ++ u64 count; ++ u32 state[5]; ++ u8 buffer[64]; ++}; ++ ++static void mcfcau_sha1_transform(__u32 *digest, const char *in, __u32 *W) ++{ ++ int i; ++ u32 *tmp_p; ++ unsigned long iflags; ++ ++ /* (a) Devide M(i) into 16 words W */ ++ for (i = 0; i < 16; i++) ++ W[i] = ((const u32 *)in)[i]; ++ ++ /* (b) W[i+16] = S^1(W[i+13] ^ W[i+8] ^ W[i+2] ^ W[i]) */ ++ tmp_p = &W[16]; ++ ++ spin_lock_irqsave(&mcfcau_lock, iflags); ++ asm("move.l %0, %%a0" : : "m"(tmp_p) : "a0"); ++ asm("moveq.l #1, %%d3" : : : "d3"); ++ ++ for (i = 0; i < 64; i++) { ++ asm("cp0ld.l -64(%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA0)); ++ asm("cp0ld.l -56(%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_XOR+MCFCAU_CA0)); ++ asm("cp0ld.l -32(%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_XOR+MCFCAU_CA0)); ++ asm("cp0ld.l -12(%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_XOR+MCFCAU_CA0)); ++ asm("cp0ld.l %%d3,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CA0) : "d3"); ++ asm("cp0st.l %%d0,(%%a0)+,#1,%0" ++ : : "n"(MCFCAU_STR+MCFCAU_CA0)); ++ } ++ ++ /* (c) */ ++ asm("move.l %0, %%a0" : : "m"(digest) : "a0"); ++ asm("cp0ld.l (%%a0)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA0) : "a0"); /* a */ ++ asm("cp0ld.l (%%a0)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA1) : "a0"); /* b */ ++ asm("cp0ld.l (%%a0)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA2) : "a0"); /* c */ ++ asm("cp0ld.l (%%a0)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA3) : "a0"); /* d */ ++ asm("cp0ld.l (%%a0)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_LDR+MCFCAU_CA4) : "a0"); /* e */ ++ ++ /* (d) */ ++ asm("moveq.l #5, %%d0" : : : "d0"); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_MVRA+MCFCAU_CA0)); ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ROTL+MCFCAU_CAA)); /*S^5(A)*/ ++ ++ tmp_p = (u32 *)K; ++ asm("move.l %0, %%a0" : : "m"(tmp_p) : "a0"); ++ asm("move.l %0, %%a1" : : "m"(W) : "a1"); ++ ++ for (i = 0; i < 20; i++) { ++ /* t = f1(b, c, d) + K1 + rol32(a, 5) + e + W[i]; */ ++ /* e = d; d = c; c = rol32(b, 30); b = a; a = t; */ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFC)); /*f(b,c,d)*/ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA4)); /*+e*/ ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA)); /*+K*/ ++ asm("cp0ld.l (%%a1)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a1"); /*+W*/ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_SHS)); ++ } ++ ++ asm("add.l #4,%%a0" : : : "a0"); /* update K */ ++ ++ for (; i < 40; i++) { ++ /* t = f2(b, c, d) + K2 + rol32(a, 5) + e + W[i]; */ ++ /* e = d; d = c; c = rol32(b, 30); b = a; a = t; */ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFH)); /*f(b,c,d)*/ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA4)); /*+e*/ ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA)); /*+K*/ ++ asm("cp0ld.l (%%a1)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a1"); /*+W*/ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_SHS)); ++ } ++ ++ asm("add.l #4,%%a0" : : : "a0"); /* update K */ ++ ++ for (; i < 60; i++) { ++ /* t = f3(b, c, d) + K3 + rol32(a, 5) + e + W[i]; */ ++ /* e = d; d = c; c = rol32(b, 30); b = a; a = t; */ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFM)); /*f(b,c,d)*/ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA4)); /*+e*/ ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA)); /*+K*/ ++ asm("cp0ld.l (%%a1)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a1"); /*+W*/ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_SHS)); ++ } ++ ++ asm("add.l #4,%%a0" : : : "a0"); /* update K */ ++ ++ for (; i < 80; i++) { ++ /* t = f2(b, c, d) + K4 + rol32(a, 5) + e + W[i]; */ ++ /* e = d; d = c; c = rol32(b, 30); b = a; a = t; */ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_HASH+MCFCAU_HFH)); /*f(b,c,d)*/ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADRA+MCFCAU_CA4)); /*+e*/ ++ asm("cp0ld.l (%%a0),%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA)); /*+K*/ ++ asm("cp0ld.l (%%a1)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CAA) : "a1"); /*+W*/ ++ asm("cp0ld.l %%d0,%%d0,#1,%0" ++ : : "n"(MCFCAU_SHS)); ++ } ++ ++ /* (e) */ ++ asm("move.l %0, %%a0" : : "m"(digest) : "a0"); ++ asm("cp0ld.l (%%a0)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CA0) : "a0"); /* +a */ ++ asm("cp0ld.l (%%a0)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CA1) : "a0"); /* +b */ ++ asm("cp0ld.l (%%a0)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CA2) : "a0"); /* +c */ ++ asm("cp0ld.l (%%a0)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CA3) : "a0"); /* +d */ ++ asm("cp0ld.l (%%a0)+,%%d0,#1,%0" ++ : : "n"(MCFCAU_ADR+MCFCAU_CA4) : "a0"); /* +e */ ++ ++ asm("cp0st.l %%d0,-(%%a0),#1,%0" ++ : : "n"(MCFCAU_STR+MCFCAU_CA4) : "a0"); ++ asm("cp0st.l %%d0,-(%%a0),#1,%0" ++ : : "n"(MCFCAU_STR+MCFCAU_CA3) : "a0"); ++ asm("cp0st.l %%d0,-(%%a0),#1,%0" ++ : : "n"(MCFCAU_STR+MCFCAU_CA2) : "a0"); ++ asm("cp0st.l %%d0,-(%%a0),#1,%0" ++ : : "n"(MCFCAU_STR+MCFCAU_CA1) : "a0"); ++ asm("cp0st.l %%d0,-(%%a0),#1,%0" ++ : : "n"(MCFCAU_STR+MCFCAU_CA0) : "a0"); ++ spin_unlock_irqrestore(&mcfcau_lock, iflags); ++} ++ ++static int mcfcau_sha1_init(struct shash_desc *desc) ++{ ++ struct mcfcau_sha1_ctx *sctx = shash_desc_ctx(desc); ++ static const struct mcfcau_sha1_ctx initstate = { ++ 0, ++ { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 }, ++ { 0, } ++ }; ++ ++ DBG("mcfcau_sha1_init\n"); ++ *sctx = initstate; ++ ++ return 0; ++} ++ ++static int mcfcau_sha1_update(struct shash_desc *desc, const u8 *data, ++ unsigned int len) ++{ ++ struct mcfcau_sha1_ctx *sctx = shash_desc_ctx(desc); ++ unsigned int partial, done; ++ const u8 *src; ++ ++ DBG("mcfcau_sha1_update\n"); ++ partial = sctx->count & 0x3f; ++ sctx->count += len; ++ done = 0; ++ src = data; ++ ++ if ((partial + len) > 63) { ++ u32 temp[MCFCAU_SHA1_WORKSPACE_WORDS]; ++ ++ if (partial) { ++ done = -partial; ++ memcpy(sctx->buffer + partial, data, done + 64); ++ src = sctx->buffer; ++ } ++ ++ do { ++ mcfcau_sha1_transform(sctx->state, src, temp); ++ done += 64; ++ src = data + done; ++ } while (done + 63 < len); ++ ++ memset(temp, 0, sizeof(temp)); ++ partial = 0; ++ } ++ memcpy(sctx->buffer + partial, src, len - done); ++ return 0; ++} ++ ++ ++/* Add padding and return the message digest. */ ++static int mcfcau_sha1_final(struct shash_desc *desc, u8 *out) ++{ ++ struct mcfcau_sha1_ctx *sctx = shash_desc_ctx(desc); ++ u32 *dst = (u32 *)out; ++ u32 i, index, padlen; ++ u64 bits; ++ static const u8 padding[64] = { 0x80, }; ++ ++ DBG("mcfcau_sha1_final\n"); ++ bits = sctx->count << 3; ++ ++ /* Pad out to 56 mod 64 */ ++ index = sctx->count & 0x3f; ++ padlen = (index < 56) ? (56 - index) : ((64+56) - index); ++ mcfcau_sha1_update(desc, padding, padlen); ++ ++ /* Append length */ ++ mcfcau_sha1_update(desc, (const u8 *)&bits, sizeof(bits)); ++ ++ /* Store state in digest */ ++ for (i = 0; i < 5; i++) ++ dst[i] = sctx->state[i]; ++ ++ /* Wipe context */ ++ memset(sctx, 0, sizeof *sctx); ++ ++ return 0; ++} ++ ++static struct shash_alg mcfcau_sha1_alg = { ++ .init = mcfcau_sha1_init, ++ .update = mcfcau_sha1_update, ++ .final = mcfcau_sha1_final, ++ .digestsize = MCFCAU_SHA1_DIGEST_SIZE, ++ .descsize = sizeof(struct mcfcau_sha1_ctx), ++ .statesize = sizeof(struct mcfcau_sha1_ctx), ++ .base = { ++ .cra_name = "sha1", ++ .cra_driver_name = "sha1-mcfcau", ++ .cra_priority = MCFCAU_CRA_PRIORITY, ++ .cra_flags = CRYPTO_ALG_TYPE_SHASH, ++ .cra_blocksize = MCFCAU_SHA1_HMAC_BLOCK_SIZE, ++ .cra_module = THIS_MODULE, ++ .cra_alignmask = 3, ++ } ++}; ++ ++static int __init init(void) ++{ ++ int ret = crypto_register_shash(&mcfcau_sha1_alg); ++ printk(KERN_INFO MCFCAU_SHA1_DRIVER_DESC " " ++ MCFCAU_SHA1_DRIVER_VERSION " %s.\n", ++ ret ? "failed" : "registered"); ++ return ret; ++} ++ ++static void __exit fini(void) ++{ ++ crypto_unregister_shash(&mcfcau_sha1_alg); ++ printk(KERN_INFO MCFCAU_SHA1_DRIVER_DESC " " ++ MCFCAU_SHA1_DRIVER_VERSION " unregistered.\n"); ++} ++ ++module_init(init); ++module_exit(fini); ++ ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION(MCFCAU_SHA1_DRIVER_DESC); ++MODULE_AUTHOR("Andrey Butok"); +--- /dev/null ++++ b/drivers/crypto/mcfcau.c +@@ -0,0 +1,33 @@ ++/*************************************************************************** ++ * mcfcau.c - Implementation of DES & Triple DES EDE Cipher Algorithms ++ * for Freescale ColdFire Cryptographic Acceleration Unit (CAU). ++ * ++ * Copyright (C) 2007-2011 Freescale Semiconductor Inc. All Rights Reserved. ++ * Author: Andrey Butok ++ * Shrek Wu B16972@freescale.com ++ * ++ * NOTE: You can find the ColdFire CAU module on MCF5445X and MCF52235. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software Foundation, ++ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ *************************************************************************** ++ * Changes: ++ * v0.01 28 September 2006 Andrey Butok ++ * Initial Release - developed on 2.6.20 Linux kernel. ++ */ ++#include <linux/module.h> ++ ++DEFINE_SPINLOCK(mcfcau_lock); ++EXPORT_SYMBOL(mcfcau_lock); +--- /dev/null ++++ b/drivers/crypto/mcfcau.h +@@ -0,0 +1,101 @@ ++/*************************************************************************** ++ * mcfcau.h - Common header file for Freescale ColdFire ++ * Cryptographic Acceleration Unit (CAU) drivers. ++ * ++ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved. ++ * Author: Andrey Butok ++ * Shrek Wu B16972@freescale.com ++ * ++ * NOTE: You can find the ColdFire CAU module on MCF5445X and MCF52235. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software Foundation, ++ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ *************************************************************************** ++ * Changes: ++ * v0.01 14 August 2007 Andrey Butok ++ */ ++ ++#ifndef MCFCAU_H ++#define MCFCAU_H ++ ++#include <linux/spinlock.h> ++ ++/* CAU Registers (CAx) */ ++#define MCFCAU_CASR (0x0) ++#define MCFCAU_CAA (0x1) ++#define MCFCAU_CA0 (0x2) ++#define MCFCAU_CA1 (0x3) ++#define MCFCAU_CA2 (0x4) ++#define MCFCAU_CA3 (0x5) ++#define MCFCAU_CA4 (0x6) ++#define MCFCAU_CA5 (0x7) ++ ++ /* CAU Commands */ ++#define MCFCAU_CNOP (0x000) ++#define MCFCAU_LDR (0x010) ++#define MCFCAU_STR (0x020) ++#define MCFCAU_ADR (0x030) ++#define MCFCAU_RADR (0x040) ++#define MCFCAU_ADRA (0x050) ++#define MCFCAU_XOR (0x060) ++#define MCFCAU_ROTL (0x070) ++#define MCFCAU_MVRA (0x080) ++#define MCFCAU_MVAR (0x090) ++#define MCFCAU_AESS (0x0A0) ++#define MCFCAU_AESIS (0x0B0) ++#define MCFCAU_AESC (0x0C0) ++#define MCFCAU_AESIC (0x0D0) ++#define MCFCAU_AESR (0x0E0) ++#define MCFCAU_AESIR (0x0F0) ++#define MCFCAU_DESR (0x100) ++#define MCFCAU_DESK (0x110) ++#define MCFCAU_HASH (0x120) ++#define MCFCAU_SHS (0x130) ++#define MCFCAU_MDS (0x140) ++#define MCFCAU_ILL (0x1F0) ++ ++/* DESR Fields */ ++#define MCFCAU_IP (0x08) /* initial permutation */ ++#define MCFCAU_FP (0x04) /* final permutation */ ++#define MCFCAU_KSL1 (0x00) /* key schedule left 1 bit */ ++#define MCFCAU_KSL2 (0x01) /* key schedule left 2 bits */ ++#define MCFCAU_KSR1 (0x02) /* key schedule right 1 bit */ ++#define MCFCAU_KSR2 (0x03) /* key schedule right 2 bits */ ++ ++/* DESK Field */ ++#define MCFCAU_DC (0x01) /* decrypt key schedule */ ++#define MCFCAU_CP (0x02) /* check parity */ ++ ++/* HASH Functions Codes */ ++#define MCFCAU_HFF (0x0) /* MD5 F() CA1&CA2 | ~CA1&CA3 */ ++#define MCFCAU_HFG (0x1) /* MD5 G() CA1&CA3 | CA2&~CA3 */ ++#define MCFCAU_HFH (0x2) /* MD5 H(), SHA Parity() CA1^CA2^CA3 */ ++#define MCFCAU_HFI (0x3) /* MD5 I() CA2^(CA1|~CA3) */ ++#define MCFCAU_HFC (0x4) /* SHA Ch() CA1&CA2 ^ ~CA1&CA3 */ ++#define MCFCAU_HFM (0x5) ++/* SHA Maj() CA1&CA2 ^ CA1&CA3 ^ CA2&CA3 */ ++ ++#define MCFCAU_CRA_PRIORITY (300) ++ ++extern spinlock_t mcfcau_lock; ++ ++#ifdef DEBUG ++#define DBG(fmt, args...) printk(KERN_INFO "[%s] " fmt ,\ ++ __func__, ## args) ++#else ++#define DBG(fmt, args...) do {} while (0) ++#endif ++ ++#endif |