ar71xx: fix inline attribute location
[openwrt.git] / target / linux / coldfire / patches / 015-m5445x_cau_crypto.patch
1 From 67e24d4008a39fa02a4748a3abf54410b15262b3 Mon Sep 17 00:00:00 2001
2 From: Kurt Mahan <kmahan@freescale.com>
3 Date: Tue, 20 Nov 2007 10:02:16 -0700
4 Subject: [PATCH] Add Coldfire CAU crypto support for DES/3DES/AES/MD5/AES.
5
6 LTIBName: m5445x-cau-crypto
7 Signed-off-by: Kurt Mahan <kmahan@freescale.com>
8 ---
9  drivers/crypto/Kconfig       |   63 ++++
10  drivers/crypto/Makefile      |    5 +
11  drivers/crypto/mcfcau-aes.c  |  311 ++++++++++++++++++++
12  drivers/crypto/mcfcau-des.c  |  437 ++++++++++++++++++++++++++++
13  drivers/crypto/mcfcau-md5.c  |  654 ++++++++++++++++++++++++++++++++++++++++++
14  drivers/crypto/mcfcau-sha1.c |  280 ++++++++++++++++++
15  drivers/crypto/mcfcau.c      |   32 ++
16  drivers/crypto/mcfcau.h      |   98 +++++++
17  8 files changed, 1880 insertions(+), 0 deletions(-)
18  create mode 100644 drivers/crypto/mcfcau-aes.c
19  create mode 100644 drivers/crypto/mcfcau-des.c
20  create mode 100644 drivers/crypto/mcfcau-md5.c
21  create mode 100644 drivers/crypto/mcfcau-sha1.c
22  create mode 100644 drivers/crypto/mcfcau.c
23  create mode 100644 drivers/crypto/mcfcau.h
24
25 --- a/drivers/crypto/Kconfig
26 +++ b/drivers/crypto/Kconfig
27 @@ -60,6 +60,69 @@ config CRYPTO_DEV_GEODE
28           To compile this driver as a module, choose M here: the module
29           will be called geode-aes.
30  
31 +config CRYPTO_DEV_MCFCAU
32 +       bool "Support for Freescale Coldfire Cryptographic Acceleration Unit (CAU)"
33 +       depends on M54455
34 +       select CRYPTO_ALGAPI
35 +       help
36 +         The cryptographic acceleration unit (CAU) is a ColdFire coprocessor
37 +         implementing a set of specialized operations in hardware. For example, you can
38 +         find it on MCF54455.
39 +
40 +config CRYPTO_DEV_MCFCAU_DES
41 +       tristate "DES and Triple DES cipher algorithms (MCF54455)"
42 +       depends on CRYPTO_DEV_MCFCAU
43 +       select CRYPTO_ALGAPI
44 +       select CRYPTO_BLKCIPHER
45 +       help
46 +         DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3).
47 +         
48 +         Say 'Y' here to use the CAU coprocessor for 
49 +         the CryptoAPI DES and 3DES alogrithms.
50 +                 
51 +         To compile this driver as a module, choose M here: the module
52 +         will be called mcfcau-des.
53 +
54 +config CRYPTO_DEV_MCFCAU_AES
55 +       tristate "AES cipher algorithm (MCF54455)"
56 +       depends on CRYPTO_DEV_MCFCAU
57 +       select CRYPTO_ALGAPI
58 +       select CRYPTO_BLKCIPHER
59 +       help
60 +         AES cipher algorithm (FIPS 197).
61 +
62 +         Say 'Y' here to use the CAU coprocessor for
63 +         the CryptoAPI AES alogrithm.
64 +
65 +         To compile this driver as a module, choose M here: the module
66 +         will be called mcfcau-aes.
67 +
68 +config CRYPTO_DEV_MCFCAU_MD5
69 +       tristate "MD5 digest algorithm (MCF54455)"
70 +       depends on CRYPTO_DEV_MCFCAU
71 +       select CRYPTO_ALGAPI
72 +       help
73 +         MD5 message digest algorithm (RFC1321).
74 +
75 +         Say 'Y' here to use the CAU coprocessor for
76 +         the CryptoAPI MD5 alogrithm.
77 +
78 +         To compile this driver as a module, choose M here: the module
79 +         will be called mcfcau-md5.
80 +
81 +config CRYPTO_DEV_MCFCAU_SHA1
82 +       tristate "SHA1 digest algorithm (MCF54455)"
83 +       depends on CRYPTO_DEV_MCFCAU
84 +       select CRYPTO_ALGAPI
85 +       help
86 +         SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
87 +
88 +         Say 'Y' here to use the CAU coprocessor for
89 +         the CryptoAPI SHA1 alogrithm.
90 +
91 +         To compile this driver as a module, choose M here: the module
92 +         will be called mcfcau-sha1.
93 +
94  config ZCRYPT
95         tristate "Support for PCI-attached cryptographic adapters"
96         depends on S390
97 --- a/drivers/crypto/Makefile
98 +++ b/drivers/crypto/Makefile
99 @@ -2,3 +2,8 @@ obj-$(CONFIG_CRYPTO_DEV_PADLOCK_AES) += 
100  obj-$(CONFIG_CRYPTO_DEV_PADLOCK_SHA) += padlock-sha.o
101  obj-$(CONFIG_CRYPTO_DEV_GEODE) += geode-aes.o
102  obj-$(CONFIG_CRYPTO_DEV_HIFN_795X) += hifn_795x.o
103 +obj-$(CONFIG_CRYPTO_DEV_MCFCAU) += mcfcau.o
104 +obj-$(CONFIG_CRYPTO_DEV_MCFCAU_DES) += mcfcau-des.o
105 +obj-$(CONFIG_CRYPTO_DEV_MCFCAU_AES) += mcfcau-aes.o
106 +obj-$(CONFIG_CRYPTO_DEV_MCFCAU_MD5) += mcfcau-md5.o
107 +obj-$(CONFIG_CRYPTO_DEV_MCFCAU_SHA1) += mcfcau-sha1.o
108 --- /dev/null
109 +++ b/drivers/crypto/mcfcau-aes.c
110 @@ -0,0 +1,311 @@
111 + /***************************************************************************
112 + * mcfcau-aes.c - Implementation of AES Cipher Algorithm
113 + *                for Freescale ColdFire Cryptographic Acceleration Unit (CAU).
114 + *
115 + * Author: Andrey Butok
116 + * Copyright Freescale Semiconductor Inc.  2007
117 + *
118 + * NOTE: You can find the ColdFire CAU module on MCF54455 and MCF52235.
119 + *
120 + * This program is free software; you can redistribute it and/or modify it
121 + * under the terms of the GNU General Public License as published by the
122 + * Free Software Foundation; either version 2 of the License, or (at your
123 + * option) any later version.
124 + *
125 + * This program is distributed in the hope that it will be useful, but
126 + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
127 + * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
128 + * for more details.
129 + *
130 + * You should have received a copy of the GNU General Public License
131 + * along with this program; if not, write to the Free Software Foundation,
132 + * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
133 + *
134 + ***************************************************************************
135 + * Changes:
136 + * v0.01       17 September 2007       Andrey Butok
137 + *             Initial Release - developed on 2.6.20 Linux kernel.
138 + */
139 +
140 +#include <linux/module.h>
141 +#include <linux/init.h>
142 +#include <linux/types.h>
143 +#include <linux/errno.h>
144 +#include <linux/crypto.h>
145 +
146 +/*
147 +#undef DEBUG
148 +#define DEBUG 1
149 +*/
150 +
151 +#include "mcfcau.h"
152 +
153 +#define MCFCAU_AES_MIN_KEY_SIZE        (16)
154 +#define MCFCAU_AES_MAX_KEY_SIZE        (32)
155 +#define MCFCAU_AES_BLOCK_SIZE  (16)
156 +
157 +#define        MCFCAU_AES_DRIVER_DESC          "AES ColdFire CAU driver"
158 +#define        MCFCAU_AES_DRIVER_VERSION       "v0.01"
159 +
160 +struct mcfcau_aes_ctx {
161 +       int Nr_1;
162 +       u32 buf[120];
163 +       u32 buf_tmp[16];
164 +};
165 +
166 +static u32 mcfcau_rco_tab[10]={ 0x01000000, 0x02000000, 0x04000000, 0x08000000,
167 +                               0x10000000, 0x20000000, 0x40000000, 0x80000000,
168 +                               0x1b000000, 0x36000000};
169 +
170 +int mcfcau_aes_setkey(struct crypto_tfm *tfm, const u8 *in_key,
171 +                      unsigned int key_len)
172 +{
173 +       struct mcfcau_aes_ctx *ctx = crypto_tfm_ctx(tfm);
174 +       const u32 * key = (const u32 *)in_key;
175 +       u32 *flags = &tfm->crt_flags;
176 +       u32 i;
177 +       u32* key_sch = (&ctx->buf[0]);
178 +       u32 * temp_p, * rcon_p;
179 +       u32 Nx;
180 +       u32 Nk;
181 +       unsigned long iflags;
182 +
183 +       DBG("\n");
184 +
185 +       if (key_len % 8) {
186 +               *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
187 +               return -EINVAL;
188 +       }
189 +
190 +       Nk = key_len>>2;
191 +
192 +       for(i=0;i<Nk;i++){
193 +               key_sch[i] = key[i];
194 +       }
195 +
196 +       ctx->Nr_1 = Nk+5;
197 +
198 +       /* Key Expansion */
199 +       temp_p=&key_sch[Nk-1];
200 +       rcon_p=&mcfcau_rco_tab[0];
201 +
202 +       spin_lock_irqsave(&mcfcau_lock, iflags);
203 +
204 +       asm volatile ("move.l   %0, %%a1"::"m"(temp_p):"a1");
205 +       asm volatile ("move.l   %0, %%a3"::"m"(rcon_p):"a3");
206 +       asm volatile ("move.l   %0, %%a4"::"m"(key_sch):"a4");
207 +
208 +       Nx=(Nk+7)<<2; /* (Nr+1)*Nb */
209 +
210 +       for(i=Nk; i<Nx; i++)
211 +       {
212 +               /* temp = key_sch[Nk-1] */
213 +               asm volatile ("cp0ld.l  (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CAA):"a1");
214 +
215 +               if(i%Nk==0){
216 +                       asm volatile ("moveq    #8, %%d0":::"d0");
217 +                       /* CAA=RotWord(temp) */
218 +                       asm volatile ("cp0ld.l  %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA):"d0");
219 +                       /* SubWord(CAA) */
220 +                       asm volatile ("cp0ld.l  %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_AESS+MCFCAU_CAA));
221 +                       /* ACC xor rcon[i/Nk] */
222 +                       asm volatile ("cp0ld.l  (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CAA):"a3");
223 +
224 +               }else if((Nk>6) && (i%Nk ==4)){
225 +                       /* SubWord(ACC) */
226 +                       asm volatile ("cp0ld.l  %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_AESS+MCFCAU_CAA));
227 +               }
228 +
229 +               /* key_sch[i]^=key_sch[i-Nk]; store ACC to key_sch[i] */
230 +               asm volatile ("cp0ld.l  (%%a4)+,%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CAA):"a4");
231 +               asm volatile ("cp0st.l  %%d0,(%%a1),#1,%0"      ::"n"(MCFCAU_STR+MCFCAU_CAA));
232 +       }
233 +       spin_unlock_irqrestore(&mcfcau_lock, iflags);
234 +
235 +       return 0;
236 +}
237 +
238 +
239 +/* encrypt a block of text */
240 +static void mcfcau_aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
241 +{
242 +       struct mcfcau_aes_ctx *ctx = crypto_tfm_ctx(tfm);
243 +       const int Nr_1 = ctx->Nr_1;
244 +
245 +       u32* key_sch = &(ctx->buf[0]);
246 +       u32 i;
247 +       unsigned long iflags;
248 +
249 +       DBG("\n");
250 +
251 +       spin_lock_irqsave(&mcfcau_lock, iflags);
252 +       asm("move.l     %0, %%a1"::"m"(in):"a1");
253 +       asm("move.l     %0, %%a0"::"m"(key_sch):"a0");
254 +       /* state=in */
255 +       asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA0):"a1");
256 +       asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA1):"a1");
257 +       asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA2):"a1");
258 +       asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA3):"a1");
259 +       /* AddRoundKey() */
260 +       asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CA0):"a0");
261 +       asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CA1):"a0");
262 +       asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CA2):"a0");
263 +       asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CA3):"a0");
264 +
265 +       for(i=Nr_1;i>0;i--){
266 +               /* SubBytes(state) */
267 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESS+MCFCAU_CA0));
268 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESS+MCFCAU_CA1));
269 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESS+MCFCAU_CA2));
270 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESS+MCFCAU_CA3));
271 +               /* ShiftRows(state) */
272 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESR));
273 +               /* MixColumns(state); AddRoundKey() */
274 +               asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_AESC+MCFCAU_CA0):"a0");
275 +               asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_AESC+MCFCAU_CA1):"a0");
276 +               asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_AESC+MCFCAU_CA2):"a0");
277 +               asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_AESC+MCFCAU_CA3):"a0");
278 +       }
279 +       /* SubBytes(state)*/
280 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESS+MCFCAU_CA0));
281 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESS+MCFCAU_CA1));
282 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESS+MCFCAU_CA2));
283 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESS+MCFCAU_CA3));
284 +       /* ShiftRows(state) */
285 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESR));
286 +       /* AddRoundKey() */
287 +       asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CA0):"a0");
288 +       asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CA1):"a0");
289 +       asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CA2):"a0");
290 +       asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CA3):"a0");
291 +       /* out = state */
292 +       asm("move.l     %0, %%a1"               ::"m"(out):"a1");
293 +       asm("cp0st.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_STR+MCFCAU_CA0):"d0");
294 +       asm("cp0st.l    %%d0,%%d1,#1,%0"        ::"n"(MCFCAU_STR+MCFCAU_CA1):"d1");
295 +
296 +       asm("move.l     %%d0,(%%a1)+":::"a1");
297 +       asm("move.l     %%d1,(%%a1)+":::"a1");
298 +
299 +       asm("cp0st.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_STR+MCFCAU_CA2):"d0");
300 +       asm("cp0st.l    %%d0,%%d1,#1,%0"        ::"n"(MCFCAU_STR+MCFCAU_CA3):"d1");
301 +
302 +       asm("move.l     %%d0,(%%a1)+":::"a1");
303 +       asm("move.l     %%d1,(%%a1)+":::"a1");
304 +       spin_unlock_irqrestore(&mcfcau_lock, iflags);
305 +}
306 +
307 +
308 +/* decrypt a block of text */
309 +static void mcfcau_aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
310 +{
311 +       struct mcfcau_aes_ctx *ctx = crypto_tfm_ctx(tfm);
312 +       u32* key_sch = &(ctx->buf[0]);
313 +       u32 i;
314 +       unsigned long iflags;
315 +       const int Nr_1 = ctx->Nr_1;
316 +       key_sch=&key_sch[(Nr_1+2)*4];
317 +
318 +       DBG("\n");
319 +
320 +       spin_lock_irqsave(&mcfcau_lock, iflags);
321 +
322 +       asm("move.l     %0, %%a1"::"m"(in):"a1");
323 +       asm("move.l     %0, %%a0"::"m"(key_sch):"a0");
324 +       /* state=in */
325 +       asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA0):"a1");
326 +       asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA1):"a1");
327 +       asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA2):"a1");
328 +       asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA3):"a1");
329 +       /* AddRoundKey() */
330 +       asm("cp0ld.l    -(%%a0),%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CA3):"a0");
331 +       asm("cp0ld.l    -(%%a0),%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CA2):"a0");
332 +       asm("cp0ld.l    -(%%a0),%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CA1):"a0");
333 +       asm("cp0ld.l    -(%%a0),%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CA0):"a0");
334 +
335 +       for(i=Nr_1;i>0;i--){
336 +               /* InvShiftRows(state) */
337 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESIR));
338 +               /* InvSubBytes(state) */
339 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESIS+MCFCAU_CA3));
340 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESIS+MCFCAU_CA2));
341 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESIS+MCFCAU_CA1));
342 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESIS+MCFCAU_CA0));
343 +               /* InvMixColumns(state); AddRoundKey() */
344 +               asm("cp0ld.l    -(%%a0),%%d0,#1,%0"     ::"n"(MCFCAU_AESIC+MCFCAU_CA3):"a0");
345 +               asm("cp0ld.l    -(%%a0),%%d0,#1,%0"     ::"n"(MCFCAU_AESIC+MCFCAU_CA2):"a0");
346 +               asm("cp0ld.l    -(%%a0),%%d0,#1,%0"     ::"n"(MCFCAU_AESIC+MCFCAU_CA1):"a0");
347 +               asm("cp0ld.l    -(%%a0),%%d0,#1,%0"     ::"n"(MCFCAU_AESIC+MCFCAU_CA0):"a0");
348 +       }
349 +       /* InvShiftRows(state) */
350 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESIR));
351 +       /* InvSubBytes(state)*/
352 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESIS+MCFCAU_CA3));
353 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESIS+MCFCAU_CA2));
354 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESIS+MCFCAU_CA1));
355 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_AESIS+MCFCAU_CA0));
356 +       /* AddRoundKey() */
357 +       asm("cp0ld.l    -(%%a0),%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CA3):"a0");
358 +       asm("cp0ld.l    -(%%a0),%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CA2):"a0");
359 +       asm("cp0ld.l    -(%%a0),%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CA1):"a0");
360 +       asm("cp0ld.l    -(%%a0),%%d0,#1,%0"     ::"n"(MCFCAU_XOR+MCFCAU_CA0):"a0");
361 +       /* out = state */
362 +       asm("move.l     %0, %%a1"               ::"m"(out):"a1");
363 +       asm("cp0st.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_STR+MCFCAU_CA0):"d0");
364 +       asm("cp0st.l    %%d0,%%d1,#1,%0"        ::"n"(MCFCAU_STR+MCFCAU_CA1):"d1");
365 +
366 +       asm("move.l     %%d0,(%%a1)+":::"a1");
367 +       asm("move.l     %%d1,(%%a1)+":::"a1");
368 +
369 +       asm("cp0st.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_STR+MCFCAU_CA2):"d0");
370 +       asm("cp0st.l    %%d0,%%d1,#1,%0"        ::"n"(MCFCAU_STR+MCFCAU_CA3):"d1");
371 +
372 +       asm("move.l     %%d0,(%%a1)+":::"a1");
373 +       asm("move.l     %%d1,(%%a1)+":::"a1");
374 +       spin_unlock_irqrestore(&mcfcau_lock, iflags);
375 +
376 +}
377 +
378 +
379 +static struct crypto_alg mcfcau_aes_alg = {
380 +       .cra_name               =       "aes",
381 +       .cra_driver_name        =       "aes-mcfcau",
382 +       .cra_priority           =       MCFCAU_CRA_PRIORITY,
383 +       .cra_flags              =       CRYPTO_ALG_TYPE_CIPHER,
384 +       .cra_blocksize          =       MCFCAU_AES_BLOCK_SIZE,
385 +       .cra_ctxsize            =       sizeof(struct mcfcau_aes_ctx),
386 +       .cra_alignmask          =       3,
387 +       .cra_module             =       THIS_MODULE,
388 +       .cra_list               =       LIST_HEAD_INIT(mcfcau_aes_alg.cra_list),
389 +       .cra_u                  =       {
390 +               .cipher = {
391 +                       .cia_min_keysize        =       MCFCAU_AES_MIN_KEY_SIZE,
392 +                       .cia_max_keysize        =       MCFCAU_AES_MAX_KEY_SIZE,
393 +                       .cia_setkey             =       mcfcau_aes_setkey,
394 +                       .cia_encrypt            =       mcfcau_aes_encrypt,
395 +                       .cia_decrypt            =       mcfcau_aes_decrypt
396 +               }
397 +       }
398 +};
399 +
400 +static int __init mcfcau_aes_init(void)
401 +{
402 +       int ret = crypto_register_alg(&mcfcau_aes_alg);
403 +
404 +       printk(KERN_INFO MCFCAU_AES_DRIVER_DESC " "
405 +               MCFCAU_AES_DRIVER_VERSION " %s.\n",ret?"failed":"registered");
406 +       return ret;
407 +}
408 +
409 +static void __exit mcfcau_aes_fini(void)
410 +{
411 +       crypto_unregister_alg(&mcfcau_aes_alg);
412 +       printk(KERN_INFO MCFCAU_AES_DRIVER_DESC " "
413 +               MCFCAU_AES_DRIVER_VERSION " unregistered.\n");
414 +}
415 +
416 +module_init(mcfcau_aes_init);
417 +module_exit(mcfcau_aes_fini);
418 +
419 +MODULE_DESCRIPTION(MCFCAU_AES_DRIVER_DESC);
420 +MODULE_LICENSE("Dual BSD/GPL");
421 +MODULE_AUTHOR("Andrey Butok");
422 --- /dev/null
423 +++ b/drivers/crypto/mcfcau-des.c
424 @@ -0,0 +1,437 @@
425 +/***************************************************************************
426 + * mcfcau-des.c - Implementation of DES & Triple DES EDE Cipher Algorithms
427 + *                for Freescale ColdFire Cryptographic Acceleration Unit (CAU).
428 + *
429 + * Author: Andrey Butok
430 + * Copyright Freescale Semiconductor Inc.  2007
431 + *
432 + * NOTE: You can find the ColdFire CAU module on MCF54455 and MCF52235.
433 + *
434 + * This program is free software; you can redistribute it and/or modify it
435 + * under the terms of the GNU General Public License as published by the
436 + * Free Software Foundation; either version 2 of the License, or (at your
437 + * option) any later version.
438 + *
439 + * This program is distributed in the hope that it will be useful, but
440 + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
441 + * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
442 + * for more details.
443 + *
444 + * You should have received a copy of the GNU General Public License
445 + * along with this program; if not, write to the Free Software Foundation,
446 + * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
447 + *
448 + ***************************************************************************
449 + * Changes:
450 + * v0.01       14 August 2007  Andrey Butok
451 + *             Initial Release - developed on 2.6.20 Linux kernel.
452 + */
453 +
454 +#include <linux/init.h>
455 +#include <linux/module.h>
456 +#include <linux/errno.h>
457 +#include <linux/crypto.h>
458 +#include <linux/types.h>
459 +
460 +/*
461 +#undef DEBUG
462 +#define DEBUG 1
463 +*/
464 +
465 +#include "mcfcau.h"
466 +
467 +#define MCFCAU_DES_KEY_SIZE            (8)
468 +#define MCFCAU_DES_EXPKEY_WORDS                (32)
469 +#define MCFCAU_DES_BLOCK_SIZE          (8)
470 +
471 +#define MCFCAU_DES3_EDE_KEY_SIZE       (3 * MCFCAU_DES_KEY_SIZE)
472 +#define MCFCAU_DES3_EDE_EXPKEY_WORDS   (3 * MCFCAU_DES_EXPKEY_WORDS)
473 +#define MCFCAU_DES3_EDE_BLOCK_SIZE     (MCFCAU_DES_BLOCK_SIZE)
474 +
475 +#define        MCFCAU_DES_DRIVER_DESC          "DES & 3DES ColdFire CAU driver"
476 +#define        MCFCAU_DES_DRIVER_VERSION       "v0.01"
477 +
478 +struct mcfcau_des_ctx {
479 +       u32 expkey[MCFCAU_DES_EXPKEY_WORDS];
480 +};
481 +
482 +struct mcfcau_des3_ede_ctx {
483 +       u32 expkey[MCFCAU_DES3_EDE_EXPKEY_WORDS];
484 +};
485 +
486 +/* DES round operations */
487 +static inline void mcfcau_des_encipher(void)
488 +{
489 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESK));
490 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_IP+MCFCAU_KSL1));
491 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSL2));
492 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSL2));
493 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSL2));
494 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSL2));
495 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSL2));
496 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSL2));
497 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSL1));
498 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSL2));
499 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSL2));
500 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSL2));
501 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSL2));
502 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSL2));
503 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSL2));
504 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSL1));
505 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_FP+MCFCAU_KSL1));
506 +}
507 +
508 +static inline void mcfcau_des_decipher(void)
509 +{
510 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESK+MCFCAU_DC));
511 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_IP+MCFCAU_KSR1));
512 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSR2));
513 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSR2));
514 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSR2));
515 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSR2));
516 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSR2));
517 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSR2));
518 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSR1));
519 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSR2));
520 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSR2));
521 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSR2));
522 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSR2));
523 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSR2));
524 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSR2));
525 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_KSR1));
526 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"::"n"(MCFCAU_DESR+MCFCAU_FP+MCFCAU_KSL1));
527 +}
528 +
529 +
530 +static int mcfcau_des_setkey(struct crypto_tfm *tfm, const u8 *key_p,
531 +                     unsigned int keylen)
532 +{
533 +       struct mcfcau_des_ctx *dctx = crypto_tfm_ctx(tfm);
534 +       u32 *flags = &tfm->crt_flags;
535 +       u32 * key = (u32 *) key_p;
536 +
537 +       DBG("\n");
538 +
539 +       /*
540 +       * RFC2451: Weak key checks SHOULD be performed.
541 +       *
542 +       * FIPS 74:
543 +       *   Keys having duals are keys which produce all zeros, all ones, or
544 +       *   alternating zero-one patterns in the C and D registers after Permuted
545 +       *   Choice 1 has operated on the key.
546 +       *
547 +       */
548 +       if(*flags & CRYPTO_TFM_REQ_WEAK_KEY){ /* FIPS 74 */
549 +               if(key[0]<0xE001E00l){
550 +                       if(key[0]<0x1FE01FE0){
551 +                               if(key[0]<0x01E001E0){
552 +                                       if(((key[0]==0x01010101)&&(key[1]==0x01010101))||
553 +                                               ((key[0]==0x011F011F)&&(key[1]==0x010E010E)) )
554 +                                               goto WEAK_KEY;
555 +                               }
556 +                               else{
557 +                                       if(((key[0]==0x01E001E0)&&(key[1]==0x01F101F1))||
558 +                                               ((key[0]==0x01FE01FE)&&(key[1]==0x01FE01FE)) )
559 +                                               goto WEAK_KEY;
560 +                               }
561 +                       }
562 +                       else{
563 +                               if(key[0]<0x1F1F1F1F){
564 +                                       if(((key[0]==0x1FE01FE0)&&(key[1]==0x0EF10EF1))||
565 +                                               ((key[0]==0x1F011F0l)&&(key[1]==0x0E010E01)) )
566 +                                               goto WEAK_KEY;
567 +                               }
568 +                               else{
569 +                                       if(((key[0]==0x1F1F1F1F)&&(key[1]==0x0E0E0E0E))||
570 +                                               ((key[0]==0x1FFE1FFE)&&(key[1]==0x0EFE0EFE)) )
571 +                                               goto WEAK_KEY;
572 +                               }
573 +                       }
574 +               } else {
575 +                       if(key[0]<0xFE01FE01){
576 +                               if(key[0]<0xE0E0E0E0){
577 +                                       if(((key[0]==0xE001E00l)&&(key[1]==0xF101F101))||
578 +                                               ((key[0]==0xE01FE01F)&&(key[1]==0xF10EF10E)) )
579 +                                               goto WEAK_KEY;
580 +                               }
581 +                               else{
582 +                                       if(((key[0]==0xE0E0E0E0)&&(key[1]==0xF1F1F1F1))||
583 +                                               ((key[0]==0xE0FEE0FE)&&(key[1]==0xF1FEF1FE)) )
584 +                                               goto WEAK_KEY;
585 +                               }
586 +                       }
587 +                       else{
588 +                               if(key[0]<0xFEE0FEE0){
589 +                                       if(((key[0]==0xFE01FE01)&&(key[1]==0xFE01FE01))||
590 +                                               ((key[0]==0xFE1FFE1F)&&(key[1]==0xFE0EFE0E)) )
591 +                                               goto WEAK_KEY;
592 +                               }
593 +                               else{
594 +                                       if(((key[0]==0xFEE0FEE0)&&(key[1]==0xFEF1FEF1))||
595 +                                               ((key[0]==0xFEFEFEFE)&&(key[1]==0xFEFEFEFE)) )
596 +                                               goto WEAK_KEY;
597 +                               }
598 +                       }
599 +               }
600 +       }
601 +       memcpy(dctx->expkey, key_p, keylen);
602 +       return 0;
603 +WEAK_KEY:
604 +       *flags |= CRYPTO_TFM_RES_WEAK_KEY;
605 +       return -EINVAL;
606 +}
607 +
608 +
609 +void mcfcau_des_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
610 +{
611 +       struct mcfcau_des_ctx *ctx = crypto_tfm_ctx(tfm);
612 +       u32 * des_key_tmp = ctx->expkey;
613 +       unsigned long iflags;
614 +
615 +       DBG("\n");
616 +
617 +       spin_lock_irqsave(&mcfcau_lock, iflags);
618 +
619 +       asm("move.l     %0, %%a0"::"m"(src):"a0");
620 +       asm("move.l     %0, %%a1"::"m"(des_key_tmp):"a1");
621 +
622 +       asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA2):"a0");
623 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_LDR+MCFCAU_CA3));
624 +       asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA0):"a1");
625 +       asm("cp0ld.l    (%%a1),%%d0,#1,%0"      ::"n"(MCFCAU_LDR+MCFCAU_CA1));
626 +
627 +       mcfcau_des_encipher();
628 +
629 +       asm("cp0st.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_STR+MCFCAU_CA2):"d0");
630 +       asm("cp0st.l    %%d0,%%d1,#1,%0"        ::"n"(MCFCAU_STR+MCFCAU_CA3):"d1");
631 +       asm("move.l     %0, %%a1"               ::"m"(dst):"a1");
632 +       asm("move.l     %d0,(%a1)+");
633 +       asm("move.l     %d1,(%a1)");
634 +
635 +       spin_unlock_irqrestore(&mcfcau_lock, iflags);
636 +}
637 +
638 +
639 +void mcfcau_des_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
640 +{
641 +       struct mcfcau_des_ctx *ctx = crypto_tfm_ctx(tfm);
642 +       u32 * des_key_tmp = ctx->expkey;
643 +       unsigned long iflags;
644 +
645 +       DBG("\n");
646 +
647 +       spin_lock_irqsave(&mcfcau_lock, iflags);
648 +
649 +       asm("move.l     %0, %%a0"::"m"(src):"a0");
650 +       asm("move.l     %0, %%a1"::"m"(des_key_tmp):"a1");
651 +
652 +       asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA2):"a0");
653 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_LDR+MCFCAU_CA3));
654 +       asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA0):"a1");
655 +       asm("cp0ld.l    (%%a1),%%d0,#1,%0"      ::"n"(MCFCAU_LDR+MCFCAU_CA1));
656 +
657 +       mcfcau_des_decipher();
658 +
659 +       asm("move.l     %0, %%a1"               ::"m"(dst):"a1");
660 +       asm("cp0st.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_STR+MCFCAU_CA2):"d0");
661 +       asm("cp0st.l    %%d0,%%d1,#1,%0"        ::"n"(MCFCAU_STR+MCFCAU_CA3):"d1");
662 +       asm("move.l     %d0,(%a1)+");
663 +       asm("move.l     %d1,(%a1)");
664 +
665 +       spin_unlock_irqrestore(&mcfcau_lock, iflags);
666 +}
667 +
668 +
669 +/*
670 + * RFC2451:
671 + *
672 + *   For DES-EDE3, there is no known need to reject weak or
673 + *   complementation keys.  Any weakness is obviated by the use of
674 + *   multiple keys.
675 + *
676 + *   However, if the first two or last two independent 64-bit keys are
677 + *   equal (k1 == k2 or k2 == k3), then the DES3 operation is simply the
678 + *   same as DES.  Implementers MUST reject keys that exhibit this
679 + *   property.
680 + *
681 + */
682 +
683 +static int mcfcau_des3_ede_setkey(struct crypto_tfm *tfm, const u8 *key_p, unsigned int keylen)
684 +{
685 +       const u32 *key = (const u32 *)key_p;
686 +       struct mcfcau_des3_ede_ctx *dctx = crypto_tfm_ctx(tfm);
687 +       u32 *flags = &tfm->crt_flags;
688 +
689 +DBG("\n");
690 +
691 +       if (unlikely(!((key[0] ^ key[2]) | (key[1] ^ key[3])) ||
692 +                    !((key[2] ^ key[4]) | (key[3] ^ key[5]))))
693 +       {
694 +               *flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED;
695 +               return -EINVAL;
696 +       }
697 +
698 +       memcpy(dctx->expkey,key_p,keylen);
699 +
700 +       return 0;
701 +}
702 +
703 +static void mcfcau_des3_ede_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
704 +{
705 +       struct mcfcau_des3_ede_ctx *dctx = crypto_tfm_ctx(tfm);
706 +       const u32 * des_key_tmp = dctx->expkey;
707 +       unsigned long iflags;
708 +
709 +       DBG("\n");
710 +
711 +       spin_lock_irqsave(&mcfcau_lock, iflags);
712 +
713 +       /*EK1*/
714 +       asm("move.l     %0, %%a0"::"m"(src):"a0");
715 +       asm("move.l     %0, %%a1"::"m"(des_key_tmp):"a1");
716 +
717 +       asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA2):"a0");
718 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_LDR+MCFCAU_CA3));
719 +       asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA0):"a1");
720 +       asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA1):"a1");
721 +
722 +       mcfcau_des_encipher();
723 +
724 +       /*DK2*/
725 +       asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA0):"a1");
726 +       asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA1):"a1");
727 +
728 +       mcfcau_des_decipher();
729 +
730 +       /*EK3*/
731 +       asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA0):"a1");
732 +       asm("cp0ld.l    (%%a1),%%d0,#1,%0"      ::"n"(MCFCAU_LDR+MCFCAU_CA1));
733 +
734 +       mcfcau_des_encipher();
735 +
736 +       asm("move.l     %0, %%a1"               ::"m"(dst):"a1");
737 +       asm("cp0st.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_STR+MCFCAU_CA2):"d0");
738 +       asm("cp0st.l    %%d0,%%d1,#1,%0"        ::"n"(MCFCAU_STR+MCFCAU_CA3):"d1");
739 +       asm("move.l     %d0,(%a1)+");
740 +       asm("move.l     %d1,(%a1)");
741 +
742 +       spin_unlock_irqrestore(&mcfcau_lock, iflags);
743 +}
744 +
745 +static void mcfcau_des3_ede_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
746 +{
747 +       struct mcfcau_des3_ede_ctx *dctx = crypto_tfm_ctx(tfm);
748 +       const u32 * des_key_tmp = dctx->expkey + 6 - 2;
749 +       unsigned long iflags;
750 +
751 +       DBG("\n");
752 +
753 +       spin_lock_irqsave(&mcfcau_lock, iflags);
754 +
755 +       /*DK3*/
756 +       asm("move.l     %0, %%a0"::"m"(src):"a0");
757 +       asm("move.l     %0, %%a1"::"m"(des_key_tmp):"a1");
758 +
759 +       asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA2):"a0");
760 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_LDR+MCFCAU_CA3));
761 +       asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA0):"a1");
762 +       asm("cp0ld.l    (%%a1),%%d0,#1,%0"      ::"n"(MCFCAU_LDR+MCFCAU_CA1));
763 +
764 +       mcfcau_des_decipher();
765 +
766 +       /*EK2*/
767 +       asm("suba.l     #12,%a1");      /*dec key pointer*/
768 +
769 +       asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA0):"a1");
770 +       asm("cp0ld.l    (%%a1),%%d0,#1,%0"      ::"n"(MCFCAU_LDR+MCFCAU_CA1));
771 +
772 +       mcfcau_des_encipher();
773 +
774 +       /*DK1*/
775 +       asm("suba.l     #12,%a1");      /*dec key pointer*/
776 +
777 +       asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA0):"a1");
778 +       asm("cp0ld.l    (%%a1),%%d0,#1,%0"      ::"n"(MCFCAU_LDR+MCFCAU_CA1));
779 +
780 +       mcfcau_des_decipher();
781 +
782 +       asm("move.l     %0, %%a1"               ::"m"(dst):"a1");
783 +       asm("cp0st.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_STR+MCFCAU_CA2):"d0");
784 +       asm("cp0st.l    %%d0,%%d1,#1,%0"        ::"n"(MCFCAU_STR+MCFCAU_CA3):"d1");
785 +       asm("move.l     %d0,(%a1)+");
786 +       asm("move.l     %d1,(%a1)");
787 +
788 +       spin_unlock_irqrestore(&mcfcau_lock, iflags);
789 +}
790 +
791 +
792 +static struct crypto_alg mcfcau_des_alg = {
793 +       .cra_name               =       "des",
794 +       .cra_driver_name        =       "des-mcfcau",
795 +       .cra_priority           =       MCFCAU_CRA_PRIORITY,
796 +       .cra_flags              =       CRYPTO_ALG_TYPE_CIPHER,
797 +       .cra_blocksize          =       MCFCAU_DES_BLOCK_SIZE,
798 +       .cra_ctxsize            =       sizeof(struct mcfcau_des_ctx),
799 +       .cra_module             =       THIS_MODULE,
800 +       .cra_alignmask          =       3,
801 +       .cra_list               =       LIST_HEAD_INIT(mcfcau_des_alg.cra_list),
802 +       .cra_u                  =       { .cipher = {
803 +       .cia_min_keysize        =       MCFCAU_DES_KEY_SIZE,
804 +       .cia_max_keysize        =       MCFCAU_DES_KEY_SIZE,
805 +       .cia_setkey             =       mcfcau_des_setkey,
806 +       .cia_encrypt            =       mcfcau_des_encrypt,
807 +       .cia_decrypt            =       mcfcau_des_decrypt } }
808 +};
809 +
810 +static struct crypto_alg mcfcau_des3_ede_alg = {
811 +       .cra_name               =       "des3_ede",
812 +       .cra_driver_name        =       "des3_ede-mcfcau",
813 +       .cra_priority           =       MCFCAU_CRA_PRIORITY,
814 +       .cra_flags              =       CRYPTO_ALG_TYPE_CIPHER,
815 +       .cra_blocksize          =       MCFCAU_DES3_EDE_BLOCK_SIZE,
816 +       .cra_ctxsize            =       sizeof(struct mcfcau_des3_ede_ctx),
817 +       .cra_module             =       THIS_MODULE,
818 +       .cra_alignmask          =       3,
819 +       .cra_list               =       LIST_HEAD_INIT(mcfcau_des3_ede_alg.cra_list),
820 +       .cra_u                  =       { .cipher = {
821 +       .cia_min_keysize        =       MCFCAU_DES3_EDE_KEY_SIZE,
822 +       .cia_max_keysize        =       MCFCAU_DES3_EDE_KEY_SIZE,
823 +       .cia_setkey             =       mcfcau_des3_ede_setkey,
824 +       .cia_encrypt            =       mcfcau_des3_ede_encrypt,
825 +       .cia_decrypt            =       mcfcau_des3_ede_decrypt } }
826 +};
827 +
828 +MODULE_ALIAS("mcfcau_des3_ede");
829 +
830 +static int __init mcfcau_des_init(void)
831 +{
832 +       int ret;
833 +
834 +       ret = crypto_register_alg(&mcfcau_des_alg);
835 +       if (ret < 0)
836 +               goto out;
837 +
838 +       ret = crypto_register_alg(&mcfcau_des3_ede_alg);
839 +       if (ret < 0)
840 +               crypto_unregister_alg(&mcfcau_des_alg);
841 +out:
842 +       printk(KERN_INFO MCFCAU_DES_DRIVER_DESC " "
843 +               MCFCAU_DES_DRIVER_VERSION " %s.\n",ret?"failed":"registered");
844 +       return ret;
845 +}
846 +
847 +static void __exit mcfcau_des_exit(void)
848 +{
849 +       crypto_unregister_alg(&mcfcau_des3_ede_alg);
850 +       crypto_unregister_alg(&mcfcau_des_alg);
851 +
852 +       printk(KERN_INFO MCFCAU_DES_DRIVER_DESC " "
853 +               MCFCAU_DES_DRIVER_VERSION " unregistered.\n");
854 +}
855 +
856 +module_init(mcfcau_des_init);
857 +module_exit(mcfcau_des_exit);
858 +
859 +MODULE_LICENSE("GPL");
860 +MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms for ColdFire CAU");
861 +MODULE_AUTHOR("Andrey Butok");
862 --- /dev/null
863 +++ b/drivers/crypto/mcfcau-md5.c
864 @@ -0,0 +1,654 @@
865 + /***************************************************************************
866 + * mcfcau-md5.c - Implementation of MD5 Message Digest Algorithm (RFC1321)
867 + *                for Freescale ColdFire Cryptographic Acceleration Unit (CAU).
868 + *
869 + * Author: Andrey Butok
870 + * Copyright Freescale Semiconductor Inc.  2007
871 + *
872 + * NOTE: You can find the ColdFire CAU module on MCF54455 and MCF52235.
873 + *
874 + * This program is free software; you can redistribute it and/or modify it
875 + * under the terms of the GNU General Public License as published by the
876 + * Free Software Foundation; either version 2 of the License, or (at your
877 + * option) any later version.
878 + *
879 + * This program is distributed in the hope that it will be useful, but
880 + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
881 + * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
882 + * for more details.
883 + *
884 + * You should have received a copy of the GNU General Public License
885 + * along with this program; if not, write to the Free Software Foundation,
886 + * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
887 + *
888 + ***************************************************************************
889 + * Changes:
890 + * v0.01       30 September 2007       Andrey Butok
891 + *             Initial Release - developed on 2.6.20 Linux kernel.
892 + */
893 +#include <linux/init.h>
894 +#include <linux/module.h>
895 +#include <linux/string.h>
896 +#include <linux/crypto.h>
897 +#include <linux/types.h>
898 +#include <asm/byteorder.h>
899 +
900 +/*
901 +#undef DEBUG
902 +#define DEBUG 1
903 +*/
904 +
905 +#include "mcfcau.h"
906 +
907 +
908 +#define MCFCAU_MD5_DIGEST_SIZE         (16)
909 +#define MCFCAU_MD5_HMAC_BLOCK_SIZE     (64)
910 +#define MCFCAU_MD5_BLOCK_WORDS         (16)
911 +#define MCFCAU_MD5_HASH_WORDS          (4)
912 +
913 +#define        MCFCAU_MD5_DRIVER_DESC          "MD5 ColdFire CAU driver"
914 +#define        MCFCAU_MD5_DRIVER_VERSION       "v0.01"
915 +
916 +
917 +struct mcfcau_md5_ctx {
918 +       u32 hash[MCFCAU_MD5_HASH_WORDS];
919 +       u32 block[MCFCAU_MD5_BLOCK_WORDS];
920 +       u64 byte_count;
921 +};
922 +
923 +u32 mcfcau_md5_t[64]={0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
924 +                       0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
925 +                       0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
926 +                       0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
927 +                       0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
928 +                       0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
929 +                       0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
930 +                       0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
931 +                       0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
932 +                       0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
933 +                       0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
934 +                       0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
935 +                       0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
936 +                       0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
937 +                       0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
938 +                       0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391};
939 +
940 +
941 +
942 +static void mcfcau_md5_transform(u32 *hash, u32 const *in)
943 +{
944 +       int i;
945 +       u32 * md5_t_p=&mcfcau_md5_t[0];
946 +       unsigned long iflags;
947 +
948 +       spin_lock_irqsave(&mcfcau_lock, iflags);
949 +       asm("move.l     %0, %%a1"::"m"(hash):"a1");
950 +       asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CAA):"a1");/*a*/
951 +       asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA1):"a1");/*b*/
952 +       asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA2):"a1");/*c*/
953 +       asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA3):"a1");/*d*/
954 +       asm("move.l     %0, %%a0"::"m"(in):"a0");       /* X[] */
955 +       asm("move.l     %0, %%a3"::"m"(md5_t_p):"a3");  /* T[] */
956 +
957 +       
958 +       /*  Round 1 */
959 +       asm("moveq.l    #7, %%d4":::"d4");      /* for rotating by 7 */
960 +       asm("moveq.l    #12, %%d5":::"d5");     /* for rotating by 12 */
961 +       asm("moveq.l    #17, %%d6":::"d6");     /* for rotating by 17 */
962 +       asm("moveq.l    #22, %%d7":::"d7");     /* for rotating by 22 */
963 +
964 +       for(i=0; i<4;i++){
965 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFF));         /* a+F(b,c,d) */
966 +               asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");    /* add byterev x[i] */
967 +               asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");     /* add t[i] */
968 +               asm("cp0ld.l    %%d4,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));         /* rotate by 7 */
969 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));         /* add b */
970 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));                     /* register to register shift */
971 +
972 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFF));
973 +               asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
974 +               asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
975 +               asm("cp0ld.l    %%d5,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
976 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
977 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
978 +
979 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFF));
980 +               asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
981 +               asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
982 +               asm("cp0ld.l    %%d6,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
983 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
984 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
985 +
986 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFF));
987 +               asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
988 +               asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
989 +               asm("cp0ld.l    %%d7,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
990 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
991 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
992 +       };
993 +
994 +
995 +       /* Round 2 */
996 +       asm("moveq.l    #5, %%d4":::"d4");      /* for rotating by 5 */
997 +       asm("moveq.l    #9, %%d5":::"d5");      /* for rotating by 9 */
998 +       asm("moveq.l    #14, %%d6":::"d6");     /* for rotating by 14 */
999 +       asm("moveq.l    #20, %%d7":::"d7");     /* for rotating by 20 */
1000 +
1001 +       asm("lea -60(%%a0),%%a0":::"a0");
1002 +
1003 +       for(i=0; i<2;i++){
1004 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFG));
1005 +               asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1006 +               asm("lea        20(%%a0),%%a0"          :::"a0");
1007 +               asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1008 +               asm("cp0ld.l    %%d4,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1009 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1010 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1011 +
1012 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFG));
1013 +               asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1014 +               asm("lea        20(%%a0),%%a0"          :::"a0");
1015 +               asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1016 +               asm("cp0ld.l    %%d5,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1017 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1018 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1019 +
1020 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFG));
1021 +               asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1022 +               asm("lea        -44(%%a0),%%a0"         :::"a0");
1023 +               asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1024 +               asm("cp0ld.l    %%d6,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1025 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1026 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1027 +
1028 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFG));
1029 +               asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1030 +               asm("lea        20(%%a0),%%a0"          :::"a0");
1031 +               asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1032 +               asm("cp0ld.l    %%d7,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1033 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1034 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1035 +       };
1036 +
1037 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFG));
1038 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1039 +       asm("lea        20(%%a0),%%a0"          :::"a0");
1040 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1041 +       asm("cp0ld.l    %%d4,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1042 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1043 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1044 +
1045 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFG));
1046 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1047 +       asm("lea        -44(%%a0),%%a0"         :::"a0");
1048 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1049 +       asm("cp0ld.l    %%d5,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1050 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1051 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1052 +
1053 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFG));
1054 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1055 +       asm("lea        20(%%a0),%%a0"          :::"a0");
1056 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1057 +       asm("cp0ld.l    %%d6,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1058 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1059 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1060 +
1061 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFG));
1062 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1063 +       asm("lea        20(%%a0),%%a0"          :::"a0");
1064 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1065 +       asm("cp0ld.l    %%d7,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1066 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1067 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1068 +
1069 +
1070 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFG));
1071 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1072 +       asm("lea        -44(%%a0),%%a0"         :::"a0");
1073 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1074 +       asm("cp0ld.l    %%d4,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1075 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1076 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1077 +
1078 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFG));
1079 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1080 +       asm("lea        20(%%a0),%%a0"          :::"a0");
1081 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1082 +       asm("cp0ld.l    %%d5,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1083 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1084 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1085 +
1086 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFG));
1087 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1088 +       asm("lea        20(%%a0),%%a0"          :::"a0");
1089 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1090 +       asm("cp0ld.l    %%d6,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1091 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1092 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1093 +
1094 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFG));
1095 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1096 +       asm("lea        -28(%%a0),%%a0"         :::"a0");
1097 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1098 +       asm("cp0ld.l    %%d7,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1099 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1100 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1101 +
1102 +
1103 +       /* Round 3 */
1104 +       asm("moveq.l    #4, %%d4":::"d4");      /* for rotating by 5 */
1105 +       asm("moveq.l    #11, %%d5":::"d5");     /* for rotating by 9 */
1106 +       asm("moveq.l    #16, %%d6":::"d6");     /* for rotating by 14 */
1107 +       asm("moveq.l    #23, %%d7":::"d7");     /* for rotating by 20 */
1108 +
1109 +
1110 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH));
1111 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1112 +       asm("lea        12(%%a0),%%a0"          :::"a0");
1113 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1114 +       asm("cp0ld.l    %%d4,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1115 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1116 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1117 +
1118 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH));
1119 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1120 +       asm("lea        12(%%a0),%%a0"          :::"a0");
1121 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1122 +       asm("cp0ld.l    %%d5,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1123 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1124 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1125 +
1126 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH));
1127 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1128 +       asm("lea        12(%%a0),%%a0"          :::"a0");
1129 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1130 +       asm("cp0ld.l    %%d6,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1131 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1132 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1133 +
1134 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH));
1135 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1136 +       asm("lea        -52(%%a0),%%a0"         :::"a0");
1137 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1138 +       asm("cp0ld.l    %%d7,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1139 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1140 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1141 +
1142 +
1143 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH));
1144 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1145 +       asm("lea        12(%%a0),%%a0"          :::"a0");
1146 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1147 +       asm("cp0ld.l    %%d4,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1148 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1149 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1150 +
1151 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH));
1152 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1153 +       asm("lea        12(%%a0),%%a0"          :::"a0");
1154 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1155 +       asm("cp0ld.l    %%d5,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1156 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1157 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1158 +
1159 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH));
1160 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1161 +       asm("lea        12(%%a0),%%a0"          :::"a0");
1162 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1163 +       asm("cp0ld.l    %%d6,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1164 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1165 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1166 +
1167 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH));
1168 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1169 +       asm("lea        12(%%a0),%%a0"          :::"a0");
1170 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1171 +       asm("cp0ld.l    %%d7,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1172 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1173 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1174 +
1175 +
1176 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH));
1177 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1178 +       asm("lea        -52(%%a0),%%a0"         :::"a0");
1179 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1180 +       asm("cp0ld.l    %%d4,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1181 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1182 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1183 +
1184 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH));
1185 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1186 +       asm("lea        12(%%a0),%%a0"          :::"a0");
1187 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1188 +       asm("cp0ld.l    %%d5,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1189 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1190 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1191 +
1192 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH));
1193 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1194 +       asm("lea        12(%%a0),%%a0"          :::"a0");
1195 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1196 +       asm("cp0ld.l    %%d6,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1197 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1198 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1199 +
1200 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH));
1201 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1202 +       asm("lea        12(%%a0),%%a0"          :::"a0");
1203 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1204 +       asm("cp0ld.l    %%d7,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1205 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1206 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1207 +
1208 +
1209 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH));
1210 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1211 +       asm("lea        12(%%a0),%%a0"          :::"a0");
1212 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1213 +       asm("cp0ld.l    %%d4,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1214 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1215 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1216 +
1217 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH));
1218 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1219 +       asm("lea        12(%%a0),%%a0"          :::"a0");
1220 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1221 +       asm("cp0ld.l    %%d5,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1222 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1223 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1224 +
1225 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH));
1226 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1227 +       asm("lea        -52(%%a0),%%a0"         :::"a0");
1228 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1229 +       asm("cp0ld.l    %%d6,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1230 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1231 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1232 +
1233 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH));
1234 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1235 +       asm("lea        -8(%%a0),%%a0"          :::"a0");
1236 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1237 +       asm("cp0ld.l    %%d7,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1238 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1239 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1240 +
1241 +       
1242 +       /* Round 4 */
1243 +       asm("moveq.l    #6, %%d4":::"d4");      /* for rotating by 6 */
1244 +       asm("moveq.l    #10, %%d5":::"d5");     /* for rotating by 10 */
1245 +       asm("moveq.l    #15, %%d6":::"d6");     /* for rotating by 15 */
1246 +       asm("moveq.l    #21, %%d7":::"d7");     /* for rotating by 21 */
1247 +
1248 +
1249 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFI));
1250 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1251 +       asm("lea        28(%%a0),%%a0"          :::"a0");
1252 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1253 +       asm("cp0ld.l    %%d4,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1254 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1255 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1256 +
1257 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFI));
1258 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1259 +       asm("lea        28(%%a0),%%a0"          :::"a0");
1260 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1261 +       asm("cp0ld.l    %%d5,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1262 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1263 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1264 +
1265 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFI));
1266 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1267 +       asm("lea        -36(%%a0),%%a0"         :::"a0");
1268 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1269 +       asm("cp0ld.l    %%d6,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1270 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1271 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1272 +
1273 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFI));
1274 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1275 +       asm("lea        28(%%a0),%%a0"          :::"a0");
1276 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1277 +       asm("cp0ld.l    %%d7,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1278 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1279 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1280 +
1281 +
1282 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFI));
1283 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1284 +       asm("lea        -36(%%a0),%%a0"         :::"a0");
1285 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1286 +       asm("cp0ld.l    %%d4,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1287 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1288 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1289 +
1290 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFI));
1291 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1292 +       asm("lea        28(%%a0),%%a0"          :::"a0");
1293 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1294 +       asm("cp0ld.l    %%d5,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1295 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1296 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1297 +
1298 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFI));
1299 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1300 +       asm("lea        -36(%%a0),%%a0"         :::"a0");
1301 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1302 +       asm("cp0ld.l    %%d6,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1303 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1304 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1305 +
1306 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFI));
1307 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1308 +       asm("lea        28(%%a0),%%a0"          :::"a0");
1309 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1310 +       asm("cp0ld.l    %%d7,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1311 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1312 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1313 +
1314 +
1315 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFI));
1316 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1317 +       asm("lea        28(%%a0),%%a0"          :::"a0");
1318 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1319 +       asm("cp0ld.l    %%d4,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1320 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1321 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1322 +
1323 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFI));
1324 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1325 +       asm("lea        -36(%%a0),%%a0"         :::"a0");
1326 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1327 +       asm("cp0ld.l    %%d5,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1328 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1329 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1330 +
1331 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFI));
1332 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1333 +       asm("lea        28(%%a0),%%a0"          :::"a0");
1334 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1335 +       asm("cp0ld.l    %%d6,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1336 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1337 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1338 +
1339 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFI));
1340 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1341 +       asm("lea        -36(%%a0),%%a0"         :::"a0");
1342 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1343 +       asm("cp0ld.l    %%d7,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1344 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1345 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1346 +
1347 +
1348 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFI));
1349 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1350 +       asm("lea        28(%%a0),%%a0"          :::"a0");
1351 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1352 +       asm("cp0ld.l    %%d4,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1353 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1354 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1355 +
1356 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFI));
1357 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1358 +       asm("lea        -36(%%a0),%%a0"         :::"a0");
1359 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1360 +       asm("cp0ld.l    %%d5,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1361 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1362 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1363 +
1364 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFI));
1365 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1366 +       asm("lea        28(%%a0),%%a0"          :::"a0");
1367 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1368 +       asm("cp0ld.l    %%d6,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1369 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1370 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1371 +
1372 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFI));
1373 +       asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_RADR+MCFCAU_CAA):"a0");
1374 +       asm("lea        28(%%a0),%%a0"          :::"a0");
1375 +       asm("cp0ld.l    (%%a3)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a3");
1376 +       asm("cp0ld.l    %%d7,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA));
1377 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA1));
1378 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MDS));
1379 +
1380 +       
1381 +       asm("move.l     %0, %%a1"::"m"(hash):"a1");
1382 +
1383 +       asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a1");/*a*/
1384 +       asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CA1):"a1");/*b*/
1385 +       asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CA2):"a1");/*c*/
1386 +       asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CA3):"a1");/*d*/
1387 +
1388 +       asm("cp0st.l    %%d0,-(%%a1),#1,%0"     ::"n"(MCFCAU_STR+MCFCAU_CA3):"a1");/*d*/
1389 +       asm("cp0st.l    %%d0,-(%%a1),#1,%0"     ::"n"(MCFCAU_STR+MCFCAU_CA2):"a1");/*c*/
1390 +       asm("cp0st.l    %%d0,-(%%a1),#1,%0"     ::"n"(MCFCAU_STR+MCFCAU_CA1):"a1");/*b*/
1391 +       asm("cp0st.l    %%d0,-(%%a1),#1,%0"     ::"n"(MCFCAU_STR+MCFCAU_CAA):"a1");/*a*/
1392 +       spin_unlock_irqrestore(&mcfcau_lock, iflags);
1393 +}
1394 +
1395 +static inline void le32_to_cpu_array(u32 *buf, unsigned int words)
1396 +{
1397 +       while (words--) {
1398 +               __le32_to_cpus(buf);
1399 +               buf++;
1400 +       }
1401 +}
1402 +
1403 +static inline void cpu_to_le32_array(u32 *buf, unsigned int words)
1404 +{
1405 +       while (words--) {
1406 +               __cpu_to_le32s(buf);
1407 +               buf++;
1408 +       }
1409 +}
1410 +
1411 +static void mcfcau_md5_initialization(struct crypto_tfm *tfm)
1412 +{
1413 +       struct mcfcau_md5_ctx *mctx = crypto_tfm_ctx(tfm);
1414 +
1415 +       DBG("\n");
1416 +       mctx->hash[0] = 0x67452301;
1417 +       mctx->hash[1] = 0xefcdab89;
1418 +       mctx->hash[2] = 0x98badcfe;
1419 +       mctx->hash[3] = 0x10325476;
1420 +       mctx->byte_count = 0;
1421 +}
1422 +
1423 +static void mcfcau_md5_update(struct crypto_tfm *tfm, const u8 *data, unsigned int len)
1424 +{
1425 +       struct mcfcau_md5_ctx *mctx = crypto_tfm_ctx(tfm);
1426 +       const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f);
1427 +
1428 +       DBG("\n");
1429 +       mctx->byte_count += len;
1430 +
1431 +       if (avail > len) {
1432 +               memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
1433 +                      data, len);
1434 +       }
1435 +       else {
1436 +               memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), data, avail);
1437 +
1438 +               mcfcau_md5_transform(mctx->hash, mctx->block);
1439 +               data += avail;
1440 +               len -= avail;
1441 +
1442 +               while (len >= sizeof(mctx->block)) {
1443 +                       memcpy(mctx->block, data, sizeof(mctx->block));
1444 +                       mcfcau_md5_transform(mctx->hash, mctx->block);
1445 +                       data += sizeof(mctx->block);
1446 +                       len -= sizeof(mctx->block);
1447 +               }
1448 +
1449 +               memcpy(mctx->block, data, len);
1450 +       }
1451 +}
1452 +
1453 +static void mcfcau_md5_final(struct crypto_tfm *tfm, u8 *out)
1454 +{
1455 +       struct mcfcau_md5_ctx *mctx = crypto_tfm_ctx(tfm);
1456 +       const unsigned int offset = mctx->byte_count & 0x3f;
1457 +       char *p = (char *)mctx->block + offset;
1458 +       int padding = 56 - (offset + 1);
1459 +
1460 +       DBG("\n");
1461 +
1462 +       *p++ = 0x80;
1463 +       if (padding < 0) {
1464 +               memset(p, 0x00, padding + sizeof (u64));
1465 +               mcfcau_md5_transform(mctx->hash, mctx->block);
1466 +               p = (char *)mctx->block;
1467 +               padding = 56;
1468 +       }
1469 +
1470 +       memset(p, 0, padding);
1471 +       mctx->block[14] = mctx->byte_count << 3;
1472 +       mctx->block[15] = mctx->byte_count >> 29;
1473 +       le32_to_cpu_array(&mctx->block[14], 2);
1474 +
1475 +       mcfcau_md5_transform(mctx->hash, mctx->block);
1476 +
1477 +       cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(u32));
1478 +       memcpy(out, mctx->hash, sizeof(mctx->hash));
1479 +       memset(mctx, 0, sizeof(*mctx));
1480 +}
1481 +
1482 +static struct crypto_alg mcfcau_md5_alg = {
1483 +       .cra_name               =       "md5",
1484 +       .cra_driver_name        =       "md5-mcfcau",
1485 +       .cra_priority           =       MCFCAU_CRA_PRIORITY,
1486 +       .cra_flags              =       CRYPTO_ALG_TYPE_DIGEST,
1487 +       .cra_blocksize          =       MCFCAU_MD5_HMAC_BLOCK_SIZE,
1488 +       .cra_ctxsize            =       sizeof(struct mcfcau_md5_ctx),
1489 +       .cra_module             =       THIS_MODULE,
1490 +       .cra_list               =       LIST_HEAD_INIT(mcfcau_md5_alg.cra_list),
1491 +       .cra_u                  =       { .digest = {
1492 +       .dia_digestsize         =       MCFCAU_MD5_DIGEST_SIZE,
1493 +       .dia_init               =       mcfcau_md5_initialization,
1494 +       .dia_update             =       mcfcau_md5_update,
1495 +       .dia_final              =       mcfcau_md5_final } }
1496 +};
1497 +
1498 +static int __init mcfcau_md5_init(void)
1499 +{
1500 +       int ret = crypto_register_alg(&mcfcau_md5_alg);
1501 +       printk(KERN_INFO MCFCAU_MD5_DRIVER_DESC " "
1502 +               MCFCAU_MD5_DRIVER_VERSION " %s.\n",ret?"failed":"registered");
1503 +       return ret;
1504 +}
1505 +
1506 +static void __exit mcfcau_md5_exit(void)
1507 +{
1508 +       crypto_unregister_alg(&mcfcau_md5_alg);
1509 +       printk(KERN_INFO MCFCAU_MD5_DRIVER_DESC " "
1510 +               MCFCAU_MD5_DRIVER_VERSION " unregistered.\n");
1511 +}
1512 +
1513 +module_init(mcfcau_md5_init);
1514 +module_exit(mcfcau_md5_exit);
1515 +
1516 +MODULE_LICENSE("GPL");
1517 +MODULE_DESCRIPTION(MCFCAU_MD5_DRIVER_DESC);
1518 +MODULE_AUTHOR("Andrey Butok");
1519 --- /dev/null
1520 +++ b/drivers/crypto/mcfcau-sha1.c
1521 @@ -0,0 +1,280 @@
1522 + /***************************************************************************
1523 + * mcfcau-sha1.c - Implementation of SHA1 Secure Hash Algorithm
1524 + *                for Freescale ColdFire Cryptographic Acceleration Unit (CAU).
1525 + *
1526 + * Author: Andrey Butok
1527 + * Copyright Freescale Semiconductor Inc.  2007
1528 + *
1529 + * NOTE: You can find the ColdFire CAU module on MCF54455 and MCF52235.
1530 + *
1531 + * This program is free software; you can redistribute it and/or modify it
1532 + * under the terms of the GNU General Public License as published by the
1533 + * Free Software Foundation; either version 2 of the License, or (at your
1534 + * option) any later version.
1535 + *
1536 + * This program is distributed in the hope that it will be useful, but
1537 + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1538 + * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1539 + * for more details.
1540 + *
1541 + * You should have received a copy of the GNU General Public License
1542 + * along with this program; if not, write to the Free Software Foundation,
1543 + * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1544 + *
1545 + ***************************************************************************
1546 + * Changes:
1547 + * v0.01       15 October 2007 Andrey Butok
1548 + *             Initial Release - developed on 2.6.20 Linux kernel.
1549 + */
1550 +
1551 +#include <linux/init.h>
1552 +#include <linux/module.h>
1553 +#include <linux/mm.h>
1554 +#include <linux/crypto.h>
1555 +#include <linux/types.h>
1556 +
1557 +
1558 +/*
1559 +#undef DEBUG
1560 +#define DEBUG 1
1561 +*/
1562 +
1563 +#include "mcfcau.h"
1564 +
1565 +#define MCFCAU_SHA1_DIGEST_WORDS       (5)
1566 +#define MCFCAU_SHA1_WORKSPACE_WORDS    (80)
1567 +
1568 +#define MCFCAU_SHA1_DIGEST_SIZE                (20)
1569 +#define MCFCAU_SHA1_HMAC_BLOCK_SIZE    (64)
1570 +
1571 +#define        MCFCAU_SHA1_DRIVER_DESC         "SHA1 ColdFire CAU driver"
1572 +#define        MCFCAU_SHA1_DRIVER_VERSION      "v0.01"
1573 +
1574 +struct mcfcau_sha1_ctx {
1575 +        u64 count;
1576 +        u32 state[5];
1577 +        u8 buffer[64];
1578 +};
1579 +
1580 +const static u32 K[4]={0x5A827999L,    /* Rounds  0-19: sqrt(2) * 2^30 */
1581 +                       0x6ED9EBA1L,    /* Rounds 20-39: sqrt(3) * 2^30 */
1582 +                       0x8F1BBCDCL,    /* Rounds 40-59: sqrt(5) * 2^30 */
1583 +                       0xCA62C1D6L};   /* Rounds 60-79: sqrt(10) * 2^30 */
1584 +
1585 +static void noinline mcfcau_sha1_transform(__u32 *digest, const char *in, __u32 *W)
1586 +{
1587 +       int i;
1588 +       u32 * tmp_p;
1589 +       unsigned long iflags;
1590 +
1591 +       /* (a) Devide M(i) into 16 words W */
1592 +       for (i = 0; i < 16; i++)
1593 +               W[i] = ((const u32 *)in)[i];
1594 +
1595 +       /* (b) W[i+16] = S^1(W[i+13] ^ W[i+8] ^ W[i+2] ^ W[i]) */
1596 +       tmp_p=&W[16];
1597 +
1598 +       spin_lock_irqsave(&mcfcau_lock, iflags);
1599 +       asm("move.l     %0, %%a0"::"m"(tmp_p):"a0");
1600 +       asm("moveq.l    #1, %%d3":::"d3");
1601 +
1602 +       for (i = 0; i < 64; i++){
1603 +               asm("cp0ld.l    -64(%%a0),%%d0,#1,%0"   ::"n"(MCFCAU_LDR+MCFCAU_CA0));
1604 +               asm("cp0ld.l    -56(%%a0),%%d0,#1,%0"   ::"n"(MCFCAU_XOR+MCFCAU_CA0));
1605 +               asm("cp0ld.l    -32(%%a0),%%d0,#1,%0"   ::"n"(MCFCAU_XOR+MCFCAU_CA0));
1606 +               asm("cp0ld.l    -12(%%a0),%%d0,#1,%0"   ::"n"(MCFCAU_XOR+MCFCAU_CA0));
1607 +               asm("cp0ld.l    %%d3,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CA0):"d3");
1608 +               asm("cp0st.l    %%d0,(%%a0)+,#1,%0"     ::"n"(MCFCAU_STR+MCFCAU_CA0));
1609 +       }
1610 +
1611 +       /* (c) */
1612 +       asm("move.l     %0, %%a0"::"m"(digest):"a0");
1613 +       asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA0):"a0"); /* a */
1614 +       asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA1):"a0"); /* b */
1615 +       asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA2):"a0"); /* c */
1616 +       asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA3):"a0"); /* d */
1617 +       asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_LDR+MCFCAU_CA4):"a0"); /* e */
1618 +
1619 +       /* (d) */
1620 +       asm("moveq.l    #5, %%d0":::"d0");
1621 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_MVRA+MCFCAU_CA0));
1622 +       asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ROTL+MCFCAU_CAA)); /*S^5(A)*/
1623 +
1624 +       tmp_p=(u32*)K;
1625 +       asm("move.l     %0, %%a0"::"m"(tmp_p):"a0");
1626 +       asm("move.l     %0, %%a1"::"m"(W):"a1");
1627 +
1628 +       for (i = 0; i < 20; i++) {
1629 +               /* t = f1(b, c, d) + K1 + rol32(a, 5) + e + W[i]; */
1630 +               /* e = d; d = c; c = rol32(b, 30); b = a; a = t; */
1631 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFC)); /*f(b,c,d)*/
1632 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA4)); /*+e*/
1633 +               asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_ADR+MCFCAU_CAA)); /*+K*/
1634 +               asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a1"); /*+W*/
1635 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_SHS));
1636 +       }
1637 +
1638 +       asm("add.l #4,%%a0"     :::"a0"); /* update K */
1639 +
1640 +       for (; i < 40; i ++) {
1641 +               /* t = f2(b, c, d) + K2 + rol32(a, 5) + e + W[i]; */
1642 +               /* e = d; d = c; c = rol32(b, 30); b = a; a = t; */
1643 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH)); /*f(b,c,d)*/
1644 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA4)); /*+e*/
1645 +               asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_ADR+MCFCAU_CAA)); /*+K*/
1646 +               asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a1"); /*+W*/
1647 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_SHS));
1648 +       }
1649 +
1650 +       asm("add.l #4,%%a0"     :::"a0"); /* update K */
1651 +
1652 +       for (; i < 60; i ++) {
1653 +               /* t = f3(b, c, d) + K3 + rol32(a, 5) + e + W[i]; */
1654 +               /* e = d; d = c; c = rol32(b, 30); b = a; a = t; */
1655 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFM)); /*f(b,c,d)*/
1656 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA4)); /*+e*/
1657 +               asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_ADR+MCFCAU_CAA)); /*+K*/
1658 +               asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a1"); /*+W*/
1659 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_SHS));
1660 +       }
1661 +
1662 +       asm("add.l #4,%%a0"     :::"a0"); /* update K */
1663 +
1664 +       for (; i < 80; i ++) {
1665 +               /* t = f2(b, c, d) + K4 + rol32(a, 5) + e + W[i]; */
1666 +               /* e = d; d = c; c = rol32(b, 30); b = a; a = t; */
1667 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_HASH+MCFCAU_HFH)); /*f(b,c,d)*/
1668 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_ADRA+MCFCAU_CA4)); /*+e*/
1669 +               asm("cp0ld.l    (%%a0),%%d0,#1,%0"      ::"n"(MCFCAU_ADR+MCFCAU_CAA)); /*+K*/
1670 +               asm("cp0ld.l    (%%a1)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CAA):"a1"); /*+W*/
1671 +               asm("cp0ld.l    %%d0,%%d0,#1,%0"        ::"n"(MCFCAU_SHS));
1672 +       }
1673 +
1674 +       /* (e) */
1675 +       asm("move.l     %0, %%a0"::"m"(digest):"a0");
1676 +       asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CA0):"a0"); /* +a */
1677 +       asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CA1):"a0"); /* +b */
1678 +       asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CA2):"a0"); /* +c */
1679 +       asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CA3):"a0"); /* +d */
1680 +       asm("cp0ld.l    (%%a0)+,%%d0,#1,%0"     ::"n"(MCFCAU_ADR+MCFCAU_CA4):"a0"); /* +e */
1681 +
1682 +       asm("cp0st.l    %%d0,-(%%a0),#1,%0"     ::"n"(MCFCAU_STR+MCFCAU_CA4):"a0");
1683 +       asm("cp0st.l    %%d0,-(%%a0),#1,%0"     ::"n"(MCFCAU_STR+MCFCAU_CA3):"a0");
1684 +       asm("cp0st.l    %%d0,-(%%a0),#1,%0"     ::"n"(MCFCAU_STR+MCFCAU_CA2):"a0");
1685 +       asm("cp0st.l    %%d0,-(%%a0),#1,%0"     ::"n"(MCFCAU_STR+MCFCAU_CA1):"a0");
1686 +       asm("cp0st.l    %%d0,-(%%a0),#1,%0"     ::"n"(MCFCAU_STR+MCFCAU_CA0):"a0");
1687 +       spin_unlock_irqrestore(&mcfcau_lock, iflags);
1688 +}
1689 +
1690 +static void mcfcau_sha1_init(struct crypto_tfm *tfm)
1691 +{
1692 +       struct mcfcau_sha1_ctx *sctx = crypto_tfm_ctx(tfm);
1693 +       static const struct mcfcau_sha1_ctx initstate = {
1694 +         0,
1695 +         { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 },
1696 +         { 0, }
1697 +       };
1698 +
1699 +       *sctx = initstate;
1700 +}
1701 +
1702 +static void mcfcau_sha1_update(struct crypto_tfm *tfm, const u8 *data,
1703 +                       unsigned int len)
1704 +{
1705 +       struct mcfcau_sha1_ctx *sctx = crypto_tfm_ctx(tfm);
1706 +       unsigned int partial, done;
1707 +       const u8 *src;
1708 +
1709 +       partial = sctx->count & 0x3f;
1710 +       sctx->count += len;
1711 +       done = 0;
1712 +       src = data;
1713 +
1714 +       if ((partial + len) > 63) {
1715 +               u32 temp[MCFCAU_SHA1_WORKSPACE_WORDS];
1716 +
1717 +               if (partial) {
1718 +                       done = -partial;
1719 +                       memcpy(sctx->buffer + partial, data, done + 64);
1720 +                       src = sctx->buffer;
1721 +               }
1722 +
1723 +               do {
1724 +                       mcfcau_sha1_transform(sctx->state, src, temp);
1725 +                       done += 64;
1726 +                       src = data + done;
1727 +               } while (done + 63 < len);
1728 +
1729 +               memset(temp, 0, sizeof(temp));
1730 +               partial = 0;
1731 +       }
1732 +       memcpy(sctx->buffer + partial, src, len - done);
1733 +}
1734 +
1735 +
1736 +/* Add padding and return the message digest. */
1737 +static void mcfcau_sha1_final(struct crypto_tfm *tfm, u8 *out)
1738 +{
1739 +       struct mcfcau_sha1_ctx *sctx = crypto_tfm_ctx(tfm);
1740 +       u32 *dst = (u32 *)out;
1741 +       u32 i, index, padlen;
1742 +       u64 bits;
1743 +       static const u8 padding[64] = { 0x80, };
1744 +
1745 +       bits = sctx->count << 3;
1746 +
1747 +       /* Pad out to 56 mod 64 */
1748 +       index = sctx->count & 0x3f;
1749 +       padlen = (index < 56) ? (56 - index) : ((64+56) - index);
1750 +       mcfcau_sha1_update(tfm, padding, padlen);
1751 +
1752 +       /* Append length */
1753 +       mcfcau_sha1_update(tfm, (const u8 *)&bits, sizeof(bits));
1754 +
1755 +       /* Store state in digest */
1756 +       for (i = 0; i < 5; i++)
1757 +               dst[i] = sctx->state[i];
1758 +
1759 +
1760 +       /* Wipe context */
1761 +       memset(sctx, 0, sizeof *sctx);
1762 +}
1763 +
1764 +static struct crypto_alg mcfcau_sha1_alg = {
1765 +       .cra_name       =       "sha1",
1766 +       .cra_driver_name=       "sha1-mcfcau",
1767 +       .cra_priority   =       MCFCAU_CRA_PRIORITY,
1768 +       .cra_flags      =       CRYPTO_ALG_TYPE_DIGEST,
1769 +       .cra_blocksize  =       MCFCAU_SHA1_HMAC_BLOCK_SIZE,
1770 +       .cra_ctxsize    =       sizeof(struct mcfcau_sha1_ctx),
1771 +       .cra_module     =       THIS_MODULE,
1772 +       .cra_alignmask  =       3,
1773 +       .cra_list       =       LIST_HEAD_INIT(mcfcau_sha1_alg.cra_list),
1774 +       .cra_u          =       { .digest = {
1775 +       .dia_digestsize =       MCFCAU_SHA1_DIGEST_SIZE,
1776 +       .dia_init       =       mcfcau_sha1_init,
1777 +       .dia_update     =       mcfcau_sha1_update,
1778 +       .dia_final      =       mcfcau_sha1_final } }
1779 +};
1780 +
1781 +static int __init init(void)
1782 +{
1783 +       int ret = crypto_register_alg(&mcfcau_sha1_alg);
1784 +       printk(KERN_INFO MCFCAU_SHA1_DRIVER_DESC " "
1785 +               MCFCAU_SHA1_DRIVER_VERSION " %s.\n",ret?"failed":"registered");
1786 +       return ret;
1787 +}
1788 +
1789 +static void __exit fini(void)
1790 +{
1791 +       crypto_unregister_alg(&mcfcau_sha1_alg);
1792 +       printk(KERN_INFO MCFCAU_SHA1_DRIVER_DESC " "
1793 +               MCFCAU_SHA1_DRIVER_VERSION " unregistered.\n");
1794 +}
1795 +
1796 +module_init(init);
1797 +module_exit(fini);
1798 +
1799 +MODULE_LICENSE("GPL");
1800 +MODULE_DESCRIPTION(MCFCAU_SHA1_DRIVER_DESC);
1801 +MODULE_AUTHOR("Andrey Butok");
1802 --- /dev/null
1803 +++ b/drivers/crypto/mcfcau.c
1804 @@ -0,0 +1,32 @@
1805 +/***************************************************************************
1806 + * mcfcau.c - Implementation of DES & Triple DES EDE Cipher Algorithms
1807 + *                for Freescale ColdFire Cryptographic Acceleration Unit (CAU).
1808 + *
1809 + * Author: Andrey Butok
1810 + * Copyright Freescale Semiconductor Inc.  2007
1811 + *
1812 + * NOTE: You can find the ColdFire CAU module on MCF54455 and MCF52235.
1813 + *
1814 + * This program is free software; you can redistribute it and/or modify it
1815 + * under the terms of the GNU General Public License as published by the
1816 + * Free Software Foundation; either version 2 of the License, or (at your
1817 + * option) any later version.
1818 + *
1819 + * This program is distributed in the hope that it will be useful, but
1820 + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1821 + * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1822 + * for more details.
1823 + *
1824 + * You should have received a copy of the GNU General Public License
1825 + * along with this program; if not, write to the Free Software Foundation,
1826 + * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1827 + *
1828 + ***************************************************************************
1829 + * Changes:
1830 + * v0.01       28 September 2006       Andrey Butok
1831 + *             Initial Release - developed on 2.6.20 Linux kernel.
1832 + */
1833 +#include <linux/module.h>
1834 +
1835 +DEFINE_SPINLOCK(mcfcau_lock);
1836 +EXPORT_SYMBOL(mcfcau_lock);
1837 --- /dev/null
1838 +++ b/drivers/crypto/mcfcau.h
1839 @@ -0,0 +1,98 @@
1840 +/***************************************************************************
1841 + * mcfcau.h - Common header file for Freescale ColdFire
1842 + *            Cryptographic Acceleration Unit (CAU) drivers.
1843 + *
1844 + * Author: Andrey Butok
1845 + * Copyright Freescale Semiconductor Inc.  2007
1846 + *
1847 + * NOTE: You can find the ColdFire CAU module on MCF54455 and MCF52235.
1848 + *
1849 + * This program is free software; you can redistribute it and/or modify it
1850 + * under the terms of the GNU General Public License as published by the
1851 + * Free Software Foundation; either version 2 of the License, or (at your
1852 + * option) any later version.
1853 + *
1854 + * This program is distributed in the hope that it will be useful, but
1855 + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1856 + * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1857 + * for more details.
1858 + *
1859 + * You should have received a copy of the GNU General Public License
1860 + * along with this program; if not, write to the Free Software Foundation,
1861 + * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1862 + *
1863 + ***************************************************************************
1864 + * Changes:
1865 + * v0.01       14 August 2007  Andrey Butok
1866 + */
1867 +
1868 +#ifndef MCFCAU_H
1869 +#define MCFCAU_H
1870 +
1871 +#include <linux/spinlock.h>
1872 +
1873 +/* CAU Registers (CAx) */
1874 +#define MCFCAU_CASR            (0x0)
1875 +#define MCFCAU_CAA             (0x1)
1876 +#define MCFCAU_CA0             (0x2)
1877 +#define MCFCAU_CA1             (0x3)
1878 +#define MCFCAU_CA2             (0x4)
1879 +#define MCFCAU_CA3             (0x5)
1880 +#define MCFCAU_CA4             (0x6)
1881 +#define MCFCAU_CA5             (0x7)
1882 +
1883 + /* CAU Commands */
1884 +#define MCFCAU_CNOP            (0x000)
1885 +#define MCFCAU_LDR             (0x010)
1886 +#define MCFCAU_STR             (0x020)
1887 +#define MCFCAU_ADR             (0x030)
1888 +#define MCFCAU_RADR            (0x040)
1889 +#define MCFCAU_ADRA            (0x050)
1890 +#define MCFCAU_XOR             (0x060)
1891 +#define MCFCAU_ROTL            (0x070)
1892 +#define MCFCAU_MVRA            (0x080)
1893 +#define MCFCAU_MVAR            (0x090)
1894 +#define MCFCAU_AESS            (0x0A0)
1895 +#define MCFCAU_AESIS           (0x0B0)
1896 +#define MCFCAU_AESC            (0x0C0)
1897 +#define MCFCAU_AESIC           (0x0D0)
1898 +#define MCFCAU_AESR            (0x0E0)
1899 +#define MCFCAU_AESIR           (0x0F0)
1900 +#define MCFCAU_DESR            (0x100)
1901 +#define MCFCAU_DESK            (0x110)
1902 +#define MCFCAU_HASH            (0x120)
1903 +#define MCFCAU_SHS             (0x130)
1904 +#define MCFCAU_MDS             (0x140)
1905 +#define MCFCAU_ILL             (0x1F0)
1906 +
1907 +/* DESR Fields */
1908 +#define MCFCAU_IP              (0x08)  /* initial permutation */
1909 +#define MCFCAU_FP              (0x04)  /* final permutation */
1910 +#define MCFCAU_KSL1            (0x00)  /* key schedule left 1 bit */
1911 +#define MCFCAU_KSL2            (0x01)  /* key schedule left 2 bits */
1912 +#define MCFCAU_KSR1            (0x02)  /* key schedule right 1 bit */
1913 +#define MCFCAU_KSR2            (0x03)  /* key schedule right 2 bits */
1914 +
1915 +/* DESK Field */
1916 +#define MCFCAU_DC              (0x01)  /* decrypt key schedule */
1917 +#define MCFCAU_CP              (0x02)  /* check parity */
1918 +
1919 +/* HASH Functions Codes */
1920 +#define MCFCAU_HFF             (0x0)   /* MD5 F() CA1&CA2 | ~CA1&CA3 */
1921 +#define MCFCAU_HFG             (0x1)   /* MD5 G() CA1&CA3 | CA2&~CA3 */
1922 +#define MCFCAU_HFH             (0x2)   /* MD5 H(), SHA Parity() CA1^CA2^CA3 */
1923 +#define MCFCAU_HFI             (0x3)   /* MD5 I() CA2^(CA1|~CA3) */
1924 +#define MCFCAU_HFC             (0x4)   /* SHA Ch() CA1&CA2 ^ ~CA1&CA3 */
1925 +#define MCFCAU_HFM             (0x5)   /* SHA Maj() CA1&CA2 ^ CA1&CA3 ^ CA2&CA3 */
1926 +
1927 +#define MCFCAU_CRA_PRIORITY    (300)
1928 +
1929 +extern spinlock_t mcfcau_lock;
1930 +
1931 +#ifdef DEBUG
1932 +#define DBG(fmt, args...)      printk( "[%s]  " fmt , __FUNCTION__, ## args)
1933 +#else
1934 +#define DBG(fmt, args...)      do{}while(0)
1935 +#endif
1936 +
1937 +#endif