aboutsummaryrefslogtreecommitdiffstats
path: root/roms/skiboot/libstb/tss2/ibmtpm20tss/utils/cryptoutils.c
diff options
context:
space:
mode:
Diffstat (limited to 'roms/skiboot/libstb/tss2/ibmtpm20tss/utils/cryptoutils.c')
-rw-r--r--roms/skiboot/libstb/tss2/ibmtpm20tss/utils/cryptoutils.c2079
1 files changed, 2079 insertions, 0 deletions
diff --git a/roms/skiboot/libstb/tss2/ibmtpm20tss/utils/cryptoutils.c b/roms/skiboot/libstb/tss2/ibmtpm20tss/utils/cryptoutils.c
new file mode 100644
index 000000000..af46b3c5f
--- /dev/null
+++ b/roms/skiboot/libstb/tss2/ibmtpm20tss/utils/cryptoutils.c
@@ -0,0 +1,2079 @@
+/********************************************************************************/
+/* */
+/* OpenSSL Crypto Utilities */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* */
+/* (c) Copyright IBM Corporation 2018 - 2020. */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following conditions are */
+/* met: */
+/* */
+/* Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the following disclaimer. */
+/* */
+/* Redistributions in binary form must reproduce the above copyright */
+/* notice, this list of conditions and the following disclaimer in the */
+/* documentation and/or other materials provided with the distribution. */
+/* */
+/* Neither the names of the IBM Corporation nor the names of its */
+/* contributors may be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
+/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
+/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */
+/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
+/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
+/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
+/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */
+/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */
+/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
+/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */
+/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
+/********************************************************************************/
+
+/* These functions are worthwhile sample code that probably (judgment call) do not belong in the TSS
+ library.
+
+ They abstract out crypto library functions.
+
+ They show how to convert public or private EC or RSA among PEM format <-> EVP format <-> EC_KEY
+ or RSA format <-> binary arrays <-> TPM format TPM2B_PRIVATE, TPM2B_SENSITIVE, TPM2B_PUBLIC
+ usable for loadexternal or import.
+
+ There are functions to convert public keys from TPM <-> RSA, ECC <-> PEM, and to verify a TPM
+ signature using a PEM format public key.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <limits.h>
+
+#ifndef TPM_TSS_NORSA
+#include <openssl/rsa.h>
+#endif /* TPM_TSS_NORSA */
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+#include <openssl/pem.h>
+
+#ifndef TPM_TSS_NOECC
+#include <openssl/ec.h>
+#endif
+
+#ifndef TPM_TSS_NOFILE
+#include <ibmtss/tssfile.h>
+#endif
+#include <ibmtss/tssutils.h>
+#include <ibmtss/tssmarshal.h>
+#include <ibmtss/tsscrypto.h>
+#include <ibmtss/tsscryptoh.h>
+#include <ibmtss/Implementation.h>
+
+#include "objecttemplates.h"
+#include "cryptoutils.h"
+
+/* verbose tracing flag shared by command line utilities */
+
+int tssUtilsVerbose;
+
+/* openssl compatibility functions, during the transition from 1.0.1, 1.0.2, 1.1.0, 1.1.1. Some
+ structures were made opaque, with gettters and setters. Some parameters were made const. Some
+ function names changed. */
+
+/* Some functions add const to parameters as of openssl 1.1.0 */
+
+/* These functions are only required for OpenSSL 1.0. OpenSSL 1.1 has them, and the structures are
+ opaque. */
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000
+
+int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)
+{
+ if (r == NULL || s == NULL)
+ return 0;
+ BN_clear_free(sig->r);
+ BN_clear_free(sig->s);
+ sig->r = r;
+ sig->s = s;
+ return 1;
+}
+
+void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
+{
+ if (pr != NULL) {
+ *pr = sig->r;
+ }
+ if (ps != NULL) {
+ *ps = sig->s;
+ }
+ return;
+}
+
+const X509_ALGOR *X509_get0_tbs_sigalg(const X509 *x)
+{
+ return x->cert_info->signature;
+}
+
+void RSA_get0_key(const RSA *rsaKey,
+ const BIGNUM **n,
+ const BIGNUM **e,
+ const BIGNUM **d)
+{
+ if (n != NULL) {
+ *n = rsaKey->n;
+ }
+ if (e != NULL) {
+ *e = rsaKey->e;
+ }
+ if (d != NULL) {
+ *d = rsaKey->d;
+ }
+ return;
+}
+
+void RSA_get0_factors(const RSA *rsaKey,
+ const BIGNUM **p,
+ const BIGNUM **q)
+{
+ if (p != NULL) {
+ *p = rsaKey->p;
+ }
+ if (q != NULL) {
+ *q = rsaKey->q;
+ }
+ return;
+}
+
+#endif /* pre openssl 1.1 */
+
+/* These functions are only required for OpenSSL 1.0.1 OpenSSL 1.0.2 has them, and the structures
+ are opaque. In 1.1.0, the parameters became const. */
+
+#if OPENSSL_VERSION_NUMBER < 0x10002000
+
+void X509_get0_signature(OSSLCONST ASN1_BIT_STRING **psig,
+ OSSLCONST X509_ALGOR **palg, const X509 *x)
+{
+ *psig = x->signature;
+ *palg = x->sig_alg;
+ return;
+}
+
+#endif /* pre openssl 1.0.2 */
+
+#ifndef TPM_TSS_NOFILE
+
+/* getCryptoLibrary() returns a string indicating the underlying crypto library.
+
+ It can be used for programs that must account for library differences.
+*/
+
+void getCryptoLibrary(const char **name)
+{
+ *name = "openssl";
+ return;
+}
+
+/* convertPemToEvpPrivKey() converts a PEM key file to an openssl EVP_PKEY key pair */
+
+TPM_RC convertPemToEvpPrivKey(EVP_PKEY **evpPkey, /* freed by caller */
+ const char *pemKeyFilename,
+ const char *password)
+{
+ TPM_RC rc = 0;
+ FILE *pemKeyFile = NULL;
+
+ if (rc == 0) {
+ rc = TSS_File_Open(&pemKeyFile, pemKeyFilename, "rb"); /* closed @2 */
+ }
+ if (rc == 0) {
+ *evpPkey = PEM_read_PrivateKey(pemKeyFile, NULL, NULL, (void *)password);
+ if (*evpPkey == NULL) {
+ printf("convertPemToEvpPrivKey: Error reading key file %s\n", pemKeyFilename);
+ rc = EXIT_FAILURE;
+ }
+ }
+ if (pemKeyFile != NULL) {
+ fclose(pemKeyFile); /* @2 */
+ }
+ return rc;
+}
+
+#endif /* TPM_TSS_NOFILE */
+
+#ifndef TPM_TSS_NOFILE
+
+/* convertPemToEvpPubKey() converts a PEM public key file to an openssl EVP_PKEY public key */
+
+TPM_RC convertPemToEvpPubKey(EVP_PKEY **evpPkey, /* freed by caller */
+ const char *pemKeyFilename)
+{
+ TPM_RC rc = 0;
+ FILE *pemKeyFile = NULL;
+
+ if (rc == 0) {
+ rc = TSS_File_Open(&pemKeyFile, pemKeyFilename, "rb"); /* closed @2 */
+ }
+ if (rc == 0) {
+ *evpPkey = PEM_read_PUBKEY(pemKeyFile, NULL, NULL, NULL);
+ if (*evpPkey == NULL) {
+ printf("convertPemToEvpPubKey: Error reading key file %s\n", pemKeyFilename);
+ rc = EXIT_FAILURE;
+ }
+ }
+ if (pemKeyFile != NULL) {
+ fclose(pemKeyFile); /* @2 */
+ }
+ return rc;
+}
+
+#endif /* TPM_TSS_NOFILE */
+
+#ifndef TPM_TSS_NOFILE
+
+/* convertPemToRsaPrivKey() converts a PEM format keypair file to a library specific RSA key
+ token.
+
+ The return is void because the structure is opaque to the caller. This accomodates other crypto
+ libraries.
+
+ rsaKey is an RSA structure
+*/
+
+TPM_RC convertPemToRsaPrivKey(void **rsaKey, /* freed by caller */
+ const char *pemKeyFilename,
+ const char *password)
+{
+ TPM_RC rc = 0;
+ FILE *pemKeyFile = NULL;
+
+ if (rc == 0) {
+ rc = TSS_File_Open(&pemKeyFile, pemKeyFilename, "rb"); /* closed @1 */
+ }
+ if (rc == 0) {
+ *rsaKey = (void *)PEM_read_RSAPrivateKey(pemKeyFile, NULL, NULL, (void *)password);
+ if (*rsaKey == NULL) {
+ printf("convertPemToRsaPrivKey: Error in OpenSSL PEM_read_RSAPrivateKey()\n");
+ rc = EXIT_FAILURE;
+ }
+ }
+ if (pemKeyFile != NULL) {
+ fclose(pemKeyFile); /* @1 */
+ }
+ return rc;
+}
+
+#endif /* TPM_TSS_NOFILE */
+
+#ifndef TPM_TSS_NOECC
+
+/* convertEvpPkeyToEckey retrieves the EC_KEY key token from the EVP_PKEY */
+
+TPM_RC convertEvpPkeyToEckey(EC_KEY **ecKey, /* freed by caller */
+ EVP_PKEY *evpPkey)
+{
+ TPM_RC rc = 0;
+
+ if (rc == 0) {
+ *ecKey = EVP_PKEY_get1_EC_KEY(evpPkey);
+ if (*ecKey == NULL) {
+ printf("convertEvpPkeyToEckey: Error extracting EC key from EVP_PKEY\n");
+ rc = EXIT_FAILURE;
+ }
+ }
+ return rc;
+}
+
+#endif /* TPM_TSS_NOECC */
+
+/* convertEvpPkeyToRsakey() retrieves the RSA key token from the EVP_PKEY */
+
+TPM_RC convertEvpPkeyToRsakey(RSA **rsaKey, /* freed by caller */
+ EVP_PKEY *evpPkey)
+{
+ TPM_RC rc = 0;
+
+ if (rc == 0) {
+ *rsaKey = EVP_PKEY_get1_RSA(evpPkey);
+ if (*rsaKey == NULL) {
+ printf("convertEvpPkeyToRsakey: EVP_PKEY_get1_RSA failed\n");
+ rc = EXIT_FAILURE;
+ }
+ }
+ return rc;
+}
+
+#ifndef TPM_TSS_NOECC
+
+/* convertEcKeyToPrivateKeyBin() converts an OpenSSL EC_KEY to a binary array
+
+ FIXME Only supports NIST P256 curve.
+*/
+
+TPM_RC convertEcKeyToPrivateKeyBin(int *privateKeyBytes,
+ uint8_t **privateKeyBin, /* freed by caller */
+ const EC_KEY *ecKey)
+{
+ TPM_RC rc = 0;
+ const EC_GROUP *ecGroup = NULL;
+ int nid;
+ const BIGNUM *privateKeyBn = NULL;
+ int bnBytes;
+
+ /* get the group from the key */
+ if (rc == 0) {
+ ecGroup = EC_KEY_get0_group(ecKey);
+ if (ecGroup == NULL) {
+ printf("convertEcKeyToPrivateKeyBin: Error extracting EC group from EC key\n");
+ rc = TSS_RC_EC_KEY_CONVERT;
+ }
+ }
+ /* and then the curve from the group */
+ if (rc == 0) {
+ nid = EC_GROUP_get_curve_name(ecGroup);
+ /* map NID to size of private key */
+ switch (nid) {
+ case NID_X9_62_prime256v1:
+ *privateKeyBytes = 32;
+ break;
+ default:
+ printf("convertEcKeyToPrivateKeyBin: Error, curve NID %u not supported\n", nid);
+ rc = TSS_RC_EC_KEY_CONVERT;
+ }
+ }
+ /* get the ECC private key as a BIGNUM from the EC_KEY */
+ if (rc == 0) {
+ privateKeyBn = EC_KEY_get0_private_key(ecKey);
+ }
+ /* sanity check the BN size against the curve */
+ if (rc == 0) {
+ bnBytes = BN_num_bytes(privateKeyBn);
+ if (bnBytes > *privateKeyBytes) {
+ printf("convertEcKeyToPrivateKeyBin: Error, private key %d bytes too large for curve\n",
+ bnBytes);
+ rc = TSS_RC_EC_KEY_CONVERT;
+ }
+ }
+ /* allocate a buffer for the private key array based on the curve */
+ if (rc == 0) {
+ rc = TSS_Malloc(privateKeyBin, *privateKeyBytes);
+ }
+ /* convert the private key bignum to binary */
+ if (rc == 0) {
+ /* TPM rev 116 required the ECC private key to be zero padded in the duplicate parameter of
+ import */
+ memset(*privateKeyBin, 0, *privateKeyBytes - bnBytes);
+ BN_bn2bin(privateKeyBn, (*privateKeyBin) + (*privateKeyBytes - bnBytes));
+ if (tssUtilsVerbose) TSS_PrintAll("convertEcKeyToPrivateKeyBin:", *privateKeyBin, *privateKeyBytes);
+ }
+ return rc;
+}
+
+#endif /* TPM_TSS_NOECC */
+
+/* convertRsaKeyToPrivateKeyBin() converts an OpenSSL RSA key token private prime p to a binary
+ array */
+
+TPM_RC convertRsaKeyToPrivateKeyBin(int *privateKeyBytes,
+ uint8_t **privateKeyBin, /* freed by caller */
+ const RSA *rsaKey)
+{
+ TPM_RC rc = 0;
+ const BIGNUM *p = NULL;
+ const BIGNUM *q;
+
+ /* get the private primes */
+ if (rc == 0) {
+ rc = getRsaKeyParts(NULL, NULL, NULL, &p, &q, rsaKey);
+ }
+ /* allocate a buffer for the private key array */
+ if (rc == 0) {
+ *privateKeyBytes = BN_num_bytes(p);
+ rc = TSS_Malloc(privateKeyBin, *privateKeyBytes);
+ }
+ /* convert the private key bignum to binary */
+ if (rc == 0) {
+ BN_bn2bin(p, *privateKeyBin);
+ }
+ return rc;
+}
+
+
+#ifndef TPM_TSS_NOECC
+
+/* convertEcKeyToPublicKeyBin() converts an OpenSSL EC_KEY public key token to a binary array */
+
+TPM_RC convertEcKeyToPublicKeyBin(int *modulusBytes,
+ uint8_t **modulusBin, /* freed by caller */
+ const EC_KEY *ecKey)
+{
+ TPM_RC rc = 0;
+ const EC_POINT *ecPoint = NULL;
+ const EC_GROUP *ecGroup = NULL;
+
+ if (rc == 0) {
+ ecPoint = EC_KEY_get0_public_key(ecKey);
+ if (ecPoint == NULL) {
+ printf("convertEcKeyToPublicKeyBin: Error extracting EC point from EC public key\n");
+ rc = TSS_RC_EC_KEY_CONVERT;
+ }
+ }
+ if (rc == 0) {
+ ecGroup = EC_KEY_get0_group(ecKey);
+ if (ecGroup == NULL) {
+ printf("convertEcKeyToPublicKeyBin: Error extracting EC group from EC public key\n");
+ rc = TSS_RC_EC_KEY_CONVERT;
+ }
+ }
+ /* get the public modulus */
+ if (rc == 0) {
+ *modulusBytes = EC_POINT_point2oct(ecGroup, ecPoint,
+ POINT_CONVERSION_UNCOMPRESSED,
+ NULL, 0, NULL);
+ }
+ if (rc == 0) {
+ rc = TSS_Malloc(modulusBin, *modulusBytes);
+ }
+ if (rc == 0) {
+ EC_POINT_point2oct(ecGroup, ecPoint,
+ POINT_CONVERSION_UNCOMPRESSED,
+ *modulusBin, *modulusBytes, NULL);
+ if (tssUtilsVerbose) TSS_PrintAll("convertEcKeyToPublicKeyBin:", *modulusBin, *modulusBytes);
+ }
+ return rc;
+}
+
+#endif /* TPM_TSS_NOECC */
+
+/* convertRsaKeyToPublicKeyBin() converts from an openssl RSA key token to a public modulus */
+
+TPM_RC convertRsaKeyToPublicKeyBin(int *modulusBytes,
+ uint8_t **modulusBin, /* freed by caller */
+ void *rsaKey)
+{
+ TPM_RC rc = 0;
+ const BIGNUM *n = NULL;
+ const BIGNUM *e;
+ const BIGNUM *d;
+
+ /* get the public modulus from the RSA key token */
+ if (rc == 0) {
+ rc = getRsaKeyParts(&n, &e, &d, NULL, NULL, rsaKey);
+ }
+ if (rc == 0) {
+ *modulusBytes = BN_num_bytes(n);
+ }
+ if (rc == 0) {
+ rc = TSS_Malloc(modulusBin, *modulusBytes);
+ }
+ if (rc == 0) {
+ BN_bn2bin(n, *modulusBin);
+ }
+ return rc;
+}
+
+#ifdef TPM_TPM20
+
+#ifndef TPM_TSS_NOECC
+
+/* convertEcPrivateKeyBinToPrivate() converts an EC 'privateKeyBin' to either a
+ TPM2B_PRIVATE or a TPM2B_SENSITIVE
+
+*/
+
+TPM_RC convertEcPrivateKeyBinToPrivate(TPM2B_PRIVATE *objectPrivate,
+ TPM2B_SENSITIVE *objectSensitive,
+ int privateKeyBytes,
+ uint8_t *privateKeyBin,
+ const char *password)
+{
+ TPM_RC rc = 0;
+ TPMT_SENSITIVE tSensitive;
+ TPM2B_SENSITIVE bSensitive;
+
+ if (rc == 0) {
+ if (((objectPrivate == NULL) && (objectSensitive == NULL)) ||
+ ((objectPrivate != NULL) && (objectSensitive != NULL))) {
+ printf("convertEcPrivateKeyBinToPrivate: Only one result supported\n");
+ rc = EXIT_FAILURE;
+ }
+ }
+ /* In some cases, the sensitive data is not encrypted and the integrity value is not present.
+ When an integrity value is not needed, it is not present and it is not represented by an
+ Empty Buffer.
+
+ In this case, the TPM2B_PRIVATE will just be a marshaled TPM2B_SENSITIVE, which is a
+ marshaled TPMT_SENSITIVE */
+
+ /* construct TPMT_SENSITIVE */
+ if (rc == 0) {
+ /* This shall be the same as the type parameter of the associated public area. */
+ tSensitive.sensitiveType = TPM_ALG_ECC;
+ tSensitive.seedValue.b.size = 0;
+ /* key password converted to TPM2B */
+ rc = TSS_TPM2B_StringCopy(&tSensitive.authValue.b, password,
+ sizeof(tSensitive.authValue.t.buffer));
+ }
+ if (rc == 0) {
+ if (privateKeyBytes > 32) { /* hard code NISTP256 */
+ printf("convertEcPrivateKeyBinToPrivate: Error, private key size %u not 32\n",
+ privateKeyBytes);
+ rc = EXIT_FAILURE;
+ }
+ }
+ if (rc == 0) {
+ tSensitive.sensitive.ecc.t.size = privateKeyBytes;
+ memcpy(tSensitive.sensitive.ecc.t.buffer, privateKeyBin, privateKeyBytes);
+ }
+ /* FIXME common code for EC and RSA */
+ /* marshal the TPMT_SENSITIVE into a TPM2B_SENSITIVE */
+ if (rc == 0) {
+ if (objectPrivate != NULL) {
+ uint32_t size = sizeof(bSensitive.t.sensitiveArea); /* max size */
+ uint8_t *buffer = bSensitive.b.buffer; /* pointer that can move */
+ bSensitive.t.size = 0; /* required before marshaling */
+ rc = TSS_TPMT_SENSITIVE_Marshalu(&tSensitive,
+ &bSensitive.b.size, /* marshaled size */
+ &buffer, /* marshal here */
+ &size); /* max size */
+ }
+ else { /* return TPM2B_SENSITIVE */
+ objectSensitive->t.sensitiveArea = tSensitive;
+ }
+ }
+ /* marshal the TPM2B_SENSITIVE (as a TPM2B_PRIVATE, see above) into a TPM2B_PRIVATE */
+ if (rc == 0) {
+ if (objectPrivate != NULL) {
+ uint32_t size = sizeof(objectPrivate->t.buffer); /* max size */
+ uint8_t *buffer = objectPrivate->t.buffer; /* pointer that can move */
+ objectPrivate->t.size = 0; /* required before marshaling */
+ rc = TSS_TPM2B_PRIVATE_Marshalu((TPM2B_PRIVATE *)&bSensitive,
+ &objectPrivate->t.size, /* marshaled size */
+ &buffer, /* marshal here */
+ &size); /* max size */
+ }
+ }
+ return rc;
+}
+
+#endif /* TPM_TSS_NOECC */
+#endif /* TPM_TPM20 */
+
+#ifdef TPM_TPM20
+
+/* convertRsaPrivateKeyBinToPrivate() converts an RSA prime 'privateKeyBin' to either a
+ TPM2B_PRIVATE or a TPM2B_SENSITIVE
+
+*/
+
+TPM_RC convertRsaPrivateKeyBinToPrivate(TPM2B_PRIVATE *objectPrivate,
+ TPM2B_SENSITIVE *objectSensitive,
+ int privateKeyBytes,
+ uint8_t *privateKeyBin,
+ const char *password)
+{
+ TPM_RC rc = 0;
+ TPMT_SENSITIVE tSensitive;
+ TPM2B_SENSITIVE bSensitive;
+
+ if (rc == 0) {
+ if (((objectPrivate == NULL) && (objectSensitive == NULL)) ||
+ ((objectPrivate != NULL) && (objectSensitive != NULL))) {
+ printf("convertRsaPrivateKeyBinToPrivate: Only one result supported\n");
+ rc = EXIT_FAILURE;
+ }
+ }
+ /* In some cases, the sensitive data is not encrypted and the integrity value is not present.
+ When an integrity value is not needed, it is not present and it is not represented by an
+ Empty Buffer.
+
+ In this case, the TPM2B_PRIVATE will just be a marshaled TPM2B_SENSITIVE, which is a
+ marshaled TPMT_SENSITIVE */
+
+ /* construct TPMT_SENSITIVE */
+ if (rc == 0) {
+ /* This shall be the same as the type parameter of the associated public area. */
+ tSensitive.sensitiveType = TPM_ALG_RSA;
+ /* generate a seed for storage keys */
+ tSensitive.seedValue.b.size = 32; /* FIXME hard coded seed length */
+ rc = TSS_RandBytes(tSensitive.seedValue.b.buffer, tSensitive.seedValue.b.size);
+ }
+ /* key password converted to TPM2B */
+ if (rc == 0) {
+ rc = TSS_TPM2B_StringCopy(&tSensitive.authValue.b, password,
+ sizeof(tSensitive.authValue.t.buffer));
+ }
+ if (rc == 0) {
+ if ((size_t)privateKeyBytes > sizeof(tSensitive.sensitive.rsa.t.buffer)) {
+ printf("convertRsaPrivateKeyBinToPrivate: "
+ "Error, private key modulus %d greater than %lu\n",
+ privateKeyBytes, (unsigned long)sizeof(tSensitive.sensitive.rsa.t.buffer));
+ rc = EXIT_FAILURE;
+ }
+ }
+ if (rc == 0) {
+ tSensitive.sensitive.rsa.t.size = privateKeyBytes;
+ memcpy(tSensitive.sensitive.rsa.t.buffer, privateKeyBin, privateKeyBytes);
+ }
+ /* FIXME common code for EC and RSA */
+ /* marshal the TPMT_SENSITIVE into a TPM2B_SENSITIVE */
+ if (rc == 0) {
+ if (objectPrivate != NULL) {
+ uint32_t size = sizeof(bSensitive.t.sensitiveArea); /* max size */
+ uint8_t *buffer = bSensitive.b.buffer; /* pointer that can move */
+ bSensitive.t.size = 0; /* required before marshaling */
+ rc = TSS_TPMT_SENSITIVE_Marshalu(&tSensitive,
+ &bSensitive.b.size, /* marshaled size */
+ &buffer, /* marshal here */
+ &size); /* max size */
+ }
+ else { /* return TPM2B_SENSITIVE */
+ objectSensitive->t.sensitiveArea = tSensitive;
+ }
+ }
+ /* marshal the TPM2B_SENSITIVE (as a TPM2B_PRIVATE, see above) into a TPM2B_PRIVATE */
+ if (rc == 0) {
+ if (objectPrivate != NULL) {
+ uint32_t size = sizeof(objectPrivate->t.buffer); /* max size */
+ uint8_t *buffer = objectPrivate->t.buffer; /* pointer that can move */
+ objectPrivate->t.size = 0; /* required before marshaling */
+ rc = TSS_TPM2B_PRIVATE_Marshalu((TPM2B_PRIVATE *)&bSensitive,
+ &objectPrivate->t.size, /* marshaled size */
+ &buffer, /* marshal here */
+ &size); /* max size */
+ }
+ }
+ return rc;
+}
+
+#endif /* TPM_TPM20 */
+
+#ifndef TPM_TSS_NOECC
+
+/* convertEcPublicKeyBinToPublic() converts an EC modulus and other parameters to a TPM2B_PUBLIC
+
+ FIXME Only supports NIST P256 curve.
+*/
+
+TPM_RC convertEcPublicKeyBinToPublic(TPM2B_PUBLIC *objectPublic,
+ int keyType,
+ TPMI_ALG_SIG_SCHEME scheme,
+ TPMI_ALG_HASH nalg,
+ TPMI_ALG_HASH halg,
+ TPMI_ECC_CURVE curveID,
+ int modulusBytes,
+ uint8_t *modulusBin)
+{
+ TPM_RC rc = 0;
+
+ scheme = scheme; /* scheme parameter not supported yet */
+ if (rc == 0) {
+ if (modulusBytes != 65) { /* 1 for compression + 32 + 32 */
+ printf("convertEcPublicKeyBinToPublic: public modulus expected 65 bytes, actual %u\n",
+ modulusBytes);
+ rc = EXIT_FAILURE;
+ }
+ }
+ if (rc == 0) {
+ /* Table 184 - Definition of TPMT_PUBLIC Structure */
+ objectPublic->publicArea.type = TPM_ALG_ECC;
+ objectPublic->publicArea.nameAlg = nalg;
+ objectPublic->publicArea.objectAttributes.val = TPMA_OBJECT_NODA;
+ objectPublic->publicArea.objectAttributes.val |= TPMA_OBJECT_USERWITHAUTH;
+ switch (keyType) {
+ case TYPE_SI:
+ objectPublic->publicArea.objectAttributes.val |= TPMA_OBJECT_SIGN;
+ objectPublic->publicArea.parameters.eccDetail.symmetric.algorithm = TPM_ALG_NULL;
+ objectPublic->publicArea.parameters.eccDetail.scheme.scheme = TPM_ALG_ECDSA;
+ break;
+ case TYPE_ST: /* for public part only */
+ objectPublic->publicArea.objectAttributes.val |= TPMA_OBJECT_DECRYPT;
+ objectPublic->publicArea.objectAttributes.val |= TPMA_OBJECT_RESTRICTED;
+ objectPublic->publicArea.parameters.eccDetail.symmetric.algorithm = TPM_ALG_AES;
+ objectPublic->publicArea.parameters.eccDetail.symmetric.keyBits.aes = 128;
+ objectPublic->publicArea.parameters.eccDetail.symmetric.mode.aes = TPM_ALG_CFB;
+ objectPublic->publicArea.parameters.eccDetail.scheme.scheme = TPM_ALG_NULL;
+ break;
+ case TYPE_DEN: /* for public and private part */
+ objectPublic->publicArea.objectAttributes.val |= TPMA_OBJECT_DECRYPT;
+ objectPublic->publicArea.objectAttributes.val &= ~TPMA_OBJECT_RESTRICTED;
+ objectPublic->publicArea.parameters.eccDetail.symmetric.algorithm = TPM_ALG_NULL;
+ objectPublic->publicArea.parameters.eccDetail.scheme.scheme = TPM_ALG_ECDH;
+ break;
+ }
+ objectPublic->publicArea.authPolicy.t.size = 0;
+ /* Table 152 - Definition of TPMU_ASYM_SCHEME Union */
+ objectPublic->publicArea.parameters.eccDetail.scheme.details.ecdsa.hashAlg = halg;
+ objectPublic->publicArea.parameters.eccDetail.curveID = curveID;
+ objectPublic->publicArea.parameters.eccDetail.kdf.scheme = TPM_ALG_NULL;
+ objectPublic->publicArea.parameters.eccDetail.kdf.details.mgf1.hashAlg = halg;
+
+ objectPublic->publicArea.unique.ecc.x.t.size = 32;
+ memcpy(objectPublic->publicArea.unique.ecc.x.t.buffer, modulusBin +1, 32);
+
+ objectPublic->publicArea.unique.ecc.y.t.size = 32;
+ memcpy(objectPublic->publicArea.unique.ecc.y.t.buffer, modulusBin +33, 32);
+ }
+ return rc;
+}
+
+#endif /* TPM_TSS_NOECC */
+
+/* convertRsaPublicKeyBinToPublic() converts a public modulus to a TPM2B_PUBLIC structure. */
+
+TPM_RC convertRsaPublicKeyBinToPublic(TPM2B_PUBLIC *objectPublic,
+ int keyType,
+ TPMI_ALG_SIG_SCHEME scheme,
+ TPMI_ALG_HASH nalg,
+ TPMI_ALG_HASH halg,
+ int modulusBytes,
+ uint8_t *modulusBin)
+{
+ TPM_RC rc = 0;
+
+ if (rc == 0) {
+ if ((size_t)modulusBytes > sizeof(objectPublic->publicArea.unique.rsa.t.buffer)) {
+ printf("convertRsaPublicKeyBinToPublic: Error, "
+ "public key modulus %d greater than %lu\n", modulusBytes,
+ (unsigned long)sizeof(objectPublic->publicArea.unique.rsa.t.buffer));
+ rc = EXIT_FAILURE;
+ }
+ }
+ if (rc == 0) {
+ /* Table 184 - Definition of TPMT_PUBLIC Structure */
+ objectPublic->publicArea.type = TPM_ALG_RSA;
+ objectPublic->publicArea.nameAlg = nalg;
+ objectPublic->publicArea.objectAttributes.val = TPMA_OBJECT_NODA;
+ objectPublic->publicArea.objectAttributes.val |= TPMA_OBJECT_USERWITHAUTH;
+ switch (keyType) {
+ case TYPE_SI:
+ objectPublic->publicArea.objectAttributes.val |= TPMA_OBJECT_SIGN;
+ objectPublic->publicArea.parameters.rsaDetail.symmetric.algorithm = TPM_ALG_NULL;
+ break;
+ case TYPE_ST: /* for public part only */
+ objectPublic->publicArea.objectAttributes.val |= TPMA_OBJECT_DECRYPT;
+ objectPublic->publicArea.objectAttributes.val |= TPMA_OBJECT_RESTRICTED;
+ objectPublic->publicArea.parameters.rsaDetail.symmetric.algorithm = TPM_ALG_AES;
+ objectPublic->publicArea.parameters.rsaDetail.symmetric.keyBits.aes = 128;
+ objectPublic->publicArea.parameters.rsaDetail.symmetric.mode.aes = TPM_ALG_CFB;
+ break;
+ case TYPE_DEN: /* for public and private part */
+ objectPublic->publicArea.objectAttributes.val |= TPMA_OBJECT_DECRYPT;
+ objectPublic->publicArea.objectAttributes.val &= ~TPMA_OBJECT_RESTRICTED;
+ objectPublic->publicArea.parameters.rsaDetail.symmetric.algorithm = TPM_ALG_NULL;
+ break;
+ }
+ objectPublic->publicArea.authPolicy.t.size = 0;
+ /* Table 182 - Definition of TPMU_PUBLIC_PARMS Union <IN/OUT, S> */
+ objectPublic->publicArea.parameters.rsaDetail.scheme.scheme = scheme;
+ objectPublic->publicArea.parameters.rsaDetail.scheme.details.rsassa.hashAlg = halg;
+ objectPublic->publicArea.parameters.rsaDetail.keyBits = modulusBytes * 8;
+ objectPublic->publicArea.parameters.rsaDetail.exponent = 0;
+
+ objectPublic->publicArea.unique.rsa.t.size = modulusBytes;
+ memcpy(objectPublic->publicArea.unique.rsa.t.buffer, modulusBin, modulusBytes);
+ }
+ return rc;
+}
+
+#ifdef TPM_TPM20
+#ifndef TPM_TSS_NOECC
+
+/* convertEcKeyToPrivate() converts an openssl EC_KEY to token to either a TPM2B_PRIVATE or
+ TPM2B_SENSITIVE
+*/
+
+TPM_RC convertEcKeyToPrivate(TPM2B_PRIVATE *objectPrivate,
+ TPM2B_SENSITIVE *objectSensitive,
+ EC_KEY *ecKey,
+ const char *password)
+{
+ TPM_RC rc = 0;
+ int privateKeyBytes;
+ uint8_t *privateKeyBin = NULL;
+
+ /* convert an openssl EC_KEY token to a binary array */
+ if (rc == 0) {
+ rc = convertEcKeyToPrivateKeyBin(&privateKeyBytes,
+ &privateKeyBin, /* freed @1 */
+ ecKey);
+ }
+ if (rc == 0) {
+ rc = convertEcPrivateKeyBinToPrivate(objectPrivate,
+ objectSensitive,
+ privateKeyBytes,
+ privateKeyBin,
+ password);
+ }
+ free(privateKeyBin); /* @1 */
+ return rc;
+}
+
+#endif /* TPM_TSS_NOECC */
+
+/* convertRsaKeyToPrivate() converts an openssl RSA key token to either a TPM2B_PRIVATE or
+ TPM2B_SENSITIVE
+*/
+
+TPM_RC convertRsaKeyToPrivate(TPM2B_PRIVATE *objectPrivate,
+ TPM2B_SENSITIVE *objectSensitive,
+ RSA *rsaKey,
+ const char *password)
+{
+ TPM_RC rc = 0;
+ int privateKeyBytes;
+ uint8_t *privateKeyBin = NULL;
+
+ /* convert an openssl RSA key token private prime p to a binary array */
+ if (rc == 0) {
+ rc = convertRsaKeyToPrivateKeyBin(&privateKeyBytes,
+ &privateKeyBin, /* freed @1 */
+ rsaKey);
+ }
+ /* convert an RSA prime 'privateKeyBin' to either a TPM2B_PRIVATE or a TPM2B_SENSITIVE */
+ if (rc == 0) {
+ rc = convertRsaPrivateKeyBinToPrivate(objectPrivate,
+ objectSensitive,
+ privateKeyBytes,
+ privateKeyBin,
+ password);
+ }
+ free(privateKeyBin); /* @1 */
+ return rc;
+}
+
+#ifndef TPM_TSS_NOECC
+
+/* convertEcKeyToPublic() converts an EC_KEY to a TPM2B_PUBLIC */
+
+TPM_RC convertEcKeyToPublic(TPM2B_PUBLIC *objectPublic,
+ int keyType,
+ TPMI_ALG_SIG_SCHEME scheme,
+ TPMI_ALG_HASH nalg,
+ TPMI_ALG_HASH halg,
+ EC_KEY *ecKey)
+{
+ TPM_RC rc = 0;
+ int modulusBytes;
+ uint8_t *modulusBin = NULL;
+ TPMI_ECC_CURVE curveID;
+
+ if (rc == 0) {
+ rc = convertEcKeyToPublicKeyBin(&modulusBytes,
+ &modulusBin, /* freed @1 */
+ ecKey);
+ }
+ if (rc == 0) {
+ rc = getEcCurve(&curveID, ecKey);
+ }
+ if (rc == 0) {
+ rc = convertEcPublicKeyBinToPublic(objectPublic,
+ keyType,
+ scheme,
+ nalg,
+ halg,
+ curveID,
+ modulusBytes,
+ modulusBin);
+ }
+ free(modulusBin); /* @1 */
+ return rc;
+}
+
+#endif /* TPM_TSS_NOECC */
+
+/* convertRsaKeyToPublic() converts from an openssl RSA key token to a TPM2B_PUBLIC */
+
+TPM_RC convertRsaKeyToPublic(TPM2B_PUBLIC *objectPublic,
+ int keyType,
+ TPMI_ALG_SIG_SCHEME scheme,
+ TPMI_ALG_HASH nalg,
+ TPMI_ALG_HASH halg,
+ void *rsaKey)
+{
+ TPM_RC rc = 0;
+ int modulusBytes;
+ uint8_t *modulusBin = NULL;
+
+ /* openssl RSA key token to a public modulus */
+ if (rc == 0) {
+ rc = convertRsaKeyToPublicKeyBin(&modulusBytes,
+ &modulusBin, /* freed @1 */
+ rsaKey);
+ }
+ /* public modulus to TPM2B_PUBLIC */
+ if (rc == 0) {
+ rc = convertRsaPublicKeyBinToPublic(objectPublic,
+ keyType,
+ scheme,
+ nalg,
+ halg,
+ modulusBytes,
+ modulusBin);
+ }
+ free(modulusBin); /* @1 */
+ return rc;
+}
+
+#endif
+
+#ifndef TPM_TSS_NOFILE
+#ifdef TPM_TPM20
+#ifndef TPM_TSS_NOECC
+
+/* convertEcPemToKeyPair() converts a PEM file to a TPM2B_PUBLIC and TPM2B_PRIVATE */
+
+TPM_RC convertEcPemToKeyPair(TPM2B_PUBLIC *objectPublic,
+ TPM2B_PRIVATE *objectPrivate,
+ int keyType,
+ TPMI_ALG_SIG_SCHEME scheme,
+ TPMI_ALG_HASH nalg,
+ TPMI_ALG_HASH halg,
+ const char *pemKeyFilename,
+ const char *password)
+{
+ TPM_RC rc = 0;
+ EVP_PKEY *evpPkey = NULL;
+ EC_KEY *ecKey = NULL;
+
+ /* convert a PEM file to an openssl EVP_PKEY */
+ if (rc == 0) {
+ rc = convertPemToEvpPrivKey(&evpPkey, /* freed @1 */
+ pemKeyFilename,
+ password);
+ }
+ if (rc == 0) {
+ rc = convertEvpPkeyToEckey(&ecKey, /* freed @2 */
+ evpPkey);
+ }
+ if (rc == 0) {
+ rc = convertEcKeyToPrivate(objectPrivate, /* TPM2B_PRIVATE */
+ NULL, /* TPM2B_SENSITIVE */
+ ecKey,
+ password);
+ }
+ if (rc == 0) {
+ rc = convertEcKeyToPublic(objectPublic,
+ keyType,
+ scheme,
+ nalg,
+ halg,
+ ecKey);
+ }
+ EC_KEY_free(ecKey); /* @2 */
+ if (evpPkey != NULL) {
+ EVP_PKEY_free(evpPkey); /* @1 */
+ }
+ return rc;
+}
+
+#endif /* TPM_TSS_NOECC */
+#endif
+#endif
+
+#ifndef TPM_TSS_NOFILE
+#ifdef TPM_TPM20
+#ifndef TPM_TSS_NOECC
+
+/* convertEcPemToPublic() converts an ECC P256 signing public key in PEM format to a
+ TPM2B_PUBLIC */
+
+TPM_RC convertEcPemToPublic(TPM2B_PUBLIC *objectPublic,
+ int keyType,
+ TPMI_ALG_SIG_SCHEME scheme,
+ TPMI_ALG_HASH nalg,
+ TPMI_ALG_HASH halg,
+ const char *pemKeyFilename)
+{
+ TPM_RC rc = 0;
+ EVP_PKEY *evpPkey = NULL;
+ EC_KEY *ecKey = NULL;
+
+ if (rc == 0) {
+ rc = convertPemToEvpPubKey(&evpPkey, /* freed @1 */
+ pemKeyFilename);
+ }
+ if (rc == 0) {
+ rc = convertEvpPkeyToEckey(&ecKey, /* freed @2 */
+ evpPkey);
+ }
+ if (rc == 0) {
+ rc = convertEcKeyToPublic(objectPublic,
+ keyType,
+ scheme,
+ nalg,
+ halg,
+ ecKey);
+ }
+ if (ecKey != NULL) {
+ EC_KEY_free(ecKey); /* @2 */
+ }
+ if (evpPkey != NULL) {
+ EVP_PKEY_free(evpPkey); /* @1 */
+ }
+ return rc;
+}
+
+#endif /* TPM_TSS_NOECC */
+#endif
+#endif
+
+#ifndef TPM_TSS_NOFILE
+#ifdef TPM_TPM20
+#ifndef TPM_TSS_NORSA
+
+/* convertRsaPemToKeyPair() converts an RSA PEM file to a TPM2B_PUBLIC and TPM2B_PRIVATE */
+
+TPM_RC convertRsaPemToKeyPair(TPM2B_PUBLIC *objectPublic,
+ TPM2B_PRIVATE *objectPrivate,
+ int keyType,
+ TPMI_ALG_SIG_SCHEME scheme,
+ TPMI_ALG_HASH nalg,
+ TPMI_ALG_HASH halg,
+ const char *pemKeyFilename,
+ const char *password)
+{
+ TPM_RC rc = 0;
+ EVP_PKEY *evpPkey = NULL;
+ RSA *rsaKey = NULL;
+
+ if (rc == 0) {
+ rc = convertPemToEvpPrivKey(&evpPkey, /* freed @1 */
+ pemKeyFilename,
+ password);
+ }
+ if (rc == 0) {
+ rc = convertEvpPkeyToRsakey(&rsaKey, /* freed @2 */
+ evpPkey);
+ }
+ if (rc == 0) {
+ rc = convertRsaKeyToPrivate(objectPrivate, /* TPM2B_PRIVATE */
+ NULL, /* TPM2B_SENSITIVE */
+ rsaKey,
+ password);
+ }
+ if (rc == 0) {
+ rc = convertRsaKeyToPublic(objectPublic,
+ keyType,
+ scheme,
+ nalg,
+ halg,
+ rsaKey);
+ }
+ TSS_RsaFree(rsaKey); /* @2 */
+ if (evpPkey != NULL) {
+ EVP_PKEY_free(evpPkey); /* @1 */
+ }
+ return rc;
+}
+
+#endif /* TPM_TSS_NORSA */
+#endif /* TPM_TPM20 */
+#endif /* TPM_TSS_NOFILE */
+
+#ifndef TPM_TSS_NOFILE
+#ifdef TPM_TPM20
+#ifndef TPM_TSS_NOECC
+
+/* convertEcDerToKeyPair() converts an EC keypair stored in DER to a TPM2B_PUBLIC and
+ TPM2B_SENSITIVE. Useful for LoadExternal.
+
+*/
+
+TPM_RC convertEcDerToKeyPair(TPM2B_PUBLIC *objectPublic,
+ TPM2B_SENSITIVE *objectSensitive,
+ int keyType,
+ TPMI_ALG_SIG_SCHEME scheme,
+ TPMI_ALG_HASH nalg,
+ TPMI_ALG_HASH halg,
+ const char *derKeyFilename,
+ const char *password)
+{
+ TPM_RC rc = 0;
+ EC_KEY *ecKey = NULL;
+ unsigned char *derBuffer = NULL;
+ size_t derSize;
+
+ /* read the DER file */
+ if (rc == 0) {
+ rc = TSS_File_ReadBinaryFile(&derBuffer, /* freed @1 */
+ &derSize,
+ derKeyFilename);
+ }
+ if (rc == 0) {
+ const unsigned char *tmpPtr = derBuffer; /* because pointer moves */
+ ecKey = d2i_ECPrivateKey(NULL, &tmpPtr, derSize); /* freed @2 */
+ if (ecKey == NULL) {
+ printf("convertEcDerToKeyPair: could not convert key to EC_KEY\n");
+ rc = TPM_RC_VALUE;
+ }
+ }
+ if (rc == 0) {
+ rc = convertEcKeyToPrivate(NULL, /* TPM2B_PRIVATE */
+ objectSensitive, /* TPM2B_SENSITIVE */
+ ecKey,
+ password);
+ }
+ if (rc == 0) {
+ rc = convertEcKeyToPublic(objectPublic,
+ keyType,
+ scheme,
+ nalg,
+ halg,
+ ecKey);
+ }
+ free(derBuffer); /* @1 */
+ if (ecKey != NULL) {
+ EC_KEY_free(ecKey); /* @2 */
+ }
+ return rc;
+}
+
+/* convertEcDerToPublic() converts an EC public key stored in DER to a TPM2B_PUBLIC. Useful to
+ calculate a Name.
+
+*/
+
+TPM_RC convertEcDerToPublic(TPM2B_PUBLIC *objectPublic,
+ int keyType,
+ TPMI_ALG_SIG_SCHEME scheme,
+ TPMI_ALG_HASH nalg,
+ TPMI_ALG_HASH halg,
+ const char *derKeyFilename)
+{
+ TPM_RC rc = 0;
+ EVP_PKEY *evpPkey = NULL;
+ EC_KEY *ecKey = NULL;
+ unsigned char *derBuffer = NULL;
+ size_t derSize;
+
+ /* read the DER file */
+ if (rc == 0) {
+ rc = TSS_File_ReadBinaryFile(&derBuffer, /* freed @1 */
+ &derSize,
+ derKeyFilename);
+ }
+ if (rc == 0) {
+ const unsigned char *tmpPtr = derBuffer; /* because pointer moves */
+ evpPkey = d2i_PUBKEY(NULL, &tmpPtr, derSize); /* freed @2 */
+ if (evpPkey == NULL) {
+ printf("convertEcDerToPublic: could not convert key to EVP_PKEY\n");
+ rc = TPM_RC_VALUE;
+ }
+ }
+ if (rc == 0) {
+ rc = convertEvpPkeyToEckey(&ecKey, /* freed @3 */
+ evpPkey);
+ }
+ if (rc == 0) {
+ rc = convertEcKeyToPublic(objectPublic,
+ keyType,
+ scheme,
+ nalg,
+ halg,
+ ecKey);
+ }
+ free(derBuffer); /* @1 */
+ if (evpPkey != NULL) {
+ EVP_PKEY_free(evpPkey); /* @1 */
+ }
+ if (ecKey != NULL) {
+ EC_KEY_free(ecKey); /* @2 */
+ }
+ return rc;
+}
+
+#endif /* TPM_TSS_NOECC */
+#endif
+#endif
+
+#ifndef TPM_TSS_NOFILE
+#ifdef TPM_TPM20
+#ifndef TPM_TSS_NORSA
+
+/* convertRsaDerToKeyPair() converts an RSA keypair stored in DER to a TPM2B_PUBLIC and
+ TPM2B_SENSITIVE. Useful for LoadExternal.
+
+*/
+
+TPM_RC convertRsaDerToKeyPair(TPM2B_PUBLIC *objectPublic,
+ TPM2B_SENSITIVE *objectSensitive,
+ int keyType,
+ TPMI_ALG_SIG_SCHEME scheme,
+ TPMI_ALG_HASH nalg,
+ TPMI_ALG_HASH halg,
+ const char *derKeyFilename,
+ const char *password)
+{
+ TPM_RC rc = 0;
+ RSA *rsaKey = NULL;
+ unsigned char *derBuffer = NULL;
+ size_t derSize;
+
+ /* read the DER file */
+ if (rc == 0) {
+ rc = TSS_File_ReadBinaryFile(&derBuffer, /* freed @1 */
+ &derSize,
+ derKeyFilename);
+ }
+ if (rc == 0) {
+ const unsigned char *tmpPtr = derBuffer; /* because pointer moves */
+ rsaKey = d2i_RSAPrivateKey(NULL, &tmpPtr, derSize); /* freed @2 */
+ if (rsaKey == NULL) {
+ printf("convertRsaDerToKeyPair: could not convert key to RSA\n");
+ rc = TPM_RC_VALUE;
+ }
+ }
+ if (rc == 0) {
+ rc = convertRsaKeyToPrivate(NULL, /* TPM2B_PRIVATE */
+ objectSensitive, /* TPM2B_SENSITIVE */
+ rsaKey,
+ password);
+ }
+ if (rc == 0) {
+ rc = convertRsaKeyToPublic(objectPublic,
+ keyType,
+ scheme,
+ nalg,
+ halg,
+ rsaKey);
+ }
+ free(derBuffer); /* @1 */
+ TSS_RsaFree(rsaKey); /* @2 */
+ return rc;
+}
+
+/* convertRsaDerToPublic() converts an RSA public key stored in DER to a TPM2B_PUBLIC. Useful to
+ calculate a Name.
+
+*/
+
+TPM_RC convertRsaDerToPublic(TPM2B_PUBLIC *objectPublic,
+ int keyType,
+ TPMI_ALG_SIG_SCHEME scheme,
+ TPMI_ALG_HASH nalg,
+ TPMI_ALG_HASH halg,
+ const char *derKeyFilename)
+{
+ TPM_RC rc = 0;
+ RSA *rsaKey = NULL;
+ unsigned char *derBuffer = NULL;
+ size_t derSize;
+
+ /* read the DER file */
+ if (rc == 0) {
+ rc = TSS_File_ReadBinaryFile(&derBuffer, /* freed @1 */
+ &derSize,
+ derKeyFilename);
+ }
+ if (rc == 0) {
+ const unsigned char *tmpPtr = derBuffer; /* because pointer moves */
+ rsaKey = d2i_RSA_PUBKEY(NULL, &tmpPtr, derSize); /* freed @2 */
+ if (rsaKey == NULL) {
+ printf("convertRsaDerToPublic: could not convert key to RSA\n");
+ rc = TPM_RC_VALUE;
+ }
+ }
+ if (rc == 0) {
+ rc = convertRsaKeyToPublic(objectPublic,
+ keyType,
+ scheme,
+ nalg,
+ halg,
+ rsaKey);
+ }
+ free(derBuffer); /* @1 */
+ TSS_RsaFree(rsaKey); /* @2 */
+ return rc;
+}
+
+#endif /* TPM_TSS_NORSA */
+#endif /* TPM_TPM20 */
+#endif /* TPM_TSS_NOFILE */
+
+#ifndef TPM_TSS_NOFILE
+#ifdef TPM_TPM20
+
+/* convertRsaPemToPublic() converts an RSA public key in PEM format to a TPM2B_PUBLIC */
+
+TPM_RC convertRsaPemToPublic(TPM2B_PUBLIC *objectPublic,
+ int keyType,
+ TPMI_ALG_SIG_SCHEME scheme,
+ TPMI_ALG_HASH nalg,
+ TPMI_ALG_HASH halg,
+ const char *pemKeyFilename)
+{
+ TPM_RC rc = 0;
+ EVP_PKEY *evpPkey = NULL;
+ RSA *rsaKey = NULL;
+
+ if (rc == 0) {
+ rc = convertPemToEvpPubKey(&evpPkey, /* freed @1 */
+ pemKeyFilename);
+ }
+ if (rc == 0) {
+ rc = convertEvpPkeyToRsakey(&rsaKey, /* freed @2 */
+ evpPkey);
+ }
+ if (rc == 0) {
+ rc = convertRsaKeyToPublic(objectPublic,
+ keyType,
+ scheme,
+ nalg,
+ halg,
+ rsaKey);
+ }
+ RSA_free(rsaKey); /* @2 */
+ if (evpPkey != NULL) {
+ EVP_PKEY_free(evpPkey); /* @1 */
+ }
+ return rc;
+}
+
+#endif
+#endif
+
+/* getRsaKeyParts() gets the RSA key parts from an OpenSSL RSA key token.
+
+ If n is not NULL, returns n, e, and d. If p is not NULL, returns p and q.
+*/
+
+TPM_RC getRsaKeyParts(const BIGNUM **n,
+ const BIGNUM **e,
+ const BIGNUM **d,
+ const BIGNUM **p,
+ const BIGNUM **q,
+ const RSA *rsaKey)
+{
+ TPM_RC rc = 0;
+ if (n != NULL) {
+ RSA_get0_key(rsaKey, n, e, d);
+ }
+ if (p != NULL) {
+ RSA_get0_factors(rsaKey, p, q);
+ }
+ return rc;
+}
+
+/* returns the type (EVP_PKEY_RSA or EVP_PKEY_EC) of the EVP_PKEY.
+
+ */
+
+int getRsaPubkeyAlgorithm(EVP_PKEY *pkey)
+{
+ int pkeyType; /* RSA or EC */
+ pkeyType = EVP_PKEY_base_id(pkey);
+ return pkeyType;
+}
+
+#ifndef TPM_TSS_NOFILE
+
+/* convertPublicToPEM() saves a PEM format public key from a TPM2B_PUBLIC
+
+*/
+
+TPM_RC convertPublicToPEM(const TPM2B_PUBLIC *public,
+ const char *pemFilename)
+{
+ TPM_RC rc = 0;
+ EVP_PKEY *evpPubkey = NULL; /* OpenSSL public key, EVP format */
+
+ /* convert TPM2B_PUBLIC to EVP_PKEY */
+ if (rc == 0) {
+ switch (public->publicArea.type) {
+#ifndef TPM_TSS_NORSA
+ case TPM_ALG_RSA:
+ rc = convertRsaPublicToEvpPubKey(&evpPubkey, /* freed @1 */
+ &public->publicArea.unique.rsa);
+ break;
+#endif /* TPM_TSS_NORSA */
+#ifndef TPM_TSS_NOECC
+ case TPM_ALG_ECC:
+ rc = convertEcPublicToEvpPubKey(&evpPubkey, /* freed @1 */
+ &public->publicArea.unique.ecc);
+ break;
+#endif /* TPM_TSS_NOECC */
+ default:
+ printf("convertPublicToPEM: Unknown publicArea.type %04hx unsupported\n",
+ public->publicArea.type);
+ rc = TSS_RC_NOT_IMPLEMENTED;
+ break;
+ }
+ }
+ /* write the openssl structure in PEM format */
+ if (rc == 0) {
+ rc = convertEvpPubkeyToPem(evpPubkey,
+ pemFilename);
+
+ }
+ if (evpPubkey != NULL) {
+ EVP_PKEY_free(evpPubkey); /* @1 */
+ }
+ return rc;
+}
+
+#endif /* TPM_TSS_NOFILE */
+
+#ifndef TPM_TSS_NORSA
+
+/* convertRsaPublicToEvpPubKey() converts an RSA TPM2B_PUBLIC to a EVP_PKEY.
+
+*/
+
+TPM_RC convertRsaPublicToEvpPubKey(EVP_PKEY **evpPubkey, /* freed by caller */
+ const TPM2B_PUBLIC_KEY_RSA *tpm2bRsa)
+{
+ TPM_RC rc = 0;
+ int irc;
+ RSA *rsaPubKey = NULL;
+
+ if (rc == 0) {
+ *evpPubkey = EVP_PKEY_new();
+ if (*evpPubkey == NULL) {
+ printf("convertRsaPublicToEvpPubKey: EVP_PKEY failed\n");
+ rc = TSS_RC_OUT_OF_MEMORY;
+ }
+ }
+ /* TPM to RSA token */
+ if (rc == 0) {
+ /* public exponent */
+ unsigned char earr[3] = {0x01, 0x00, 0x01};
+ rc = TSS_RSAGeneratePublicTokenI
+ ((void **)&rsaPubKey, /* freed as part of EVP_PKEY */
+ tpm2bRsa->t.buffer, /* public modulus */
+ tpm2bRsa->t.size,
+ earr, /* public exponent */
+ sizeof(earr));
+ }
+ /* RSA token to EVP */
+ if (rc == 0) {
+ irc = EVP_PKEY_assign_RSA(*evpPubkey, rsaPubKey);
+ if (irc == 0) {
+ TSS_RsaFree(rsaPubKey); /* because not assigned tp EVP_PKEY */
+ printf("convertRsaPublicToEvpPubKey: EVP_PKEY_assign_RSA failed\n");
+ rc = TSS_RC_RSA_KEY_CONVERT;
+ }
+ }
+ return rc;
+}
+
+#endif /* TPM_TSS_NORSA */
+
+#ifndef TPM_TSS_NOECC
+
+/* convertEcPublicToEvpPubKey() converts an EC TPMS_ECC_POINT to an EVP_PKEY.
+ */
+
+TPM_RC convertEcPublicToEvpPubKey(EVP_PKEY **evpPubkey, /* freed by caller */
+ const TPMS_ECC_POINT *tpmsEccPoint)
+{
+ TPM_RC rc = 0;
+ int irc;
+ EC_GROUP *ecGroup = NULL;
+ EC_KEY *ecKey = NULL;
+ BIGNUM *x = NULL; /* freed @2 */
+ BIGNUM *y = NULL; /* freed @3 */
+
+ if (rc == 0) {
+ ecKey = EC_KEY_new(); /* freed @1 */
+ if (ecKey == NULL) {
+ printf("convertEcPublicToEvpPubKey: Error creating EC_KEY\n");
+ rc = TSS_RC_OUT_OF_MEMORY;
+ }
+ }
+ if (rc == 0) {
+ ecGroup = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); /* freed @4 */
+ if (ecGroup == NULL) {
+ printf("convertEcPublicToEvpPubKey: Error in EC_GROUP_new_by_curve_name\n");
+ rc = TSS_RC_OUT_OF_MEMORY;
+ }
+ }
+ if (rc == 0) {
+ /* returns void */
+ EC_GROUP_set_asn1_flag(ecGroup, OPENSSL_EC_NAMED_CURVE);
+ }
+ /* assign curve to EC_KEY */
+ if (rc == 0) {
+ irc = EC_KEY_set_group(ecKey, ecGroup);
+ if (irc != 1) {
+ printf("convertEcPublicToEvpPubKey: Error in EC_KEY_set_group\n");
+ rc = TSS_RC_EC_KEY_CONVERT;
+ }
+ }
+ if (rc == 0) {
+ rc = convertBin2Bn(&x, /* freed @2 */
+ tpmsEccPoint->x.t.buffer,
+ tpmsEccPoint->x.t.size);
+ }
+ if (rc == 0) {
+ rc = convertBin2Bn(&y, /* freed @3 */
+ tpmsEccPoint->y.t.buffer,
+ tpmsEccPoint->y.t.size);
+ }
+ if (rc == 0) {
+ irc = EC_KEY_set_public_key_affine_coordinates(ecKey, x, y);
+ if (irc != 1) {
+ printf("convertEcPublicToEvpPubKey: "
+ "Error converting public key from X Y to EC_KEY format\n");
+ rc = TSS_RC_EC_KEY_CONVERT;
+ }
+ }
+ if (rc == 0) {
+ *evpPubkey = EVP_PKEY_new(); /* freed by caller */
+ if (*evpPubkey == NULL) {
+ printf("convertEcPublicToEvpPubKey: EVP_PKEY failed\n");
+ rc = TSS_RC_OUT_OF_MEMORY;
+ }
+ }
+ if (rc == 0) {
+ irc = EVP_PKEY_set1_EC_KEY(*evpPubkey, ecKey);
+ if (irc != 1) {
+ printf("convertEcPublicToEvpPubKey: "
+ "Error converting public key from EC to EVP format\n");
+ rc = TSS_RC_EC_KEY_CONVERT;
+ }
+ }
+ if (ecGroup != NULL) {
+ EC_GROUP_free(ecGroup); /* @4 */
+ }
+ if (ecKey != NULL) {
+ EC_KEY_free(ecKey); /* @1 */
+ }
+ if (x != NULL) {
+ BN_free(x); /* @2 */
+ }
+ if (y != NULL) {
+ BN_free(y); /* @3 */
+ }
+ return rc;
+}
+
+#endif /* TPM_TSS_NOECC */
+
+#ifndef TPM_TSS_NOFILE
+
+TPM_RC convertEvpPubkeyToPem(EVP_PKEY *evpPubkey,
+ const char *pemFilename)
+{
+ TPM_RC rc = 0;
+ int irc;
+ FILE *pemFile = NULL;
+
+ if (rc == 0) {
+ pemFile = fopen(pemFilename, "wb"); /* close @1 */
+ if (pemFile == NULL) {
+ printf("convertEvpPubkeyToPem: Unable to open PEM file %s for write\n", pemFilename);
+ rc = TSS_RC_FILE_OPEN;
+ }
+ }
+ if (rc == 0) {
+ irc = PEM_write_PUBKEY(pemFile, evpPubkey);
+ if (irc == 0) {
+ printf("convertEvpPubkeyToPem: Unable to write PEM file %s\n", pemFilename);
+ rc = TSS_RC_FILE_WRITE;
+ }
+ }
+ if (pemFile != NULL) {
+ fclose(pemFile); /* @1 */
+ }
+ return rc;
+}
+
+#endif
+#ifndef TPM_TSS_NOFILE
+
+/* verifySignatureFromPem() verifies the signature 'tSignature' against the digest 'message' using
+ the public key in the PEM format file 'pemFilename'.
+
+*/
+
+TPM_RC verifySignatureFromPem(unsigned char *message,
+ unsigned int messageSize,
+ TPMT_SIGNATURE *tSignature,
+ TPMI_ALG_HASH halg,
+ const char *pemFilename)
+{
+ TPM_RC rc = 0;
+ EVP_PKEY *evpPkey = NULL; /* OpenSSL public key, EVP format */
+
+ /* read the public key from PEM format */
+ if (rc == 0) {
+ rc = convertPemToEvpPubKey(&evpPkey, /* freed @1*/
+ pemFilename);
+ }
+ /* RSA or EC */
+ if (rc == 0) {
+ switch(tSignature->sigAlg) {
+#ifndef TPM_TSS_NORSA
+ case TPM_ALG_RSASSA:
+ case TPM_ALG_RSAPSS:
+ rc = verifyRSASignatureFromEvpPubKey(message,
+ messageSize,
+ tSignature,
+ halg,
+ evpPkey);
+ break;
+#else
+ halg = halg;
+#endif /* TPM_TSS_NORSA */
+#ifndef TPM_TSS_NOECC
+ case TPM_ALG_ECDSA:
+ rc = verifyEcSignatureFromEvpPubKey(message,
+ messageSize,
+ tSignature,
+ evpPkey);
+ break;
+#endif /* TPM_TSS_NOECC */
+ default:
+ printf("verifySignatureFromPem: Unknown signature algorithm %04x\n", tSignature->sigAlg);
+ rc = TSS_RC_BAD_SIGNATURE_ALGORITHM;
+ }
+ }
+ if (evpPkey != NULL) {
+ EVP_PKEY_free(evpPkey); /* @1 */
+ }
+ return rc;
+}
+
+#endif
+
+#ifndef TPM_TSS_NORSA
+
+/* verifyRSASignatureFromEvpPubKey() verifies the signature 'tSignature' against the digest
+ 'message' using the RSA public key in evpPkey.
+
+*/
+
+TPM_RC verifyRSASignatureFromEvpPubKey(unsigned char *message,
+ unsigned int messageSize,
+ TPMT_SIGNATURE *tSignature,
+ TPMI_ALG_HASH halg,
+ EVP_PKEY *evpPkey)
+{
+ TPM_RC rc = 0;
+ RSA *rsaPubKey = NULL; /* OpenSSL public key, RSA format */
+
+ /* construct the RSA key token */
+ if (rc == 0) {
+ rsaPubKey = EVP_PKEY_get1_RSA(evpPkey); /* freed @1 */
+ if (rsaPubKey == NULL) {
+ printf("verifyRSASignatureFromEvpPubKey: EVP_PKEY_get1_RSA failed\n");
+ rc = TSS_RC_RSA_KEY_CONVERT;
+ }
+ }
+ if (rc == 0) {
+ rc = verifyRSASignatureFromRSA(message,
+ messageSize,
+ tSignature,
+ halg,
+ rsaPubKey);
+ }
+ TSS_RsaFree(rsaPubKey); /* @1 */
+ return rc;
+}
+
+/* signRSAFromRSA() signs digest to signature, using th4 RSA key rsaKey. */
+
+TPM_RC signRSAFromRSA(uint8_t *signature, size_t *signatureLength,
+ size_t signatureSize,
+ const uint8_t *digest, size_t digestLength,
+ TPMI_ALG_HASH hashAlg,
+ void *rsaKey)
+{
+ TPM_RC rc = 0;
+ int irc;
+ int nid; /* openssl hash algorithm */
+
+ /* map the hash algorithm to the openssl NID */
+ if (rc == 0) {
+ switch (hashAlg) {
+ case TPM_ALG_SHA1:
+ nid = NID_sha1;
+ break;
+ case TPM_ALG_SHA256:
+ nid = NID_sha256;
+ break;
+ case TPM_ALG_SHA384:
+ nid = NID_sha384;
+ break;
+ case TPM_ALG_SHA512:
+ nid = NID_sha512;
+ break;
+ default:
+ printf("signRSAFromRSA: Error, hash algorithm %04hx unsupported\n", hashAlg);
+ rc = TSS_RC_BAD_HASH_ALGORITHM;
+ }
+ }
+ /* validate that the length of the resulting signature will fit in the
+ signature array */
+ if (rc == 0) {
+ unsigned int keySize = RSA_size(rsaKey);
+ if (keySize > signatureSize) {
+ printf("signRSAFromRSA: Error, private key length %u > signature buffer %u\n",
+ keySize, (unsigned int)signatureSize);
+ rc = TSS_RC_INSUFFICIENT_BUFFER;
+ }
+ }
+ if (rc == 0) {
+ unsigned int siglen;
+ irc = RSA_sign(nid,
+ digest, digestLength,
+ signature, &siglen,
+ rsaKey);
+ *signatureLength = siglen;
+ if (irc != 1) {
+ printf("signRSAFromRSA: Error in OpenSSL RSA_sign()\n");
+ rc = TSS_RC_RSA_SIGNATURE;
+ }
+ }
+ return rc;
+}
+
+/* verifyRSASignatureFromRSA() verifies the signature 'tSignature' against the digest 'message'
+ using the RSA public key in the OpenSSL RSA format.
+
+ Supports RSASSA and RSAPSS schemes.
+*/
+
+TPM_RC verifyRSASignatureFromRSA(unsigned char *message,
+ unsigned int messageSize,
+ TPMT_SIGNATURE *tSignature,
+ TPMI_ALG_HASH halg,
+ void *rsaPubKey)
+{
+ TPM_RC rc = 0;
+ int irc;
+ int nid = 0; /* initialized these two to suppress false gcc -O3
+ warnings */
+ const EVP_MD *md = NULL;
+ /* map from hash algorithm to openssl nid */
+ if (rc == 0) {
+ switch (halg) {
+ case TPM_ALG_SHA1:
+ nid = NID_sha1;
+ md = EVP_sha1();
+ break;
+ case TPM_ALG_SHA256:
+ nid = NID_sha256;
+ md = EVP_sha256();
+ break;
+ case TPM_ALG_SHA384:
+ nid = NID_sha384;
+ md = EVP_sha384();
+ break;
+ case TPM_ALG_SHA512:
+ nid = NID_sha512;
+ md = EVP_sha512();
+ break;
+ default:
+ printf("verifyRSASignatureFromRSA: Unknown hash algorithm %04x\n", halg);
+ rc = TSS_RC_BAD_HASH_ALGORITHM;
+ }
+ }
+ /* verify the signature */
+ if (tSignature->sigAlg == TPM_ALG_RSASSA) {
+ if (rc == 0) {
+ irc = RSA_verify(nid,
+ message, messageSize,
+ tSignature->signature.rsassa.sig.t.buffer,
+ tSignature->signature.rsassa.sig.t.size,
+ rsaPubKey);
+ if (irc != 1) {
+ printf("verifyRSASignatureFromRSA: Bad signature\n");
+ rc = TSS_RC_RSA_SIGNATURE;
+ }
+ }
+ }
+ else if (tSignature->sigAlg == TPM_ALG_RSAPSS) {
+ uint8_t decryptedSig[sizeof(tSignature->signature.rsapss.sig.t.buffer)];
+ if (rc == 0) {
+ irc = RSA_public_decrypt(tSignature->signature.rsapss.sig.t.size,
+ tSignature->signature.rsapss.sig.t.buffer,
+ decryptedSig,
+ rsaPubKey,
+ RSA_NO_PADDING);
+ if (irc == -1) {
+ printf("verifyRSASignatureFromRSA: RSAPSS Bad signature\n");
+ rc = TSS_RC_RSA_SIGNATURE;
+ }
+ }
+ if (rc == 0) {
+ irc = RSA_verify_PKCS1_PSS(rsaPubKey,
+ message,
+ md,
+ decryptedSig,
+ -2); /* salt length recovered from signature*/
+ if (irc != 1) {
+ printf("verifyRSASignatureFromRSA: RSAPSS Bad signature\n");
+ rc = TSS_RC_RSA_SIGNATURE;
+ }
+ }
+ }
+ else {
+ printf("verifyRSASignatureFromRSA: Bad signature scheme %04x\n",
+ tSignature->sigAlg);
+ }
+ return rc;
+}
+
+#endif /* TPM_TSS_NORSA */
+
+#ifndef TPM_TSS_NOECC
+
+/* verifyEcSignatureFromEvpPubKey() verifies the signature 'tSignature' against the digest 'message'
+ using the EC public key in evpPkey.
+
+*/
+
+TPM_RC verifyEcSignatureFromEvpPubKey(unsigned char *message,
+ unsigned int messageSize,
+ TPMT_SIGNATURE *tSignature,
+ EVP_PKEY *evpPkey)
+{
+ TPM_RC rc = 0;
+ int irc;
+ EC_KEY *ecKey = NULL;
+ BIGNUM *r = NULL;
+ BIGNUM *s = NULL;
+ ECDSA_SIG *ecdsaSig = NULL;
+
+ /* construct the EC key token */
+ if (rc == 0) {
+ ecKey = EVP_PKEY_get1_EC_KEY(evpPkey); /* freed @1 */
+ if (ecKey == NULL) {
+ printf("verifyEcSignatureFromEvpPubKey: EVP_PKEY_get1_EC_KEY failed\n");
+ rc = TSS_RC_EC_KEY_CONVERT;
+ }
+ }
+ /* construct the ECDSA_SIG signature token */
+ if (rc == 0) {
+ rc = convertBin2Bn(&r, /* freed @2 */
+ tSignature->signature.ecdsa.signatureR.t.buffer,
+ tSignature->signature.ecdsa.signatureR.t.size);
+ }
+ if (rc == 0) {
+ rc = convertBin2Bn(&s, /* freed @2 */
+ tSignature->signature.ecdsa.signatureS.t.buffer,
+ tSignature->signature.ecdsa.signatureS.t.size);
+ }
+ /* ECDSA_SIG_new() allocates an empty ECDSA_SIG structure. */
+ if (rc == 0) {
+ ecdsaSig = ECDSA_SIG_new(); /* freed @2 */
+ if (ecdsaSig == NULL) {
+ printf("verifyEcSignatureFromEvpPubKey: Error creating ECDSA_SIG_new\n");
+ rc = TSS_RC_OUT_OF_MEMORY;
+ }
+ }
+ if (rc == 0) {
+ int irc = ECDSA_SIG_set0(ecdsaSig, r, s);
+ if (irc != 1) {
+ printf("verifyEcSignatureFromEvpPubKey: Error in ECDSA_SIG_set0()\n");
+ rc = TSS_RC_EC_KEY_CONVERT;
+ }
+ }
+ /* verify the signature */
+ if (rc == 0) {
+ irc = ECDSA_do_verify(message, messageSize,
+ ecdsaSig, ecKey);
+ if (irc != 1) { /* quote signature did not verify */
+ printf("verifyEcSignatureFromEvpPubKey: Bad signature\n");
+ rc = TSS_RC_EC_SIGNATURE;
+ }
+ }
+ if (ecKey != NULL) {
+ EC_KEY_free(ecKey); /* @1 */
+ }
+ /* if the ECDSA_SIG was allocated correctly, r and s are implicitly freed */
+ if (ecdsaSig != NULL) {
+ ECDSA_SIG_free(ecdsaSig); /* @2 */
+ }
+ /* if not, explicitly free */
+ else {
+ if (r != NULL) BN_free(r); /* @2 */
+ if (s != NULL) BN_free(s); /* @2 */
+ }
+ return rc;
+}
+
+#endif /* TPM_TSS_NOECC */
+
+#ifndef TPM_TSS_NOFILE
+
+/* verifySignatureFromHmacKey() verifies the signature (MAC) against the digest 'message'
+ using the HMAC key in raw binary format.
+*/
+
+TPM_RC verifySignatureFromHmacKey(unsigned char *message,
+ unsigned int messageSize,
+ TPMT_SIGNATURE *tSignature,
+ TPMI_ALG_HASH halg,
+ const char *hmacKeyFilename)
+{
+ TPM_RC rc = 0;
+ TPM2B_KEY hmacKey;
+ uint32_t sizeInBytes;
+
+ /* read the HMAC key */
+ if (rc == 0) {
+ rc = TSS_File_Read2B(&hmacKey.b,
+ sizeof(hmacKey.t.buffer),
+ hmacKeyFilename);
+ }
+ if (rc == 0) {
+ sizeInBytes = TSS_GetDigestSize(halg);
+ rc = TSS_HMAC_Verify(&tSignature->signature.hmac,
+ &hmacKey, /* input HMAC key */
+ sizeInBytes,
+ messageSize, message,
+ 0, NULL);
+ }
+ return rc;
+}
+
+#endif /* TPM_TSS_NOFILE */
+
+/* convertRsaBinToTSignature() converts an RSA binary signature to a TPMT_SIGNATURE */
+
+TPM_RC convertRsaBinToTSignature(TPMT_SIGNATURE *tSignature,
+ TPMI_ALG_HASH halg,
+ uint8_t *signatureBin,
+ size_t signatureBinLen)
+{
+ TPM_RC rc = 0;
+
+ tSignature->sigAlg = TPM_ALG_RSASSA;
+ tSignature->signature.rsassa.hash = halg;
+ tSignature->signature.rsassa.sig.t.size = (uint16_t)signatureBinLen;
+ memcpy(&tSignature->signature.rsassa.sig.t.buffer, signatureBin, signatureBinLen);
+ return rc;
+}
+
+#ifdef TPM_TPM20
+#ifndef TPM_TSS_NOECC
+
+/* convertEcBinToTSignature() converts an EC binary signature to a TPMT_SIGNATURE */
+
+TPM_RC convertEcBinToTSignature(TPMT_SIGNATURE *tSignature,
+ TPMI_ALG_HASH halg,
+ const uint8_t *signatureBin,
+ size_t signatureBinLen)
+{
+ TPM_RC rc = 0;
+ ECDSA_SIG *ecSig = NULL;
+ int rBytes;
+ int sBytes;
+ const BIGNUM *pr = NULL;
+ const BIGNUM *ps = NULL;
+
+ if (rc == 0) {
+ tSignature->sigAlg = TPM_ALG_ECDSA;
+ tSignature->signature.ecdsa.hash = halg;
+ }
+ /* convert DER to ECDSA_SIG */
+ if (rc == 0) {
+ ecSig = d2i_ECDSA_SIG(NULL, &signatureBin, signatureBinLen); /* freed @1 */
+ if (ecSig == NULL) {
+ printf("convertEcBinToTSignature: could not convert signature to ECDSA_SIG\n");
+ rc = TPM_RC_VALUE;
+ }
+ }
+ /* check that the signature size agrees with the currently hard coded P256 curve */
+ if (rc == 0) {
+ ECDSA_SIG_get0(ecSig, &pr, &ps);
+ rBytes = BN_num_bytes(pr);
+ sBytes = BN_num_bytes(ps);
+ if ((rBytes > 32) ||
+ (sBytes > 32)) {
+ printf("convertEcBinToTSignature: signature rBytes %u or sBytes %u greater than 32\n",
+ rBytes, sBytes);
+ rc = TPM_RC_VALUE;
+ }
+ }
+ /* extract the raw signature bytes from the openssl structure BIGNUMs */
+ if (rc == 0) {
+ tSignature->signature.ecdsa.signatureR.t.size = rBytes;
+ tSignature->signature.ecdsa.signatureS.t.size = sBytes;
+
+ BN_bn2bin(pr, (unsigned char *)&tSignature->signature.ecdsa.signatureR.t.buffer);
+ BN_bn2bin(ps, (unsigned char *)&tSignature->signature.ecdsa.signatureS.t.buffer);
+ if (tssUtilsVerbose) {
+ TSS_PrintAll("convertEcBinToTSignature: signature R",
+ tSignature->signature.ecdsa.signatureR.t.buffer,
+ tSignature->signature.ecdsa.signatureR.t.size);
+ TSS_PrintAll("convertEcBinToTSignature: signature S",
+ tSignature->signature.ecdsa.signatureS.t.buffer,
+ tSignature->signature.ecdsa.signatureS.t.size);
+ }
+ }
+ if (ecSig != NULL) {
+ ECDSA_SIG_free(ecSig); /* @1 */
+ }
+ return rc;
+}
+
+#endif /* TPM_TSS_NOECC */
+
+#ifndef TPM_TSS_NOECC
+
+/* getEcCurve() gets the TCG algorithm ID curve associated with the openssl EC_KEY */
+
+TPM_RC getEcCurve(TPMI_ECC_CURVE *curveID,
+ const EC_KEY *ecKey)
+{
+ TPM_RC rc = 0;
+ const EC_GROUP *ecGroup;
+ int nid;
+
+ if (rc == 0) {
+ ecGroup = EC_KEY_get0_group(ecKey);
+ nid = EC_GROUP_get_curve_name(ecGroup); /* openssl NID */
+ /* NID to TCG curve ID */
+ switch (nid) {
+ case NID_X9_62_prime256v1:
+ *curveID = TPM_ECC_NIST_P256;
+ break;
+ default:
+ printf("getEcCurve: Error, curve NID %u not supported \n", nid);
+ rc = TSS_RC_EC_KEY_CONVERT;
+ }
+ }
+ return rc;
+}
+
+#endif /* TPM_TSS_NOECC */
+#endif
+
+/* convertBin2Bn() wraps the openSSL function in an error handler
+
+ Converts a char array to bignum
+*/
+
+TPM_RC convertBin2Bn(BIGNUM **bn, /* freed by caller */
+ const unsigned char *bin,
+ unsigned int bytes)
+{
+ TPM_RC rc = 0;
+
+ /* BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret);
+
+ BN_bin2bn() converts the positive integer in big-endian form of length len at s into a BIGNUM
+ and places it in ret. If ret is NULL, a new BIGNUM is created.
+
+ BN_bin2bn() returns the BIGNUM, NULL on error.
+ */
+ if (rc == 0) {
+ *bn = BN_bin2bn(bin, bytes, *bn);
+ if (*bn == NULL) {
+ printf("convertBin2Bn: Error in BN_bin2bn\n");
+ rc = TSS_RC_BIGNUM;
+ }
+ }
+ return rc;
+}
+