1454 lines
50 KiB
Diff
1454 lines
50 KiB
Diff
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
|
|
|