diff options
Diffstat (limited to 'crypto/asymmetric_keys')
-rw-r--r-- | crypto/asymmetric_keys/asym_tpm.c | 156 |
1 files changed, 155 insertions, 1 deletions
diff --git a/crypto/asymmetric_keys/asym_tpm.c b/crypto/asymmetric_keys/asym_tpm.c index a5a5f913a74f..5d4c270463f6 100644 --- a/crypto/asymmetric_keys/asym_tpm.c +++ b/crypto/asymmetric_keys/asym_tpm.c | |||
@@ -435,7 +435,8 @@ static int tpm_key_query(const struct kernel_pkey_params *params, | |||
435 | 435 | ||
436 | info->supported_ops = KEYCTL_SUPPORTS_ENCRYPT | | 436 | info->supported_ops = KEYCTL_SUPPORTS_ENCRYPT | |
437 | KEYCTL_SUPPORTS_DECRYPT | | 437 | KEYCTL_SUPPORTS_DECRYPT | |
438 | KEYCTL_SUPPORTS_VERIFY; | 438 | KEYCTL_SUPPORTS_VERIFY | |
439 | KEYCTL_SUPPORTS_SIGN; | ||
439 | 440 | ||
440 | ret = 0; | 441 | ret = 0; |
441 | error_free_tfm: | 442 | error_free_tfm: |
@@ -557,6 +558,156 @@ error: | |||
557 | } | 558 | } |
558 | 559 | ||
559 | /* | 560 | /* |
561 | * Hash algorithm OIDs plus ASN.1 DER wrappings [RFC4880 sec 5.2.2]. | ||
562 | */ | ||
563 | static const u8 digest_info_md5[] = { | ||
564 | 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, | ||
565 | 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, /* OID */ | ||
566 | 0x05, 0x00, 0x04, 0x10 | ||
567 | }; | ||
568 | |||
569 | static const u8 digest_info_sha1[] = { | ||
570 | 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, | ||
571 | 0x2b, 0x0e, 0x03, 0x02, 0x1a, | ||
572 | 0x05, 0x00, 0x04, 0x14 | ||
573 | }; | ||
574 | |||
575 | static const u8 digest_info_rmd160[] = { | ||
576 | 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, | ||
577 | 0x2b, 0x24, 0x03, 0x02, 0x01, | ||
578 | 0x05, 0x00, 0x04, 0x14 | ||
579 | }; | ||
580 | |||
581 | static const u8 digest_info_sha224[] = { | ||
582 | 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, | ||
583 | 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, | ||
584 | 0x05, 0x00, 0x04, 0x1c | ||
585 | }; | ||
586 | |||
587 | static const u8 digest_info_sha256[] = { | ||
588 | 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, | ||
589 | 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, | ||
590 | 0x05, 0x00, 0x04, 0x20 | ||
591 | }; | ||
592 | |||
593 | static const u8 digest_info_sha384[] = { | ||
594 | 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, | ||
595 | 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, | ||
596 | 0x05, 0x00, 0x04, 0x30 | ||
597 | }; | ||
598 | |||
599 | static const u8 digest_info_sha512[] = { | ||
600 | 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, | ||
601 | 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, | ||
602 | 0x05, 0x00, 0x04, 0x40 | ||
603 | }; | ||
604 | |||
605 | static const struct asn1_template { | ||
606 | const char *name; | ||
607 | const u8 *data; | ||
608 | size_t size; | ||
609 | } asn1_templates[] = { | ||
610 | #define _(X) { #X, digest_info_##X, sizeof(digest_info_##X) } | ||
611 | _(md5), | ||
612 | _(sha1), | ||
613 | _(rmd160), | ||
614 | _(sha256), | ||
615 | _(sha384), | ||
616 | _(sha512), | ||
617 | _(sha224), | ||
618 | { NULL } | ||
619 | #undef _ | ||
620 | }; | ||
621 | |||
622 | static const struct asn1_template *lookup_asn1(const char *name) | ||
623 | { | ||
624 | const struct asn1_template *p; | ||
625 | |||
626 | for (p = asn1_templates; p->name; p++) | ||
627 | if (strcmp(name, p->name) == 0) | ||
628 | return p; | ||
629 | return NULL; | ||
630 | } | ||
631 | |||
632 | /* | ||
633 | * Sign operation is performed with the private key in the TPM. | ||
634 | */ | ||
635 | static int tpm_key_sign(struct tpm_key *tk, | ||
636 | struct kernel_pkey_params *params, | ||
637 | const void *in, void *out) | ||
638 | { | ||
639 | struct tpm_buf *tb; | ||
640 | uint32_t keyhandle; | ||
641 | uint8_t srkauth[SHA1_DIGEST_SIZE]; | ||
642 | uint8_t keyauth[SHA1_DIGEST_SIZE]; | ||
643 | void *asn1_wrapped = NULL; | ||
644 | uint32_t in_len = params->in_len; | ||
645 | int r; | ||
646 | |||
647 | pr_devel("==>%s()\n", __func__); | ||
648 | |||
649 | if (strcmp(params->encoding, "pkcs1")) | ||
650 | return -ENOPKG; | ||
651 | |||
652 | if (params->hash_algo) { | ||
653 | const struct asn1_template *asn1 = | ||
654 | lookup_asn1(params->hash_algo); | ||
655 | |||
656 | if (!asn1) | ||
657 | return -ENOPKG; | ||
658 | |||
659 | /* request enough space for the ASN.1 template + input hash */ | ||
660 | asn1_wrapped = kzalloc(in_len + asn1->size, GFP_KERNEL); | ||
661 | if (!asn1_wrapped) | ||
662 | return -ENOMEM; | ||
663 | |||
664 | /* Copy ASN.1 template, then the input */ | ||
665 | memcpy(asn1_wrapped, asn1->data, asn1->size); | ||
666 | memcpy(asn1_wrapped + asn1->size, in, in_len); | ||
667 | |||
668 | in = asn1_wrapped; | ||
669 | in_len += asn1->size; | ||
670 | } | ||
671 | |||
672 | if (in_len > tk->key_len / 8 - 11) { | ||
673 | r = -EOVERFLOW; | ||
674 | goto error_free_asn1_wrapped; | ||
675 | } | ||
676 | |||
677 | r = -ENOMEM; | ||
678 | tb = kzalloc(sizeof(*tb), GFP_KERNEL); | ||
679 | if (!tb) | ||
680 | goto error_free_asn1_wrapped; | ||
681 | |||
682 | /* TODO: Handle a non-all zero SRK authorization */ | ||
683 | memset(srkauth, 0, sizeof(srkauth)); | ||
684 | |||
685 | r = tpm_loadkey2(tb, SRKHANDLE, srkauth, | ||
686 | tk->blob, tk->blob_len, &keyhandle); | ||
687 | if (r < 0) { | ||
688 | pr_devel("loadkey2 failed (%d)\n", r); | ||
689 | goto error_free_tb; | ||
690 | } | ||
691 | |||
692 | /* TODO: Handle a non-all zero key authorization */ | ||
693 | memset(keyauth, 0, sizeof(keyauth)); | ||
694 | |||
695 | r = tpm_sign(tb, keyhandle, keyauth, in, in_len, out, params->out_len); | ||
696 | if (r < 0) | ||
697 | pr_devel("tpm_sign failed (%d)\n", r); | ||
698 | |||
699 | if (tpm_flushspecific(tb, keyhandle) < 0) | ||
700 | pr_devel("flushspecific failed (%d)\n", r); | ||
701 | |||
702 | error_free_tb: | ||
703 | kzfree(tb); | ||
704 | error_free_asn1_wrapped: | ||
705 | kfree(asn1_wrapped); | ||
706 | pr_devel("<==%s() = %d\n", __func__, r); | ||
707 | return r; | ||
708 | } | ||
709 | |||
710 | /* | ||
560 | * Do encryption, decryption and signing ops. | 711 | * Do encryption, decryption and signing ops. |
561 | */ | 712 | */ |
562 | static int tpm_key_eds_op(struct kernel_pkey_params *params, | 713 | static int tpm_key_eds_op(struct kernel_pkey_params *params, |
@@ -573,6 +724,9 @@ static int tpm_key_eds_op(struct kernel_pkey_params *params, | |||
573 | case kernel_pkey_decrypt: | 724 | case kernel_pkey_decrypt: |
574 | ret = tpm_key_decrypt(tk, params, in, out); | 725 | ret = tpm_key_decrypt(tk, params, in, out); |
575 | break; | 726 | break; |
727 | case kernel_pkey_sign: | ||
728 | ret = tpm_key_sign(tk, params, in, out); | ||
729 | break; | ||
576 | default: | 730 | default: |
577 | BUG(); | 731 | BUG(); |
578 | } | 732 | } |