You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1453 lines
50 KiB

From c93d780442052ae113871f4033d788a5bbe288fa Mon Sep 17 00:00:00 2001
From: Ken Goldman <kgoldman@us.ibm.com>
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 <kgoldman@us.ibm.com>
---
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 <string.h>
#include <stdint.h>
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
#include "cryptoutils.h"
#ifndef TPM_TSS_MBEDTLS
@@ -64,9 +69,74 @@
/* NOTE: This is currently openssl only. */
#include <ekutils.h>
+/* 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