aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/crypto')
-rw-r--r--drivers/crypto/Kconfig45
-rw-r--r--drivers/crypto/Makefile8
-rw-r--r--drivers/crypto/padlock-aes.c258
-rw-r--r--drivers/crypto/padlock-generic.c63
-rw-r--r--drivers/crypto/padlock-sha.c318
-rw-r--r--drivers/crypto/padlock.c58
-rw-r--r--drivers/crypto/padlock.h17
7 files changed, 624 insertions, 143 deletions
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 4263935443cc..adb554153f67 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -2,22 +2,53 @@ menu "Hardware crypto devices"
2 2
3config CRYPTO_DEV_PADLOCK 3config CRYPTO_DEV_PADLOCK
4 tristate "Support for VIA PadLock ACE" 4 tristate "Support for VIA PadLock ACE"
5 depends on CRYPTO && X86_32 5 depends on X86_32
6 select CRYPTO_ALGAPI
7 default m
6 help 8 help
7 Some VIA processors come with an integrated crypto engine 9 Some VIA processors come with an integrated crypto engine
8 (so called VIA PadLock ACE, Advanced Cryptography Engine) 10 (so called VIA PadLock ACE, Advanced Cryptography Engine)
9 that provides instructions for very fast {en,de}cryption 11 that provides instructions for very fast cryptographic
10 with some algorithms. 12 operations with supported algorithms.
11 13
12 The instructions are used only when the CPU supports them. 14 The instructions are used only when the CPU supports them.
13 Otherwise software encryption is used. If you are unsure, 15 Otherwise software encryption is used.
14 say Y. 16
17 Selecting M for this option will compile a helper module
18 padlock.ko that should autoload all below configured
19 algorithms. Don't worry if your hardware does not support
20 some or all of them. In such case padlock.ko will
21 simply write a single line into the kernel log informing
22 about its failure but everything will keep working fine.
23
24 If you are unsure, say M. The compiled module will be
25 called padlock.ko
15 26
16config CRYPTO_DEV_PADLOCK_AES 27config CRYPTO_DEV_PADLOCK_AES
17 bool "Support for AES in VIA PadLock" 28 tristate "PadLock driver for AES algorithm"
18 depends on CRYPTO_DEV_PADLOCK 29 depends on CRYPTO_DEV_PADLOCK
19 default y 30 select CRYPTO_BLKCIPHER
31 default m
20 help 32 help
21 Use VIA PadLock for AES algorithm. 33 Use VIA PadLock for AES algorithm.
22 34
35 Available in VIA C3 and newer CPUs.
36
37 If unsure say M. The compiled module will be
38 called padlock-aes.ko
39
40config CRYPTO_DEV_PADLOCK_SHA
41 tristate "PadLock driver for SHA1 and SHA256 algorithms"
42 depends on CRYPTO_DEV_PADLOCK
43 select CRYPTO_SHA1
44 select CRYPTO_SHA256
45 default m
46 help
47 Use VIA PadLock for SHA1/SHA256 algorithms.
48
49 Available in VIA C7 and newer processors.
50
51 If unsure say M. The compiled module will be
52 called padlock-sha.ko
53
23endmenu 54endmenu
diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
index 45426ca19a23..4c3d0ec1cf80 100644
--- a/drivers/crypto/Makefile
+++ b/drivers/crypto/Makefile
@@ -1,7 +1,3 @@
1
2obj-$(CONFIG_CRYPTO_DEV_PADLOCK) += padlock.o 1obj-$(CONFIG_CRYPTO_DEV_PADLOCK) += padlock.o
3 2obj-$(CONFIG_CRYPTO_DEV_PADLOCK_AES) += padlock-aes.o
4padlock-objs-$(CONFIG_CRYPTO_DEV_PADLOCK_AES) += padlock-aes.o 3obj-$(CONFIG_CRYPTO_DEV_PADLOCK_SHA) += padlock-sha.o
5
6padlock-objs := padlock-generic.o $(padlock-objs-y)
7
diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c
index b643d71298a9..d4501dc7e650 100644
--- a/drivers/crypto/padlock-aes.c
+++ b/drivers/crypto/padlock-aes.c
@@ -43,11 +43,11 @@
43 * --------------------------------------------------------------------------- 43 * ---------------------------------------------------------------------------
44 */ 44 */
45 45
46#include <crypto/algapi.h>
46#include <linux/module.h> 47#include <linux/module.h>
47#include <linux/init.h> 48#include <linux/init.h>
48#include <linux/types.h> 49#include <linux/types.h>
49#include <linux/errno.h> 50#include <linux/errno.h>
50#include <linux/crypto.h>
51#include <linux/interrupt.h> 51#include <linux/interrupt.h>
52#include <linux/kernel.h> 52#include <linux/kernel.h>
53#include <asm/byteorder.h> 53#include <asm/byteorder.h>
@@ -59,6 +59,17 @@
59#define AES_EXTENDED_KEY_SIZE 64 /* in uint32_t units */ 59#define AES_EXTENDED_KEY_SIZE 64 /* in uint32_t units */
60#define AES_EXTENDED_KEY_SIZE_B (AES_EXTENDED_KEY_SIZE * sizeof(uint32_t)) 60#define AES_EXTENDED_KEY_SIZE_B (AES_EXTENDED_KEY_SIZE * sizeof(uint32_t))
61 61
62/* Control word. */
63struct cword {
64 unsigned int __attribute__ ((__packed__))
65 rounds:4,
66 algo:3,
67 keygen:1,
68 interm:1,
69 encdec:1,
70 ksize:2;
71} __attribute__ ((__aligned__(PADLOCK_ALIGNMENT)));
72
62/* Whenever making any changes to the following 73/* Whenever making any changes to the following
63 * structure *make sure* you keep E, d_data 74 * structure *make sure* you keep E, d_data
64 * and cword aligned on 16 Bytes boundaries!!! */ 75 * and cword aligned on 16 Bytes boundaries!!! */
@@ -286,9 +297,9 @@ aes_hw_extkey_available(uint8_t key_len)
286 return 0; 297 return 0;
287} 298}
288 299
289static inline struct aes_ctx *aes_ctx(struct crypto_tfm *tfm) 300static inline struct aes_ctx *aes_ctx_common(void *ctx)
290{ 301{
291 unsigned long addr = (unsigned long)crypto_tfm_ctx(tfm); 302 unsigned long addr = (unsigned long)ctx;
292 unsigned long align = PADLOCK_ALIGNMENT; 303 unsigned long align = PADLOCK_ALIGNMENT;
293 304
294 if (align <= crypto_tfm_ctx_alignment()) 305 if (align <= crypto_tfm_ctx_alignment())
@@ -296,16 +307,27 @@ static inline struct aes_ctx *aes_ctx(struct crypto_tfm *tfm)
296 return (struct aes_ctx *)ALIGN(addr, align); 307 return (struct aes_ctx *)ALIGN(addr, align);
297} 308}
298 309
310static inline struct aes_ctx *aes_ctx(struct crypto_tfm *tfm)
311{
312 return aes_ctx_common(crypto_tfm_ctx(tfm));
313}
314
315static inline struct aes_ctx *blk_aes_ctx(struct crypto_blkcipher *tfm)
316{
317 return aes_ctx_common(crypto_blkcipher_ctx(tfm));
318}
319
299static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, 320static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
300 unsigned int key_len, u32 *flags) 321 unsigned int key_len)
301{ 322{
302 struct aes_ctx *ctx = aes_ctx(tfm); 323 struct aes_ctx *ctx = aes_ctx(tfm);
303 const __le32 *key = (const __le32 *)in_key; 324 const __le32 *key = (const __le32 *)in_key;
325 u32 *flags = &tfm->crt_flags;
304 uint32_t i, t, u, v, w; 326 uint32_t i, t, u, v, w;
305 uint32_t P[AES_EXTENDED_KEY_SIZE]; 327 uint32_t P[AES_EXTENDED_KEY_SIZE];
306 uint32_t rounds; 328 uint32_t rounds;
307 329
308 if (key_len != 16 && key_len != 24 && key_len != 32) { 330 if (key_len % 8) {
309 *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; 331 *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
310 return -EINVAL; 332 return -EINVAL;
311 } 333 }
@@ -430,80 +452,212 @@ static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
430 padlock_xcrypt_ecb(in, out, ctx->D, &ctx->cword.decrypt, 1); 452 padlock_xcrypt_ecb(in, out, ctx->D, &ctx->cword.decrypt, 1);
431} 453}
432 454
433static unsigned int aes_encrypt_ecb(const struct cipher_desc *desc, u8 *out, 455static struct crypto_alg aes_alg = {
434 const u8 *in, unsigned int nbytes) 456 .cra_name = "aes",
457 .cra_driver_name = "aes-padlock",
458 .cra_priority = PADLOCK_CRA_PRIORITY,
459 .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
460 .cra_blocksize = AES_BLOCK_SIZE,
461 .cra_ctxsize = sizeof(struct aes_ctx),
462 .cra_alignmask = PADLOCK_ALIGNMENT - 1,
463 .cra_module = THIS_MODULE,
464 .cra_list = LIST_HEAD_INIT(aes_alg.cra_list),
465 .cra_u = {
466 .cipher = {
467 .cia_min_keysize = AES_MIN_KEY_SIZE,
468 .cia_max_keysize = AES_MAX_KEY_SIZE,
469 .cia_setkey = aes_set_key,
470 .cia_encrypt = aes_encrypt,
471 .cia_decrypt = aes_decrypt,
472 }
473 }
474};
475
476static int ecb_aes_encrypt(struct blkcipher_desc *desc,
477 struct scatterlist *dst, struct scatterlist *src,
478 unsigned int nbytes)
435{ 479{
436 struct aes_ctx *ctx = aes_ctx(desc->tfm); 480 struct aes_ctx *ctx = blk_aes_ctx(desc->tfm);
437 padlock_xcrypt_ecb(in, out, ctx->E, &ctx->cword.encrypt, 481 struct blkcipher_walk walk;
438 nbytes / AES_BLOCK_SIZE); 482 int err;
439 return nbytes & ~(AES_BLOCK_SIZE - 1); 483
484 blkcipher_walk_init(&walk, dst, src, nbytes);
485 err = blkcipher_walk_virt(desc, &walk);
486
487 while ((nbytes = walk.nbytes)) {
488 padlock_xcrypt_ecb(walk.src.virt.addr, walk.dst.virt.addr,
489 ctx->E, &ctx->cword.encrypt,
490 nbytes / AES_BLOCK_SIZE);
491 nbytes &= AES_BLOCK_SIZE - 1;
492 err = blkcipher_walk_done(desc, &walk, nbytes);
493 }
494
495 return err;
440} 496}
441 497
442static unsigned int aes_decrypt_ecb(const struct cipher_desc *desc, u8 *out, 498static int ecb_aes_decrypt(struct blkcipher_desc *desc,
443 const u8 *in, unsigned int nbytes) 499 struct scatterlist *dst, struct scatterlist *src,
500 unsigned int nbytes)
444{ 501{
445 struct aes_ctx *ctx = aes_ctx(desc->tfm); 502 struct aes_ctx *ctx = blk_aes_ctx(desc->tfm);
446 padlock_xcrypt_ecb(in, out, ctx->D, &ctx->cword.decrypt, 503 struct blkcipher_walk walk;
447 nbytes / AES_BLOCK_SIZE); 504 int err;
448 return nbytes & ~(AES_BLOCK_SIZE - 1); 505
506 blkcipher_walk_init(&walk, dst, src, nbytes);
507 err = blkcipher_walk_virt(desc, &walk);
508
509 while ((nbytes = walk.nbytes)) {
510 padlock_xcrypt_ecb(walk.src.virt.addr, walk.dst.virt.addr,
511 ctx->D, &ctx->cword.decrypt,
512 nbytes / AES_BLOCK_SIZE);
513 nbytes &= AES_BLOCK_SIZE - 1;
514 err = blkcipher_walk_done(desc, &walk, nbytes);
515 }
516
517 return err;
449} 518}
450 519
451static unsigned int aes_encrypt_cbc(const struct cipher_desc *desc, u8 *out, 520static struct crypto_alg ecb_aes_alg = {
452 const u8 *in, unsigned int nbytes) 521 .cra_name = "ecb(aes)",
453{ 522 .cra_driver_name = "ecb-aes-padlock",
454 struct aes_ctx *ctx = aes_ctx(desc->tfm); 523 .cra_priority = PADLOCK_COMPOSITE_PRIORITY,
455 u8 *iv; 524 .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
525 .cra_blocksize = AES_BLOCK_SIZE,
526 .cra_ctxsize = sizeof(struct aes_ctx),
527 .cra_alignmask = PADLOCK_ALIGNMENT - 1,
528 .cra_type = &crypto_blkcipher_type,
529 .cra_module = THIS_MODULE,
530 .cra_list = LIST_HEAD_INIT(ecb_aes_alg.cra_list),
531 .cra_u = {
532 .blkcipher = {
533 .min_keysize = AES_MIN_KEY_SIZE,
534 .max_keysize = AES_MAX_KEY_SIZE,
535 .setkey = aes_set_key,
536 .encrypt = ecb_aes_encrypt,
537 .decrypt = ecb_aes_decrypt,
538 }
539 }
540};
456 541
457 iv = padlock_xcrypt_cbc(in, out, ctx->E, desc->info, 542static int cbc_aes_encrypt(struct blkcipher_desc *desc,
458 &ctx->cword.encrypt, nbytes / AES_BLOCK_SIZE); 543 struct scatterlist *dst, struct scatterlist *src,
459 memcpy(desc->info, iv, AES_BLOCK_SIZE); 544 unsigned int nbytes)
545{
546 struct aes_ctx *ctx = blk_aes_ctx(desc->tfm);
547 struct blkcipher_walk walk;
548 int err;
549
550 blkcipher_walk_init(&walk, dst, src, nbytes);
551 err = blkcipher_walk_virt(desc, &walk);
552
553 while ((nbytes = walk.nbytes)) {
554 u8 *iv = padlock_xcrypt_cbc(walk.src.virt.addr,
555 walk.dst.virt.addr, ctx->E,
556 walk.iv, &ctx->cword.encrypt,
557 nbytes / AES_BLOCK_SIZE);
558 memcpy(walk.iv, iv, AES_BLOCK_SIZE);
559 nbytes &= AES_BLOCK_SIZE - 1;
560 err = blkcipher_walk_done(desc, &walk, nbytes);
561 }
460 562
461 return nbytes & ~(AES_BLOCK_SIZE - 1); 563 return err;
462} 564}
463 565
464static unsigned int aes_decrypt_cbc(const struct cipher_desc *desc, u8 *out, 566static int cbc_aes_decrypt(struct blkcipher_desc *desc,
465 const u8 *in, unsigned int nbytes) 567 struct scatterlist *dst, struct scatterlist *src,
568 unsigned int nbytes)
466{ 569{
467 struct aes_ctx *ctx = aes_ctx(desc->tfm); 570 struct aes_ctx *ctx = blk_aes_ctx(desc->tfm);
468 padlock_xcrypt_cbc(in, out, ctx->D, desc->info, &ctx->cword.decrypt, 571 struct blkcipher_walk walk;
469 nbytes / AES_BLOCK_SIZE); 572 int err;
470 return nbytes & ~(AES_BLOCK_SIZE - 1); 573
574 blkcipher_walk_init(&walk, dst, src, nbytes);
575 err = blkcipher_walk_virt(desc, &walk);
576
577 while ((nbytes = walk.nbytes)) {
578 padlock_xcrypt_cbc(walk.src.virt.addr, walk.dst.virt.addr,
579 ctx->D, walk.iv, &ctx->cword.decrypt,
580 nbytes / AES_BLOCK_SIZE);
581 nbytes &= AES_BLOCK_SIZE - 1;
582 err = blkcipher_walk_done(desc, &walk, nbytes);
583 }
584
585 return err;
471} 586}
472 587
473static struct crypto_alg aes_alg = { 588static struct crypto_alg cbc_aes_alg = {
474 .cra_name = "aes", 589 .cra_name = "cbc(aes)",
475 .cra_driver_name = "aes-padlock", 590 .cra_driver_name = "cbc-aes-padlock",
476 .cra_priority = 300, 591 .cra_priority = PADLOCK_COMPOSITE_PRIORITY,
477 .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 592 .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
478 .cra_blocksize = AES_BLOCK_SIZE, 593 .cra_blocksize = AES_BLOCK_SIZE,
479 .cra_ctxsize = sizeof(struct aes_ctx), 594 .cra_ctxsize = sizeof(struct aes_ctx),
480 .cra_alignmask = PADLOCK_ALIGNMENT - 1, 595 .cra_alignmask = PADLOCK_ALIGNMENT - 1,
596 .cra_type = &crypto_blkcipher_type,
481 .cra_module = THIS_MODULE, 597 .cra_module = THIS_MODULE,
482 .cra_list = LIST_HEAD_INIT(aes_alg.cra_list), 598 .cra_list = LIST_HEAD_INIT(cbc_aes_alg.cra_list),
483 .cra_u = { 599 .cra_u = {
484 .cipher = { 600 .blkcipher = {
485 .cia_min_keysize = AES_MIN_KEY_SIZE, 601 .min_keysize = AES_MIN_KEY_SIZE,
486 .cia_max_keysize = AES_MAX_KEY_SIZE, 602 .max_keysize = AES_MAX_KEY_SIZE,
487 .cia_setkey = aes_set_key, 603 .ivsize = AES_BLOCK_SIZE,
488 .cia_encrypt = aes_encrypt, 604 .setkey = aes_set_key,
489 .cia_decrypt = aes_decrypt, 605 .encrypt = cbc_aes_encrypt,
490 .cia_encrypt_ecb = aes_encrypt_ecb, 606 .decrypt = cbc_aes_decrypt,
491 .cia_decrypt_ecb = aes_decrypt_ecb,
492 .cia_encrypt_cbc = aes_encrypt_cbc,
493 .cia_decrypt_cbc = aes_decrypt_cbc,
494 } 607 }
495 } 608 }
496}; 609};
497 610
498int __init padlock_init_aes(void) 611static int __init padlock_init(void)
499{ 612{
500 printk(KERN_NOTICE PFX "Using VIA PadLock ACE for AES algorithm.\n"); 613 int ret;
614
615 if (!cpu_has_xcrypt) {
616 printk(KERN_ERR PFX "VIA PadLock not detected.\n");
617 return -ENODEV;
618 }
619
620 if (!cpu_has_xcrypt_enabled) {
621 printk(KERN_ERR PFX "VIA PadLock detected, but not enabled. Hmm, strange...\n");
622 return -ENODEV;
623 }
501 624
502 gen_tabs(); 625 gen_tabs();
503 return crypto_register_alg(&aes_alg); 626 if ((ret = crypto_register_alg(&aes_alg)))
627 goto aes_err;
628
629 if ((ret = crypto_register_alg(&ecb_aes_alg)))
630 goto ecb_aes_err;
631
632 if ((ret = crypto_register_alg(&cbc_aes_alg)))
633 goto cbc_aes_err;
634
635 printk(KERN_NOTICE PFX "Using VIA PadLock ACE for AES algorithm.\n");
636
637out:
638 return ret;
639
640cbc_aes_err:
641 crypto_unregister_alg(&ecb_aes_alg);
642ecb_aes_err:
643 crypto_unregister_alg(&aes_alg);
644aes_err:
645 printk(KERN_ERR PFX "VIA PadLock AES initialization failed.\n");
646 goto out;
504} 647}
505 648
506void __exit padlock_fini_aes(void) 649static void __exit padlock_fini(void)
507{ 650{
651 crypto_unregister_alg(&cbc_aes_alg);
652 crypto_unregister_alg(&ecb_aes_alg);
508 crypto_unregister_alg(&aes_alg); 653 crypto_unregister_alg(&aes_alg);
509} 654}
655
656module_init(padlock_init);
657module_exit(padlock_fini);
658
659MODULE_DESCRIPTION("VIA PadLock AES algorithm support");
660MODULE_LICENSE("GPL");
661MODULE_AUTHOR("Michal Ludvig");
662
663MODULE_ALIAS("aes-padlock");
diff --git a/drivers/crypto/padlock-generic.c b/drivers/crypto/padlock-generic.c
deleted file mode 100644
index 18cf0e8274a7..000000000000
--- a/drivers/crypto/padlock-generic.c
+++ /dev/null
@@ -1,63 +0,0 @@
1/*
2 * Cryptographic API.
3 *
4 * Support for VIA PadLock hardware crypto engine.
5 *
6 * Copyright (c) 2004 Michal Ludvig <michal@logix.cz>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 */
13
14#include <linux/module.h>
15#include <linux/init.h>
16#include <linux/types.h>
17#include <linux/errno.h>
18#include <linux/crypto.h>
19#include <asm/byteorder.h>
20#include "padlock.h"
21
22static int __init
23padlock_init(void)
24{
25 int ret = -ENOSYS;
26
27 if (!cpu_has_xcrypt) {
28 printk(KERN_ERR PFX "VIA PadLock not detected.\n");
29 return -ENODEV;
30 }
31
32 if (!cpu_has_xcrypt_enabled) {
33 printk(KERN_ERR PFX "VIA PadLock detected, but not enabled. Hmm, strange...\n");
34 return -ENODEV;
35 }
36
37#ifdef CONFIG_CRYPTO_DEV_PADLOCK_AES
38 if ((ret = padlock_init_aes())) {
39 printk(KERN_ERR PFX "VIA PadLock AES initialization failed.\n");
40 return ret;
41 }
42#endif
43
44 if (ret == -ENOSYS)
45 printk(KERN_ERR PFX "Hmm, VIA PadLock was compiled without any algorithm.\n");
46
47 return ret;
48}
49
50static void __exit
51padlock_fini(void)
52{
53#ifdef CONFIG_CRYPTO_DEV_PADLOCK_AES
54 padlock_fini_aes();
55#endif
56}
57
58module_init(padlock_init);
59module_exit(padlock_fini);
60
61MODULE_DESCRIPTION("VIA PadLock crypto engine support.");
62MODULE_LICENSE("Dual BSD/GPL");
63MODULE_AUTHOR("Michal Ludvig");
diff --git a/drivers/crypto/padlock-sha.c b/drivers/crypto/padlock-sha.c
new file mode 100644
index 000000000000..a781fd23b607
--- /dev/null
+++ b/drivers/crypto/padlock-sha.c
@@ -0,0 +1,318 @@
1/*
2 * Cryptographic API.
3 *
4 * Support for VIA PadLock hardware crypto engine.
5 *
6 * Copyright (c) 2006 Michal Ludvig <michal@logix.cz>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 */
14
15#include <crypto/algapi.h>
16#include <linux/err.h>
17#include <linux/module.h>
18#include <linux/init.h>
19#include <linux/errno.h>
20#include <linux/cryptohash.h>
21#include <linux/interrupt.h>
22#include <linux/kernel.h>
23#include <linux/scatterlist.h>
24#include "padlock.h"
25
26#define SHA1_DEFAULT_FALLBACK "sha1-generic"
27#define SHA1_DIGEST_SIZE 20
28#define SHA1_HMAC_BLOCK_SIZE 64
29
30#define SHA256_DEFAULT_FALLBACK "sha256-generic"
31#define SHA256_DIGEST_SIZE 32
32#define SHA256_HMAC_BLOCK_SIZE 64
33
34struct padlock_sha_ctx {
35 char *data;
36 size_t used;
37 int bypass;
38 void (*f_sha_padlock)(const char *in, char *out, int count);
39 struct hash_desc fallback;
40};
41
42static inline struct padlock_sha_ctx *ctx(struct crypto_tfm *tfm)
43{
44 return crypto_tfm_ctx(tfm);
45}
46
47/* We'll need aligned address on the stack */
48#define NEAREST_ALIGNED(ptr) \
49 ((void *)ALIGN((size_t)(ptr), PADLOCK_ALIGNMENT))
50
51static struct crypto_alg sha1_alg, sha256_alg;
52
53static void padlock_sha_bypass(struct crypto_tfm *tfm)
54{
55 if (ctx(tfm)->bypass)
56 return;
57
58 crypto_hash_init(&ctx(tfm)->fallback);
59 if (ctx(tfm)->data && ctx(tfm)->used) {
60 struct scatterlist sg;
61
62 sg_set_buf(&sg, ctx(tfm)->data, ctx(tfm)->used);
63 crypto_hash_update(&ctx(tfm)->fallback, &sg, sg.length);
64 }
65
66 ctx(tfm)->used = 0;
67 ctx(tfm)->bypass = 1;
68}
69
70static void padlock_sha_init(struct crypto_tfm *tfm)
71{
72 ctx(tfm)->used = 0;
73 ctx(tfm)->bypass = 0;
74}
75
76static void padlock_sha_update(struct crypto_tfm *tfm,
77 const uint8_t *data, unsigned int length)
78{
79 /* Our buffer is always one page. */
80 if (unlikely(!ctx(tfm)->bypass &&
81 (ctx(tfm)->used + length > PAGE_SIZE)))
82 padlock_sha_bypass(tfm);
83
84 if (unlikely(ctx(tfm)->bypass)) {
85 struct scatterlist sg;
86 sg_set_buf(&sg, (uint8_t *)data, length);
87 crypto_hash_update(&ctx(tfm)->fallback, &sg, length);
88 return;
89 }
90
91 memcpy(ctx(tfm)->data + ctx(tfm)->used, data, length);
92 ctx(tfm)->used += length;
93}
94
95static inline void padlock_output_block(uint32_t *src,
96 uint32_t *dst, size_t count)
97{
98 while (count--)
99 *dst++ = swab32(*src++);
100}
101
102static void padlock_do_sha1(const char *in, char *out, int count)
103{
104 /* We can't store directly to *out as it may be unaligned. */
105 /* BTW Don't reduce the buffer size below 128 Bytes!
106 * PadLock microcode needs it that big. */
107 char buf[128+16];
108 char *result = NEAREST_ALIGNED(buf);
109
110 ((uint32_t *)result)[0] = 0x67452301;
111 ((uint32_t *)result)[1] = 0xEFCDAB89;
112 ((uint32_t *)result)[2] = 0x98BADCFE;
113 ((uint32_t *)result)[3] = 0x10325476;
114 ((uint32_t *)result)[4] = 0xC3D2E1F0;
115
116 asm volatile (".byte 0xf3,0x0f,0xa6,0xc8" /* rep xsha1 */
117 : "+S"(in), "+D"(result)
118 : "c"(count), "a"(0));
119
120 padlock_output_block((uint32_t *)result, (uint32_t *)out, 5);
121}
122
123static void padlock_do_sha256(const char *in, char *out, int count)
124{
125 /* We can't store directly to *out as it may be unaligned. */
126 /* BTW Don't reduce the buffer size below 128 Bytes!
127 * PadLock microcode needs it that big. */
128 char buf[128+16];
129 char *result = NEAREST_ALIGNED(buf);
130
131 ((uint32_t *)result)[0] = 0x6A09E667;
132 ((uint32_t *)result)[1] = 0xBB67AE85;
133 ((uint32_t *)result)[2] = 0x3C6EF372;
134 ((uint32_t *)result)[3] = 0xA54FF53A;
135 ((uint32_t *)result)[4] = 0x510E527F;
136 ((uint32_t *)result)[5] = 0x9B05688C;
137 ((uint32_t *)result)[6] = 0x1F83D9AB;
138 ((uint32_t *)result)[7] = 0x5BE0CD19;
139
140 asm volatile (".byte 0xf3,0x0f,0xa6,0xd0" /* rep xsha256 */
141 : "+S"(in), "+D"(result)
142 : "c"(count), "a"(0));
143
144 padlock_output_block((uint32_t *)result, (uint32_t *)out, 8);
145}
146
147static void padlock_sha_final(struct crypto_tfm *tfm, uint8_t *out)
148{
149 if (unlikely(ctx(tfm)->bypass)) {
150 crypto_hash_final(&ctx(tfm)->fallback, out);
151 ctx(tfm)->bypass = 0;
152 return;
153 }
154
155 /* Pass the input buffer to PadLock microcode... */
156 ctx(tfm)->f_sha_padlock(ctx(tfm)->data, out, ctx(tfm)->used);
157
158 ctx(tfm)->used = 0;
159}
160
161static int padlock_cra_init(struct crypto_tfm *tfm)
162{
163 const char *fallback_driver_name = tfm->__crt_alg->cra_name;
164 struct crypto_hash *fallback_tfm;
165
166 /* For now we'll allocate one page. This
167 * could eventually be configurable one day. */
168 ctx(tfm)->data = (char *)__get_free_page(GFP_KERNEL);
169 if (!ctx(tfm)->data)
170 return -ENOMEM;
171
172 /* Allocate a fallback and abort if it failed. */
173 fallback_tfm = crypto_alloc_hash(fallback_driver_name, 0,
174 CRYPTO_ALG_ASYNC |
175 CRYPTO_ALG_NEED_FALLBACK);
176 if (IS_ERR(fallback_tfm)) {
177 printk(KERN_WARNING PFX "Fallback driver '%s' could not be loaded!\n",
178 fallback_driver_name);
179 free_page((unsigned long)(ctx(tfm)->data));
180 return PTR_ERR(fallback_tfm);
181 }
182
183 ctx(tfm)->fallback.tfm = fallback_tfm;
184 return 0;
185}
186
187static int padlock_sha1_cra_init(struct crypto_tfm *tfm)
188{
189 ctx(tfm)->f_sha_padlock = padlock_do_sha1;
190
191 return padlock_cra_init(tfm);
192}
193
194static int padlock_sha256_cra_init(struct crypto_tfm *tfm)
195{
196 ctx(tfm)->f_sha_padlock = padlock_do_sha256;
197
198 return padlock_cra_init(tfm);
199}
200
201static void padlock_cra_exit(struct crypto_tfm *tfm)
202{
203 if (ctx(tfm)->data) {
204 free_page((unsigned long)(ctx(tfm)->data));
205 ctx(tfm)->data = NULL;
206 }
207
208 crypto_free_hash(ctx(tfm)->fallback.tfm);
209 ctx(tfm)->fallback.tfm = NULL;
210}
211
212static struct crypto_alg sha1_alg = {
213 .cra_name = "sha1",
214 .cra_driver_name = "sha1-padlock",
215 .cra_priority = PADLOCK_CRA_PRIORITY,
216 .cra_flags = CRYPTO_ALG_TYPE_DIGEST |
217 CRYPTO_ALG_NEED_FALLBACK,
218 .cra_blocksize = SHA1_HMAC_BLOCK_SIZE,
219 .cra_ctxsize = sizeof(struct padlock_sha_ctx),
220 .cra_module = THIS_MODULE,
221 .cra_list = LIST_HEAD_INIT(sha1_alg.cra_list),
222 .cra_init = padlock_sha1_cra_init,
223 .cra_exit = padlock_cra_exit,
224 .cra_u = {
225 .digest = {
226 .dia_digestsize = SHA1_DIGEST_SIZE,
227 .dia_init = padlock_sha_init,
228 .dia_update = padlock_sha_update,
229 .dia_final = padlock_sha_final,
230 }
231 }
232};
233
234static struct crypto_alg sha256_alg = {
235 .cra_name = "sha256",
236 .cra_driver_name = "sha256-padlock",
237 .cra_priority = PADLOCK_CRA_PRIORITY,
238 .cra_flags = CRYPTO_ALG_TYPE_DIGEST |
239 CRYPTO_ALG_NEED_FALLBACK,
240 .cra_blocksize = SHA256_HMAC_BLOCK_SIZE,
241 .cra_ctxsize = sizeof(struct padlock_sha_ctx),
242 .cra_module = THIS_MODULE,
243 .cra_list = LIST_HEAD_INIT(sha256_alg.cra_list),
244 .cra_init = padlock_sha256_cra_init,
245 .cra_exit = padlock_cra_exit,
246 .cra_u = {
247 .digest = {
248 .dia_digestsize = SHA256_DIGEST_SIZE,
249 .dia_init = padlock_sha_init,
250 .dia_update = padlock_sha_update,
251 .dia_final = padlock_sha_final,
252 }
253 }
254};
255
256static void __init padlock_sha_check_fallbacks(void)
257{
258 if (!crypto_has_hash("sha1", 0, CRYPTO_ALG_ASYNC |
259 CRYPTO_ALG_NEED_FALLBACK))
260 printk(KERN_WARNING PFX
261 "Couldn't load fallback module for sha1.\n");
262
263 if (!crypto_has_hash("sha256", 0, CRYPTO_ALG_ASYNC |
264 CRYPTO_ALG_NEED_FALLBACK))
265 printk(KERN_WARNING PFX
266 "Couldn't load fallback module for sha256.\n");
267}
268
269static int __init padlock_init(void)
270{
271 int rc = -ENODEV;
272
273 if (!cpu_has_phe) {
274 printk(KERN_ERR PFX "VIA PadLock Hash Engine not detected.\n");
275 return -ENODEV;
276 }
277
278 if (!cpu_has_phe_enabled) {
279 printk(KERN_ERR PFX "VIA PadLock detected, but not enabled. Hmm, strange...\n");
280 return -ENODEV;
281 }
282
283 padlock_sha_check_fallbacks();
284
285 rc = crypto_register_alg(&sha1_alg);
286 if (rc)
287 goto out;
288
289 rc = crypto_register_alg(&sha256_alg);
290 if (rc)
291 goto out_unreg1;
292
293 printk(KERN_NOTICE PFX "Using VIA PadLock ACE for SHA1/SHA256 algorithms.\n");
294
295 return 0;
296
297out_unreg1:
298 crypto_unregister_alg(&sha1_alg);
299out:
300 printk(KERN_ERR PFX "VIA PadLock SHA1/SHA256 initialization failed.\n");
301 return rc;
302}
303
304static void __exit padlock_fini(void)
305{
306 crypto_unregister_alg(&sha1_alg);
307 crypto_unregister_alg(&sha256_alg);
308}
309
310module_init(padlock_init);
311module_exit(padlock_fini);
312
313MODULE_DESCRIPTION("VIA PadLock SHA1/SHA256 algorithms support.");
314MODULE_LICENSE("GPL");
315MODULE_AUTHOR("Michal Ludvig");
316
317MODULE_ALIAS("sha1-padlock");
318MODULE_ALIAS("sha256-padlock");
diff --git a/drivers/crypto/padlock.c b/drivers/crypto/padlock.c
new file mode 100644
index 000000000000..d6d7dd5bb98c
--- /dev/null
+++ b/drivers/crypto/padlock.c
@@ -0,0 +1,58 @@
1/*
2 * Cryptographic API.
3 *
4 * Support for VIA PadLock hardware crypto engine.
5 *
6 * Copyright (c) 2006 Michal Ludvig <michal@logix.cz>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 */
14
15#include <linux/module.h>
16#include <linux/init.h>
17#include <linux/errno.h>
18#include <linux/crypto.h>
19#include <linux/cryptohash.h>
20#include <linux/interrupt.h>
21#include <linux/kernel.h>
22#include <linux/scatterlist.h>
23#include "padlock.h"
24
25static int __init padlock_init(void)
26{
27 int success = 0;
28
29 if (crypto_has_cipher("aes-padlock", 0, 0))
30 success++;
31
32 if (crypto_has_hash("sha1-padlock", 0, 0))
33 success++;
34
35 if (crypto_has_hash("sha256-padlock", 0, 0))
36 success++;
37
38 if (!success) {
39 printk(KERN_WARNING PFX "No VIA PadLock drivers have been loaded.\n");
40 return -ENODEV;
41 }
42
43 printk(KERN_NOTICE PFX "%d drivers are available.\n", success);
44
45 return 0;
46}
47
48static void __exit padlock_fini(void)
49{
50}
51
52module_init(padlock_init);
53module_exit(padlock_fini);
54
55MODULE_DESCRIPTION("Load all configured PadLock algorithms.");
56MODULE_LICENSE("GPL");
57MODULE_AUTHOR("Michal Ludvig");
58
diff --git a/drivers/crypto/padlock.h b/drivers/crypto/padlock.h
index b78489bc298a..b728e4518bd1 100644
--- a/drivers/crypto/padlock.h
+++ b/drivers/crypto/padlock.h
@@ -15,22 +15,9 @@
15 15
16#define PADLOCK_ALIGNMENT 16 16#define PADLOCK_ALIGNMENT 16
17 17
18/* Control word. */
19struct cword {
20 unsigned int __attribute__ ((__packed__))
21 rounds:4,
22 algo:3,
23 keygen:1,
24 interm:1,
25 encdec:1,
26 ksize:2;
27} __attribute__ ((__aligned__(PADLOCK_ALIGNMENT)));
28
29#define PFX "padlock: " 18#define PFX "padlock: "
30 19
31#ifdef CONFIG_CRYPTO_DEV_PADLOCK_AES 20#define PADLOCK_CRA_PRIORITY 300
32int padlock_init_aes(void); 21#define PADLOCK_COMPOSITE_PRIORITY 400
33void padlock_fini_aes(void);
34#endif
35 22
36#endif /* _CRYPTO_PADLOCK_H */ 23#endif /* _CRYPTO_PADLOCK_H */