]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/crypto/geode-aes.c
[CRYPTO] geode: move defines into a headerfile
[linux-2.6-omap-h63xx.git] / drivers / crypto / geode-aes.c
1  /* Copyright (C) 2004-2006, Advanced Micro Devices, Inc.
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or
6  * (at your option) any later version.
7  */
8
9 #include <linux/module.h>
10 #include <linux/kernel.h>
11 #include <linux/pci.h>
12 #include <linux/pci_ids.h>
13 #include <linux/crypto.h>
14 #include <linux/spinlock.h>
15 #include <crypto/algapi.h>
16 #include <crypto/aes.h>
17
18 #include <asm/io.h>
19 #include <asm/delay.h>
20
21 #include "geode-aes.h"
22
23 /* Static structures */
24
25 static void __iomem * _iobase;
26 static spinlock_t lock;
27
28 /* Write a 128 bit field (either a writable key or IV) */
29 static inline void
30 _writefield(u32 offset, void *value)
31 {
32         int i;
33         for(i = 0; i < 4; i++)
34                 iowrite32(((u32 *) value)[i], _iobase + offset + (i * 4));
35 }
36
37 /* Read a 128 bit field (either a writable key or IV) */
38 static inline void
39 _readfield(u32 offset, void *value)
40 {
41         int i;
42         for(i = 0; i < 4; i++)
43                 ((u32 *) value)[i] = ioread32(_iobase + offset + (i * 4));
44 }
45
46 static int
47 do_crypt(void *src, void *dst, int len, u32 flags)
48 {
49         u32 status;
50         u32 counter = AES_OP_TIMEOUT;
51
52         iowrite32(virt_to_phys(src), _iobase + AES_SOURCEA_REG);
53         iowrite32(virt_to_phys(dst), _iobase + AES_DSTA_REG);
54         iowrite32(len,  _iobase + AES_LENA_REG);
55
56         /* Start the operation */
57         iowrite32(AES_CTRL_START | flags, _iobase + AES_CTRLA_REG);
58
59         do {
60                 status = ioread32(_iobase + AES_INTR_REG);
61                 cpu_relax();
62         } while(!(status & AES_INTRA_PENDING) && --counter);
63
64         /* Clear the event */
65         iowrite32((status & 0xFF) | AES_INTRA_PENDING, _iobase + AES_INTR_REG);
66         return counter ? 0 : 1;
67 }
68
69 static unsigned int
70 geode_aes_crypt(struct geode_aes_op *op)
71 {
72         u32 flags = 0;
73         unsigned long iflags;
74         int ret;
75
76         if (op->len == 0)
77                 return 0;
78
79         /* If the source and destination is the same, then
80          * we need to turn on the coherent flags, otherwise
81          * we don't need to worry
82          */
83
84         flags |= (AES_CTRL_DCA | AES_CTRL_SCA);
85
86         if (op->dir == AES_DIR_ENCRYPT)
87                 flags |= AES_CTRL_ENCRYPT;
88
89         /* Start the critical section */
90
91         spin_lock_irqsave(&lock, iflags);
92
93         if (op->mode == AES_MODE_CBC) {
94                 flags |= AES_CTRL_CBC;
95                 _writefield(AES_WRITEIV0_REG, op->iv);
96         }
97
98         if (!(op->flags & AES_FLAGS_HIDDENKEY)) {
99                 flags |= AES_CTRL_WRKEY;
100                 _writefield(AES_WRITEKEY0_REG, op->key);
101         }
102
103         ret = do_crypt(op->src, op->dst, op->len, flags);
104         BUG_ON(ret);
105
106         if (op->mode == AES_MODE_CBC)
107                 _readfield(AES_WRITEIV0_REG, op->iv);
108
109         spin_unlock_irqrestore(&lock, iflags);
110
111         return op->len;
112 }
113
114 /* CRYPTO-API Functions */
115
116 static int
117 geode_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int len)
118 {
119         struct geode_aes_op *op = crypto_tfm_ctx(tfm);
120
121         if (len != AES_KEY_LENGTH) {
122                 tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
123                 return -EINVAL;
124         }
125
126         memcpy(op->key, key, len);
127         return 0;
128 }
129
130 static void
131 geode_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
132 {
133         struct geode_aes_op *op = crypto_tfm_ctx(tfm);
134
135         if ((out == NULL) || (in == NULL))
136                 return;
137
138         op->src = (void *) in;
139         op->dst = (void *) out;
140         op->mode = AES_MODE_ECB;
141         op->flags = 0;
142         op->len = AES_MIN_BLOCK_SIZE;
143         op->dir = AES_DIR_ENCRYPT;
144
145         geode_aes_crypt(op);
146 }
147
148
149 static void
150 geode_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
151 {
152         struct geode_aes_op *op = crypto_tfm_ctx(tfm);
153
154         if ((out == NULL) || (in == NULL))
155                 return;
156
157         op->src = (void *) in;
158         op->dst = (void *) out;
159         op->mode = AES_MODE_ECB;
160         op->flags = 0;
161         op->len = AES_MIN_BLOCK_SIZE;
162         op->dir = AES_DIR_DECRYPT;
163
164         geode_aes_crypt(op);
165 }
166
167
168 static struct crypto_alg geode_alg = {
169         .cra_name               =       "aes",
170         .cra_driver_name        =       "geode-aes-128",
171         .cra_priority           =       300,
172         .cra_alignmask          =       15,
173         .cra_flags              =       CRYPTO_ALG_TYPE_CIPHER,
174         .cra_blocksize          =       AES_MIN_BLOCK_SIZE,
175         .cra_ctxsize            =       sizeof(struct geode_aes_op),
176         .cra_module             =       THIS_MODULE,
177         .cra_list               =       LIST_HEAD_INIT(geode_alg.cra_list),
178         .cra_u                  =       {
179                 .cipher = {
180                         .cia_min_keysize        =  AES_KEY_LENGTH,
181                         .cia_max_keysize        =  AES_KEY_LENGTH,
182                         .cia_setkey             =  geode_setkey,
183                         .cia_encrypt            =  geode_encrypt,
184                         .cia_decrypt            =  geode_decrypt
185                 }
186         }
187 };
188
189 static int
190 geode_cbc_decrypt(struct blkcipher_desc *desc,
191                   struct scatterlist *dst, struct scatterlist *src,
192                   unsigned int nbytes)
193 {
194         struct geode_aes_op *op = crypto_blkcipher_ctx(desc->tfm);
195         struct blkcipher_walk walk;
196         int err, ret;
197
198         blkcipher_walk_init(&walk, dst, src, nbytes);
199         err = blkcipher_walk_virt(desc, &walk);
200         memcpy(op->iv, walk.iv, AES_IV_LENGTH);
201
202         while((nbytes = walk.nbytes)) {
203                 op->src = walk.src.virt.addr,
204                 op->dst = walk.dst.virt.addr;
205                 op->mode = AES_MODE_CBC;
206                 op->len = nbytes - (nbytes % AES_MIN_BLOCK_SIZE);
207                 op->dir = AES_DIR_DECRYPT;
208
209                 ret = geode_aes_crypt(op);
210
211                 nbytes -= ret;
212                 err = blkcipher_walk_done(desc, &walk, nbytes);
213         }
214
215         memcpy(walk.iv, op->iv, AES_IV_LENGTH);
216         return err;
217 }
218
219 static int
220 geode_cbc_encrypt(struct blkcipher_desc *desc,
221                   struct scatterlist *dst, struct scatterlist *src,
222                   unsigned int nbytes)
223 {
224         struct geode_aes_op *op = crypto_blkcipher_ctx(desc->tfm);
225         struct blkcipher_walk walk;
226         int err, ret;
227
228         blkcipher_walk_init(&walk, dst, src, nbytes);
229         err = blkcipher_walk_virt(desc, &walk);
230         memcpy(op->iv, walk.iv, AES_IV_LENGTH);
231
232         while((nbytes = walk.nbytes)) {
233                 op->src = walk.src.virt.addr,
234                 op->dst = walk.dst.virt.addr;
235                 op->mode = AES_MODE_CBC;
236                 op->len = nbytes - (nbytes % AES_MIN_BLOCK_SIZE);
237                 op->dir = AES_DIR_ENCRYPT;
238
239                 ret = geode_aes_crypt(op);
240                 nbytes -= ret;
241                 err = blkcipher_walk_done(desc, &walk, nbytes);
242         }
243
244         memcpy(walk.iv, op->iv, AES_IV_LENGTH);
245         return err;
246 }
247
248 static struct crypto_alg geode_cbc_alg = {
249         .cra_name               =       "cbc(aes)",
250         .cra_driver_name        =       "cbc-aes-geode-128",
251         .cra_priority           =       400,
252         .cra_flags              =       CRYPTO_ALG_TYPE_BLKCIPHER,
253         .cra_blocksize          =       AES_MIN_BLOCK_SIZE,
254         .cra_ctxsize            =       sizeof(struct geode_aes_op),
255         .cra_alignmask          =       15,
256         .cra_type               =       &crypto_blkcipher_type,
257         .cra_module             =       THIS_MODULE,
258         .cra_list               =       LIST_HEAD_INIT(geode_cbc_alg.cra_list),
259         .cra_u                  =       {
260                 .blkcipher = {
261                         .min_keysize            =       AES_KEY_LENGTH,
262                         .max_keysize            =       AES_KEY_LENGTH,
263                         .setkey                 =       geode_setkey,
264                         .encrypt                =       geode_cbc_encrypt,
265                         .decrypt                =       geode_cbc_decrypt,
266                         .ivsize                 =       AES_IV_LENGTH,
267                 }
268         }
269 };
270
271 static int
272 geode_ecb_decrypt(struct blkcipher_desc *desc,
273                   struct scatterlist *dst, struct scatterlist *src,
274                   unsigned int nbytes)
275 {
276         struct geode_aes_op *op = crypto_blkcipher_ctx(desc->tfm);
277         struct blkcipher_walk walk;
278         int err, ret;
279
280         blkcipher_walk_init(&walk, dst, src, nbytes);
281         err = blkcipher_walk_virt(desc, &walk);
282
283         while((nbytes = walk.nbytes)) {
284                 op->src = walk.src.virt.addr,
285                 op->dst = walk.dst.virt.addr;
286                 op->mode = AES_MODE_ECB;
287                 op->len = nbytes - (nbytes % AES_MIN_BLOCK_SIZE);
288                 op->dir = AES_DIR_DECRYPT;
289
290                 ret = geode_aes_crypt(op);
291                 nbytes -= ret;
292                 err = blkcipher_walk_done(desc, &walk, nbytes);
293         }
294
295         return err;
296 }
297
298 static int
299 geode_ecb_encrypt(struct blkcipher_desc *desc,
300                   struct scatterlist *dst, struct scatterlist *src,
301                   unsigned int nbytes)
302 {
303         struct geode_aes_op *op = crypto_blkcipher_ctx(desc->tfm);
304         struct blkcipher_walk walk;
305         int err, ret;
306
307         blkcipher_walk_init(&walk, dst, src, nbytes);
308         err = blkcipher_walk_virt(desc, &walk);
309
310         while((nbytes = walk.nbytes)) {
311                 op->src = walk.src.virt.addr,
312                 op->dst = walk.dst.virt.addr;
313                 op->mode = AES_MODE_ECB;
314                 op->len = nbytes - (nbytes % AES_MIN_BLOCK_SIZE);
315                 op->dir = AES_DIR_ENCRYPT;
316
317                 ret = geode_aes_crypt(op);
318                 nbytes -= ret;
319                 ret =  blkcipher_walk_done(desc, &walk, nbytes);
320         }
321
322         return err;
323 }
324
325 static struct crypto_alg geode_ecb_alg = {
326         .cra_name               =       "ecb(aes)",
327         .cra_driver_name        =       "ecb-aes-geode-128",
328         .cra_priority           =       400,
329         .cra_flags              =       CRYPTO_ALG_TYPE_BLKCIPHER,
330         .cra_blocksize          =       AES_MIN_BLOCK_SIZE,
331         .cra_ctxsize            =       sizeof(struct geode_aes_op),
332         .cra_alignmask          =       15,
333         .cra_type               =       &crypto_blkcipher_type,
334         .cra_module             =       THIS_MODULE,
335         .cra_list               =       LIST_HEAD_INIT(geode_ecb_alg.cra_list),
336         .cra_u                  =       {
337                 .blkcipher = {
338                         .min_keysize            =       AES_KEY_LENGTH,
339                         .max_keysize            =       AES_KEY_LENGTH,
340                         .setkey                 =       geode_setkey,
341                         .encrypt                =       geode_ecb_encrypt,
342                         .decrypt                =       geode_ecb_decrypt,
343                 }
344         }
345 };
346
347 static void
348 geode_aes_remove(struct pci_dev *dev)
349 {
350         crypto_unregister_alg(&geode_alg);
351         crypto_unregister_alg(&geode_ecb_alg);
352         crypto_unregister_alg(&geode_cbc_alg);
353
354         pci_iounmap(dev, _iobase);
355         _iobase = NULL;
356
357         pci_release_regions(dev);
358         pci_disable_device(dev);
359 }
360
361
362 static int
363 geode_aes_probe(struct pci_dev *dev, const struct pci_device_id *id)
364 {
365         int ret;
366
367         if ((ret = pci_enable_device(dev)))
368                 return ret;
369
370         if ((ret = pci_request_regions(dev, "geode-aes-128")))
371                 goto eenable;
372
373         _iobase = pci_iomap(dev, 0, 0);
374
375         if (_iobase == NULL) {
376                 ret = -ENOMEM;
377                 goto erequest;
378         }
379
380         spin_lock_init(&lock);
381
382         /* Clear any pending activity */
383         iowrite32(AES_INTR_PENDING | AES_INTR_MASK, _iobase + AES_INTR_REG);
384
385         if ((ret = crypto_register_alg(&geode_alg)))
386                 goto eiomap;
387
388         if ((ret = crypto_register_alg(&geode_ecb_alg)))
389                 goto ealg;
390
391         if ((ret = crypto_register_alg(&geode_cbc_alg)))
392                 goto eecb;
393
394         printk(KERN_NOTICE "geode-aes: GEODE AES engine enabled.\n");
395         return 0;
396
397  eecb:
398         crypto_unregister_alg(&geode_ecb_alg);
399
400  ealg:
401         crypto_unregister_alg(&geode_alg);
402
403  eiomap:
404         pci_iounmap(dev, _iobase);
405
406  erequest:
407         pci_release_regions(dev);
408
409  eenable:
410         pci_disable_device(dev);
411
412         printk(KERN_ERR "geode-aes:  GEODE AES initialization failed.\n");
413         return ret;
414 }
415
416 static struct pci_device_id geode_aes_tbl[] = {
417         { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LX_AES, PCI_ANY_ID, PCI_ANY_ID} ,
418         { 0, }
419 };
420
421 MODULE_DEVICE_TABLE(pci, geode_aes_tbl);
422
423 static struct pci_driver geode_aes_driver = {
424         .name = "Geode LX AES",
425         .id_table = geode_aes_tbl,
426         .probe = geode_aes_probe,
427         .remove = __devexit_p(geode_aes_remove)
428 };
429
430 static int __init
431 geode_aes_init(void)
432 {
433         return pci_register_driver(&geode_aes_driver);
434 }
435
436 static void __exit
437 geode_aes_exit(void)
438 {
439         pci_unregister_driver(&geode_aes_driver);
440 }
441
442 MODULE_AUTHOR("Advanced Micro Devices, Inc.");
443 MODULE_DESCRIPTION("Geode LX Hardware AES driver");
444 MODULE_LICENSE("GPL");
445
446 module_init(geode_aes_init);
447 module_exit(geode_aes_exit);