1 /* tpm2.c - Supporting TPM routines for the IBM TSS
2 * Copyright (C) 2021 James Bottomley <James.Bottomley@HansenPartnership.com>
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <https://www.gnu.org/licenses/>.
18 * SPDX-License-Identifier: GPL-3.0-or-later
30 #include <arpa/inet.h>
34 #include "../common/i18n.h"
35 #include "../common/sexp-parse.h"
38 tpm2_start (TSS_CONTEXT **tssc)
40 return TSS_start(tssc);
44 tpm2_end (TSS_CONTEXT *tssc)
50 tpm2_get_parent (TSS_CONTEXT *tssc, TPM_HANDLE p)
53 TPM2B_SENSITIVE_CREATE inSensitive;
54 TPM2B_PUBLIC inPublic;
55 TPM_HANDLE objectHandle;
57 p = tpm2_handle_int(tssc, p);
58 if (tpm2_handle_mso(tssc, p, TPM_HT_PERSISTENT))
59 return p; /* should only be permanent */
61 /* assume no hierarchy auth */
62 VAL_2B (inSensitive.sensitive.userAuth, size) = 0;
63 /* no sensitive date for storage keys */
64 VAL_2B (inSensitive.sensitive.data, size) = 0;
66 /* public parameters for a P-256 EC key */
67 inPublic.publicArea.type = TPM_ALG_ECC;
68 inPublic.publicArea.nameAlg = TPM_ALG_SHA256;
69 VAL (inPublic.publicArea.objectAttributes) =
71 TPMA_OBJECT_SENSITIVEDATAORIGIN |
72 TPMA_OBJECT_USERWITHAUTH |
74 TPMA_OBJECT_RESTRICTED |
75 TPMA_OBJECT_FIXEDPARENT |
78 inPublic.publicArea.parameters.eccDetail.symmetric.algorithm = TPM_ALG_AES;
79 inPublic.publicArea.parameters.eccDetail.symmetric.keyBits.aes = 128;
80 inPublic.publicArea.parameters.eccDetail.symmetric.mode.aes = TPM_ALG_CFB;
81 inPublic.publicArea.parameters.eccDetail.scheme.scheme = TPM_ALG_NULL;
82 inPublic.publicArea.parameters.eccDetail.curveID = TPM_ECC_NIST_P256;
83 inPublic.publicArea.parameters.eccDetail.kdf.scheme = TPM_ALG_NULL;
85 VAL_2B (inPublic.publicArea.unique.ecc.x, size) = 0;
86 VAL_2B (inPublic.publicArea.unique.ecc.y, size) = 0;
87 VAL_2B (inPublic.publicArea.authPolicy, size) = 0;
89 rc = tpm2_CreatePrimary (tssc, p, &inSensitive, &inPublic, &objectHandle);
92 tpm2_error (rc, "TSS_CreatePrimary");
99 tpm2_flush_handle (TSS_CONTEXT *tssc, TPM_HANDLE h)
101 /* only flush volatile handles */
102 if (tpm2_handle_mso(tssc, h, TPM_HT_PERSISTENT))
105 tpm2_FlushContext(tssc, h);
109 tpm2_get_hmac_handle (TSS_CONTEXT *tssc, TPM_HANDLE *handle,
113 TPMT_SYM_DEF symmetric;
115 symmetric.algorithm = TPM_ALG_AES;
116 symmetric.keyBits.aes = 128;
117 symmetric.mode.aes = TPM_ALG_CFB;
119 rc = tpm2_StartAuthSession(tssc, salt_key, TPM_RH_NULL, TPM_SE_HMAC,
120 &symmetric, TPM_ALG_SHA256, handle, NULL);
123 tpm2_error (rc, "TPM2_StartAuthSession");
131 tpm2_pre_auth (ctrl_t ctrl, TSS_CONTEXT *tssc,
132 gpg_error_t (*pin_cb)(ctrl_t ctrl, const char *info,
134 TPM_HANDLE *ah, char **auth)
139 rc = pin_cb (ctrl, _("TPM Key Passphrase"), auth);
145 * TPMs can't accept a longer passphrase than the name algorithm.
146 * We hard code the name algorithm to SHA256 so the max passphrase
151 log_error ("Truncating Passphrase to TPM allowed 32\n");
155 rc = tpm2_get_hmac_handle (tssc, ah, TPM_RH_NULL);
161 tpm2_post_auth (TSS_CONTEXT *tssc, TPM_RC rc, TPM_HANDLE ah,
162 char **auth, const char *cmd_str)
168 tpm2_error (rc, cmd_str);
169 tpm2_flush_handle (tssc, ah);
172 case TPM_RC_BAD_AUTH:
173 case TPM_RC_AUTH_FAIL:
174 return GPG_ERR_BAD_PASSPHRASE;
182 static unsigned char *
183 make_tpm2_shadow_info (uint32_t parent, const char *pub, int pub_len,
184 const char *priv, int priv_len, size_t *len)
189 gcry_sexp_build (&s_exp, NULL, "(%u%b%b)", parent, pub_len, pub,
192 *len = gcry_sexp_sprint (s_exp, GCRYSEXP_FMT_CANON, NULL, 0);
193 info = xtrymalloc (*len);
196 gcry_sexp_sprint (s_exp, GCRYSEXP_FMT_CANON, info, *len);
199 gcry_sexp_release (s_exp);
200 return (unsigned char *)info;
204 parse_tpm2_shadow_info (const unsigned char *shadow_info,
206 const char **pub, int *pub_len,
207 const char **priv, int *priv_len)
209 const unsigned char *s;
215 return gpg_error (GPG_ERR_INV_SEXP);
219 return gpg_error (GPG_ERR_INV_SEXP);
221 for (i = 0; i < n; i++)
224 *parent += atoi_1(s+i);
230 return gpg_error (GPG_ERR_INV_SEXP);
238 return gpg_error (GPG_ERR_INV_SEXP);
247 tpm2_load_key (TSS_CONTEXT *tssc, const unsigned char *shadow_info,
248 TPM_HANDLE *key, TPMI_ALG_PUBLIC *type)
251 TPM_HANDLE parentHandle;
252 PRIVATE_2B inPrivate;
253 TPM2B_PUBLIC inPublic;
254 const char *pub, *priv;
255 int ret, pub_len, priv_len;
260 ret = parse_tpm2_shadow_info (shadow_info, &parent, &pub, &pub_len,
265 parentHandle = tpm2_get_parent (tssc, parent);
269 TPM2B_PRIVATE_Unmarshal ((TPM2B_PRIVATE *)&inPrivate, &buf, &size);
273 TPM2B_PUBLIC_Unmarshal (&inPublic, &buf, &size, FALSE);
275 *type = inPublic.publicArea.type;
277 rc = tpm2_Load (tssc, parentHandle, &inPrivate, &inPublic, key,
280 tpm2_flush_handle (tssc, parentHandle);
282 if (rc != TPM_RC_SUCCESS)
284 tpm2_error (rc, "TPM2_Load");
292 tpm2_sign (ctrl_t ctrl, TSS_CONTEXT *tssc, TPM_HANDLE key,
293 gpg_error_t (*pin_cb)(ctrl_t ctrl, const char *info,
295 TPMI_ALG_PUBLIC type,
296 const unsigned char *digest, size_t digestlen,
297 unsigned char **r_sig, size_t *r_siglen)
301 TPMT_SIG_SCHEME inScheme;
302 TPMT_SIGNATURE signature;
306 /* The TPM insists on knowing the digest type, so
307 * calculate that from the size */
311 inScheme.details.rsassa.hashAlg = TPM_ALG_SHA1;
314 inScheme.details.rsassa.hashAlg = TPM_ALG_SHA256;
317 inScheme.details.rsassa.hashAlg = TPM_ALG_SHA384;
319 #ifdef TPM_ALG_SHA512
321 inScheme.details.rsassa.hashAlg = TPM_ALG_SHA512;
325 log_error ("Unknown signature digest length, cannot deduce hash type for TPM\n");
326 return GPG_ERR_NO_SIGNATURE_SCHEME;
328 digest2b.size = digestlen;
329 memcpy (digest2b.buffer, digest, digestlen);
331 if (type == TPM_ALG_RSA)
332 inScheme.scheme = TPM_ALG_RSASSA;
333 else if (type == TPM_ALG_ECC)
334 inScheme.scheme = TPM_ALG_ECDSA;
336 return GPG_ERR_PUBKEY_ALGO;
338 ret = tpm2_pre_auth (ctrl, tssc, pin_cb, &ah, &auth);
341 ret = tpm2_Sign (tssc, key, &digest2b, &inScheme, &signature, ah, auth);
342 ret = tpm2_post_auth (tssc, ret, ah, &auth, "TPM2_Sign");
346 if (type == TPM_ALG_RSA)
347 *r_siglen = VAL_2B (signature.signature.rsassa.sig, size);
348 else if (type == TPM_ALG_ECC)
349 *r_siglen = VAL_2B (signature.signature.ecdsa.signatureR, size)
350 + VAL_2B (signature.signature.ecdsa.signatureS, size);
352 *r_sig = xtrymalloc (*r_siglen);
354 return GPG_ERR_ENOMEM;
356 if (type == TPM_ALG_RSA)
358 memcpy (*r_sig, VAL_2B (signature.signature.rsassa.sig, buffer),
361 else if (type == TPM_ALG_ECC)
363 memcpy (*r_sig, VAL_2B (signature.signature.ecdsa.signatureR, buffer),
364 VAL_2B (signature.signature.ecdsa.signatureR, size));
365 memcpy (*r_sig + VAL_2B (signature.signature.ecdsa.signatureR, size),
366 VAL_2B (signature.signature.ecdsa.signatureS, buffer),
367 VAL_2B (signature.signature.ecdsa.signatureS, size));
374 sexp_to_tpm2_sensitive_ecc (TPMT_SENSITIVE *s, gcry_sexp_t key)
381 s->sensitiveType = TPM_ALG_ECC;
382 VAL_2B (s->seedValue, size) = 0;
384 l = gcry_sexp_find_token (key, "d", 0);
387 d = gcry_sexp_nth_mpi (l, 1, GCRYMPI_FMT_USG);
388 gcry_sexp_release (l);
389 len = sizeof (VAL_2B (s->sensitive.ecc, buffer));
390 rc = gcry_mpi_print (GCRYMPI_FMT_USG, VAL_2B (s->sensitive.ecc, buffer),
392 VAL_2B (s->sensitive.ecc, size) = len;
393 gcry_mpi_release (d);
398 /* try to match the libgcrypt curve names to known TPM parameters.
400 * As of 2018 the TCG defined curves are only NIST
401 * (192,224,256,384,521) Barreto-Naehring (256,638) and the Chinese
402 * SM2 (256), which means only the NIST ones overlap with libgcrypt */
407 { "NIST P-192", TPM_ECC_NIST_P192 },
408 { "prime192v1", TPM_ECC_NIST_P192 },
409 { "secp192r1", TPM_ECC_NIST_P192 },
410 { "nistp192", TPM_ECC_NIST_P192 },
411 { "NIST P-224", TPM_ECC_NIST_P224 },
412 { "secp224r1", TPM_ECC_NIST_P224 },
413 { "nistp224", TPM_ECC_NIST_P224 },
414 { "NIST P-256", TPM_ECC_NIST_P256 },
415 { "prime256v1", TPM_ECC_NIST_P256 },
416 { "secp256r1", TPM_ECC_NIST_P256 },
417 { "nistp256", TPM_ECC_NIST_P256 },
418 { "NIST P-384", TPM_ECC_NIST_P384 },
419 { "secp384r1", TPM_ECC_NIST_P384 },
420 { "nistp384", TPM_ECC_NIST_P384 },
421 { "NIST P-521", TPM_ECC_NIST_P521 },
422 { "secp521r1", TPM_ECC_NIST_P521 },
423 { "nistp521", TPM_ECC_NIST_P521 },
427 tpm2_ecc_curve (const char *curve_name, TPMI_ECC_CURVE *c)
431 for (i = 0; i < DIM (tpm2_curves); i++)
432 if (strcmp (tpm2_curves[i].name, curve_name) == 0)
434 if (i == DIM (tpm2_curves))
436 log_error ("curve %s does not match any available TPM curves\n", curve_name);
437 return GPG_ERR_UNKNOWN_CURVE;
440 *c = tpm2_curves[i].c;
446 sexp_to_tpm2_public_ecc (TPMT_PUBLIC *p, gcry_sexp_t key)
450 int rc = GPG_ERR_BAD_PUBKEY;
452 TPMI_ECC_CURVE curve;
455 l = gcry_sexp_find_token (key, "curve", 0);
458 curve_name = gcry_sexp_nth_string (l, 1);
461 rc = tpm2_ecc_curve (curve_name, &curve);
462 gcry_free (curve_name);
465 gcry_sexp_release (l);
467 l = gcry_sexp_find_token (key, "q", 0);
470 q = gcry_sexp_nth_data (l, 1, &len);
471 /* This is a point representation, the first byte tells you what
472 * type. The only format we understand is uncompressed (0x04)
473 * which has layout 0x04 | x | y */
476 log_error ("Point format for q is not uncompressed\n");
481 /* now should have to equal sized big endian point numbers */
482 if ((len & 0x01) == 1)
484 log_error ("Point format for q has incorrect length\n");
490 p->type = TPM_ALG_ECC;
491 p->nameAlg = TPM_ALG_SHA256;
492 VAL (p->objectAttributes) = TPMA_OBJECT_NODA |
494 TPMA_OBJECT_DECRYPT |
495 TPMA_OBJECT_USERWITHAUTH;
496 VAL_2B (p->authPolicy, size) = 0;
497 p->parameters.eccDetail.symmetric.algorithm = TPM_ALG_NULL;
498 p->parameters.eccDetail.scheme.scheme = TPM_ALG_NULL;
499 p->parameters.eccDetail.curveID = curve;
500 p->parameters.eccDetail.kdf.scheme = TPM_ALG_NULL;
501 memcpy (VAL_2B (p->unique.ecc.x, buffer), q, len);
502 VAL_2B (p->unique.ecc.x, size) = len;
503 memcpy (VAL_2B (p->unique.ecc.y, buffer), q + len, len);
504 VAL_2B (p->unique.ecc.y, size) = len;
506 gcry_sexp_release (l);
511 sexp_to_tpm2_sensitive_rsa (TPMT_SENSITIVE *s, gcry_sexp_t key)
518 s->sensitiveType = TPM_ALG_RSA;
519 VAL_2B (s->seedValue, size) = 0;
521 l = gcry_sexp_find_token (key, "p", 0);
524 p = gcry_sexp_nth_mpi (l, 1, GCRYMPI_FMT_USG);
525 gcry_sexp_release (l);
526 len = sizeof (VAL_2B (s->sensitive.rsa, buffer));
527 rc = gcry_mpi_print (GCRYMPI_FMT_USG, VAL_2B (s->sensitive.rsa, buffer),
529 VAL_2B (s->sensitive.rsa, size) = len;
530 gcry_mpi_release (p);
536 sexp_to_tpm2_public_rsa (TPMT_PUBLIC *p, gcry_sexp_t key)
542 /* longer than an int */
543 unsigned char ebuf[5];
546 p->type = TPM_ALG_RSA;
547 p->nameAlg = TPM_ALG_SHA256;
548 VAL (p->objectAttributes) = TPMA_OBJECT_NODA |
549 TPMA_OBJECT_DECRYPT |
551 TPMA_OBJECT_USERWITHAUTH;
552 VAL_2B (p->authPolicy, size) = 0;
553 p->parameters.rsaDetail.symmetric.algorithm = TPM_ALG_NULL;
554 p->parameters.rsaDetail.scheme.scheme = TPM_ALG_NULL;
556 l = gcry_sexp_find_token (key, "n", 0);
559 n = gcry_sexp_nth_mpi (l, 1, GCRYMPI_FMT_USG);
560 gcry_sexp_release (l);
561 len = sizeof (VAL_2B (p->unique.rsa, buffer));
562 p->parameters.rsaDetail.keyBits = gcry_mpi_get_nbits (n);
563 rc = gcry_mpi_print (GCRYMPI_FMT_USG, VAL_2B (p->unique.rsa, buffer),
565 VAL_2B (p->unique.rsa, size) = len;
566 gcry_mpi_release (n);
570 l = gcry_sexp_find_token (key, "e", 0);
573 e = gcry_sexp_nth_mpi (l, 1, GCRYMPI_FMT_USG);
574 gcry_sexp_release (l);
576 rc = gcry_mpi_print (GCRYMPI_FMT_USG, ebuf, len, &len, e);
577 gcry_mpi_release (e);
583 /* MPI are simply big endian integers, so convert to uint32 */
584 for (i = 0; i < len; i++)
590 p->parameters.rsaDetail.exponent = 0;
592 p->parameters.rsaDetail.exponent = exp;
597 sexp_to_tpm2(TPMT_PUBLIC *p, TPMT_SENSITIVE *s, gcry_sexp_t s_skey)
602 /* find the value of (private-key */
603 l1 = gcry_sexp_nth (s_skey, 1);
607 l2 = gcry_sexp_find_token (l1, "rsa", 0);
610 rc = sexp_to_tpm2_public_rsa (p, l2);
612 rc = sexp_to_tpm2_sensitive_rsa (s, l2);
616 l2 = gcry_sexp_find_token (l1, "ecc", 0);
619 rc = sexp_to_tpm2_public_ecc (p, l2);
621 rc = sexp_to_tpm2_sensitive_ecc (s, l2);
624 gcry_sexp_release (l2);
627 gcry_sexp_release (l1);
631 /* copied from TPM implementation code */
633 tpm2_ObjectPublic_GetName (NAME_2B *name,
634 TPMT_PUBLIC *tpmtPublic)
637 uint16_t written = 0;
639 uint32_t sizeInBytes;
640 uint8_t buffer[MAX_RESPONSE_SIZE];
642 /* marshal the TPMT_PUBLIC */
645 INT32 size = MAX_RESPONSE_SIZE;
646 uint8_t *buffer1 = buffer;
647 rc = TSS_TPMT_PUBLIC_Marshal (tpmtPublic, &written, &buffer1, &size);
649 /* hash the public area */
652 sizeInBytes = TSS_GetDigestSize (tpmtPublic->nameAlg);
653 digest.hashAlg = tpmtPublic->nameAlg; /* Name digest algorithm */
654 /* generate the TPMT_HA */
655 rc = TSS_Hash_Generate (&digest, written, buffer, 0, NULL);
659 TPMI_ALG_HASH nameAlgNbo;
661 /* copy the digest */
662 memcpy (name->name + sizeof (TPMI_ALG_HASH),
663 (uint8_t *)&digest.digest, sizeInBytes);
664 /* copy the hash algorithm */
665 nameAlgNbo = htons (tpmtPublic->nameAlg);
666 memcpy (name->name, (uint8_t *)&nameAlgNbo, sizeof (TPMI_ALG_HASH));
668 name->size = sizeInBytes + sizeof (TPMI_ALG_HASH);
674 * Cut down version of Part 4 Supporting Routines 7.6.3.10
676 * Hard coded to symmetrically encrypt with aes128 as the inner
677 * wrapper and no outer wrapper but with a prototype that allows
678 * drop in replacement with a tss equivalent
680 TPM_RC tpm2_SensitiveToDuplicate (TPMT_SENSITIVE *s,
683 TPMT_SYM_DEF_OBJECT *symdef,
687 BYTE *buf = p->buffer;
690 memset (p, 0, sizeof (*p));
692 /* hard code AES CFB */
693 if (symdef->algorithm == TPM_ALG_AES
694 && symdef->mode.aes == TPM_ALG_CFB)
697 const int hlen = TSS_GetDigestSize (nalg);
698 TPM2B *digest = (TPM2B *)buf;
701 unsigned char null_iv[AES_128_BLOCK_SIZE_BYTES];
702 UINT16 bsize, written = 0;
705 /* WARNING: don't use the static null_iv trick here:
706 * the AES routines alter the passed in iv */
707 memset (null_iv, 0, sizeof (null_iv));
709 /* reserve space for hash before the encrypted sensitive */
710 bsize = sizeof (digest->size) + hlen;
715 /* marshal the digest size */
716 buf = (BYTE *)&digest->size;
719 TSS_UINT16_Marshal (&bsize, &written, &buf, &size);
721 /* marshal the unencrypted sensitive in place */
725 TSS_TPMT_SENSITIVE_Marshal (s, &bsize, &buf, &size);
726 buf = (BYTE *)&s2b->size;
728 TSS_UINT16_Marshal (&bsize, &written, &buf, &size);
730 bsize = bsize + sizeof (s2b->size);
733 /* compute hash of unencrypted marshalled sensitive and
734 * write to the digest buffer */
736 TSS_Hash_Generate (&hash, bsize, s2b,
737 name->size, name->name,
739 memcpy (digest->buffer, &hash.digest, hlen);
740 gcry_cipher_open (&hd, GCRY_CIPHER_AES128,
741 GCRY_CIPHER_MODE_CFB, GCRY_CIPHER_SECURE);
742 gcry_cipher_setiv (hd, null_iv, sizeof (null_iv));
743 gcry_cipher_setkey (hd, innerkey->buffer, innerkey->size);
744 /* encrypt the hash and sensitive in-place */
745 gcry_cipher_encrypt (hd, p->buffer, p->size, NULL, 0);
746 gcry_cipher_close (hd);
749 else if (symdef->algorithm == TPM_ALG_NULL)
751 /* Code is for debugging only, should never be used in production */
752 TPM2B *s2b = (TPM2B *)buf;
753 int32_t size = sizeof (*s);
754 UINT16 bsize = 0, written = 0;
756 log_error ("Secret key sent to TPM unencrypted\n");
759 /* marshal the unencrypted sensitive in place */
760 TSS_TPMT_SENSITIVE_Marshal (s, &bsize, &buf, &size);
761 buf = (BYTE *)&s2b->size;
763 TSS_UINT16_Marshal (&bsize, &written, &buf, &size);
765 p->size += bsize + sizeof (s2b->size);
769 log_error ("Unknown symmetric algorithm\n");
770 return TPM_RC_SYMMETRIC;
773 return TPM_RC_SUCCESS;
777 tpm2_import_key (ctrl_t ctrl, TSS_CONTEXT *tssc,
778 gpg_error_t (*pin_cb)(ctrl_t ctrl, const char *info,
780 unsigned char **shadow_info, size_t *shadow_len,
781 gcry_sexp_t s_skey, unsigned long parent)
783 TPM_HANDLE parentHandle;
784 DATA_2B encryptionKey;
785 TPM2B_PUBLIC objectPublic;
786 PRIVATE_2B duplicate;
787 ENCRYPTED_SECRET_2B inSymSeed;
788 TPMT_SYM_DEF_OBJECT symmetricAlg;
789 PRIVATE_2B outPrivate;
791 const int aes_key_bits = 128;
792 const int aes_key_bytes = aes_key_bits/8;
804 char pub[sizeof (TPM2B_PUBLIC)];
806 char priv[sizeof (TPM2B_PRIVATE)];
810 parent = EXT_TPM_RH_OWNER;
812 ret = sexp_to_tpm2 (&objectPublic.publicArea, &s, s_skey);
815 log_error ("Failed to parse Key s-expression: key corrupt?\n");
819 /* add an authorization password to the key which the TPM will check */
821 ret = pin_cb (ctrl, _("Please enter the TPM Authorization passphrase for the key."), &passphrase);
824 len = strlen(passphrase);
825 if (len > TSS_GetDigestSize(objectPublic.publicArea.nameAlg))
827 len = TSS_GetDigestSize(objectPublic.publicArea.nameAlg);
828 log_error ("Truncating Passphrase to TPM allowed %d\n", len);
830 VAL_2B (s.authValue, size) = len;
831 memcpy (VAL_2B (s.authValue, buffer), passphrase, len);
833 /* We're responsible for securing the data in transmission to the
834 * TPM here. The TPM provides parameter encryption via a session,
835 * but only for the first parameter. For TPM2_Import, the first
836 * parameter is a symmetric key used to encrypt the sensitive data,
837 * so we must populate this key with random value and encrypt the
838 * sensitive data with it */
839 parentHandle = tpm2_get_parent (tssc, parent);
840 tpm2_ObjectPublic_GetName (&name, &objectPublic.publicArea);
841 gcry_randomize (encryptionKey.buffer,
842 aes_key_bytes, GCRY_STRONG_RANDOM);
843 encryptionKey.size = aes_key_bytes;
845 /* set random symSeed */
847 symmetricAlg.algorithm = TPM_ALG_AES;
848 symmetricAlg.keyBits.aes = aes_key_bits;
849 symmetricAlg.mode.aes = TPM_ALG_CFB;
851 tpm2_SensitiveToDuplicate (&s, &name, objectPublic.publicArea.nameAlg,
852 &symmetricAlg, &encryptionKey, &duplicate);
854 /* use salted parameter encryption to hide the key. First we read
855 * the public parameters of the parent key and use them to agree an
856 * encryption for the first parameter */
857 rc = tpm2_get_hmac_handle (tssc, &ah, parentHandle);
860 tpm2_flush_handle (tssc, parentHandle);
864 rc = tpm2_Import (tssc, parentHandle, &encryptionKey, &objectPublic,
865 &duplicate, &inSymSeed, &symmetricAlg, &outPrivate,
867 tpm2_flush_handle (tssc, parentHandle);
870 tpm2_error (rc, "TPM2_Import");
871 /* failure means auth handle is not flushed */
872 tpm2_flush_handle (tssc, ah);
874 if ((rc & 0xbf) == TPM_RC_VALUE)
876 log_error ("TPM cannot import RSA key: wrong size");
877 return GPG_ERR_UNSUPPORTED_ALGORITHM;
879 else if ((rc & 0xbf) == TPM_RC_CURVE)
881 log_error ("TPM cannot import requested curve");
882 return GPG_ERR_UNKNOWN_CURVE;
890 TSS_TPM2B_PUBLIC_Marshal (&objectPublic,
891 &len, &buffer, &size);
894 size = sizeof (priv);
897 TSS_TPM2B_PRIVATE_Marshal ((TPM2B_PRIVATE *)&outPrivate,
898 &len, &buffer, &size);
901 *shadow_info = make_tpm2_shadow_info (parent, pub, pub_len,
902 priv, priv_len, shadow_len);
907 tpm2_ecc_decrypt (ctrl_t ctrl, TSS_CONTEXT *tssc, TPM_HANDLE key,
908 gpg_error_t (*pin_cb)(ctrl_t ctrl, const char *info,
910 const char *ciphertext, int ciphertext_len,
911 char **decrypt, size_t *decrypt_len)
913 TPM2B_ECC_POINT inPoint;
914 TPM2B_ECC_POINT outPoint;
920 /* This isn't really a decryption per se. The ciphertext actually
921 * contains an EC Point which we must multiply by the private key number.
923 * The reason is to generate a diffe helman agreement on a shared
924 * point. This shared point is then used to generate the per
925 * session encryption key.
927 if (ciphertext[0] != 0x04)
929 log_error ("Decryption Shared Point format is not uncompressed\n");
930 return GPG_ERR_ENCODING_PROBLEM;
932 if ((ciphertext_len & 0x01) != 1)
934 log_error ("Decryption Shared Point has incorrect length\n");
935 return GPG_ERR_ENCODING_PROBLEM;
937 len = ciphertext_len >> 1;
939 memcpy (VAL_2B (inPoint.point.x, buffer), ciphertext + 1, len);
940 VAL_2B (inPoint.point.x, size) = len;
941 memcpy (VAL_2B (inPoint.point.y, buffer), ciphertext + 1 + len, len);
942 VAL_2B (inPoint.point.y, size) = len;
944 ret = tpm2_pre_auth (ctrl, tssc, pin_cb, &ah, &auth);
947 ret = tpm2_ECDH_ZGen (tssc, key, &inPoint, &outPoint, ah, auth);
948 ret = tpm2_post_auth (tssc, ret, ah, &auth, "TPM2_ECDH_ZGen");
952 *decrypt_len = VAL_2B (outPoint.point.x, size) +
953 VAL_2B (outPoint.point.y, size) + 1;
954 *decrypt = xtrymalloc (*decrypt_len);
955 (*decrypt)[0] = 0x04;
956 memcpy (*decrypt + 1, VAL_2B (outPoint.point.x, buffer),
957 VAL_2B (outPoint.point.x, size));
958 memcpy (*decrypt + 1 + VAL_2B (outPoint.point.x, size),
959 VAL_2B (outPoint.point.y, buffer),
960 VAL_2B (outPoint.point.y, size));
966 tpm2_rsa_decrypt (ctrl_t ctrl, TSS_CONTEXT *tssc, TPM_HANDLE key,
967 gpg_error_t (*pin_cb)(ctrl_t ctrl, const char *info,
969 const char *ciphertext, int ciphertext_len,
970 char **decrypt, size_t *decrypt_len)
973 PUBLIC_KEY_RSA_2B cipherText;
974 TPMT_RSA_DECRYPT inScheme;
975 PUBLIC_KEY_RSA_2B message;
979 inScheme.scheme = TPM_ALG_RSAES;
981 * apparent gcrypt error: occasionally rsa ciphertext will
982 * be one byte too long and have a leading zero
984 if ((ciphertext_len & 1) == 1 && ciphertext[0] == 0)
986 log_info ("Fixing Wrong Ciphertext size %d\n", ciphertext_len);
990 cipherText.size = ciphertext_len;
991 memcpy (cipherText.buffer, ciphertext, ciphertext_len);
993 ret = tpm2_pre_auth (ctrl, tssc, pin_cb, &ah, &auth);
996 ret = tpm2_RSA_Decrypt (tssc, key, &cipherText, &inScheme, &message,
997 ah, auth, TPMA_SESSION_ENCRYPT);
998 ret = tpm2_post_auth (tssc, ret, ah, &auth, "TPM2_RSA_Decrypt");
1002 *decrypt_len = message.size;
1003 *decrypt = xtrymalloc (message.size);
1004 memcpy (*decrypt, message.buffer, message.size);