summaryrefslogtreecommitdiffstats
path: root/crypto/asymmetric_keys
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/asymmetric_keys')
-rw-r--r--crypto/asymmetric_keys/asym_tpm.c156
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;
441error_free_tfm: 442error_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 */
563static 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
569static 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
575static 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
581static 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
587static 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
593static 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
599static 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
605static 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
622static 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 */
635static 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
702error_free_tb:
703 kzfree(tb);
704error_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 */
562static int tpm_key_eds_op(struct kernel_pkey_params *params, 713static 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 }