diff options
Diffstat (limited to 'drivers/crypto')
-rw-r--r-- | drivers/crypto/Kconfig | 45 | ||||
-rw-r--r-- | drivers/crypto/Makefile | 8 | ||||
-rw-r--r-- | drivers/crypto/padlock-aes.c | 258 | ||||
-rw-r--r-- | drivers/crypto/padlock-generic.c | 63 | ||||
-rw-r--r-- | drivers/crypto/padlock-sha.c | 318 | ||||
-rw-r--r-- | drivers/crypto/padlock.c | 58 | ||||
-rw-r--r-- | drivers/crypto/padlock.h | 17 |
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 | ||
3 | config CRYPTO_DEV_PADLOCK | 3 | config 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 | ||
16 | config CRYPTO_DEV_PADLOCK_AES | 27 | config 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 | |||
40 | config 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 | |||
23 | endmenu | 54 | endmenu |
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 | |||
2 | obj-$(CONFIG_CRYPTO_DEV_PADLOCK) += padlock.o | 1 | obj-$(CONFIG_CRYPTO_DEV_PADLOCK) += padlock.o |
3 | 2 | obj-$(CONFIG_CRYPTO_DEV_PADLOCK_AES) += padlock-aes.o | |
4 | padlock-objs-$(CONFIG_CRYPTO_DEV_PADLOCK_AES) += padlock-aes.o | 3 | obj-$(CONFIG_CRYPTO_DEV_PADLOCK_SHA) += padlock-sha.o |
5 | |||
6 | padlock-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. */ | ||
63 | struct 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 | ||
289 | static inline struct aes_ctx *aes_ctx(struct crypto_tfm *tfm) | 300 | static 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 | ||
310 | static inline struct aes_ctx *aes_ctx(struct crypto_tfm *tfm) | ||
311 | { | ||
312 | return aes_ctx_common(crypto_tfm_ctx(tfm)); | ||
313 | } | ||
314 | |||
315 | static inline struct aes_ctx *blk_aes_ctx(struct crypto_blkcipher *tfm) | ||
316 | { | ||
317 | return aes_ctx_common(crypto_blkcipher_ctx(tfm)); | ||
318 | } | ||
319 | |||
299 | static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, | 320 | static 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 | ||
433 | static unsigned int aes_encrypt_ecb(const struct cipher_desc *desc, u8 *out, | 455 | static 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 | |||
476 | static 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 | ||
442 | static unsigned int aes_decrypt_ecb(const struct cipher_desc *desc, u8 *out, | 498 | static 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 | ||
451 | static unsigned int aes_encrypt_cbc(const struct cipher_desc *desc, u8 *out, | 520 | static 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, | 542 | static 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 | ||
464 | static unsigned int aes_decrypt_cbc(const struct cipher_desc *desc, u8 *out, | 566 | static 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 | ||
473 | static struct crypto_alg aes_alg = { | 588 | static 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 | ||
498 | int __init padlock_init_aes(void) | 611 | static 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 | |||
637 | out: | ||
638 | return ret; | ||
639 | |||
640 | cbc_aes_err: | ||
641 | crypto_unregister_alg(&ecb_aes_alg); | ||
642 | ecb_aes_err: | ||
643 | crypto_unregister_alg(&aes_alg); | ||
644 | aes_err: | ||
645 | printk(KERN_ERR PFX "VIA PadLock AES initialization failed.\n"); | ||
646 | goto out; | ||
504 | } | 647 | } |
505 | 648 | ||
506 | void __exit padlock_fini_aes(void) | 649 | static 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 | |||
656 | module_init(padlock_init); | ||
657 | module_exit(padlock_fini); | ||
658 | |||
659 | MODULE_DESCRIPTION("VIA PadLock AES algorithm support"); | ||
660 | MODULE_LICENSE("GPL"); | ||
661 | MODULE_AUTHOR("Michal Ludvig"); | ||
662 | |||
663 | MODULE_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 | |||
22 | static int __init | ||
23 | padlock_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 | |||
50 | static void __exit | ||
51 | padlock_fini(void) | ||
52 | { | ||
53 | #ifdef CONFIG_CRYPTO_DEV_PADLOCK_AES | ||
54 | padlock_fini_aes(); | ||
55 | #endif | ||
56 | } | ||
57 | |||
58 | module_init(padlock_init); | ||
59 | module_exit(padlock_fini); | ||
60 | |||
61 | MODULE_DESCRIPTION("VIA PadLock crypto engine support."); | ||
62 | MODULE_LICENSE("Dual BSD/GPL"); | ||
63 | MODULE_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 | |||
34 | struct 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 | |||
42 | static 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 | |||
51 | static struct crypto_alg sha1_alg, sha256_alg; | ||
52 | |||
53 | static 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 | |||
70 | static void padlock_sha_init(struct crypto_tfm *tfm) | ||
71 | { | ||
72 | ctx(tfm)->used = 0; | ||
73 | ctx(tfm)->bypass = 0; | ||
74 | } | ||
75 | |||
76 | static 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 | |||
95 | static 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 | |||
102 | static 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 | |||
123 | static 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 | |||
147 | static 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 | |||
161 | static 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 | |||
187 | static 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 | |||
194 | static 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 | |||
201 | static 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 | |||
212 | static 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 | |||
234 | static 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 | |||
256 | static 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 | |||
269 | static 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 | |||
297 | out_unreg1: | ||
298 | crypto_unregister_alg(&sha1_alg); | ||
299 | out: | ||
300 | printk(KERN_ERR PFX "VIA PadLock SHA1/SHA256 initialization failed.\n"); | ||
301 | return rc; | ||
302 | } | ||
303 | |||
304 | static void __exit padlock_fini(void) | ||
305 | { | ||
306 | crypto_unregister_alg(&sha1_alg); | ||
307 | crypto_unregister_alg(&sha256_alg); | ||
308 | } | ||
309 | |||
310 | module_init(padlock_init); | ||
311 | module_exit(padlock_fini); | ||
312 | |||
313 | MODULE_DESCRIPTION("VIA PadLock SHA1/SHA256 algorithms support."); | ||
314 | MODULE_LICENSE("GPL"); | ||
315 | MODULE_AUTHOR("Michal Ludvig"); | ||
316 | |||
317 | MODULE_ALIAS("sha1-padlock"); | ||
318 | MODULE_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 | |||
25 | static 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 | |||
48 | static void __exit padlock_fini(void) | ||
49 | { | ||
50 | } | ||
51 | |||
52 | module_init(padlock_init); | ||
53 | module_exit(padlock_fini); | ||
54 | |||
55 | MODULE_DESCRIPTION("Load all configured PadLock algorithms."); | ||
56 | MODULE_LICENSE("GPL"); | ||
57 | MODULE_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. */ | ||
19 | struct 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 |
32 | int padlock_init_aes(void); | 21 | #define PADLOCK_COMPOSITE_PRIORITY 400 |
33 | void padlock_fini_aes(void); | ||
34 | #endif | ||
35 | 22 | ||
36 | #endif /* _CRYPTO_PADLOCK_H */ | 23 | #endif /* _CRYPTO_PADLOCK_H */ |