From c15dc5405740873385c0af7f89c2813b72e53750 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0t=C4=9Bp=C3=A1n=20Hor=C3=A1=C4=8Dek?= Date: Wed, 19 Jan 2022 18:35:33 +0100 Subject: [PATCH] Fix failures introduced with OpenSSL 3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolves: rhbz#1984621 Resolves: rhbz#1992339 Signed-off-by: Štěpán Horáček --- ...Update-certifyx509-for-Openssl-3.0.0.patch | 1453 +++++++++++++++++ ...ve-unused-variables-from-certifyx509.patch | 54 + 0003-Update-certifyx509-for-Windows.patch | 99 ++ ...ean-up-certifyx509-memory-allocation.patch | 111 ++ ...tils-Fix-errors-detected-by-gcc-asan.patch | 91 ++ ...-Port-HMAC-operations-to-openssl-3.0.patch | 103 ++ ...enssl-3.0.0-replaces-RSA-with-EVP_PK.patch | 1376 ++++++++++++++++ tss2.spec | 14 +- 8 files changed, 3300 insertions(+), 1 deletion(-) create mode 100644 0001-utils-Update-certifyx509-for-Openssl-3.0.0.patch create mode 100644 0002-utils-Remove-unused-variables-from-certifyx509.patch create mode 100644 0003-Update-certifyx509-for-Windows.patch create mode 100644 0004-utils-Clean-up-certifyx509-memory-allocation.patch create mode 100644 0005-utils-Fix-errors-detected-by-gcc-asan.patch create mode 100644 0006-tss-Port-HMAC-operations-to-openssl-3.0.patch create mode 100644 0007-utils-Port-to-openssl-3.0.0-replaces-RSA-with-EVP_PK.patch diff --git a/0001-utils-Update-certifyx509-for-Openssl-3.0.0.patch b/0001-utils-Update-certifyx509-for-Openssl-3.0.0.patch new file mode 100644 index 0000000..042e8a1 --- /dev/null +++ b/0001-utils-Update-certifyx509-for-Openssl-3.0.0.patch @@ -0,0 +1,1453 @@ +From c93d780442052ae113871f4033d788a5bbe288fa Mon Sep 17 00:00:00 2001 +From: Ken Goldman +Date: Mon, 23 Aug 2021 16:09:41 -0400 +Subject: [PATCH 1/7] utils: Update certifyx509 for Openssl 3.0.0 + +i2d_x509 no longer accepts a partial structure. Therefore, replace +the input and output parsers with the ASN.1 parsing macros. +Eliminated the custom DER parsing. Set the version from the TPM +output rather than hard coding to v3. + +Add x509 validity time compatibility functions to cryptutils.c + +Add -check_ss_sig to the regression test because openssl verify does +not verify the signature on self signed certificates. + +Signed-off-by: Ken Goldman +--- + utils/certifyx509.c | 952 +++++++++++++------------------------ + utils/cryptoutils.c | 32 +- + utils/cryptoutils.h | 5 +- + utils/regtests/testx509.sh | 9 +- + 4 files changed, 365 insertions(+), 633 deletions(-) + +diff --git a/utils/certifyx509.c b/utils/certifyx509.c +index 7e8ba8d..ed42ac0 100644 +--- a/utils/certifyx509.c ++++ b/utils/certifyx509.c +@@ -4,7 +4,7 @@ + /* Written by Ken Goldman */ + /* IBM Thomas J. Watson Research Center */ + /* */ +-/* (c) Copyright IBM Corporation 2019 - 2020. */ ++/* (c) Copyright IBM Corporation 2019 - 2021. */ + /* */ + /* All rights reserved. */ + /* */ +@@ -50,6 +50,11 @@ + #include + #include + ++#include ++#include ++#include ++#include ++ + #include "cryptoutils.h" + + #ifndef TPM_TSS_MBEDTLS +@@ -64,9 +69,74 @@ + /* NOTE: This is currently openssl only. */ + #include + ++/* definition of the partial certificate, from Part 3 TPM2_CertifyX509. ++ 1) Signature Algorithm Identifier (optional) ++ 2) Issuer (mandatory) ++ 3) Validity (mandatory) ++ 4) Subject Name (mandatory) ++ 5) Extensions (mandatory) ++*/ ++ ++typedef struct { ++ ASN1_TIME *notBefore; ++ ASN1_TIME *notAfter; ++} TPM_PARTIAL_CERT_VALIDITY; ++ ++/* partial certificate TPM input parameter entire structure */ ++typedef struct { ++ X509_ALGOR *algorithm; /* signature algorithm */ ++ X509_NAME *issuer; ++ TPM_PARTIAL_CERT_VALIDITY *validity; ++ X509_NAME *subject; ++ STACK_OF(X509_EXTENSION) *extensions; ++} TPM_PARTIAL_CERT; ++ ++ASN1_SEQUENCE(TPM_PARTIAL_CERT_VALIDITY) = { ++ ASN1_SIMPLE(TPM_PARTIAL_CERT_VALIDITY, notBefore, ASN1_TIME), ++ ASN1_SIMPLE(TPM_PARTIAL_CERT_VALIDITY, notAfter, ASN1_TIME), ++} ASN1_SEQUENCE_END(TPM_PARTIAL_CERT_VALIDITY) ++ ++/* the signature algorithm is optional while the extension list is mandatory */ ++ASN1_SEQUENCE(TPM_PARTIAL_CERT) = { ++ ASN1_OPT(TPM_PARTIAL_CERT, algorithm, X509_ALGOR), ++ ASN1_SIMPLE(TPM_PARTIAL_CERT, issuer, X509_NAME), ++ ASN1_SIMPLE(TPM_PARTIAL_CERT, validity, TPM_PARTIAL_CERT_VALIDITY), ++ ASN1_SIMPLE(TPM_PARTIAL_CERT, subject, X509_NAME), ++ ASN1_EXP_SEQUENCE_OF(TPM_PARTIAL_CERT, extensions, X509_EXTENSION, 3), ++} ASN1_SEQUENCE_END(TPM_PARTIAL_CERT) ++ ++DECLARE_ASN1_FUNCTIONS(TPM_PARTIAL_CERT) ++IMPLEMENT_ASN1_FUNCTIONS(TPM_PARTIAL_CERT) ++ ++/* add to signature TPM output parameter */ ++ ++typedef struct { ++ ASN1_INTEGER *version; ++ ASN1_INTEGER *serialNumber; ++ X509_ALGOR *signatureAlgorithm; ++ X509_PUBKEY *key; ++} TPM_ADDTOCERT; ++ ++ASN1_SEQUENCE(TPM_ADDTOCERT) = { ++ ASN1_EXP_OPT(TPM_ADDTOCERT, version, ASN1_INTEGER, 0), ++ ASN1_SIMPLE(TPM_ADDTOCERT, serialNumber, ASN1_INTEGER), ++ ASN1_SIMPLE(TPM_ADDTOCERT, signatureAlgorithm, X509_ALGOR), ++ ASN1_SIMPLE(TPM_ADDTOCERT, key, X509_PUBKEY), ++} ASN1_SEQUENCE_END(TPM_ADDTOCERT) ++ ++DECLARE_ASN1_FUNCTIONS(TPM_ADDTOCERT) ++IMPLEMENT_ASN1_FUNCTIONS(TPM_ADDTOCERT) ++ + static void printUsage(void); + +-TPM_RC createPartialCertificate(X509 *x509Certificate, ++TPM_RC addPartialCertExtension(TPM_PARTIAL_CERT *partialCertificate, ++ X509 *x509Certificate, ++ int nid, const char *value); ++TPM_RC addPartialCertExtensionTpmaOid(TPM_PARTIAL_CERT *partialCertificate, ++ X509 *x509Certificate, ++ uint32_t tpmaObject); ++TPM_RC createPartialCertificate(TPM_PARTIAL_CERT *certificate, ++ X509 *x509Certificate, + uint8_t *partialCertificateDer, + uint16_t *partialCertificateDerLength, + size_t partialCertificateDerSize, +@@ -74,22 +144,11 @@ TPM_RC createPartialCertificate(X509 *x509Certificate, + uint32_t tpmaObject, + int addTpmaObject, + int subeqiss); +-TPM_RC convertCertToPartialCert(uint16_t *partialCertificateDerLength, +- uint8_t *partialCertificateDer, +- uint16_t certificateDerLength, +- uint8_t *certificateDer); + TPM_RC reformCertificate(X509 *x509Certificate, + TPMI_ALG_HASH halg, + TPMI_ALG_SIG_SCHEME scheme, +- TPMI_ECC_CURVE curveID, +- TPM2B_MAX_BUFFER *addedToCertificate, +- TPMT_SIGNATURE *tSignature); +-TPM_RC addSerialNumber(X509 *x509Certificate, +- unsigned char *tmpAddedToCert, +- uint16_t *tmpAddedToCertIndex); +-TPM_RC addPubKeyRsa(X509 *x509Certificate, +- unsigned char *tmpAddedToCert, +- uint16_t *tmpAddedToCertIndex); ++ TPM_ADDTOCERT *addToCert, ++ TPMT_SIGNATURE *tSignature); + TPM_RC addSignatureRsa(X509 *x509Certificate, + TPMI_ALG_HASH halg, + TPMT_SIGNATURE *tSignature); +@@ -97,38 +156,10 @@ TPM_RC addSignatureRsa(X509 *x509Certificate, + TPM_RC addSignatureEcc(X509 *x509Certificate, + TPMI_ALG_HASH halg, + TPMT_SIGNATURE *signature); +-TPM_RC addPubKeyEcc(X509 *x509Certificate, +- unsigned char *tmpAddedToCert, +- uint16_t *tmpAddedToCertIndex, +- TPMI_ECC_CURVE curveID); + #endif /* TPM_TSS_NOECC */ +-TPM_RC addCertExtensionTpmaOid(X509 *x509Certificate, +- uint32_t tpmaObject); +- +-TPM_RC getDataLength(uint8_t type, +- uint16_t *wrapperLength, +- uint16_t *dataLength, +- uint16_t *certificateDerIndex, +- uint8_t *certificateDer); +- +-TPM_RC skipSequence(uint16_t *certificateDerIndex, uint8_t *certificateDer); +-TPM_RC skipBitString(uint16_t *dataLength, +- uint16_t *certificateDerIndex, uint8_t *certificateDer); +- +-TPM_RC copyType(uint8_t type, +- uint16_t *partialCertificateDerLength, uint8_t *partialCertificateDer, +- uint16_t *certificateDerIndex, uint8_t *certificateDer); +- +-TPM_RC getInteger(uint16_t *integerLength, unsigned char *integerStream, +- uint16_t *certificateDerIndex, unsigned char *certificateDer); +-TPM_RC prependSequence(uint16_t *partialCertificateDerLength, uint8_t *partialCertificateDer); + + int verbose = FALSE; + +-/* FIXME +- length checks +-*/ +- + int main(int argc, char *argv[]) + { + TPM_RC rc = 0; +@@ -145,8 +176,8 @@ int main(int argc, char *argv[]) + TPMI_ALG_HASH halg = TPM_ALG_SHA256; + unsigned int bit = 0; + int testBit = FALSE; +- const char *keyPassword = NULL; +- const char *objectPassword = NULL; ++ const char *keyPassword = NULL; ++ const char *objectPassword = NULL; + const char *outPartialCertificateFilename = NULL; + const char *outCertificateFilename = NULL; + const char *addedToCertificateFilename = NULL; +@@ -167,6 +198,8 @@ int main(int argc, char *argv[]) + X509 *x509Certificate = NULL; + unsigned char *x509Der = NULL; + uint32_t x509DerLength = 0; ++ TPM_PARTIAL_CERT *partialCertificate = NULL; ++ TPM_ADDTOCERT *addToCert = NULL; + + setvbuf(stdout, 0, _IONBF, 0); /* output may be going through pipe to log file */ + TSS_SetProperty(NULL, TPM_TRACE_LEVEL, "1"); +@@ -453,9 +486,8 @@ int main(int argc, char *argv[]) + } + in.reserved.t.size = 0; + } +- /* initialize a new, empty X509 structure. It will first be used to form the partialCertificate +- command parameter, and then be used to reform the certificate from the response +- parameters. */ ++ /* initialize a new, empty X509 structure. It will be used to reform the certificate from ++ the response parameters. */ + if (rc == 0) { + x509Certificate = X509_new(); /* freed @1 */ + if (x509Certificate == NULL) { +@@ -463,9 +495,19 @@ int main(int argc, char *argv[]) + rc = TSS_RC_OUT_OF_MEMORY; + } + } +- /* form partial certificate */ ++ /* initialize a new, empty TPM_PARTIAL_CERT structure. It will be used to form the ++ partialCertificate command parameter */ ++ if (rc == 0) { ++ partialCertificate = TPM_PARTIAL_CERT_new(); /* freed @2 */ ++ if (partialCertificate == NULL) { ++ printf("main: Error in TPM_PARTIAL_CERT_new\n"); ++ rc = TSS_RC_OUT_OF_MEMORY; ++ } ++ } ++ /* form partial certificate and populate the X509 certificate with the values */ + if (rc == 0) { +- rc = createPartialCertificate(x509Certificate, ++ rc = createPartialCertificate(partialCertificate, ++ x509Certificate, + in.partialCertificate.t.buffer, + &in.partialCertificate.b.size, + sizeof(in.partialCertificate.t.buffer), +@@ -474,6 +516,7 @@ int main(int argc, char *argv[]) + addTpmaObject, + subeqiss); + } ++ /* for debug testing */ + if ((rc == 0) && (testBit)) { + unsigned int bitInByte = bit % 8; + unsigned int byteInDer = bit / 8; +@@ -481,7 +524,7 @@ int main(int argc, char *argv[]) + if (verbose) { + printf("main: Testing byte %u bit %u\n", byteInDer, bitInByte); + printf("main: Byte was %02x\n", in.partialCertificate.t.buffer[byteInDer]); +- } ++ } + in.partialCertificate.t.buffer[byteInDer] ^= (1 << bitInByte); + if (verbose) printf("main: Byte is %02x\n", in.partialCertificate.t.buffer[byteInDer]); + } +@@ -530,17 +573,22 @@ int main(int argc, char *argv[]) + printf("%s%s%s\n", msg, submsg, num); + rc = EXIT_FAILURE; + } +- /* write response parameters for debug */ ++ /* ++ write response parameters for debug ++ */ ++ /* added to certificate */ + if ((rc == 0) && (addedToCertificateFilename != NULL)) { + rc = TSS_File_WriteBinaryFile(out.addedToCertificate.t.buffer, + out.addedToCertificate.t.size, + addedToCertificateFilename); + } ++ /* to be signed digest */ + if ((rc == 0) && (tbsDigestFilename != NULL)) { + rc = TSS_File_WriteBinaryFile(out.tbsDigest.t.buffer, + out.tbsDigest.t.size, + tbsDigestFilename); + } ++ /* signature */ + if ((rc == 0) && (signatureFilename != NULL)) { + rc = TSS_File_WriteStructure(&out.signature, + (MarshalFunction_t)TSS_TPMT_SIGNATURE_Marshalu, +@@ -549,11 +597,21 @@ int main(int argc, char *argv[]) + if (rc == 0) { + if (verbose) TSS_TPMT_SIGNATURE_Print(&out.signature, 0); + } +- /* reform the signed certificate from the original input plus the response parameters */ ++ /* convert the TPM output addedToCertificate DER to the OpenSSL structure */ ++ if (rc == 0) { ++ const unsigned char *tmpptr = out.addedToCertificate.t.buffer; ++ addToCert = d2i_TPM_ADDTOCERT(NULL, /* freed @3 */ ++ &tmpptr, out.addedToCertificate.t.size); ++ if (addToCert == NULL) { ++ printf("d2i_TPM_ADDTOCERT failed %p\n", addToCert); ++ rc = EXIT_FAILURE; ++ } ++ } ++ /* reform the signed certificate from the original X509 input plus the response parameters */ + if (rc == 0) { + rc = reformCertificate(x509Certificate, +- halg, scheme, curveID, +- &out.addedToCertificate, ++ halg, scheme, ++ addToCert, + &out.signature); + } + if (rc == 0) { +@@ -569,7 +627,8 @@ int main(int argc, char *argv[]) + if (x509Certificate != NULL) { + X509_free(x509Certificate); /* @1 */ + } +- free(x509Der); /* @2 */ ++ free(x509Der); /* @2 */ ++ free(addToCert); /* @3 */ + return rc; + } + +@@ -587,7 +646,7 @@ char *issuerEntries[] = { + "IBM" , + NULL , + "CA" , +- NULL ++ NULL + }; + + char *subjectEntries[] = { +@@ -597,22 +656,23 @@ char *subjectEntries[] = { + "IBM" , + NULL , + "Subject" , +- NULL ++ NULL + }; + +-/* createPartialCertificate() forms the partialCertificate DER. It starts with an empty X509 +- structure and adds the needed parameters. Then (in a total hack), converts the X509 structure to +- DER, parses the DER field by field, and outputs just the fields required for the +- partialCertificate parameter. ++/* createPartialCertificate() forms the partialCertificate DER. It starts with an empty X509 and ++ TPM_PARTIAL_CERT structures. It adds the needed parameters to both structures. It then ++ serializes the TPM_PARTIAL_CERT structure to partialCertificateDer; + + subeqiss FALSE: subject name is independent of issuer name + subeqiss TRUE: subject name is the same as the issuer name + */ + +-TPM_RC createPartialCertificate(X509 *x509Certificate, /* input / output */ ++TPM_RC createPartialCertificate(TPM_PARTIAL_CERT *partialCertificate, /* input / output */ ++ X509 *x509Certificate, /* input / output */ + uint8_t *partialCertificateDer, /* output */ + uint16_t *partialCertificateDerLength, +- size_t partialCertificateDerSize, ++ size_t partialCertificateDerSize, /* input, size of ++ partialCertificateDer */ + const char *keyUsage, + uint32_t tpmaObject, + int addTpmaObject, +@@ -626,40 +686,31 @@ TPM_RC createPartialCertificate(X509 *x509Certificate, /* input / output */ + X509_NAME *x509SubjectName = NULL;/* composite subject name, key/value pairs */ + size_t issuerEntriesSize = sizeof(issuerEntries)/sizeof(char *); + size_t subjectEntriesSize = sizeof(subjectEntries)/sizeof(char *); +- +- uint32_t certificateDerLength = 0; +- uint8_t *certificateDer = NULL; ++ ASN1_TIME *notBefore = NULL; ++ ASN1_TIME *notAfter = NULL; ++ uint8_t *tmpPartialDer = NULL; /* for the i2d */ + +- partialCertificateDerSize = partialCertificateDerSize; /* FIXME needs size check */ +- +- /* add certificate version X509 v3 */ +- if (rc == 0) { +- irc = X509_set_version(x509Certificate, 2L); /* value 2 == v3 */ +- if (irc != 1) { +- printf("createPartialCertificate: Error in X509_set_version\n"); +- rc = TSS_RC_X509_ERROR; +- } +- } + /* add issuer */ + if (rc == 0) { + if (verbose) printf("createPartialCertificate: Adding issuer, size %lu\n", +- (unsigned long)issuerEntriesSize); +- rc = createX509Name(&x509IssuerName, /* freed @1 */ ++ (unsigned long)issuerEntriesSize); ++ rc = createX509Name(&partialCertificate->issuer, /* freed @1 */ + issuerEntriesSize, + issuerEntries); + } + if (rc == 0) { +- irc = X509_set_issuer_name(x509Certificate, x509IssuerName); ++ irc = X509_set_issuer_name(x509Certificate, partialCertificate->issuer); + if (irc != 1) { + printf("createPartialCertificate: Error setting issuer\n"); + rc = TSS_RC_X509_ERROR; + } + } +- /* add validity */ ++ /* ++ validity before ++ */ + if (rc == 0) { +- /* can't fail, just returns a structure member */ +- ASN1_TIME *notBefore = X509_get_notBefore(x509Certificate); +- arc = X509_gmtime_adj(notBefore ,0L); /* set to today */ ++ /* set to today */ ++ arc = X509_gmtime_adj(partialCertificate->validity->notBefore ,0L); + if (arc == NULL) { + printf("createPartialCertificate: Error setting notBefore time\n"); + rc = TSS_RC_X509_ERROR; +@@ -667,20 +718,39 @@ TPM_RC createPartialCertificate(X509 *x509Certificate, /* input / output */ + } + if (rc == 0) { + /* can't fail, just returns a structure member */ +- ASN1_TIME *notAfter = X509_get_notAfter(x509Certificate); +- arc = X509_gmtime_adj(notAfter, CERT_DURATION); /* set to duration */ ++ notBefore = X509_get_notBefore(x509Certificate); ++ irc = X509_set1_notBefore(x509Certificate, partialCertificate->validity->notBefore); ++ if (irc == 0) { ++ printf("createPartialCertificate: Error setting notBefore time\n"); ++ rc = TSS_RC_X509_ERROR; ++ } ++ } ++ /* ++ validity after ++ */ ++ if (rc == 0) { ++ /* set to duration */ ++ arc = X509_gmtime_adj(partialCertificate->validity->notAfter, CERT_DURATION); + if (arc == NULL) { + printf("createPartialCertificate: Error setting notAfter time\n"); + rc = TSS_RC_X509_ERROR; + } + } ++ if (rc == 0) { ++ notAfter = X509_get_notAfter(x509Certificate); ++ irc = X509_set1_notAfter(x509Certificate,partialCertificate->validity->notAfter); ++ if (irc == 0) { ++ printf("createPartialCertificate: Error setting notAfter time\n"); ++ rc = TSS_RC_X509_ERROR; ++ } ++ } + /* add subject */ + if (rc == 0) { + /* normal case */ + if (!subeqiss) { + if (verbose) printf("createPartialCertificate: Adding subject, size %lu\n", + (unsigned long)subjectEntriesSize); +- rc = createX509Name(&x509SubjectName, /* freed @2 */ ++ rc = createX509Name(&partialCertificate->subject, /* freed @2 */ + subjectEntriesSize, + subjectEntries); + } +@@ -688,13 +758,13 @@ TPM_RC createPartialCertificate(X509 *x509Certificate, /* input / output */ + else { + if (verbose) printf("createPartialCertificate: Adding subject (issuer), size %lu\n", + (unsigned long)issuerEntriesSize); +- rc = createX509Name(&x509SubjectName, /* freed @2 */ ++ rc = createX509Name(&partialCertificate->subject, /* freed @2 */ + issuerEntriesSize, + issuerEntries); + } + } + if (rc == 0) { +- irc = X509_set_subject_name(x509Certificate, x509SubjectName); ++ irc = X509_set_subject_name(x509Certificate, partialCertificate->subject); + if (irc != 1) { + printf("createPartialCertificate: Error setting subject\n"); + rc = TSS_RC_X509_ERROR; +@@ -703,109 +773,179 @@ TPM_RC createPartialCertificate(X509 *x509Certificate, /* input / output */ + /* add some certificate extensions, requires corresponding bits in subject key */ + if (rc == 0) { + if (verbose) printf("createPartialCertificate: Adding extensions\n"); +- rc = addCertExtension(x509Certificate, +- NID_key_usage, keyUsage); ++ rc = addPartialCertExtension(partialCertificate, ++ x509Certificate, ++ NID_key_usage, keyUsage); + } + /* optional TPMA_OBJECT extension */ + /* From TCG OID registry tcg-tpmaObject 2.23.133.10.1.1.1 */ + if (rc == 0) { + if (addTpmaObject) { +- rc = addCertExtensionTpmaOid(x509Certificate, tpmaObject); ++ rc = addPartialCertExtensionTpmaOid(partialCertificate, ++ x509Certificate, ++ tpmaObject); + } + } +- /* convertX509ToDer() serializes the openSSL X509 structure to a DER certificate stream */ ++ /* serialize the openSSL partial certificate structure to a DER stream */ ++ if (rc == 0) { ++ *partialCertificateDerLength = ++ (uint16_t)i2d_TPM_PARTIAL_CERT(partialCertificate, ++ &tmpPartialDer); /* freed @3 */ ++ } ++ /* check the i2d size, and copy the DER to the TPM input parameter */ + if (rc == 0) { +- rc = convertX509ToDer(&certificateDerLength, +- &certificateDer, /* freed @4 */ +- x509Certificate); /* input */ ++ if (*partialCertificateDerLength <= partialCertificateDerSize) { ++ memcpy(partialCertificateDer, tmpPartialDer, *partialCertificateDerLength); ++ } ++ else { ++ printf("createPartialCertificate: Partial cert size %u too large\n", ++ *partialCertificateDerLength); ++ rc = TSS_RC_X509_ERROR; ++ } + } +- /* for debug. The structure is incomplete and so will trace with errors */ ++#if 0 ++ /* for debug. The X509 structure is incomplete and so will trace with errors */ + if (rc == 0) { + if (verbose) printf("createPartialCertificate: Trace preliminary certificate\n"); + if (verbose) X509_print_fp(stdout, x509Certificate); + } +-#if 1 +- /* for debug. Use dumpasn1 to view the incomplete certificate */ ++#endif ++ X509_NAME_free(x509IssuerName); /* @1 */ ++ X509_NAME_free(x509SubjectName); /* @2 */ ++ free(tmpPartialDer); /* @3 */ ++ return rc; ++} ++ ++/* addPartialCertExtension() adds the extension type 'nid' to the partial certificate ++ ++ */ ++ ++TPM_RC addPartialCertExtension(TPM_PARTIAL_CERT *partialCertificate, ++ X509 *x509Certificate, ++ int nid, const char *value) ++{ ++ TPM_RC rc = 0; ++ X509_EXTENSION *extension = NULL; /* freed @1 */ ++ ++ if (rc == 0) { ++#if OPENSSL_VERSION_NUMBER < 0x10100000 ++ /* the cast is required for the older openssl 1.0 API */ ++ extension = X509V3_EXT_conf_nid(NULL, NULL, /* freed @1 */ ++ nid, (char *)value); ++#else ++ extension = X509V3_EXT_conf_nid(NULL, NULL, /* freed @1 */ ++ nid, value); ++#endif ++ if (extension == NULL) { ++ printf("addPartialCertExtension: Error creating nid %i extension %s\n", ++ nid, value); ++ rc = -1; ++ } ++ } + if (rc == 0) { +- rc = TSS_File_WriteBinaryFile(certificateDer, certificateDerLength , "tmpx509i.bin"); ++ STACK_OF(X509_EXTENSION) *src = ++ X509v3_add_ext(&partialCertificate->extensions, ++ extension, /* the extension to add */ ++ -1); /* location - append */ ++ if (src == NULL) { ++ printf("addPartialCertExtension: Error adding nid %i extension %s\n", ++ nid, value); ++ } + } +-#endif +- /* extract the partialCertificate DER from the X509 DER */ + if (rc == 0) { +- rc = convertCertToPartialCert(partialCertificateDerLength, +- partialCertificateDer, /* output partial */ +- certificateDerLength, +- certificateDer); /* input X509 */ ++ int irc = X509_add_ext(x509Certificate, ++ extension, /* the extension to add */ ++ -1); /* location - append */ ++ if (irc != 1) { ++ printf("addCertExtension: Error adding oid to extension\n"); ++ } ++ } ++ if (extension != NULL) { ++ X509_EXTENSION_free(extension); /* @1 */ + } +- X509_NAME_free(x509IssuerName); /* @1 */ +- X509_NAME_free(x509SubjectName); /* @2 */ +- free(certificateDer); /* @4 */ + return rc; + } + +-/* addCertExtension() adds the tpmaObject extension oid to the X509 certificate ++/* addPartialCertExtensionTpmaOid() adds the tpmaObject extension oid to the X509 certificate + +- */ ++ */ + +-TPM_RC addCertExtensionTpmaOid(X509 *x509Certificate, uint32_t tpmaObject) ++TPM_RC addPartialCertExtensionTpmaOid(TPM_PARTIAL_CERT *partialCertificate, ++ X509 *x509Certificate, ++ uint32_t tpmaObject) + { + TPM_RC rc = 0; + X509_EXTENSION *extension = NULL; /* freed @1 */ + + + uint8_t tpmaObjectOid[] = {0x06, 0x07, 0x67, 0x81, 0x05, 0x0A, 0x01, 0x01, 0x01}; +- const uint8_t *tmpOidPtr; ++ const uint8_t *tmpOidPtr; /* const for d2i_ASN1_OBJECT */ + + /* BIT STRING 0x03 length 5 no padding 0, 4 dummy bytes of TPMA_OBJECT */ + uint8_t tpmaObjectData[] = {0x03, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00}; + ASN1_OBJECT *object = NULL; +- ASN1_OCTET_STRING *osData = NULL; ++ ASN1_OCTET_STRING *osData = NULL; + uint8_t *tmpOdPtr; + uint32_t tpmaObjectNbo = htonl(tpmaObject); + ++ ++ /* create the object */ + if (rc == 0) { +- tmpOidPtr = tpmaObjectOid; ++ tmpOidPtr = tpmaObjectOid; + object = d2i_ASN1_OBJECT(NULL, &tmpOidPtr, sizeof(tpmaObjectOid)); /* freed @2 */ + if (object == NULL) { +- printf("d2i_ASN1_OBJECT failed\n"); ++ printf("addPartialCertExtensionTpmaOid: d2i_ASN1_OBJECT failed\n"); + rc = TSS_RC_X509_ERROR; + } + } + if (rc == 0) { + osData = ASN1_OCTET_STRING_new(); /* freed @3 */ + if (osData == NULL) { +- printf("d2i_ASN1_OCTET_STRING failed\n"); ++ printf("addPartialCertExtensionTpmaOid: ASN1_OCTET_STRING_new failed\n"); + rc = TSS_RC_X509_ERROR; + } + } ++ /* copy the TPMA_OBJECT bytes to the BIT STRING place holder, set the result in the ++ ASN1_OCTET_STRING */ + if (rc == 0) { + tmpOdPtr = tpmaObjectData; + memcpy(tmpOdPtr + 3, &tpmaObjectNbo, sizeof(uint32_t)); + ASN1_OCTET_STRING_set(osData, tmpOdPtr, sizeof (tpmaObjectData)); + } ++ /* create the extension with the TPMA_OBJECT in the ASN1_OBJECT */ + if (rc == 0) { + extension = X509_EXTENSION_create_by_OBJ(NULL, /* freed @1 */ + object, +- 0, /* int crit */ ++ 0, /* int crit */ + osData); + if (extension == NULL) { +- printf("X509_EXTENSION_create_by_OBJ failed\n"); ++ printf("addPartialCertExtensionTpmaOid: X509_EXTENSION_create_by_OBJ failed\n"); + rc = TSS_RC_X509_ERROR; + } + } ++ /* append the extensions to the partial certificate stack */ ++ if (rc == 0) { ++ STACK_OF(X509_EXTENSION) *src = X509v3_add_ext(&partialCertificate->extensions, ++ extension, /* the extension to add */ ++ -1); /* location - append */ ++ if (src == NULL) { ++ printf("addPartialCertExtensionTpmaOid: Error adding oid to extension\n"); ++ } ++ } ++ /* append the extensions to the X509 certificate */ + if (rc == 0) { +- int irc = X509_add_ext(x509Certificate, /* the certificate */ ++ int irc = X509_add_ext(x509Certificate, /* the certificate */ + extension, /* the extension to add */ + -1); /* location - append */ + if (irc != 1) { +- printf("addCertExtension: Error adding oid to extension\n"); ++ printf("addPartialCertExtensionTpmaOid: Error adding oid to extension\n"); + } + } + if (extension != NULL) { + X509_EXTENSION_free(extension); /* @1 */ + } + if (object != NULL) { +- ASN1_OBJECT_free(object); /* @2 */ ++ ASN1_OBJECT_free(object); /* @2 */ + } + if (osData != NULL) { + ASN1_OCTET_STRING_free(osData); /* @3 */ +@@ -813,327 +953,95 @@ TPM_RC addCertExtensionTpmaOid(X509 *x509Certificate, uint32_t tpmaObject) + return rc; + } + +- +-/* convertCertToPartialCert() extracts the partialCertificate DER from the X509 DER +- +- It assumes that the input is well formed and has exactly the fields required. +-*/ +- +-TPM_RC convertCertToPartialCert(uint16_t *partialCertificateDerLength, +- uint8_t *partialCertificateDer, +- uint16_t certificateDerLength, +- uint8_t *certificateDer) +-{ +- TPM_RC rc = 0; +- uint16_t certificateDerIndex = 0; /* index into the DER input */ +- +- +- certificateDerLength = certificateDerLength; /* FIXME for future error checking */ +- *partialCertificateDerLength = 0; /* updates on each call */ +- +- /* skip the outer SEQUENCE wrapper */ +- if (rc == 0) { +- if (verbose) printf("convertCertToPartialCert: Skip outer SEQUENCE wrapper\n"); +- rc = skipSequence(&certificateDerIndex, certificateDer); +- } +- /* skip the inner SEQUENCE wrapper, will be back filled with the total length */ +- if (rc == 0) { +- if (verbose) printf("convertCertToPartialCert: Skip inner SEQUENCE wrapper\n"); +- rc = skipSequence(&certificateDerIndex, certificateDer); +- } +- /* skip the a3 wrapping the version */ +- if (rc == 0) { +- if (verbose) printf("convertCertToPartialCert: Skip a3 version wrapper\n"); +- rc = copyType(0xa0, NULL, NULL, /* NULL says to skip */ +- &certificateDerIndex, certificateDer); +- } +- /* skip the integer (version) */ +- if (rc == 0) { +- if (verbose) printf("convertCertToPartialCert: Skip version\n"); +- rc = copyType(0x02, NULL, NULL, /* NULL says to skip */ +- &certificateDerIndex, certificateDer); +- } +- /* skip the sequence (serial number) */ +- if (rc == 0) { +- if (verbose) printf("convertCertToPartialCert: Skip serial number\n"); +- rc = copyType(0x30, NULL, NULL, /* NULL says to skip */ +- &certificateDerIndex, certificateDer); +- } +- /* copy the next SEQUENCE, issuer */ +- if (rc == 0) { +- if (verbose) printf("convertCertToPartialCert: Copy issuer\n"); +- rc = copyType(0x30, partialCertificateDerLength, partialCertificateDer, +- &certificateDerIndex, certificateDer); +- } +- /* copy the next SEQUENCE, validity */ +- if (rc == 0) { +- if (verbose) printf("convertCertToPartialCert: Copy validity\n"); +- rc = copyType(0x30, partialCertificateDerLength, partialCertificateDer, +- &certificateDerIndex, certificateDer); +- } +- /* copy the next SEQUENCE, subject */ +- if (rc == 0) { +- if (verbose) printf("convertCertToPartialCert: Copy subject\n"); +- rc = copyType(0x30, partialCertificateDerLength, partialCertificateDer, +- &certificateDerIndex, certificateDer); +- } +- /* skip the SEQUENCE (public key) */ +- if (rc == 0) { +- if (verbose) printf("convertCertToPartialCert: Skip public key\n"); +- rc = copyType(0x30, NULL, NULL, /* NULL says to skip */ +- &certificateDerIndex, certificateDer); +- } +- /* copy the a3 and encapsulating sequence */ +- if (rc == 0) { +- if (verbose) printf("convertCertToPartialCert: Copy a3 extensions\n"); +- rc = copyType(0xa3, partialCertificateDerLength, partialCertificateDer, +- &certificateDerIndex, certificateDer); +- } +- /* shift and back fill the sequence length */ +- if (rc == 0) { +- rc = prependSequence(partialCertificateDerLength, partialCertificateDer); +- } +- return rc; +-} +- +-/* reformCertificate() starts with the X509 certificate used as the input partialCertificate +- parameter plus a few fields like the version. It adds the output addedToCertificate and +- signature values to reform the X509 certificate that the TPM signed. +-*/ ++/* reformCertificate() starts with the X509 certificate filled with the input partialCertificate ++ parameter. It adds the output addedToCertificate and signature values to reform the X509 ++ certificate that the TPM signed. */ + + TPM_RC reformCertificate(X509 *x509Certificate, + TPMI_ALG_HASH halg, + TPMI_ALG_SIG_SCHEME scheme, +- TPMI_ECC_CURVE curveID, +- TPM2B_MAX_BUFFER *addedToCertificate, ++ TPM_ADDTOCERT *addToCert, + TPMT_SIGNATURE *tSignature) + { + TPM_RC rc = 0; +- unsigned char *tmpAddedToCert = NULL; +- /* size_t tmpAddedToCertLength = 0; FIXME better to sanity check length */ +- +- /* the index increments, so this function must parse the addedToCertificate in its order */ +- uint16_t tmpAddedToCertIndex = 0; +- +- tmpAddedToCert = addedToCertificate->t.buffer; +- /* tmpAddedToCertLength = addedToCertificate->t.size; */ +- +- /* add serial number */ +- if (rc == 0) { +- rc = addSerialNumber(x509Certificate, +- tmpAddedToCert, +- &tmpAddedToCertIndex); +- } +- if (scheme == TPM_ALG_RSASSA) { +- /* add public key algorithm and public key */ +- if (rc == 0) { +- rc = addPubKeyRsa(x509Certificate, +- tmpAddedToCert, +- &tmpAddedToCertIndex); +- } +- /* add certificate signature */ +- if (rc == 0) { +- rc = addSignatureRsa(x509Certificate, halg, tSignature); ++ int irc; ++ long versionl; ++ EVP_PKEY *evpPubkey = NULL; /* EVP format public key to be certified */ ++ ++ /* version */ ++#if OPENSSL_VERSION_NUMBER < 0x10100000 ++ /* Older openssl does not has the uint64 function. This function is deprecated but OK since ++ X509 certificates never have a negative version. */ ++ if (rc == 0) { ++ versionl= ASN1_INTEGER_get(addToCert->version); ++ if (versionl < 0) { ++ printf("reformCertificate: Error in ASN1_INTEGER_get version\n"); ++ rc = TSS_RC_X509_ERROR; + } + } +-#ifndef TPM_TSS_NOECC +- else { /* scheme == TPM_ALG_ECDSA */ +- /* add public key */ +- if (rc == 0) { +- rc = addPubKeyEcc(x509Certificate, +- tmpAddedToCert, +- &tmpAddedToCertIndex, +- curveID); ++#else ++ if (rc == 0) { ++ uint64_t version64; ++ irc = ASN1_INTEGER_get_uint64(&version64, addToCert->version); ++ if (irc != 1) { ++ printf("reformCertificate: Error in ASN1_INTEGER_get_uint64 version\n"); ++ rc = TSS_RC_X509_ERROR; + } +- /* add certificate signature */ +- if (rc == 0) { +- rc = addSignatureEcc(x509Certificate, halg, tSignature); ++ else if (version64 > LONG_MAX) { ++ printf("reformCertificate: Version out of range\n"); ++ rc = TSS_RC_X509_ERROR; ++ } ++ else { ++ versionl = (long)version64; + } + } +-#endif /* TPM_TSS_NOECC */ +- return rc; +-} +- +-/* addSerialNumber() is the first call from reforming the certificate. tmpAddedToCertIndex will be +- 0. +- +- After the call, tmpAddedToCertIndex will point after the serial number. +-*/ +- +-TPM_RC addSerialNumber(X509 *x509Certificate, +- unsigned char *tmpAddedToCert, +- uint16_t *tmpAddedToCertIndex) +-{ +- TPM_RC rc = 0; +- ASN1_INTEGER *x509Serial; /* certificate serial number in ASN1 */ +- BIGNUM *x509SerialBN; /* certificate serial number as a BIGNUM */ +- unsigned char x509SerialBin[1048]; /* certificate serial number in binary */ +- uint16_t integerLength = 0; +- +- /* FIXME check the size */ +- +- x509SerialBN = NULL; +- +- /* skip outer sequence */ +- if (rc == 0) { +- rc = skipSequence(tmpAddedToCertIndex, tmpAddedToCert); +- } +- /* skip version */ +- if (rc == 0) { +- rc = copyType(0xa0, NULL, NULL, /* NULL says to skip */ +- tmpAddedToCertIndex, tmpAddedToCert); +- } +- /* get integer serial number from addedToCertificate */ +- if (rc == 0) { +- rc = getInteger(&integerLength, x509SerialBin, +- tmpAddedToCertIndex, tmpAddedToCert); +- } +- /* convert the integer stream to a BIGNUM */ ++#endif + if (rc == 0) { +- x509SerialBN = BN_bin2bn(x509SerialBin, integerLength, x509SerialBN); /* freed @1 */ +- if (x509SerialBN == NULL) { +- printf("addSerialNumber: Error in serial number BN_bin2bn\n"); ++ irc = X509_set_version(x509Certificate, versionl); ++ if (irc != 1) { ++ printf("reformCertificate: Error in X509_set_version\n"); + rc = TSS_RC_X509_ERROR; + } + } +- /* add it into the final certificate */ ++ /* serial number */ + if (rc == 0) { +- /* get the serial number structure member, can't fail */ +- x509Serial = X509_get_serialNumber(x509Certificate); +- /* convert the BIGNUM to ASN1 and add to X509 certificate */ +- x509Serial = BN_to_ASN1_INTEGER(x509SerialBN, x509Serial); +- if (x509Serial == NULL) { +- printf("addSerialNumber: Error setting certificate serial number\n"); ++ irc = X509_set_serialNumber(x509Certificate, addToCert->serialNumber); ++ if (irc != 1) { ++ printf("reformCertificate: Error in X509_set_serialNumber\n"); + rc = TSS_RC_X509_ERROR; + } + } +- if (x509SerialBN != NULL) BN_clear_free(x509SerialBN ); /* @1 */ +- return rc; +-} +- +-/* addPubKeyRsa() adds the public key to the certificate. tmpAddedToCertIndex must point to the +- public key. +- */ +- +-TPM_RC addPubKeyRsa(X509 *x509Certificate, +- unsigned char *tmpAddedToCert, +- uint16_t *tmpAddedToCertIndex) +-{ +- TPM_RC rc = 0; +- TPM2B_PUBLIC_KEY_RSA tpm2bRsa; +- uint16_t dataLength; +- +- /* skip the SEQUENCE with the Signature Algorithm object identifier */ +- if (rc == 0) { +- rc = copyType(0x30, NULL, NULL, /* NULL says to skip */ +- tmpAddedToCertIndex, tmpAddedToCert); +- } +- /* skip the SEQUENCE wrapper for the Subject Public Key Info */ +- if (rc == 0) { +- rc = skipSequence(tmpAddedToCertIndex, tmpAddedToCert); +- } +- /* skip the SEQUENCE Public Key Algorithm */ +- if (rc == 0) { +- rc = copyType(0x30, NULL, NULL, /* NULL says to skip */ +- tmpAddedToCertIndex, tmpAddedToCert); +- } +- /* skip the BIT STRING intoduction to the public key */ +- if (rc == 0) { +- rc = skipBitString(&dataLength, tmpAddedToCertIndex, tmpAddedToCert); +- } +- /* skip the SEQUENCE wrapper for the public key */ +- if (rc == 0) { +- rc = skipSequence(tmpAddedToCertIndex, tmpAddedToCert); +- } +- /* get the integer public modulus FIXME missing length check */ +- if (rc == 0) { +- rc = getInteger(&tpm2bRsa.t.size, tpm2bRsa.t.buffer, +- tmpAddedToCertIndex, tmpAddedToCert); +- } ++ /* public key including algorithm */ + if (rc == 0) { +- rc = addCertKeyRsa(x509Certificate, +- &tpm2bRsa); /* certified public key */ +- } +- /* skip the INTEGER public exponent - should not matter since it's the last item */ +- /* FIXME test for 010001 */ +- if (rc == 0) { +- uint16_t dummy; +- rc = getInteger(&dummy, NULL, +- tmpAddedToCertIndex, tmpAddedToCert); +- } +- return rc; +-} +- +-#ifndef TPM_TSS_NOECC +-/* addPubKeyEcc() adds the public key to the certificate. tmpAddedToCertIndex must point to the +- public key. +- +- Supports TPM_ECC_NIST_P256, TPM_ECC_NIST_P384. +-*/ +- +- +-TPM_RC addPubKeyEcc(X509 *x509Certificate, +- unsigned char *tmpAddedToCert, +- uint16_t *tmpAddedToCertIndex, +- TPMI_ECC_CURVE curveID) +-{ +- TPM_RC rc = 0; +- uint16_t dataLength; +- uint16_t pointSize; +- +- /* skip the SEQUENCE with the Signature Algorithm object identifier ecdsaWithSHAnnn */ +- if (rc == 0) { +- rc = copyType(0x30, NULL, NULL, /* NULL says to skip */ +- tmpAddedToCertIndex, tmpAddedToCert); +- } +- /* skip the SEQUENCE wrapper for the Subject Public Key Info */ +- if (rc == 0) { +- rc = skipSequence(tmpAddedToCertIndex, tmpAddedToCert); +- } +- /* skip the SEQUENCE Public Key Algorithm */ +- if (rc == 0) { +- rc = copyType(0x30, NULL, NULL, /* NULL says to skip */ +- tmpAddedToCertIndex, tmpAddedToCert); +- } +- /* skip the BIT STRING intoduction to the public key */ +- if (rc == 0) { +- rc = skipBitString(&dataLength, tmpAddedToCertIndex, tmpAddedToCert); ++ evpPubkey = X509_PUBKEY_get(addToCert->key); /* freed @1 */ ++ if (evpPubkey == NULL) { ++ printf("reformCertificate: X509_PUBKEY_get failed\n"); ++ rc = TSS_RC_OUT_OF_MEMORY; ++ } + } + if (rc == 0) { +- switch(curveID) { +- case TPM_ECC_NIST_P256: +- pointSize = 256/8; +- break; +- case TPM_ECC_NIST_P384: +- pointSize = 384/8; +- break; +- default: /* should never occur */ +- printf("addPubKeyEcc: Bad curveID %04x\n", curveID); +- rc = TSS_RC_BAD_SIGNATURE_ALGORITHM; +- break; ++ irc = X509_set_pubkey(x509Certificate, evpPubkey); ++ if (irc != 1) { ++ printf("reformCertificate: Error X509_set_pubkey failed\n"); ++ rc = TSS_RC_X509_ERROR; + } + } +- /* the next bytes are the 04, x and y */ ++ /* add certificate signature */ + if (rc == 0) { +- TPMT_PUBLIC tpmtPublic; +- +- *tmpAddedToCertIndex += 1; /* skip the 0x04 compression byte */ +- +- tpmtPublic.unique.ecc.x.t.size = pointSize; +- memcpy(tpmtPublic.unique.ecc.x.t.buffer, tmpAddedToCert + *tmpAddedToCertIndex, pointSize); +- *tmpAddedToCertIndex += pointSize; +- +- +- tpmtPublic.unique.ecc.y.t.size = pointSize; +- memcpy(tpmtPublic.unique.ecc.y.t.buffer, tmpAddedToCert + *tmpAddedToCertIndex, pointSize); +- *tmpAddedToCertIndex += pointSize; +- +- tpmtPublic.parameters.eccDetail.curveID = curveID; +- rc = addCertKeyEccT(x509Certificate, &tpmtPublic); ++ if (scheme == TPM_ALG_RSASSA) { ++ if (rc == 0) { ++ rc = addSignatureRsa(x509Certificate, halg, tSignature); ++ } ++ } ++ else { /* scheme == TPM_ALG_ECDSA */ ++ if (rc == 0) { ++ rc = addSignatureEcc(x509Certificate, halg, tSignature); ++ } ++ } + } ++ EVP_PKEY_free(evpPubkey); /* @1 **/ + return rc; + } +-#endif /* TPM_TSS_NOECC */ + + /* addSignatureRsa() copies the TPMT_SIGNATURE output of the TPM2_CertifyX509 command to the X509 + certificate. +@@ -1148,9 +1056,9 @@ TPM_RC addSignatureRsa(X509 *x509Certificate, + X509_ALGOR *signatureAlgorithm = NULL; + X509_ALGOR *certSignatureAlgorithm = NULL; + ASN1_BIT_STRING *asn1Signature = NULL; +- ++ + /* FIXME check sign length */ +- ++ + if (rc == 0) { + certSignatureAlgorithm = (X509_ALGOR *)X509_get0_tbs_sigalg(x509Certificate); + X509_get0_signature((OSSLCONST ASN1_BIT_STRING**)&asn1Signature, +@@ -1194,6 +1102,7 @@ TPM_RC addSignatureRsa(X509 *x509Certificate, + } + + #ifndef TPM_TSS_NOECC ++ + /* addSignatureEcc() copies the TPMT_SIGNATURE output of the TPM2_CertifyX509 command to the X509 + certificate. + */ +@@ -1214,7 +1123,7 @@ TPM_RC addSignatureEcc(X509 *x509Certificate, + int ecdsaSigBinLength; + + /* FIXME check sign length */ +- ++ + if (rc == 0) { + certSignatureAlgorithm = (X509_ALGOR *)X509_get0_tbs_sigalg(x509Certificate); + X509_get0_signature((OSSLCONST ASN1_BIT_STRING**)&asn1Signature, +@@ -1319,211 +1228,6 @@ TPM_RC addSignatureEcc(X509 *x509Certificate, + } + #endif /* TPM_TSS_NOECC */ + +-/* getDataLength() checks the type, gets the length of the wrapper and following data */ +- +-TPM_RC getDataLength(uint8_t type, /* expected type */ +- uint16_t *wrapperLength, /* wrapper */ +- uint16_t *dataLength, /* data */ +- uint16_t *certificateDerIndex, +- uint8_t *certificateDer) +-{ +- TPM_RC rc = 0; +- uint32_t i = 0; +- uint16_t lengthLength = 0; /* number of length bytes */ +- +- /* validate the wrapper type */ +- if (rc == 0) { +- if (certificateDer[*certificateDerIndex] != type) { +- printf("getDataLength: index %u expect %02x actual %02x\n", +- *certificateDerIndex, type, certificateDer[*certificateDerIndex]); +- rc = TSS_RC_X509_ERROR; +- } +- } +- /* get the length */ +- if (rc == 0) { +- /* long form length starts with the 'length of the length' */ +- if ((certificateDer[*certificateDerIndex + 1] & 0x80)) { +- lengthLength = certificateDer[*certificateDerIndex + 1] & 0x7f; +- if (lengthLength <= sizeof(*dataLength)) { +- +- *dataLength = 0; +- for (i = 0 ; i < lengthLength ; i++) { +- *dataLength <<= (i * 8); +- *dataLength += certificateDer[*certificateDerIndex + 2 + i]; +- } +- } +- else { +- printf("getDataLength: lengthLength %u too large for uint16_t\n", lengthLength); +- rc = TSS_RC_X509_ERROR; +- } +- } +- /* short form length is in byte following type */ +- else { +- *dataLength = certificateDer[*certificateDerIndex + 1] & 0x7f; +- } +- } +- if (rc == 0) { +- *wrapperLength = 2 + lengthLength; +- if (verbose) printf("getDataLength: wrapperLength %u dataLength %u\n", +- *wrapperLength, *dataLength); +- } +- return rc; +-} +- +-/* skipSequence() moves the certificateDerIndex past the SEQUENCE and its length. I.e., it just +- skips the wrapper, not the contents +-*/ +- +-TPM_RC skipSequence(uint16_t *certificateDerIndex, uint8_t *certificateDer) +-{ +- TPM_RC rc = 0; +- uint16_t wrapperLength; +- uint16_t dataLength; +- +- if (rc == 0) { +- rc = getDataLength(0x30, /* variable length SEQUENCE */ +- &wrapperLength, +- &dataLength, +- certificateDerIndex, certificateDer); +- } +- if (rc == 0) { +- *certificateDerIndex += wrapperLength; +- } +- return rc; +-} +- +-/* skipBitString() moves the certificateDerIndex past the BIT STRING, its length, and its padding, +- not the contents +-*/ +- +-TPM_RC skipBitString(uint16_t *dataLength, +- uint16_t *certificateDerIndex, uint8_t *certificateDer) +-{ +- TPM_RC rc = 0; +- uint16_t wrapperLength; +- +- if (rc == 0) { +- rc = getDataLength(0x03, /* BIT STRING */ +- &wrapperLength, +- dataLength, +- certificateDerIndex, certificateDer); +- } +- if (rc == 0) { +- *certificateDerIndex += wrapperLength; +- *certificateDerIndex += 1; /* BIT STRING padding */ +- } +- return rc; +-} +- +-/* copyType() copies the type at certificateDerIndex to partialCertificateDer. +- +- certificateDerIndex and partialCertificateDerLength are updated +-*/ +- +-TPM_RC copyType(uint8_t type, /* expected type */ +- uint16_t *partialCertificateDerLength, uint8_t *partialCertificateDer, +- uint16_t *certificateDerIndex, uint8_t *certificateDer) +-{ +- TPM_RC rc = 0; +- uint16_t wrapperLength = 0; +- uint16_t dataLength = 0; +- +- if (rc == 0) { +- rc = getDataLength(type, +- &wrapperLength, +- &dataLength, +- certificateDerIndex, certificateDer); +- } +- if (rc == 0) { +- if (partialCertificateDer != NULL) { +- memcpy(partialCertificateDer + *partialCertificateDerLength, +- &(certificateDer[*certificateDerIndex]), +- wrapperLength + dataLength); +- *partialCertificateDerLength += wrapperLength + dataLength; +- } +- *certificateDerIndex += wrapperLength + dataLength; +- } +- return rc; +-} +- +-/* getInteger() copies the INTEGER data (not including the wrapper) to integerStream. +- +- certificateDerIndex is updated. +-*/ +- +-TPM_RC getInteger(uint16_t *integerDataLength, unsigned char *integerStream, +- uint16_t *certificateDerIndex, unsigned char *certificateDer) +-{ +- TPM_RC rc = 0; +- uint16_t wrapperLength = 0; +- +- if (rc == 0) { +- rc = getDataLength(0x02, /* INTEGER */ +- &wrapperLength, +- integerDataLength, +- certificateDerIndex, certificateDer); +- } +- if (rc == 0) { +- if (integerStream != NULL) { +- memcpy(integerStream, +- certificateDer + *certificateDerIndex + wrapperLength, +- *integerDataLength); +- } +- *certificateDerIndex += wrapperLength + *integerDataLength; +- } +- return rc; +-} +- +-/* prependSequence() shifts the DER down and back fills the SEQUENCE and length */ +- +-TPM_RC prependSequence(uint16_t *partialCertificateDerLength, uint8_t *partialCertificateDer) +-{ +- TPM_RC rc = 0; +- uint16_t prefixLength; +- uint16_t lengthLength = 0; +- uint16_t i = 0; +- +- if (verbose) printf("prependSequence: total length %u %04x\n", +- *partialCertificateDerLength, *partialCertificateDerLength); +- /* calculate the number of prepended bytes */ +- if (rc == 0) { +- /* long form length when greater than 7f */ +- if ((*partialCertificateDerLength) > 0x7f) { +- lengthLength = (*partialCertificateDerLength / 0x100) + 1; /* +1 to round up */ +- prefixLength = 2 + lengthLength; /* SEQUENCE + length of length + length bytes */ +- } +- /* short form length when up to 7f */ +- else { +- prefixLength = 2; /* SEQUENCE + length byte */ +- } +- } +- /* shift the partialCertificateDer down by prefix length */ +- if (rc == 0) { +- memmove(partialCertificateDer + prefixLength, +- partialCertificateDer, +- *partialCertificateDerLength); +- } +- /* construct the prefix */ +- if (rc == 0) { +- partialCertificateDer[0] = 0x30; /* SEQUENCE */ +- /* long form length */ +- if (lengthLength > 0) { +- partialCertificateDer[1] = 0x80 + lengthLength; /* byte 1 bit 7 set for long form */ +- for (i = 0 ; i < lengthLength ; i++) { /* start at byte 2 */ +- partialCertificateDer[2 + i] = /* add length bytes */ +- (*partialCertificateDerLength >> ((lengthLength - i - 1) * 8)) & 0xff; +- } +- } +- /* short form length */ +- else { +- /* just length for short form, cast safe bacause of above test */ +- partialCertificateDer[1] = (uint8_t)*partialCertificateDerLength; +- } +- *partialCertificateDerLength += prefixLength; /* adjust the total length of the DER */ +- } +- return rc; +-} +- + static void printUsage(void) + { + printf("\n"); +@@ -1550,7 +1254,7 @@ static void printUsage(void) + printf("\t\te.g. decrypt: critical,dataEncipherment,keyAgreement,encipherOnly,decipherOnly\n"); + printf("\t\te.g. fixedTPM: critical,nonRepudiation\n"); + printf("\t\te.g. parent (restrict decrypt): critical,keyEncipherment\n"); +- ++ + printf("\t[-bit\tbit in partialCertificate to toggle]\n"); + printf("\t[-sub\tsubject same as issuer for self signed (root) certificate]\n"); + printf("\t[-opc\tpartial certificate file name (default do not save)]\n"); +@@ -1563,7 +1267,7 @@ static void printUsage(void) + printf("\t01\tcontinue\n"); + printf("\t20\tcommand decrypt\n"); + printf("\t40\tresponse encrypt\n"); +- exit(1); ++ exit(1); + } + + #endif /* TPM_TSS_MBEDTLS */ +diff --git a/utils/cryptoutils.c b/utils/cryptoutils.c +index 7c4e931..eb5f0d2 100644 +--- a/utils/cryptoutils.c ++++ b/utils/cryptoutils.c +@@ -4,7 +4,7 @@ + /* Written by Ken Goldman */ + /* IBM Thomas J. Watson Research Center */ + /* */ +-/* (c) Copyright IBM Corporation 2018 - 2020. */ ++/* (c) Copyright IBM Corporation 2018 - 2021. */ + /* */ + /* All rights reserved. */ + /* */ +@@ -160,6 +160,36 @@ void RSA_get0_factors(const RSA *rsaKey, + return; + } + ++static int ossl_x509_set1_time(ASN1_TIME **ptm, const ASN1_TIME *tm); ++ ++int X509_set1_notBefore(X509 *x, const ASN1_TIME *tm) ++{ ++ if (x == NULL) ++ return 0; ++ return ossl_x509_set1_time(&x->cert_info->validity->notBefore, tm); ++} ++ ++int X509_set1_notAfter(X509 *x, const ASN1_TIME *tm) ++{ ++ if (x == NULL) ++ return 0; ++ return ossl_x509_set1_time(&x->cert_info->validity->notAfter, tm); ++} ++ ++static int ossl_x509_set1_time(ASN1_TIME **ptm, const ASN1_TIME *tm) ++{ ++ ASN1_TIME *in; ++ in = *ptm; ++ if (in != tm) { ++ in = ASN1_STRING_dup(tm); ++ if (in != NULL) { ++ ASN1_TIME_free(*ptm); ++ *ptm = in; ++ } ++ } ++ return (in != NULL); ++} ++ + #endif /* pre openssl 1.1 */ + + /* These functions are only required for OpenSSL 1.0.1 OpenSSL 1.0.2 has them, and the structures +diff --git a/utils/cryptoutils.h b/utils/cryptoutils.h +index c2ddc6c..03452de 100644 +--- a/utils/cryptoutils.h ++++ b/utils/cryptoutils.h +@@ -4,7 +4,7 @@ + /* Written by Ken Goldman */ + /* IBM Thomas J. Watson Research Center */ + /* */ +-/* (c) Copyright IBM Corporation 2017 - 2019. */ ++/* (c) Copyright IBM Corporation 2017 - 2021. */ + /* */ + /* All rights reserved. */ + /* */ +@@ -225,6 +225,9 @@ extern "C" { + void RSA_get0_factors(const RSA *rsaKey, + const BIGNUM **p, + const BIGNUM **q); ++ int X509_set1_notBefore(X509 *x, const ASN1_TIME *tm); ++ int X509_set1_notAfter(X509 *x, const ASN1_TIME *tm); ++ EVP_PKEY *X509_PUBKEY_get0(X509_PUBKEY *key); + #endif /* pre openssl 1.1 */ + + #if OPENSSL_VERSION_NUMBER < 0x10002000 +diff --git a/utils/regtests/testx509.sh b/utils/regtests/testx509.sh +index 813085f..5640985 100755 +--- a/utils/regtests/testx509.sh ++++ b/utils/regtests/testx509.sh +@@ -73,8 +73,6 @@ do + checkSuccess $? + + +- # dumpasn1 -a -l -d tmpx509i.bin > tmpx509i1.dump +- # dumpasn1 -a -l -d -hh tmpx509i.bin > tmpx509i1.dumphh + # dumpasn1 -a -l -d tmppart1.bin > tmppart1.dump + # dumpasn1 -a -l -d -hh tmppart1.bin > tmppart1.dumphh + # dumpasn1 -a -l -d tmpadd1.bin > tmpadd1.dump +@@ -88,7 +86,7 @@ do + echo " INFO:" + + echo "Verify ${SALG[i]} self signed issuer root" +- openssl verify -CAfile tmpx5091.pem tmpx5091.pem > run.out 2>&1 ++ openssl verify -check_ss_sig -CAfile tmpx5091.pem tmpx5091.pem > run.out 2>&1 + grep -q OK run.out + checkSuccess $? + +@@ -96,8 +94,6 @@ do + ${PREFIX}certifyx509 -hk 80000001 -ho 80000002 -halg ${HALG[i]} -pwdk sig -pwdo sig -opc tmppart2.bin -os tmpsig2.bin -oa tmpadd2.bin -otbs tmptbs2.bin -ocert tmpx5092.bin ${SALG[i]} -iob 00040472 > run.out + checkSuccess $? + +- # dumpasn1 -a -l -d tmpx509i.bin > tmpx509i2.dump +- # dumpasn1 -a -l -d -hh tmpx509i.bin > tmpx509i2.dumphh + # dumpasn1 -a -l -d tmppart2.bin > tmppart2.dump + # dumpasn1 -a -l -d -hh tmppart2.bin > tmppart2.dumphhe + # dumpasn1 -a -l -d tmpadd2.bin > tmpadd2.dump +@@ -111,7 +107,7 @@ do + echo " INFO:" + + echo "Verify ${SALG[i]} subject against issuer" +- openssl verify -CAfile tmpx5091.pem tmpx5092.pem > run.out 2>&1 ++ openssl verify -check_ss_sig -CAfile tmpx5091.pem tmpx5092.pem > run.out 2>&1 + grep -q OK run.out + checkSuccess $? + +@@ -333,7 +329,6 @@ rm -r tmpsig1.bin + rm -r tmpx5091.bin + rm -r tmpx5091.pem + rm -r tmpx5092.pem +-rm -r tmpx509i.bin + rm -r tmppart2.bin + rm -r tmpadd2.bin + rm -r tmptbs2.bin +-- +2.34.1 + diff --git a/0002-utils-Remove-unused-variables-from-certifyx509.patch b/0002-utils-Remove-unused-variables-from-certifyx509.patch new file mode 100644 index 0000000..18a41b2 --- /dev/null +++ b/0002-utils-Remove-unused-variables-from-certifyx509.patch @@ -0,0 +1,54 @@ +From 87120cf7fedcfc063ba5cd28ae4571909209a547 Mon Sep 17 00:00:00 2001 +From: Ken Goldman +Date: Mon, 23 Aug 2021 17:30:56 -0400 +Subject: [PATCH 2/7] utils: Remove unused variables from certifyx509 + +notBefore and notAfter are set driectly in the partialCertificate +structure, and that is used to directly set the x509 structure. + +Signed-off-by: Ken Goldman +--- + utils/certifyx509.c | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + +diff --git a/utils/certifyx509.c b/utils/certifyx509.c +index ed42ac0..44640aa 100644 +--- a/utils/certifyx509.c ++++ b/utils/certifyx509.c +@@ -204,6 +204,7 @@ int main(int argc, char *argv[]) + setvbuf(stdout, 0, _IONBF, 0); /* output may be going through pipe to log file */ + TSS_SetProperty(NULL, TPM_TRACE_LEVEL, "1"); + ++ curveID = curveID; /* no longer used, get from parent */ + /* command line argument defaults */ + for (i=1 ; (ivalidity->notBefore); + if (irc == 0) { + printf("createPartialCertificate: Error setting notBefore time\n"); +@@ -737,7 +734,6 @@ TPM_RC createPartialCertificate(TPM_PARTIAL_CERT *partialCertificate, /* input / + } + } + if (rc == 0) { +- notAfter = X509_get_notAfter(x509Certificate); + irc = X509_set1_notAfter(x509Certificate,partialCertificate->validity->notAfter); + if (irc == 0) { + printf("createPartialCertificate: Error setting notAfter time\n"); +-- +2.34.1 + diff --git a/0003-Update-certifyx509-for-Windows.patch b/0003-Update-certifyx509-for-Windows.patch new file mode 100644 index 0000000..b8be4d5 --- /dev/null +++ b/0003-Update-certifyx509-for-Windows.patch @@ -0,0 +1,99 @@ +From 1c462889a517d6dbab721aa3e0597878e9c237d5 Mon Sep 17 00:00:00 2001 +From: Ken Goldman +Date: Wed, 25 Aug 2021 18:02:11 -0400 +Subject: [PATCH 3/7] : Update certifyx509 for Windows + +Add static_ to the ASN1_SEQUENCE_END macros to suppress a gcc warning. +Change free to OPENSSL_free, required with i2d when OpenSSL is a dll. + +Remove the tmpx509i file handling from the .bat file since certifyx509 +no longer outputs it. + +Signed-off-by: Ken Goldman +--- + utils/certifyx509.c | 10 +++++----- + utils/regtests/testx509.bat | 5 ----- + 2 files changed, 5 insertions(+), 10 deletions(-) + +diff --git a/utils/certifyx509.c b/utils/certifyx509.c +index 44640aa..5602f62 100644 +--- a/utils/certifyx509.c ++++ b/utils/certifyx509.c +@@ -94,7 +94,7 @@ typedef struct { + ASN1_SEQUENCE(TPM_PARTIAL_CERT_VALIDITY) = { + ASN1_SIMPLE(TPM_PARTIAL_CERT_VALIDITY, notBefore, ASN1_TIME), + ASN1_SIMPLE(TPM_PARTIAL_CERT_VALIDITY, notAfter, ASN1_TIME), +-} ASN1_SEQUENCE_END(TPM_PARTIAL_CERT_VALIDITY) ++} static_ASN1_SEQUENCE_END(TPM_PARTIAL_CERT_VALIDITY) + + /* the signature algorithm is optional while the extension list is mandatory */ + ASN1_SEQUENCE(TPM_PARTIAL_CERT) = { +@@ -103,7 +103,7 @@ ASN1_SEQUENCE(TPM_PARTIAL_CERT) = { + ASN1_SIMPLE(TPM_PARTIAL_CERT, validity, TPM_PARTIAL_CERT_VALIDITY), + ASN1_SIMPLE(TPM_PARTIAL_CERT, subject, X509_NAME), + ASN1_EXP_SEQUENCE_OF(TPM_PARTIAL_CERT, extensions, X509_EXTENSION, 3), +-} ASN1_SEQUENCE_END(TPM_PARTIAL_CERT) ++} static_ASN1_SEQUENCE_END(TPM_PARTIAL_CERT) + + DECLARE_ASN1_FUNCTIONS(TPM_PARTIAL_CERT) + IMPLEMENT_ASN1_FUNCTIONS(TPM_PARTIAL_CERT) +@@ -122,7 +122,7 @@ ASN1_SEQUENCE(TPM_ADDTOCERT) = { + ASN1_SIMPLE(TPM_ADDTOCERT, serialNumber, ASN1_INTEGER), + ASN1_SIMPLE(TPM_ADDTOCERT, signatureAlgorithm, X509_ALGOR), + ASN1_SIMPLE(TPM_ADDTOCERT, key, X509_PUBKEY), +-} ASN1_SEQUENCE_END(TPM_ADDTOCERT) ++} static_ASN1_SEQUENCE_END(TPM_ADDTOCERT) + + DECLARE_ASN1_FUNCTIONS(TPM_ADDTOCERT) + IMPLEMENT_ASN1_FUNCTIONS(TPM_ADDTOCERT) +@@ -629,7 +629,7 @@ int main(int argc, char *argv[]) + X509_free(x509Certificate); /* @1 */ + } + free(x509Der); /* @2 */ +- free(addToCert); /* @3 */ ++ OPENSSL_free(addToCert); /* @3 */ + return rc; + } + +@@ -808,7 +808,7 @@ TPM_RC createPartialCertificate(TPM_PARTIAL_CERT *partialCertificate, /* input / + #endif + X509_NAME_free(x509IssuerName); /* @1 */ + X509_NAME_free(x509SubjectName); /* @2 */ +- free(tmpPartialDer); /* @3 */ ++ OPENSSL_free(tmpPartialDer); /* @3 */ + return rc; + } + +diff --git a/utils/regtests/testx509.bat b/utils/regtests/testx509.bat +index 0951ad6..17b69f6 100644 +--- a/utils/regtests/testx509.bat ++++ b/utils/regtests/testx509.bat +@@ -80,8 +80,6 @@ for /L %%i in (1,1,!L!) do ( + exit /B 1 + ) + +- rem # dumpasn1 -a -l -d tmpx509i.bin > tmpx509i1.dump +- rem # dumpasn1 -a -l -d -hh tmpx509i.bin > tmpx509i1.dumphh + rem # dumpasn1 -a -l -d tmppart1.bin > tmppart1.dump + rem # dumpasn1 -a -l -d -hh tmppart1.bin > tmppart1.dumphh + rem # dumpasn1 -a -l -d tmpadd1.bin > tmpadd1.dump +@@ -102,8 +100,6 @@ for /L %%i in (1,1,!L!) do ( + exit /B 1 + ) + +-rem # dumpasn1 -a -l -d tmpx509i.bin > tmpx509i2.dump +-rem # dumpasn1 -a -l -d -hh tmpx509i.bin > tmpx509i2.dumphh + rem # dumpasn1 -a -l -d tmppart2.bin > tmppart2.dump + rem # dumpasn1 -a -l -d -hh tmppart2.bin > tmppart2.dumphhe + rem # dumpasn1 -a -l -d tmpadd2.bin > tmpadd2.dump +@@ -446,7 +442,6 @@ rm tmpsig1.bin + rm tmpx5091.bin + rm tmpx5091.pem + rm tmpx5092.pem +-rm tmpx509i.bin + rm tmppart2.bin + rm tmpadd2.bin + rm tmptbs2.bin +-- +2.34.1 + diff --git a/0004-utils-Clean-up-certifyx509-memory-allocation.patch b/0004-utils-Clean-up-certifyx509-memory-allocation.patch new file mode 100644 index 0000000..5b3c331 --- /dev/null +++ b/0004-utils-Clean-up-certifyx509-memory-allocation.patch @@ -0,0 +1,111 @@ +From d77514273aa88f67b85c398a222ab2195c42f5fd Mon Sep 17 00:00:00 2001 +From: Ken Goldman +Date: Tue, 31 Aug 2021 13:45:21 -0400 +Subject: [PATCH 4/7] utils: Clean up certifyx509 memory allocation + +Make TPM_ADDTOCERT input const. Annotate malloc and free calls. Free +TPM_PARTIAL_CERT. Use TPM_ADDTOCERT_free. Remove unused +x509IssuerName and x509SubjectName and their frees. Free +TPM_PARTIAL_CERT issuer and subject because createX509Name() mallocs. + +Signed-off-by: Ken Goldman +--- + utils/certifyx509.c | 26 +++++++++++++++++--------- + 1 file changed, 17 insertions(+), 9 deletions(-) + +diff --git a/utils/certifyx509.c b/utils/certifyx509.c +index 5602f62..8ac5abd 100644 +--- a/utils/certifyx509.c ++++ b/utils/certifyx509.c +@@ -147,7 +147,7 @@ TPM_RC createPartialCertificate(TPM_PARTIAL_CERT *certificate, + TPM_RC reformCertificate(X509 *x509Certificate, + TPMI_ALG_HASH halg, + TPMI_ALG_SIG_SCHEME scheme, +- TPM_ADDTOCERT *addToCert, ++ const TPM_ADDTOCERT *addToCert, + TPMT_SIGNATURE *tSignature); + TPM_RC addSignatureRsa(X509 *x509Certificate, + TPMI_ALG_HASH halg, +@@ -618,7 +618,7 @@ int main(int argc, char *argv[]) + if (rc == 0) { + if (verbose) X509_print_fp(stdout, x509Certificate); /* for debug */ + rc = convertX509ToDer(&x509DerLength, +- &x509Der, /* freed @2 */ ++ &x509Der, /* freed @4 */ + x509Certificate); + } + if ((rc == 0) && (outCertificateFilename != NULL)) { +@@ -628,8 +628,13 @@ int main(int argc, char *argv[]) + if (x509Certificate != NULL) { + X509_free(x509Certificate); /* @1 */ + } +- free(x509Der); /* @2 */ +- OPENSSL_free(addToCert); /* @3 */ ++ if (partialCertificate != NULL) { ++ TPM_PARTIAL_CERT_free(partialCertificate); /* @2 */ ++ } ++ if (addToCert != NULL) { ++ TPM_ADDTOCERT_free(addToCert); /* @3 */ ++ } ++ free(x509Der); /* @4 */ + return rc; + } + +@@ -683,8 +688,6 @@ TPM_RC createPartialCertificate(TPM_PARTIAL_CERT *partialCertificate, /* input / + int irc; + ASN1_TIME *arc; /* return code */ + +- X509_NAME *x509IssuerName = NULL; /* composite issuer name, key/value pairs */ +- X509_NAME *x509SubjectName = NULL;/* composite subject name, key/value pairs */ + size_t issuerEntriesSize = sizeof(issuerEntries)/sizeof(char *); + size_t subjectEntriesSize = sizeof(subjectEntries)/sizeof(char *); + uint8_t *tmpPartialDer = NULL; /* for the i2d */ +@@ -693,6 +696,9 @@ TPM_RC createPartialCertificate(TPM_PARTIAL_CERT *partialCertificate, /* input / + if (rc == 0) { + if (verbose) printf("createPartialCertificate: Adding issuer, size %lu\n", + (unsigned long)issuerEntriesSize); ++ /* _new allocates the member. free it because createX509Name() allocates a new structure */ ++ X509_NAME_free(partialCertificate->issuer); ++ partialCertificate->issuer = NULL; + rc = createX509Name(&partialCertificate->issuer, /* freed @1 */ + issuerEntriesSize, + issuerEntries); +@@ -746,6 +752,8 @@ TPM_RC createPartialCertificate(TPM_PARTIAL_CERT *partialCertificate, /* input / + if (!subeqiss) { + if (verbose) printf("createPartialCertificate: Adding subject, size %lu\n", + (unsigned long)subjectEntriesSize); ++ X509_NAME_free(partialCertificate->subject); ++ partialCertificate->subject = NULL; + rc = createX509Name(&partialCertificate->subject, /* freed @2 */ + subjectEntriesSize, + subjectEntries); +@@ -754,6 +762,8 @@ TPM_RC createPartialCertificate(TPM_PARTIAL_CERT *partialCertificate, /* input / + else { + if (verbose) printf("createPartialCertificate: Adding subject (issuer), size %lu\n", + (unsigned long)issuerEntriesSize); ++ X509_NAME_free(partialCertificate->subject); ++ partialCertificate->subject = NULL; + rc = createX509Name(&partialCertificate->subject, /* freed @2 */ + issuerEntriesSize, + issuerEntries); +@@ -806,8 +816,6 @@ TPM_RC createPartialCertificate(TPM_PARTIAL_CERT *partialCertificate, /* input / + if (verbose) X509_print_fp(stdout, x509Certificate); + } + #endif +- X509_NAME_free(x509IssuerName); /* @1 */ +- X509_NAME_free(x509SubjectName); /* @2 */ + OPENSSL_free(tmpPartialDer); /* @3 */ + return rc; + } +@@ -956,7 +964,7 @@ TPM_RC addPartialCertExtensionTpmaOid(TPM_PARTIAL_CERT *partialCertificate, + TPM_RC reformCertificate(X509 *x509Certificate, + TPMI_ALG_HASH halg, + TPMI_ALG_SIG_SCHEME scheme, +- TPM_ADDTOCERT *addToCert, ++ const TPM_ADDTOCERT *addToCert, + TPMT_SIGNATURE *tSignature) + { + TPM_RC rc = 0; +-- +2.34.1 + diff --git a/0005-utils-Fix-errors-detected-by-gcc-asan.patch b/0005-utils-Fix-errors-detected-by-gcc-asan.patch new file mode 100644 index 0000000..1c20911 --- /dev/null +++ b/0005-utils-Fix-errors-detected-by-gcc-asan.patch @@ -0,0 +1,91 @@ +From bcbc2f0400cfc2f596283e8c528aed4576bfea69 Mon Sep 17 00:00:00 2001 +From: Ken Goldman +Date: Fri, 3 Sep 2021 14:58:20 -0400 +Subject: [PATCH 5/7] utils: Fix errors detected by gcc asan + +In Uint32_Convert(), case the byte to uint32_t before the left shift +24 to suppress a warning. + +In TSS_EFI_GetNameIndex(), do not compare data if the length does not +match, because this could cause a buffer overflow. Test should be &&, +not &. + +TSS_Delete should only memset sessionData if the pointer is not NULL. + +Signed-off-by: Ken Goldman +--- + utils/efilib.c | 11 +++++++---- + utils/eventlib.c | 10 +++++----- + utils/tss.c | 6 ++++-- + 3 files changed, 16 insertions(+), 11 deletions(-) + +diff --git a/utils/efilib.c b/utils/efilib.c +index 201a1f5..ab8177b 100644 +--- a/utils/efilib.c ++++ b/utils/efilib.c +@@ -399,16 +399,19 @@ static void TSS_EFI_GetNameIndex(size_t *index, + const uint8_t *name, + uint64_t nameLength) /* half the total bytes in array */ + { +- int m1,m2; ++ int m1 = 0; ++ int m2 = 0; + for (*index = 0 ; + *index < sizeof(tagTable) / sizeof(TAG_TABLE) ; + (*index)++) { + + /* length match */ + m1 = (nameLength * 2) == tagTable[*index].nameLength; +- /* string match */ +- m2 = memcmp(name, tagTable[*index].name, (size_t)(nameLength * 2)) == 0; +- if (m1 & m2) { ++ if (m1) { ++ /* string match */ ++ m2 = memcmp(name, tagTable[*index].name, (size_t)(nameLength * 2)) == 0; ++ } ++ if (m1 && m2) { + return; + } + } +diff --git a/utils/eventlib.c b/utils/eventlib.c +index 0c2801c..c56a22f 100644 +--- a/utils/eventlib.c ++++ b/utils/eventlib.c +@@ -1346,12 +1346,12 @@ static uint32_t Uint32_Convert(uint32_t in) + { + uint32_t out = 0; + unsigned char *inb = (unsigned char *)∈ +- ++ + /* little endian input */ +- out = (inb[0] << 0) | +- (inb[1] << 8) | +- (inb[2] << 16) | +- (inb[3] << 24); ++ out = ((((uint32_t)inb[0]) << 0) | ++ (((uint32_t)inb[1]) << 8) | ++ (((uint32_t)inb[2]) << 16) | ++ (((uint32_t)inb[3]) << 24)); + return out; + } + #endif /* TPM_TSS_NOFILE */ +diff --git a/utils/tss.c b/utils/tss.c +index 574c448..6f0eede 100644 +--- a/utils/tss.c ++++ b/utils/tss.c +@@ -179,8 +179,10 @@ TPM_RC TSS_Delete(TSS_CONTEXT *tssContext) + for (i = 0 ; i < (sizeof(tssContext->sessions) / sizeof(TSS_SESSIONS)) ; i++) { + tssContext->sessions[i].sessionHandle = TPM_RH_NULL; + /* erase any secrets */ +- memset(tssContext->sessions[i].sessionData, +- 0, tssContext->sessions[i].sessionDataLength); ++ if (tssContext->sessions[i].sessionData != NULL) { ++ memset(tssContext->sessions[i].sessionData, ++ 0, tssContext->sessions[i].sessionDataLength); ++ } + free(tssContext->sessions[i].sessionData); + tssContext->sessions[i].sessionData = NULL; + tssContext->sessions[i].sessionDataLength = 0; +-- +2.34.1 + diff --git a/0006-tss-Port-HMAC-operations-to-openssl-3.0.patch b/0006-tss-Port-HMAC-operations-to-openssl-3.0.patch new file mode 100644 index 0000000..8b47144 --- /dev/null +++ b/0006-tss-Port-HMAC-operations-to-openssl-3.0.patch @@ -0,0 +1,103 @@ +From 7128994537a7103b25acb1df238db747d7cb3274 Mon Sep 17 00:00:00 2001 +From: Ken Goldman +Date: Fri, 10 Sep 2021 16:33:10 -0400 +Subject: [PATCH 6/7] tss: Port HMAC operations to openssl 3.0 + +Replace the deprecated APIs. + +- Compared to the next branch commit 6e22032d, changes related to HMAC are + ommited. + +Signed-off-by: Ken Goldman +--- + utils/tsscrypto.c | 58 ++++++++++++++++++++++++++++++----------------- + 1 file changed, 37 insertions(+), 21 deletions(-) + +diff --git a/utils/tsscrypto.c b/utils/tsscrypto.c +index 23d3b6e..1974563 100644 +--- a/utils/tsscrypto.c ++++ b/utils/tsscrypto.c +@@ -79,6 +79,7 @@ extern int tssVerbose; + + /* local prototypes */ + ++static TPM_RC TSS_Hash_GetOsslString(const char **str, TPMI_ALG_HASH hashAlg); + static TPM_RC TSS_Hash_GetMd(const EVP_MD **md, + TPMI_ALG_HASH hashAlg); + +@@ -129,36 +130,51 @@ TPM_RC TSS_Crypto_Init(void) + Digests + */ + +-static TPM_RC TSS_Hash_GetMd(const EVP_MD **md, +- TPMI_ALG_HASH hashAlg) ++/* TSS_Hash_GetString() maps from the TCG hash algorithm to the OpenSSL string */ ++ ++static TPM_RC TSS_Hash_GetOsslString(const char **str, TPMI_ALG_HASH hashAlg) + { +- TPM_RC rc = 0; ++ TPM_RC rc = 0; + +- if (rc == 0) { +- switch (hashAlg) { ++ switch (hashAlg) { + #ifdef TPM_ALG_SHA1 +- case TPM_ALG_SHA1: +- *md = EVP_get_digestbyname("sha1"); +- break; ++ case TPM_ALG_SHA1: ++ *str = "sha1"; ++ break; + #endif +-#ifdef TPM_ALG_SHA256 +- case TPM_ALG_SHA256: +- *md = EVP_get_digestbyname("sha256"); +- break; ++#ifdef TPM_ALG_SHA256 ++ case TPM_ALG_SHA256: ++ *str = "sha256"; ++ break; + #endif + #ifdef TPM_ALG_SHA384 +- case TPM_ALG_SHA384: +- *md = EVP_get_digestbyname("sha384"); +- break; ++ case TPM_ALG_SHA384: ++ *str = "sha384"; ++ break; + #endif + #ifdef TPM_ALG_SHA512 +- case TPM_ALG_SHA512: +- *md = EVP_get_digestbyname("sha512"); +- break; ++ case TPM_ALG_SHA512: ++ *str = "sha512"; ++ break; + #endif +- default: +- rc = TSS_RC_BAD_HASH_ALGORITHM; +- } ++ default: ++ *str = NULL; ++ rc = TSS_RC_BAD_HASH_ALGORITHM; ++ } ++ return rc; ++} ++ ++static TPM_RC TSS_Hash_GetMd(const EVP_MD **md, ++ TPMI_ALG_HASH hashAlg) ++{ ++ TPM_RC rc = 0; ++ const char *str = NULL; ++ ++ if (rc == 0) { ++ rc = TSS_Hash_GetOsslString(&str, hashAlg); ++ } ++ if (rc == 0) { ++ *md = EVP_get_digestbyname(str); + } + return rc; + } +-- +2.34.1 + diff --git a/0007-utils-Port-to-openssl-3.0.0-replaces-RSA-with-EVP_PK.patch b/0007-utils-Port-to-openssl-3.0.0-replaces-RSA-with-EVP_PK.patch new file mode 100644 index 0000000..a1c7f1e --- /dev/null +++ b/0007-utils-Port-to-openssl-3.0.0-replaces-RSA-with-EVP_PK.patch @@ -0,0 +1,1376 @@ +From de47f3c95f973fa8fc873287ca8927038d225aa8 Mon Sep 17 00:00:00 2001 +From: Ken Goldman +Date: Fri, 17 Sep 2021 19:04:39 -0400 +Subject: [PATCH 7/7] utils: Port to openssl 3.0.0 replaces RSA with EVP_PKEY + +The RSA structure is deprecated. This flows through all the +utilities, including the X509 public key handling, the PEM and DER +public and private key converters, the functions to convert to and +from the RSA bignums, the sign and encrypt functions. + +TODO are the equivalent updates for ECC and AES. + +- Compared to the next branch commit 65c77e87, changes related to HMAC are + ommited and a conflict is resolved. + +Signed-off-by: Ken Goldman +--- + utils/cryptoutils.c | 349 ++++++++++++++++++++++++++++++++++----- + utils/cryptoutils.h | 22 ++- + utils/efilib.c | 27 ++- + utils/ekutils.c | 50 ++++-- + utils/ekutils.h | 4 +- + utils/ibmtss/tsscrypto.h | 3 +- + utils/sign.c | 4 +- + utils/tsscrypto.c | 202 +++++++++++++++++++--- + 8 files changed, 572 insertions(+), 89 deletions(-) + +diff --git a/utils/cryptoutils.c b/utils/cryptoutils.c +index eb5f0d2..57eade7 100644 +--- a/utils/cryptoutils.c ++++ b/utils/cryptoutils.c +@@ -61,6 +61,9 @@ + #include + #include + #include ++#if OPENSSL_VERSION_NUMBER >= 0x30000000 ++#include ++#endif + + #ifndef TPM_TSS_NOECC + #include +@@ -75,6 +78,9 @@ + #include + #include + ++TPM_RC TSS_Hash_GetMd(const EVP_MD **md, ++ TPMI_ALG_HASH hashAlg); ++ + #include "objecttemplates.h" + #include "cryptoutils.h" + +@@ -283,7 +289,8 @@ TPM_RC convertPemToEvpPubKey(EVP_PKEY **evpPkey, /* freed by caller */ + The return is void because the structure is opaque to the caller. This accomodates other crypto + libraries. + +- rsaKey is an RSA structure ++ For Openssl < 3, rsaKey is an RSA structure. ++ For Openssl 3, rsaKey is an EVP_PKEY, + */ + + TPM_RC convertPemToRsaPrivKey(void **rsaKey, /* freed by caller */ +@@ -297,7 +304,11 @@ TPM_RC convertPemToRsaPrivKey(void **rsaKey, /* freed by caller */ + rc = TSS_File_Open(&pemKeyFile, pemKeyFilename, "rb"); /* closed @1 */ + } + if (rc == 0) { ++#if OPENSSL_VERSION_NUMBER < 0x30000000 + *rsaKey = (void *)PEM_read_RSAPrivateKey(pemKeyFile, NULL, NULL, (void *)password); ++#else ++ *rsaKey = (void *)PEM_read_PrivateKey(pemKeyFile, NULL, NULL, (void *)password); ++#endif + if (*rsaKey == NULL) { + printf("convertPemToRsaPrivKey: Error in OpenSSL PEM_read_RSAPrivateKey()\n"); + rc = TSS_RC_PEM_ERROR; +@@ -334,6 +345,8 @@ TPM_RC convertEvpPkeyToEckey(EC_KEY **ecKey, /* freed by caller */ + #endif /* TPM_TSS_NOECC */ + #endif /* TPM_TPM20 */ + ++#if OPENSSL_VERSION_NUMBER < 0x30000000 ++ + /* convertEvpPkeyToRsakey() retrieves the RSA key token from the EVP_PKEY */ + + TPM_RC convertEvpPkeyToRsakey(RSA **rsaKey, /* freed by caller */ +@@ -350,6 +363,7 @@ TPM_RC convertEvpPkeyToRsakey(RSA **rsaKey, /* freed by caller */ + } + return rc; + } ++#endif + + #ifdef TPM_TPM20 + #ifndef TPM_TSS_NOECC +@@ -426,19 +440,26 @@ TPM_RC convertEcKeyToPrivateKeyBin(int *privateKeyBytes, + #endif /* TPM_TPM20 */ + + /* convertRsaKeyToPrivateKeyBin() converts an OpenSSL RSA key token private prime p to a binary +- array */ ++ array ++ ++ For Openssl < 3, rsaKey is an RSA structure. ++ For Openssl 3, rsaKey is an EVP_PKEY, ++*/ + + TPM_RC convertRsaKeyToPrivateKeyBin(int *privateKeyBytes, + uint8_t **privateKeyBin, /* freed by caller */ ++#if OPENSSL_VERSION_NUMBER < 0x30000000 + const RSA *rsaKey) ++#else ++ const EVP_PKEY *rsaKey) ++#endif + { + 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); ++ rc = getRsaKeyParts(NULL, NULL, NULL, &p, NULL, rsaKey); /* freed @2 */ + } + /* allocate a buffer for the private key array */ + if (rc == 0) { +@@ -448,7 +469,10 @@ TPM_RC convertRsaKeyToPrivateKeyBin(int *privateKeyBytes, + /* convert the private key bignum to binary */ + if (rc == 0) { + BN_bn2bin(p, *privateKeyBin); +- } ++ } ++#if OPENSSL_VERSION_NUMBER >= 0x30000000 ++ BN_free((BIGNUM *)p); /* @2 */ ++#endif + return rc; + } + +@@ -500,7 +524,11 @@ TPM_RC convertEcKeyToPublicKeyBin(int *modulusBytes, + #endif /* TPM_TSS_NOECC */ + #endif /* TPM_TPM20 */ + +-/* convertRsaKeyToPublicKeyBin() converts from an openssl RSA key token to a public modulus */ ++/* convertRsaKeyToPublicKeyBin() converts from an openssl RSA key token to a public modulus ++ ++ For Openssl < 3, rsaKey is an RSA structure. ++ For Openssl 3, rsaKey is an EVP_PKEY, ++*/ + + TPM_RC convertRsaKeyToPublicKeyBin(int *modulusBytes, + uint8_t **modulusBin, /* freed by caller */ +@@ -508,12 +536,10 @@ TPM_RC convertRsaKeyToPublicKeyBin(int *modulusBytes, + { + 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); ++ rc = getRsaKeyParts(&n, NULL, NULL, NULL, NULL, rsaKey); + } + if (rc == 0) { + *modulusBytes = BN_num_bytes(n); +@@ -524,7 +550,10 @@ TPM_RC convertRsaKeyToPublicKeyBin(int *modulusBytes, + if (rc == 0) { + BN_bn2bin(n, *modulusBin); + } +- return rc; ++#if OPENSSL_VERSION_NUMBER >= 0x30000000 ++ BN_free((BIGNUM *)n); /* @2 */ ++#endif ++ return rc; + } + + #ifdef TPM_TPM20 +@@ -882,11 +911,18 @@ TPM_RC convertEcKeyToPrivate(TPM2B_PRIVATE *objectPrivate, + + /* convertRsaKeyToPrivate() converts an openssl RSA key token to either a TPM2B_PRIVATE or + TPM2B_SENSITIVE ++ ++ For Openssl < 3, rsaKey is an RSA structure. ++ For Openssl 3, rsaKey is an EVP_PKEY, + */ + + TPM_RC convertRsaKeyToPrivate(TPM2B_PRIVATE *objectPrivate, + TPM2B_SENSITIVE *objectSensitive, +- RSA *rsaKey, ++#if OPENSSL_VERSION_NUMBER < 0x30000000 ++ RSA *rsaKey, ++#else ++ EVP_PKEY *rsaKey, ++#endif + const char *password) + { + TPM_RC rc = 0; +@@ -957,7 +993,11 @@ TPM_RC convertEcKeyToPublic(TPM2B_PUBLIC *objectPublic, + + #ifdef TPM_TPM20 + +-/* convertRsaKeyToPublic() converts from an openssl RSA key token to a TPM2B_PUBLIC */ ++/* convertRsaKeyToPublic() converts from an openssl RSA key token to a TPM2B_PUBLIC ++ ++ For Openssl < 3, rsaKey is an RSA structure. ++ For Openssl 3, rsaKey is an EVP_PKEY, ++*/ + + TPM_RC convertRsaKeyToPublic(TPM2B_PUBLIC *objectPublic, + int keyType, +@@ -1110,16 +1150,25 @@ TPM_RC convertRsaPemToKeyPair(TPM2B_PUBLIC *objectPublic, + { + TPM_RC rc = 0; + EVP_PKEY *evpPkey = NULL; ++#if OPENSSL_VERSION_NUMBER < 0x30000000 + RSA *rsaKey = NULL; +- ++#else ++ EVP_PKEY *rsaKey = NULL; ++#endif ++ + if (rc == 0) { + rc = convertPemToEvpPrivKey(&evpPkey, /* freed @1 */ + pemKeyFilename, + password); + } + if (rc == 0) { ++#if OPENSSL_VERSION_NUMBER < 0x30000000 + rc = convertEvpPkeyToRsakey(&rsaKey, /* freed @2 */ + evpPkey); ++#else ++ /* openssl 3.0.0 and up use the EVP_PKEY directly */ ++ rsaKey = evpPkey; ++#endif + } + if (rc == 0) { + rc = convertRsaKeyToPrivate(objectPrivate, /* TPM2B_PRIVATE */ +@@ -1135,10 +1184,12 @@ TPM_RC convertRsaPemToKeyPair(TPM2B_PUBLIC *objectPublic, + halg, + rsaKey); + } +- TSS_RsaFree(rsaKey); /* @2 */ + if (evpPkey != NULL) { + EVP_PKEY_free(evpPkey); /* @1 */ + } ++#if OPENSSL_VERSION_NUMBER < 0x30000000 ++ TSS_RsaFree(rsaKey); /* @2 */ ++#endif + return rc; + } + +@@ -1281,7 +1332,11 @@ TPM_RC convertRsaDerToKeyPair(TPM2B_PUBLIC *objectPublic, + const char *password) + { + TPM_RC rc = 0; ++#if OPENSSL_VERSION_NUMBER < 0x30000000 + RSA *rsaKey = NULL; ++#else ++ EVP_PKEY *rsaKey = NULL; ++#endif + unsigned char *derBuffer = NULL; + size_t derSize; + +@@ -1293,7 +1348,12 @@ TPM_RC convertRsaDerToKeyPair(TPM2B_PUBLIC *objectPublic, + } + if (rc == 0) { + const unsigned char *tmpPtr = derBuffer; /* because pointer moves */ ++#if OPENSSL_VERSION_NUMBER < 0x30000000 + rsaKey = d2i_RSAPrivateKey(NULL, &tmpPtr, (long)derSize); /* freed @2 */ ++#else ++ rsaKey = d2i_PrivateKey(EVP_PKEY_RSA, NULL, ++ &tmpPtr, (long)derSize); ++#endif + if (rsaKey == NULL) { + printf("convertRsaDerToKeyPair: could not convert key to RSA\n"); + rc = TPM_RC_VALUE; +@@ -1331,7 +1391,11 @@ TPM_RC convertRsaDerToPublic(TPM2B_PUBLIC *objectPublic, + const char *derKeyFilename) + { + TPM_RC rc = 0; ++#if OPENSSL_VERSION_NUMBER < 0x30000000 + RSA *rsaKey = NULL; ++#else ++ EVP_PKEY *rsaKey = NULL; ++#endif + unsigned char *derBuffer = NULL; + size_t derSize; + +@@ -1343,7 +1407,11 @@ TPM_RC convertRsaDerToPublic(TPM2B_PUBLIC *objectPublic, + } + if (rc == 0) { + const unsigned char *tmpPtr = derBuffer; /* because pointer moves */ ++#if OPENSSL_VERSION_NUMBER < 0x30000000 + rsaKey = d2i_RSA_PUBKEY(NULL, &tmpPtr, (long)derSize); /* freed @2 */ ++#else ++ rsaKey = d2i_PUBKEY(NULL, &tmpPtr, (long)derSize); ++#endif + if (rsaKey == NULL) { + printf("convertRsaDerToPublic: could not convert key to RSA\n"); + rc = TPM_RC_VALUE; +@@ -1362,13 +1430,6 @@ TPM_RC convertRsaDerToPublic(TPM2B_PUBLIC *objectPublic, + 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, +@@ -1380,15 +1441,24 @@ TPM_RC convertRsaPemToPublic(TPM2B_PUBLIC *objectPublic, + { + TPM_RC rc = 0; + EVP_PKEY *evpPkey = NULL; ++#if OPENSSL_VERSION_NUMBER < 0x30000000 + RSA *rsaKey = NULL; ++#else ++ EVP_PKEY *rsaKey = NULL; ++#endif + + if (rc == 0) { + rc = convertPemToEvpPubKey(&evpPkey, /* freed @1 */ + pemKeyFilename); + } + if (rc == 0) { ++#if OPENSSL_VERSION_NUMBER < 0x30000000 + rc = convertEvpPkeyToRsakey(&rsaKey, /* freed @2 */ + evpPkey); ++#else ++ /* openssl 3.0.0 and up use the EVP_PKEY directly */ ++ rsaKey = evpPkey; ++#endif + } + if (rc == 0) { + rc = convertRsaKeyToPublic(objectPublic, +@@ -1398,35 +1468,97 @@ TPM_RC convertRsaPemToPublic(TPM2B_PUBLIC *objectPublic, + halg, + rsaKey); + } +- RSA_free(rsaKey); /* @2 */ + if (evpPkey != NULL) { + EVP_PKEY_free(evpPkey); /* @1 */ + } ++#if OPENSSL_VERSION_NUMBER < 0x30000000 ++ TSS_RsaFree(rsaKey); /* @2 */ ++#endif + return rc; + } + ++#endif /* TPM_TSS_NORSA */ + #endif /* TPM_TPM20 */ + #endif /* TPM_TSS_NOFILE */ + + /* 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. ++ ++ For openssl < 3.0.0, the bignums are references to the RSA key and should not be freed separately. ++ ++ For openssl >= 3.0.0, the bignums are allocated and must be freed. ++ ++ FIXME - is there a better way? + */ + + TPM_RC getRsaKeyParts(const BIGNUM **n, +- const BIGNUM **e, +- const BIGNUM **d, +- const BIGNUM **p, +- const BIGNUM **q, +- const RSA *rsaKey) ++ const BIGNUM **e, ++ const BIGNUM **d, ++ const BIGNUM **p, ++ const BIGNUM **q, ++#if OPENSSL_VERSION_NUMBER < 0x30000000 ++ const RSA *rsaKey) ++#else ++ const EVP_PKEY *rsaKey) ++#endif + { + TPM_RC rc = 0; ++#if OPENSSL_VERSION_NUMBER < 0x30000000 + if (n != NULL) { + RSA_get0_key(rsaKey, n, e, d); + } + if (p != NULL) { + RSA_get0_factors(rsaKey, p, q); + } ++#else ++ int irc; ++ if (rc == 0) { ++ if (n != NULL) { ++ irc = EVP_PKEY_get_bn_param(rsaKey, OSSL_PKEY_PARAM_RSA_N, (BIGNUM **)n); ++ if (irc != 1) { ++ printf("getRsaKeyParts: Error getting n\n"); ++ rc = TSS_RC_RSA_KEY_CONVERT; ++ } ++ } ++ } ++ if (rc == 0) { ++ if (e != NULL) { ++ irc = EVP_PKEY_get_bn_param(rsaKey, OSSL_PKEY_PARAM_RSA_E, (BIGNUM **)e); ++ if (irc != 1) { ++ printf("getRsaKeyParts: Error getting e\n"); ++ rc = TSS_RC_RSA_KEY_CONVERT; ++ } ++ } ++ } ++ if (rc == 0) { ++ if (d != NULL) { ++ irc = EVP_PKEY_get_bn_param(rsaKey, OSSL_PKEY_PARAM_RSA_D, (BIGNUM **)d); ++ if (irc != 1) { ++ printf("getRsaKeyParts: Error getting d\n"); ++ rc = TSS_RC_RSA_KEY_CONVERT; ++ } ++ } ++ } ++ if (rc == 0) { ++ if (p != NULL) { ++ irc = EVP_PKEY_get_bn_param(rsaKey, OSSL_PKEY_PARAM_RSA_FACTOR1, (BIGNUM **)p); ++ if (irc != 1) { ++ printf("getRsaKeyParts: Error getting p\n"); ++ rc = TSS_RC_RSA_KEY_CONVERT; ++ } ++ } ++ } ++ if (rc == 0) { ++ if (q != NULL) { ++ irc = EVP_PKEY_get_bn_param(rsaKey, OSSL_PKEY_PARAM_RSA_FACTOR2, (BIGNUM **)q); ++ if (irc != 1) { ++ printf("getRsaKeyParts: Error getting q\n"); ++ rc = TSS_RC_RSA_KEY_CONVERT; ++ } ++ } ++ } ++#endif + return rc; + } + +@@ -1501,11 +1633,16 @@ TPM_RC convertRsaPublicToEvpPubKey(EVP_PKEY **evpPubkey, /* freed by caller */ + const TPM2B_PUBLIC_KEY_RSA *tpm2bRsa) + { + TPM_RC rc = 0; ++ /* public exponent */ ++ unsigned char earr[3] = {0x01, 0x00, 0x01}; ++#if OPENSSL_VERSION_NUMBER < 0x30000000 + int irc; + RSA *rsaPubKey = NULL; +- ++#endif ++ ++#if OPENSSL_VERSION_NUMBER < 0x30000000 + if (rc == 0) { +- *evpPubkey = EVP_PKEY_new(); ++ *evpPubkey = EVP_PKEY_new(); /* freed by caller */ + if (*evpPubkey == NULL) { + printf("convertRsaPublicToEvpPubKey: EVP_PKEY failed\n"); + rc = TSS_RC_OUT_OF_MEMORY; +@@ -1513,10 +1650,10 @@ TPM_RC convertRsaPublicToEvpPubKey(EVP_PKEY **evpPubkey, /* freed by caller */ + } + /* TPM to RSA token */ + if (rc == 0) { +- /* public exponent */ +- unsigned char earr[3] = {0x01, 0x00, 0x01}; ++ /* For Openssl < 3, rsaKey is an RSA structure. */ ++ /* For Openssl 3, rsaKey is an EVP_PKEY. */ + rc = TSS_RSAGeneratePublicTokenI +- ((void **)&rsaPubKey, /* freed as part of EVP_PKEY */ ++ ((void **)&rsaPubKey, /* freed by caller */ + tpm2bRsa->t.buffer, /* public modulus */ + tpm2bRsa->t.size, + earr, /* public exponent */ +@@ -1526,11 +1663,24 @@ TPM_RC convertRsaPublicToEvpPubKey(EVP_PKEY **evpPubkey, /* freed by caller */ + if (rc == 0) { + irc = EVP_PKEY_assign_RSA(*evpPubkey, rsaPubKey); + if (irc == 0) { +- TSS_RsaFree(rsaPubKey); /* because not assigned tp EVP_PKEY */ ++ TSS_RsaFree(rsaPubKey); /* because not assigned to EVP_PKEY */ + printf("convertRsaPublicToEvpPubKey: EVP_PKEY_assign_RSA failed\n"); + rc = TSS_RC_RSA_KEY_CONVERT; + } + } ++#else /* FIXME this should always work? */ ++ /* TPM to RSA token */ ++ if (rc == 0) { ++ /* For Openssl < 3, rsaKey is an RSA structure. */ ++ /* For Openssl 3, rsaKey is an EVP_PKEY. */ ++ rc = TSS_RSAGeneratePublicTokenI ++ ((void **)evpPubkey, /* freed by caller */ ++ tpm2bRsa->t.buffer, /* public modulus */ ++ tpm2bRsa->t.size, ++ earr, /* public exponent */ ++ sizeof(earr)); ++ } ++#endif + return rc; + } + +@@ -1828,8 +1978,9 @@ TPM_RC verifyRSASignatureFromEvpPubKey(unsigned char *message, + EVP_PKEY *evpPkey) + { + TPM_RC rc = 0; ++#if OPENSSL_VERSION_NUMBER < 0x30000000 + RSA *rsaPubKey = NULL; /* OpenSSL public key, RSA format */ +- ++ + /* construct the RSA key token */ + if (rc == 0) { + rsaPubKey = EVP_PKEY_get1_RSA(evpPkey); /* freed @1 */ +@@ -1838,6 +1989,9 @@ TPM_RC verifyRSASignatureFromEvpPubKey(unsigned char *message, + rc = TSS_RC_RSA_KEY_CONVERT; + } + } ++#else ++ EVP_PKEY *rsaPubKey = evpPkey; ++#endif + if (rc == 0) { + rc = verifyRSASignatureFromRSA(message, + messageSize, +@@ -1845,11 +1999,17 @@ TPM_RC verifyRSASignatureFromEvpPubKey(unsigned char *message, + halg, + rsaPubKey); + } ++#if OPENSSL_VERSION_NUMBER < 0x30000000 + TSS_RsaFree(rsaPubKey); /* @1 */ ++#endif + return rc; + } + +-/* signRSAFromRSA() signs digest to signature, using th4 RSA key rsaKey. */ ++/* signRSAFromRSA() signs digest to signature, using rsaKey. ++ ++ For Openssl < 3, rsaKey is an RSA structure. ++ For Openssl 3, rsaKey is an EVP_PKEY, ++*/ + + TPM_RC signRSAFromRSA(uint8_t *signature, size_t *signatureLength, + size_t signatureSize, +@@ -1859,8 +2019,9 @@ TPM_RC signRSAFromRSA(uint8_t *signature, size_t *signatureLength, + { + TPM_RC rc = 0; + int irc; ++#if OPENSSL_VERSION_NUMBER < 0x30000000 + int nid; /* openssl hash algorithm */ +- ++ + /* map the hash algorithm to the openssl NID */ + if (rc == 0) { + switch (hashAlg) { +@@ -1903,6 +2064,54 @@ TPM_RC signRSAFromRSA(uint8_t *signature, size_t *signatureLength, + rc = TSS_RC_RSA_SIGNATURE; + } + } ++#else ++ EVP_PKEY_CTX *ctx = NULL; ++ const EVP_MD *md; ++ ++ if (rc == 0) { ++ ctx = EVP_PKEY_CTX_new(rsaKey, NULL); /* freed @1 */ ++ if (ctx == NULL) { ++ printf("signRSAFromRSA: Error in EVP_PKEY_CTX_new()\n"); ++ rc = TSS_RC_RSA_KEY_CONVERT; ++ } ++ } ++ if (rc == 0) { ++ irc = EVP_PKEY_sign_init(ctx); ++ if (irc != 1) { ++ printf("signRSAFromRSA: Error in EVP_PKEY_sign_init()\n"); ++ rc = TSS_RC_RSA_SIGNATURE; ++ } ++ } ++ if (rc == 0) { ++ rc = TSS_Hash_GetMd(&md, hashAlg); ++ } ++ if (rc == 0) { ++ irc = EVP_PKEY_CTX_set_signature_md(ctx, md); ++ if (irc <= 0) { ++ printf("signRSAFromRSA: Error in EVP_PKEY_CTX_set_signature_md()\n"); ++ rc = TSS_RC_RSA_SIGNATURE; ++ } ++ } ++ if (rc == 0) { ++ irc = EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING); ++ if (irc <= 0) { ++ printf("signRSAFromRSA: Error in EVP_PKEY_CTX_set_rsa_padding()\n"); ++ rc = TSS_RC_RSA_SIGNATURE; ++ } ++ } ++ if (rc == 0) { ++ size_t siglen = signatureSize; ++ irc = EVP_PKEY_sign(ctx, ++ signature, &siglen, ++ digest, (unsigned int)digestLength); ++ *signatureLength = siglen; ++ if (irc != 1) { ++ printf("signRSAFromRSA: Error in EVP_PKEY_sign()\n"); ++ rc = TSS_RC_RSA_SIGNATURE; ++ } ++ } ++ EVP_PKEY_CTX_free(ctx); /* @1 */ ++#endif + return rc; + } + +@@ -1910,6 +2119,9 @@ TPM_RC signRSAFromRSA(uint8_t *signature, size_t *signatureLength, + using the RSA public key in the OpenSSL RSA format. + + Supports RSASSA and RSAPSS schemes. ++ ++ For Openssl < 3, rsaKey is an RSA structure. ++ For Openssl 3, rsaKey is an EVP_PKEY, + */ + + TPM_RC verifyRSASignatureFromRSA(unsigned char *message, +@@ -1920,9 +2132,10 @@ TPM_RC verifyRSASignatureFromRSA(unsigned char *message, + { + TPM_RC rc = 0; + int irc; ++ const EVP_MD *md = NULL; ++#if OPENSSL_VERSION_NUMBER < 0x30000000 + 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) { +@@ -1989,8 +2202,68 @@ TPM_RC verifyRSASignatureFromRSA(unsigned char *message, + else { + printf("verifyRSASignatureFromRSA: Bad signature scheme %04x\n", + tSignature->sigAlg); ++ rc = TSS_RC_RSA_SIGNATURE; + } +- return rc; ++#else ++ EVP_PKEY_CTX *ctx = NULL; ++ ++ if (rc == 0) { ++ ctx = EVP_PKEY_CTX_new(rsaPubKey, NULL); /* freed @1 */ ++ if (ctx == NULL) { ++ printf("verifyRSAFSignatureromRSA: Error in EVP_PKEY_CTX_new()\n"); ++ rc = TSS_RC_RSA_KEY_CONVERT; ++ } ++ } ++ if (rc == 0) { ++ irc = EVP_PKEY_verify_init(ctx); ++ if (irc != 1) { ++ printf("verifyRSASignatureFromRSA: Error in EVP_PKEY_verify_init()\n"); ++ rc = TSS_RC_RSA_SIGNATURE; ++ } ++ } ++ if (rc == 0) { ++ rc = TSS_Hash_GetMd(&md, halg); ++ } ++ if (rc == 0) { ++ irc = EVP_PKEY_CTX_set_signature_md(ctx, md); ++ if (irc <= 0) { ++ printf("verifyRSASignatureFromRSA: Error in EVP_PKEY_CTX_set_signature_md()\n"); ++ rc = TSS_RC_RSA_SIGNATURE; ++ } ++ } ++ /* verify the signature */ ++ if (rc == 0) { ++ if (tSignature->sigAlg == TPM_ALG_RSASSA) { ++ irc = EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING); ++ } ++ else if (tSignature->sigAlg == TPM_ALG_RSAPSS) { ++ irc = EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING); ++ } ++ else { ++ rc = TSS_RC_RSA_SIGNATURE; ++ printf("verifyRSASignatureFromRSA: Bad signature scheme %04x\n", ++ tSignature->sigAlg); ++ } ++ } ++ if (rc == 0) { ++ if (irc <= 0) { ++ printf("verifyRSASignatureFromRSA: Error in EVP_PKEY_CTX_set_rsa_padding()\n"); ++ rc = TSS_RC_RSA_SIGNATURE; ++ } ++ } ++ if (rc == 0) { ++ irc = EVP_PKEY_verify(ctx, ++ tSignature->signature.rsapss.sig.t.buffer, ++ tSignature->signature.rsapss.sig.t.size, ++ message, messageSize); ++ if (irc != 1) { ++ printf("verifyRSASignatureFromRSA: Error in EVP_PKEY_verify()\n"); ++ rc = TSS_RC_RSA_SIGNATURE; ++ } ++ } ++ EVP_PKEY_CTX_free(ctx); /* @1 */ ++#endif ++ return rc; + } + + #endif /* TPM_TSS_NORSA */ +diff --git a/utils/cryptoutils.h b/utils/cryptoutils.h +index 03452de..6809dea 100644 +--- a/utils/cryptoutils.h ++++ b/utils/cryptoutils.h +@@ -248,9 +248,10 @@ extern "C" { + + TPM_RC convertEvpPkeyToRsakey(RSA **rsaKey, + EVP_PKEY *evpPkey); +- TPM_RC convertRsaKeyToPrivateKeyBin(int *privateKeyBytes, ++#if OPENSSL_VERSION_NUMBER < 0x30000000 ++ TPM_RC convertRsaKeyToPrivateKeyBin(int *privateKeyBytes, + uint8_t **privateKeyBin, +- const RSA *rsaKey); ++ const RSA *rsaKey); + TPM_RC convertRsaKeyToPrivate(TPM2B_PRIVATE *objectPrivate, + TPM2B_SENSITIVE *objectSensitive, + RSA *rsaKey, +@@ -260,7 +261,22 @@ extern "C" { + const BIGNUM **d, + const BIGNUM **p, + const BIGNUM **q, +- const RSA *rsaKey); ++ const RSA *rsaKey); ++#else ++ TPM_RC convertRsaKeyToPrivateKeyBin(int *privateKeyBytes, ++ uint8_t **privateKeyBin, ++ const EVP_PKEY *rsaKey); ++ TPM_RC convertRsaKeyToPrivate(TPM2B_PRIVATE *objectPrivate, ++ TPM2B_SENSITIVE *objectSensitive, ++ EVP_PKEY *rsaKey, ++ const char *password); ++ TPM_RC getRsaKeyParts(const BIGNUM **n, ++ const BIGNUM **e, ++ const BIGNUM **d, ++ const BIGNUM **p, ++ const BIGNUM **q, ++ const EVP_PKEY *rsaKey); ++#endif + int getRsaPubkeyAlgorithm(EVP_PKEY *pkey); + TPM_RC convertRsaPublicToEvpPubKey(EVP_PKEY **evpPubkey, + const TPM2B_PUBLIC_KEY_RSA *tpm2bRsa); +diff --git a/utils/efilib.c b/utils/efilib.c +index ab8177b..afed9dd 100644 +--- a/utils/efilib.c ++++ b/utils/efilib.c +@@ -64,6 +64,7 @@ + #include + #include + #include ++#include + + #include "eventlib.h" + #include "efilib.h" +@@ -4805,7 +4806,13 @@ static void TSS_EfiEventTag_Trace(TSST_EFIData *efiData) + uint32_t count; + TSS_UEFI_TAGGED_EVENT *taggedEventList = &efiData->efiData.taggedEventList; + #ifndef TPM_TSS_MBEDTLS +- RSA *rsaKey = NULL; ++#ifndef TPM_TSS_NORSA ++#if OPENSSL_VERSION_NUMBER < 0x30000000 ++ RSA *rsaKey = NULL; ++#else ++ EVP_PKEY *rsaKey = NULL; ++#endif ++#endif /* TPM_TSS_NORSA */ + #endif /* TPM_TSS_MBEDTLS */ + + printf(" tagged events %u\n", taggedEventList->count); +@@ -4815,17 +4822,25 @@ static void TSS_EfiEventTag_Trace(TSST_EFIData *efiData) + printf(" taggedEventID %08x\n", taggedEvent->taggedEventID); + /* https://github.com/mattifestation/TCGLogTools/blob/master/TCGLogTools.psm1 */ + /* by observation 0x00060002 appears to be a DER encoded public key */ +-#ifndef TPM_TSS_MBEDTLS ++#if ! defined TPM_TSS_MBEDTLS && ! defined TPM_TSS_NORSA + if (taggedEvent->taggedEventID == 0x00060002) { + const unsigned char *tmpData = NULL; + /* tmp pointer because d2i moves the pointer */ + tmpData = taggedEvent->taggedEventData; +- rsaKey = d2i_RSA_PUBKEY(NULL, &tmpData , taggedEvent->taggedEventDataSize); /* freed @2 */ ++#if OPENSSL_VERSION_NUMBER < 0x30000000 ++ rsaKey = d2i_RSA_PUBKEY(NULL, &tmpData ,taggedEvent->taggedEventDataSize); /* freed @2 */ ++#else ++ rsaKey = d2i_PUBKEY(NULL, &tmpData, (long)taggedEvent->taggedEventDataSize); ++#endif /* OPENSSL_VERSION_NUMBER */ + if (rsaKey != NULL) { /* success */ ++#if OPENSSL_VERSION_NUMBER < 0x30000000 + RSA_print_fp(stdout, rsaKey, 4); ++#else ++ EVP_PKEY_print_public_fp(stdout, rsaKey, 4, NULL); ++#endif /* OPENSSL_VERSION_NUMBER */ + } + if (rsaKey != NULL) { +- RSA_free(rsaKey); ++ TSS_RsaFree(rsaKey); /* @2 */ + } + } + /* if it's not 0x00060002 or if the d2i fails */ +@@ -4834,10 +4849,10 @@ static void TSS_EfiEventTag_Trace(TSST_EFIData *efiData) + TSS_PrintAll(" taggedEvent", + taggedEvent->taggedEventData, taggedEvent->taggedEventDataSize); + } +-#else ++#else /* TPM_TSS_MBEDTLS or TPM_TSS_NORSA */ + TSS_PrintAll(" taggedEvent", + taggedEvent->taggedEventData, taggedEvent->taggedEventDataSize); +-#endif /* TPM_TSS_MBEDTLS */ ++#endif /* TPM_TSS_MBEDTLS TPM_TSS_NORSA */ + } + return; + } +diff --git a/utils/ekutils.c b/utils/ekutils.c +index a0a2734..cb7f938 100644 +--- a/utils/ekutils.c ++++ b/utils/ekutils.c +@@ -567,9 +567,12 @@ TPM_RC getIndexX509Certificate(TSS_CONTEXT *tssContext, + certificate stored in a file. + + Returns both the OpenSSL X509 certificate token and RSA public key token. ++ ++ For Openssl < 3, rsaKey is an RSA structure. ++ For Openssl 3, rsaKey is an EVP_PKEY, + */ + +-uint32_t getPubkeyFromDerCertFile(RSA **rsaPkey, ++uint32_t getPubkeyFromDerCertFile(void **rsaPkey, /* freed by caller */ + X509 **x509, + const char *derCertificateFileName) + { +@@ -594,7 +597,7 @@ uint32_t getPubkeyFromDerCertFile(RSA **rsaPkey, + } + /* extract the OpenSSL format public key from the X509 token */ + if (rc == 0) { +- rc = getPubKeyFromX509Cert(rsaPkey, *x509); ++ rc = getPubKeyFromX509Cert(rsaPkey, *x509); /* freed by caller */ + } + /* for debug, print the X509 certificate */ + if (rc == 0) { +@@ -612,9 +615,13 @@ uint32_t getPubkeyFromDerCertFile(RSA **rsaPkey, + #ifndef TPM_TSS_NORSA + + /* getPubKeyFromX509Cert() gets an OpenSSL RSA public key token from an OpenSSL X509 certificate +- token. */ ++ token. ++ ++ For Openssl < 3, rsaKey is an RSA structure. ++ For Openssl 3, rsaKey is an EVP_PKEY, ++*/ + +-uint32_t getPubKeyFromX509Cert(RSA **rsaPkey, ++uint32_t getPubKeyFromX509Cert(void **rsaPkey, + X509 *x509) + { + uint32_t rc = 0; +@@ -623,20 +630,24 @@ uint32_t getPubKeyFromX509Cert(RSA **rsaPkey, + if (rc == 0) { + evpPkey = X509_get_pubkey(x509); /* freed @1 */ + if (evpPkey == NULL) { +- printf("getPubKeyFromX509Cert: X509_get_pubkey failed\n"); ++ printf("getPubKeyFromX509Cert: X509_get_pubkey failed\n"); + rc = TSS_RC_X509_ERROR; + } + } ++#if OPENSSL_VERSION_NUMBER < 0x30000000 + if (rc == 0) { + *rsaPkey = EVP_PKEY_get1_RSA(evpPkey); + if (*rsaPkey == NULL) { +- printf("getPubKeyFromX509Cert: EVP_PKEY_get1_RSA failed\n"); ++ printf("getPubKeyFromX509Cert: EVP_PKEY_get1_RSA failed\n"); + rc = TSS_RC_X509_ERROR; + } + } + if (evpPkey != NULL) { + EVP_PKEY_free(evpPkey); /* @1 */ + } ++#else ++ *rsaPkey = evpPkey; ++#endif + return rc; + } + #endif /* TPM_TSS_NORSA */ +@@ -1105,8 +1116,8 @@ TPM_RC convertX509ToEc(EC_KEY **ecKey, /* freed by caller */ + + If print is true, prints the EK certificate + +- The return is void because the structure is opaque to the caller. This accomodates other crypto +- libraries. ++ The ekCertificate return is void because the structure is opaque to the caller. This ++ accommodates other crypto libraries. + + ekCertificate is an X509 structure. + */ +@@ -1158,7 +1169,11 @@ TPM_RC convertCertificatePubKey(uint8_t **modulusBin, /* freed by caller */ + case EK_CERT_RSA_3072_INDEX_H6: + case EK_CERT_RSA_4096_INDEX_H7: + { ++#if OPENSSL_VERSION_NUMBER < 0x30000000 + RSA *rsaKey = NULL; ++#else ++ EVP_PKEY *rsaKey = NULL; ++#endif + /* check that the public key algorithm matches the ekCertIndex algorithm */ + if (rc == 0) { + if (pkeyType != EVP_PKEY_RSA) { +@@ -1169,12 +1184,16 @@ TPM_RC convertCertificatePubKey(uint8_t **modulusBin, /* freed by caller */ + } + /* convert the public key to OpenSSL structure */ + if (rc == 0) { ++#if OPENSSL_VERSION_NUMBER < 0x30000000 + rsaKey = EVP_PKEY_get1_RSA(pkey); /* freed @3 */ + if (rsaKey == NULL) { + printf("convertCertificatePubKey: Could not extract RSA public key " + "from X509 certificate\n"); + rc = TPM_RC_INTEGRITY; + } ++#else /* use the EVP_PKEY directly */ ++ rsaKey = pkey; ++#endif + } + if (rc == 0) { + rc = convertRsaKeyToPublicKeyBin(modulusBytes, +@@ -1185,7 +1204,9 @@ TPM_RC convertCertificatePubKey(uint8_t **modulusBin, /* freed by caller */ + if (print) TSS_PrintAll("Certificate public key:", + *modulusBin, *modulusBytes); + } ++#if OPENSSL_VERSION_NUMBER < 0x30000000 + RSA_free(rsaKey); /* @3 */ ++#endif + } + break; + #endif /* TPM_TSS_NORSA */ +@@ -1254,7 +1275,11 @@ TPM_RC convertCertificatePubKey12(uint8_t **modulusBin, /* freed by caller */ + const unsigned char *pk = NULL; /* do not free */ + int ppklen; + X509_ALGOR *palg = NULL; /* algorithm identifier for public key */ ++#if OPENSSL_VERSION_NUMBER < 0x30000000 + RSA *rsaKey = NULL; ++#else ++ EVP_PKEY *rsaKey = NULL; ++#endif + + /* get internal pointer to the public key in the certificate */ + if (rc == 0) { +@@ -1278,7 +1303,12 @@ TPM_RC convertCertificatePubKey12(uint8_t **modulusBin, /* freed by caller */ + } + if (rc == 0) { + const unsigned char *tmppk = pk; /* because d2i moves the pointer */ ++#if OPENSSL_VERSION_NUMBER < 0x30000000 + rsaKey = d2i_RSAPublicKey(NULL, &tmppk, ppklen); /* freed @1 */ ++#else ++ rsaKey = d2i_PublicKey(EVP_PKEY_RSA, NULL, ++ &tmppk, (long)ppklen); ++#endif + if (rsaKey == NULL) { + printf("convertCertificatePubKey12: Could not convert to RSA structure\n"); + rc = TPM_RC_INTEGRITY; +@@ -1290,9 +1320,7 @@ TPM_RC convertCertificatePubKey12(uint8_t **modulusBin, /* freed by caller */ + rsaKey); + TSS_PrintAll("convertCertificatePubKey12", *modulusBin, *modulusBytes); + } +- if (rsaKey != NULL) { +- RSA_free(rsaKey); /* @1 */ +- } ++ TSS_RsaFree(rsaKey); /* @1 */ + return rc; + } + +diff --git a/utils/ekutils.h b/utils/ekutils.h +index f37b7d2..18b0e48 100644 +--- a/utils/ekutils.h ++++ b/utils/ekutils.h +@@ -218,10 +218,10 @@ extern "C" { + #ifndef TPM_TSS_NO_OPENSSL + + +- uint32_t getPubkeyFromDerCertFile(RSA **rsaPkey, ++ uint32_t getPubkeyFromDerCertFile(void **rsaPkey, + X509 **x509, + const char *derCertificateFileName); +- uint32_t getPubKeyFromX509Cert(RSA **rsaPkey, ++ uint32_t getPubKeyFromX509Cert(void **rsaPkey, + X509 *x509); + TPM_RC getCaStore(X509_STORE **caStore, + X509 *caCert[], +diff --git a/utils/ibmtss/tsscrypto.h b/utils/ibmtss/tsscrypto.h +index 5bf5591..30d2ef1 100644 +--- a/utils/ibmtss/tsscrypto.h ++++ b/utils/ibmtss/tsscrypto.h +@@ -4,7 +4,7 @@ + /* Written by Ken Goldman */ + /* IBM Thomas J. Watson Research Center */ + /* */ +-/* (c) Copyright IBM Corporation 2015 - 2019. */ ++/* (c) Copyright IBM Corporation 2015 - 2021. */ + /* */ + /* All rights reserved. */ + /* */ +@@ -107,6 +107,7 @@ extern "C" { + LIB_EXPORT + TPM_RC TSS_RsaNew(void **rsaKey); + ++ /* deprecated */ + LIB_EXPORT + TPM_RC TSS_RSAGeneratePublicToken(RSA **rsa_pub_key, /* freed by caller */ + const unsigned char *narr, /* public modulus */ +diff --git a/utils/sign.c b/utils/sign.c +index 0635366..ba2be27 100644 +--- a/utils/sign.c ++++ b/utils/sign.c +@@ -4,7 +4,7 @@ + /* Written by Ken Goldman */ + /* IBM Thomas J. Watson Research Center */ + /* */ +-/* (c) Copyright IBM Corporation 2015 - 2019. */ ++/* (c) Copyright IBM Corporation 2015 - 2021. */ + /* */ + /* All rights reserved. */ + /* */ +@@ -426,6 +426,8 @@ int main(int argc, char *argv[]) + /* construct the OpenSSL RSA public key token */ + if (rc == 0) { + unsigned char earr[3] = {0x01, 0x00, 0x01}; ++ /* For Openssl < 3, rsaKey is an RSA structure. */ ++ /* For Openssl 3, rsaKey is an EVP_PKEY. */ + rc = TSS_RSAGeneratePublicTokenI + (&rsaPubKey, /* freed @2 */ + public.publicArea.unique.rsa.t.buffer, /* public modulus */ +diff --git a/utils/tsscrypto.c b/utils/tsscrypto.c +index 1974563..2efddfc 100644 +--- a/utils/tsscrypto.c ++++ b/utils/tsscrypto.c +@@ -5,7 +5,7 @@ + /* IBM Thomas J. Watson Research Center */ + /* ECC Salt functions written by Bill Martin */ + /* */ +-/* (c) Copyright IBM Corporation 2015 - 2019. */ ++/* (c) Copyright IBM Corporation 2015 - 2021. */ + /* */ + /* All rights reserved. */ + /* */ +@@ -37,7 +37,7 @@ + /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + /********************************************************************************/ + +-/* Interface to OpenSSL version 1.0 or 1.1 crypto library */ ++/* Interface to OpenSSL version 1.0.2, 1.1.1, 3.0.0 crypto library */ + + #include + #include +@@ -59,6 +59,10 @@ + #include + #include + ++#if OPENSSL_VERSION_NUMBER >= 0x30000000 ++#include ++#endif ++ + #include + #include + #include +@@ -67,6 +71,9 @@ + #include + #include + ++TPM_RC TSS_Hash_GetMd(const EVP_MD **md, ++ TPMI_ALG_HASH hashAlg); ++ + extern int tssVverbose; + extern int tssVerbose; + +@@ -80,8 +87,6 @@ extern int tssVerbose; + /* local prototypes */ + + static TPM_RC TSS_Hash_GetOsslString(const char **str, TPMI_ALG_HASH hashAlg); +-static TPM_RC TSS_Hash_GetMd(const EVP_MD **md, +- TPMI_ALG_HASH hashAlg); + + #ifndef TPM_TSS_NOECC + +@@ -164,8 +169,8 @@ static TPM_RC TSS_Hash_GetOsslString(const char **str, TPMI_ALG_HASH hashAlg) + return rc; + } + +-static TPM_RC TSS_Hash_GetMd(const EVP_MD **md, +- TPMI_ALG_HASH hashAlg) ++TPM_RC TSS_Hash_GetMd(const EVP_MD **md, ++ TPMI_ALG_HASH hashAlg) + { + TPM_RC rc = 0; + const char *str = NULL; +@@ -352,7 +357,8 @@ TPM_RC TSS_RandBytes(unsigned char *buffer, uint32_t size) + + This abstracts the crypto library specific allocation. + +- For Openssl, rsaKey is an RSA structure. ++ For Openssl < 3, rsaKey is an RSA structure. ++ For Openssl 3, rsaKey is an EVP_PKEY, + */ + + TPM_RC TSS_RsaNew(void **rsaKey) +@@ -369,6 +375,7 @@ TPM_RC TSS_RsaNew(void **rsaKey) + } + } + /* construct the OpenSSL private key object */ ++#if OPENSSL_VERSION_NUMBER < 0x30000000 + if (rc == 0) { + *rsaKey = RSA_new(); /* freed by caller */ + if (*rsaKey == NULL) { +@@ -376,20 +383,36 @@ TPM_RC TSS_RsaNew(void **rsaKey) + rc = TSS_RC_RSA_KEY_CONVERT; + } + } ++#else ++ if (rc == 0) { ++ *rsaKey = EVP_PKEY_new(); ++ if (*rsaKey == NULL) { ++ if (tssVerbose) printf("TSS_RsaNew: Error in EVP_PKEY_new()\n"); ++ rc = TSS_RC_RSA_KEY_CONVERT; ++ } ++ } ++ if (rc == 0) { ++ } ++#endif + return rc; + } + + /* TSS_RsaFree() frees an openssl RSA key token. + + This abstracts the crypto library specific free. +- +- For Openssl, rsaKey is an RSA structure. ++ ++ For Openssl < 3, rsaKey is an RSA structure. ++ For Openssl 3, rsaKey is an EVP_PKEY, + */ + + void TSS_RsaFree(void *rsaKey) + { + if (rsaKey != NULL) { ++#if OPENSSL_VERSION_NUMBER < 0x30000000 + RSA_free(rsaKey); ++#else ++ EVP_PKEY_free(rsaKey); ++#endif + } + return; + } +@@ -418,42 +441,122 @@ TPM_RC TSS_RSAGeneratePublicToken(RSA **rsa_pub_key, /* freed by caller */ + /* TSS_RSAGeneratePublicTokenI() generates an RSA key token from n and e + + Free rsa_pub_key using TSS_RsaFree(); ++ ++ For Openssl < 3, rsaKey is an RSA structure. ++ For Openssl 3, rsaKey is an EVP_PKEY. + */ + + TPM_RC TSS_RSAGeneratePublicTokenI(void **rsa_pub_key, /* freed by caller */ +- const unsigned char *narr, /* public modulus */ ++ const unsigned char *narr, /* public modulus */ + uint32_t nbytes, +- const unsigned char *earr, /* public exponent */ ++ const unsigned char *earr, /* public exponent */ + uint32_t ebytes) + { + TPM_RC rc = 0; ++#if OPENSSL_VERSION_NUMBER >= 0x10100000 ++ int irc; ++#endif + BIGNUM * n = NULL; + BIGNUM * e = NULL; ++#if OPENSSL_VERSION_NUMBER < 0x30000000 + RSA ** rsaPubKey = (RSA **)rsa_pub_key; /* openssl specific structure */ ++#else ++ EVP_PKEY_CTX *ctx = NULL; ++ OSSL_PARAM_BLD *param_bld = NULL; ++ OSSL_PARAM *params = NULL; ++#endif + + /* construct the OpenSSL private key object */ ++#if OPENSSL_VERSION_NUMBER < 0x30000000 + if (rc == 0) { +- rc = TSS_RsaNew(rsa_pub_key); +- } +- if (rc == 0) { +- rc = TSS_bin2bn(&n, narr, nbytes); /* freed by caller */ ++ rc = TSS_RsaNew(rsa_pub_key); /* freed by caller */ + } ++#endif + if (rc == 0) { +- rc = TSS_bin2bn(&e, earr, ebytes); /* freed by caller */ +- } ++ rc = TSS_bin2bn(&n, narr, nbytes); /* freed by caller, < 3.0.0 */ ++ } /* freed @4, 3.0.0 */ + if (rc == 0) { ++ rc = TSS_bin2bn(&e, earr, ebytes); /* freed by caller, < 3.0.0 */ ++ } /* freed @5, 3.0.0 */ + #if OPENSSL_VERSION_NUMBER < 0x10100000 ++ if (rc == 0) { + (*rsaPubKey)->n = n; + (*rsaPubKey)->e = e; + (*rsaPubKey)->d = NULL; +-#else +- int irc = RSA_set0_key(*rsaPubKey, n, e, NULL); ++ } ++#elif OPENSSL_VERSION_NUMBER < 0x30000000 ++ if (rc == 0) { ++ irc = RSA_set0_key(*rsaPubKey, n, e, NULL); + if (irc != 1) { + if (tssVerbose) printf("TSS_RSAGeneratePublicTokenI: Error in RSA_set0_key()\n"); + rc = TSS_RC_RSA_KEY_CONVERT; + } +-#endif + } ++#else ++ if (rc == 0) { ++ param_bld = OSSL_PARAM_BLD_new(); /* freed @2 */ ++ if (param_bld == NULL) { ++ if (tssVerbose) printf("TSS_RSAGeneratePublicTokenI: Error in OSSL_PARAM_BLD_new()\n"); ++ rc = TSS_RC_RSA_KEY_CONVERT; ++ } ++ } ++ if (rc == 0) { ++ irc = OSSL_PARAM_BLD_push_BN(param_bld, "n", n); ++ if (irc != 1) { ++ if (tssVerbose) printf("TSS_RSAGeneratePublicTokenI: " ++ "Error in OSSL_PARAM_BLD_push_BN()\n"); ++ rc = TSS_RC_RSA_KEY_CONVERT; ++ } ++ } ++ if (rc == 0) { ++ irc = OSSL_PARAM_BLD_push_BN(param_bld, "e", e); ++ if (irc != 1) { ++ if (tssVerbose) printf("TSS_RSAGeneratePublicTokenI: " ++ "Error in OSSL_PARAM_BLD_push_BN()\n"); ++ rc = TSS_RC_RSA_KEY_CONVERT; ++ } ++ } ++ if (rc == 0) { ++ params = OSSL_PARAM_BLD_to_param(param_bld); /* freed @3 */ ++ if (params == NULL) { ++ if (tssVerbose) printf("TSS_RSAGeneratePublicTokenI: " ++ "Error in OSSL_PARAM_BLD_to_param()\n"); ++ rc = TSS_RC_RSA_KEY_CONVERT; ++ } ++ } ++ if (rc == 0) { ++ ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL); /* freed @1 */ ++ if (ctx == NULL) { ++ if (tssVerbose) printf("TSS_RSAGeneratePublicTokenI: " ++ "Error in EVP_PKEY_CTX_new_from_name()\n"); ++ rc = TSS_RC_RSA_KEY_CONVERT; ++ } ++ } ++ if (rc == 0) { ++ irc = EVP_PKEY_fromdata_init(ctx); ++ if (irc != 1) { ++ if (tssVerbose) printf("TSS_RSAGeneratePublicTokenI: " ++ "Error in EVP_PKEY_fromdata_init()\n"); ++ rc = TSS_RC_RSA_KEY_CONVERT; ++ } ++ } ++ if (rc == 0) { ++ irc = EVP_PKEY_fromdata(ctx, (EVP_PKEY **)rsa_pub_key, /* freed by caller */ ++ EVP_PKEY_PUBLIC_KEY, params); ++ if (irc != 1) { ++ if (tssVerbose) printf("TSS_RSAGeneratePublicTokenI: " ++ "Error in OSSL_PARAM_BLD_push_BN()\n"); ++ rc = TSS_RC_RSA_KEY_CONVERT; ++ } ++ } ++ OSSL_PARAM_free(params); /* @3 */ ++ OSSL_PARAM_BLD_free(param_bld); /* @2 */ ++ EVP_PKEY_CTX_free(ctx); /* @1 */ ++ /* for openssl < 3.0.0, n and e are part of the RSA structure, freed with it. For 3.0.0 and up, ++ they're copied to the EVP_PKEY, so the parts are freed here. */ ++ BN_free(n); /* @4 */ ++ BN_free(e); /* @5 */ ++#endif + return rc; + } + +@@ -475,7 +578,12 @@ TPM_RC TSS_RSAPublicEncrypt(unsigned char *encrypt_data, /* encrypted data */ + { + TPM_RC rc = 0; + int irc; ++#if OPENSSL_VERSION_NUMBER < 0x30000000 + RSA *rsa_pub_key = NULL; ++#else ++ EVP_PKEY *rsa_pub_key = NULL; ++ EVP_PKEY_CTX *ctx = NULL; ++#endif + unsigned char *padded_data = NULL; + + if (tssVverbose) printf(" TSS_RSAPublicEncrypt: Input data size %lu\n", +@@ -486,12 +594,16 @@ TPM_RC TSS_RSAPublicEncrypt(unsigned char *encrypt_data, /* encrypted data */ + } + /* construct the OpenSSL public key object */ + if (rc == 0) { +- rc = TSS_RSAGeneratePublicTokenI((void **)&rsa_pub_key, /* freed @1 */ ++ /* For Openssl < 3, rsaKey is an RSA structure. */ ++ /* For Openssl 3, rsaKey is an EVP_PKEY, */ ++ rc = TSS_RSAGeneratePublicTokenI((void **)&rsa_pub_key, /* freed @3 */ + narr, /* public modulus */ + nbytes, + earr, /* public exponent */ + ebytes); + } ++ /* Must pad first and then encrypt because the encrypt call cannot specify an encoding ++ parameter */ + if (rc == 0) { + padded_data[0] = 0x00; + rc = TSS_RSA_padding_add_PKCS1_OAEP(padded_data, /* to */ +@@ -508,25 +620,61 @@ TPM_RC TSS_RSAPublicEncrypt(unsigned char *encrypt_data, /* encrypted data */ + (unsigned long)encrypt_data_size); + if (tssVverbose) TSS_PrintAll(" TPM_RSAPublicEncrypt: Padded data", padded_data, + (uint32_t)encrypt_data_size); +- /* encrypt with public key. Must pad first and then encrypt because the encrypt +- call cannot specify an encoding parameter */ ++ } ++#if OPENSSL_VERSION_NUMBER < 0x30000000 ++ if (rc == 0) { ++ /* encrypt with public key. */ + /* returns the size of the encrypted data. On error, -1 is returned */ + irc = RSA_public_encrypt((int)encrypt_data_size, /* from length */ + padded_data, /* from - the clear text data */ + encrypt_data, /* the padded and encrypted data */ +- rsa_pub_key, /* key */ ++ rsa_pub_key, /* RSA key structure */ + RSA_NO_PADDING); /* padding */ + if (irc < 0) { + if (tssVerbose) printf("TSS_RSAPublicEncrypt: Error in RSA_public_encrypt()\n"); + rc = TSS_RC_RSA_ENCRYPT; + } + } ++#else ++ /* create EVP_PKEY_CTX for the encrypt */ ++ if (rc == 0) { ++ ctx = EVP_PKEY_CTX_new(rsa_pub_key, NULL); /* freed @1 */ ++ if (ctx == NULL) { ++ printf("TSS_RSAPublicEncrypt: Error in EVP_PKEY_CTX_new()\n"); ++ rc = TSS_RC_RSA_ENCRYPT; ++ } ++ } ++ if (rc == 0) { ++ irc = EVP_PKEY_encrypt_init(ctx); ++ if (irc != 1) { ++ printf("TSS_RSAPublicEncrypt: Error in EVP_PKEY_encrypt_init()\n"); ++ rc = TSS_RC_RSA_ENCRYPT; ++ } ++ } ++ if (rc == 0) { ++ irc = EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_NO_PADDING); ++ if (irc <= 0) { ++ if (tssVerbose) printf("TSS_RSAPublicEncrypt: Error in EVP_PKEY_CTX_set_rsa_padding\n"); ++ rc = TSS_RC_RSA_ENCRYPT; ++ } ++ } ++ if (rc == 0) { ++ size_t outlen = encrypt_data_size; ++ irc = EVP_PKEY_encrypt(ctx, ++ encrypt_data, &outlen, ++ padded_data, encrypt_data_size); ++ } ++#endif + if (rc == 0) { + if (tssVverbose) printf(" TSS_RSAPublicEncrypt: RSA_public_encrypt() success\n"); + } +- TSS_RsaFree(rsa_pub_key); /* @1 */ +- free(padded_data); /* @2 */ +- return rc; ++#if OPENSSL_VERSION_NUMBER < 0x30000000 ++#else ++ EVP_PKEY_CTX_free(ctx); /* @1 */ ++#endif ++ TSS_RsaFree(rsa_pub_key); /* @3 */ ++ free(padded_data); /* @2 */ ++ return rc; + } + + #endif /* TPM_TSS_NORSA */ +-- +2.34.1 + diff --git a/tss2.spec b/tss2.spec index 24eac8c..4e95853 100644 --- a/tss2.spec +++ b/tss2.spec @@ -7,7 +7,7 @@ Name: tss2 Version: 1.6.0 -Release: 4%{?dist} +Release: 5%{?dist} Epoch: 1 Summary: IBM's TCG Software Stack (TSS) for TPM 2.0 and related utilities @@ -15,6 +15,13 @@ License: BSD URL: http://sourceforge.net/projects/ibmtpm20tss/ Source0: https://sourceforge.net/projects/ibmtpm20tss/files/ibmtss%{version}.tar.gz Patch0: tss2-1.6.0-manpage-cleanup.patch +Patch1: 0001-utils-Update-certifyx509-for-Openssl-3.0.0.patch +Patch2: 0002-utils-Remove-unused-variables-from-certifyx509.patch +Patch3: 0003-Update-certifyx509-for-Windows.patch +Patch4: 0004-utils-Clean-up-certifyx509-memory-allocation.patch +Patch5: 0005-utils-Fix-errors-detected-by-gcc-asan.patch +Patch6: 0006-tss-Port-HMAC-operations-to-openssl-3.0.patch +Patch7: 0007-utils-Port-to-openssl-3.0.0-replaces-RSA-with-EVP_PK.patch BuildRequires: automake BuildRequires: autoconf @@ -70,6 +77,11 @@ find %{buildroot} -type f -name "*.la" -delete -print %doc ibmtss.doc %changelog +* Fri Jan 28 2022 Stepan Horacek - 1:1.6.0-5 +- Fix failures introduced with OpenSSL 3 + Resolves: rhbz#1984621 + Resolves: rhbz#1992339 + * Tue Aug 10 2021 Mohan Boddu - 1:1.6.0-4 - Rebuilt for IMA sigs, glibc 2.34, aarch64 flags Related: rhbz#1991688