tpm2: Some x509 related fixes

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
This commit is contained in:
Stefan Berger 2019-10-23 17:06:41 -04:00 committed by Stefan Berger
parent baa5b3995d
commit db1d01526a
4 changed files with 154 additions and 145 deletions

View File

@ -271,6 +271,6 @@ MAKE_OID(_ECC_SM2_P256); // Don't know where I found this OID. It needs check
#define OID_ECC_BN_P256 NULL
#endif // ECC_BN_P256
#endif // ALG_ECC
#undef MAKE_OID
// #undef MAKE_OID
#define OID_SIZE(OID) (OID[1] + 2)
#endif // !_OIDS_H_

View File

@ -85,14 +85,7 @@
#define SUBJECT_PUBLIC_KEY_REF (SUBJECT_KEY_REF + 1)
#define EXTENSIONS_REF (SUBJECT_PUBLIC_KEY_REF + 1)
#define REF_COUNT (EXTENSIONS_REF + 1)
#undef MAKE_OID
#ifdef _X509_SPT_
# define MAKE_OID(NAME) \
const BYTE OID##NAME[] = {OID##NAME##_VALUE}
#else
# define MAKE_OID(NAME) \
extern const BYTE OID##NAME[]
#endif
// 10.1.16.4 Structures Used to access the fields of a TBSsignature some of which are in the
// in_CertifyX509 structure and some of which are in the out_CertifyX509 structure.
typedef struct stringRef
@ -107,8 +100,8 @@ typedef union x509KeyUsageUnion {
// 10.1.16.5 Global X509 Constants These values are instanced by X509_spt.c and referenced by other
// X509-related files. This is the DER-encoded value for the Key Usage OID (2.5.29.15). This is the
// full OID, not just the numeric value
#define OID_KEY_USAGE_EXTENSTION_VALUE 0x06, 0x03, 0x55, 0x1D, 0x0F
MAKE_OID(_KEY_USAGE_EXTENSTION);
#define OID_KEY_USAGE_EXTENSION_VALUE 0x06, 0x03, 0x55, 0x1D, 0x0F
MAKE_OID(_KEY_USAGE_EXTENSION);
// This is the DER-encoded value for the TCG-defined TPMA_OBJECT OID (2.23.133.10.1.1.1)
#define OID_TCG_TPMA_OBJECT_VALUE 0x06, 0x07, 0x67, 0x81, 0x05, 0x0a, 0x01, \
0x01, 0x01

View File

@ -3,7 +3,7 @@
/* TPM X509 RSA */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: X509_RSA.c 1490 2019-07-26 21:13:22Z kgoldman $ */
/* $Id: X509_RSA.c 1509 2019-10-07 19:10:05Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -91,114 +91,114 @@ X509AddSigningAlgorithmRSA(
if(hashDef->hashAlg != hashAlg)
return 0;
switch(scheme->scheme)
{
case ALG_RSASSA_VALUE:
{
// if the hash is implemented but there is no PKCS1 OID defined
// then this is not a valid signing combination.
if(hashDef->PKCS1[0] != ASN1_OBJECT_IDENTIFIER)
break;
if(ctx == NULL)
return 1;
ASN1StartMarshalContext(ctx);
ASN1PushOID(ctx, hashDef->PKCS1);
return ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE);
}
case ALG_RSAPSS_VALUE:
// leave if this is just an implementation check
if(ctx == NULL)
return 1;
// In the case of SHA1, everything is default and RFC4055 says that
// implementations that do signature generation MUST omit the parameter
// when defaults are used. )-:
if(hashDef->hashAlg == ALG_SHA1_VALUE)
{
return X509PushAlgorithmIdentifierSequence(ctx, OID_RSAPSS);
}
else
{
// Going to build something that looks like:
// SEQUENCE (2 elem)
// OBJECT IDENTIFIER 1.2.840.113549.1.1.10 rsaPSS (PKCS #1)
// SEQUENCE (3 elem)
// [0] (1 elem)
// SEQUENCE (2 elem)
// OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256
// NULL
// [1] (1 elem)
// SEQUENCE (2 elem)
// OBJECT IDENTIFIER 1.2.840.113549.1.1.8 pkcs1-MGF
// SEQUENCE (2 elem)
// OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256
// NULL
// [2] (1 elem) salt length
// INTEGER 32
// The indentation is just to keep track of where we are in the
// structure
ASN1StartMarshalContext(ctx); // SEQUENCE (2 elements)
{
ASN1StartMarshalContext(ctx); // SEQUENCE (3 elements)
{
// [2] (1 elem) salt length
// INTEGER 32
ASN1StartMarshalContext(ctx);
{
INT16 saltSize =
CryptRsaPssSaltSize((INT16)hashDef->digestSize,
(INT16)signKey->publicArea.unique.rsa.t.size);
ASN1PushUINT(ctx, saltSize);
}
ASN1EndEncapsulation(ctx, ASN1_APPLICAIION_SPECIFIC + 2);
// Add the mask generation algorithm
// [1] (1 elem)
// SEQUENCE (2 elem) 1st
// OBJECT IDENTIFIER 1.2.840.113549.1.1.8 pkcs1-MGF
// SEQUENCE (2 elem) 2nd
// OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256
// NULL
ASN1StartMarshalContext(ctx); // mask context [1] (1 elem)
{
ASN1StartMarshalContext(ctx); // SEQUENCE (2 elem) 1st
// Handle the 2nd Sequence (sequence (object, null))
{
X509PushAlgorithmIdentifierSequence(ctx,
hashDef->OID);
// add the pkcs1-MGF OID
ASN1PushOID(ctx, OID_MGF1);
}
// End outer sequence
ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE);
}
// End the [1]
ASN1EndEncapsulation(ctx, ASN1_APPLICAIION_SPECIFIC + 1);
// Add the hash algorithm
// [0] (1 elem)
// SEQUENCE (2 elem) (done by
// X509PushAlgorithmIdentifierSequence)
// OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256 (NIST)
// NULL
ASN1StartMarshalContext(ctx); // [0] (1 elem)
{
X509PushAlgorithmIdentifierSequence(ctx, hashDef->OID);
}
ASN1EndEncapsulation(ctx, (ASN1_APPLICAIION_SPECIFIC + 0));
}
// SEQUENCE (3 elements) end
ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE);
// RSA PSS OID
// OBJECT IDENTIFIER 1.2.840.113549.1.1.10 rsaPSS (PKCS #1)
ASN1PushOID(ctx, OID_RSAPSS);
}
// End Sequence (2 elements)
return ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE);
}
default:
break;
}
{
case ALG_RSASSA_VALUE:
{
// if the hash is implemented but there is no PKCS1 OID defined
// then this is not a valid signing combination.
if(hashDef->PKCS1[0] != ASN1_OBJECT_IDENTIFIER)
break;
if(ctx == NULL)
return 1;
return X509PushAlgorithmIdentifierSequence(ctx, hashDef->PKCS1);
}
case ALG_RSAPSS_VALUE:
// leave if this is just an implementation check
if(ctx == NULL)
return 1;
// In the case of SHA1, everything is default and RFC4055 says that
// implementations that do signature generation MUST omit the parameter
// when defaults are used. )-:
if(hashDef->hashAlg == ALG_SHA1_VALUE)
{
return X509PushAlgorithmIdentifierSequence(ctx, OID_RSAPSS);
}
else
{
// Going to build something that looks like:
// SEQUENCE (2 elem)
// OBJECT IDENTIFIER 1.2.840.113549.1.1.10 rsaPSS (PKCS #1)
// SEQUENCE (3 elem)
// [0] (1 elem)
// SEQUENCE (2 elem)
// OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256
// NULL
// [1] (1 elem)
// SEQUENCE (2 elem)
// OBJECT IDENTIFIER 1.2.840.113549.1.1.8 pkcs1-MGF
// SEQUENCE (2 elem)
// OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256
// NULL
// [2] (1 elem) salt length
// INTEGER 32
// The indentation is just to keep track of where we are in the
// structure
ASN1StartMarshalContext(ctx); // SEQUENCE (2 elements)
{
ASN1StartMarshalContext(ctx); // SEQUENCE (3 elements)
{
// [2] (1 elem) salt length
// INTEGER 32
ASN1StartMarshalContext(ctx);
{
INT16 saltSize =
CryptRsaPssSaltSize((INT16)hashDef->digestSize,
(INT16)signKey->publicArea.unique.rsa.t.size);
ASN1PushUINT(ctx, saltSize);
}
ASN1EndEncapsulation(ctx, ASN1_APPLICAIION_SPECIFIC + 2);
// Add the mask generation algorithm
// [1] (1 elem)
// SEQUENCE (2 elem) 1st
// OBJECT IDENTIFIER 1.2.840.113549.1.1.8 pkcs1-MGF
// SEQUENCE (2 elem) 2nd
// OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256
// NULL
ASN1StartMarshalContext(ctx); // mask context [1] (1 elem)
{
ASN1StartMarshalContext(ctx); // SEQUENCE (2 elem) 1st
// Handle the 2nd Sequence (sequence (object, null))
{
// This adds a NULL, then an OID and a SEQUENCE
// wrapper.
X509PushAlgorithmIdentifierSequence(ctx,
hashDef->OID);
// add the pkcs1-MGF OID
ASN1PushOID(ctx, OID_MGF1);
}
// End outer sequence
ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE);
}
// End the [1]
ASN1EndEncapsulation(ctx, ASN1_APPLICAIION_SPECIFIC + 1);
// Add the hash algorithm
// [0] (1 elem)
// SEQUENCE (2 elem) (done by
// X509PushAlgorithmIdentifierSequence)
// OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256 (NIST)
// NULL
ASN1StartMarshalContext(ctx); // [0] (1 elem)
{
X509PushAlgorithmIdentifierSequence(ctx, hashDef->OID);
}
ASN1EndEncapsulation(ctx, (ASN1_APPLICAIION_SPECIFIC + 0));
}
// SEQUENCE (3 elements) end
ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE);
// RSA PSS OID
// OBJECT IDENTIFIER 1.2.840.113549.1.1.10 rsaPSS (PKCS #1)
ASN1PushOID(ctx, OID_RSAPSS);
}
// End Sequence (2 elements)
return ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE);
}
default:
break;
}
return 0;
}
/* 10.2.25.2.2 X509AddPublicRSA() */

View File

@ -3,7 +3,7 @@
/* X509 Support */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* $Id: X509_spt.c 1490 2019-07-26 21:13:22Z kgoldman $ */
/* $Id: X509_spt.c 1511 2019-10-07 20:40:15Z kgoldman $ */
/* */
/* Licenses and Notices */
/* */
@ -199,33 +199,45 @@ X509ProcessExtensions(
return TPM_RCS_VALUE;
// Get the keyUsage extension. This one is required
if(X509FindExtensionByOID(&ctx, &extensionCtx, OID_KEY_USAGE_EXTENSTION) &&
X509GetExtensionBits(&extensionCtx, &value))
{
x509KeyUsageUnion keyUsage;
TPMA_OBJECT attributes = object->publicArea.objectAttributes;
//
keyUsage.integer = value;
// For KeyUsage:
// the 'sign' attribute is SET if Key Usage includes signing
if(
((keyUsageSign.integer & keyUsage.integer) != 0
&& !IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign))
if(X509FindExtensionByOID(&ctx, &extensionCtx, OID_KEY_USAGE_EXTENSION) &&
X509GetExtensionBits(&extensionCtx, &value))
{
x509KeyUsageUnion keyUsage;
TPMA_OBJECT attributes = object->publicArea.objectAttributes;
keyUsage.integer = value;
#if 0 /* for debugging */
int badSign;
int badDecrypt;
int badFixedTpm;
int badRestricted;
// and the 'decrypt' attribute is Set if Key Usage includes decryption uses
|| ((keyUsageDecrypt.integer & keyUsage.integer) != 0
&& !IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt))
// Check that 'fixedTPM' is SET if Key Usage is non-repudiation
|| (IS_ATTRIBUTE(keyUsage.x509, TPMA_X509_KEY_USAGE, nonrepudiation)
&& !IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM))
badSign = ( (keyUsageSign.integer & keyUsage.integer) != 0
&& !IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign));
badDecrypt = ( (keyUsageDecrypt.integer & keyUsage.integer) != 0
&& !IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt));
badFixedTpm = ( IS_ATTRIBUTE(keyUsage.x509, TPMA_X509_KEY_USAGE, nonrepudiation)
&& !IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM));
badRestricted = ( IS_ATTRIBUTE(keyUsage.x509, TPMA_X509_KEY_USAGE, keyAgreement)
&& !IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted));
|| (IS_ATTRIBUTE(keyUsage.x509, TPMA_X509_KEY_USAGE, keyAgreement)
&& !IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted))
)
return TPM_RCS_ATTRIBUTES;
}
#endif
// For KeyUsage:
// the 'sign' attribute is SET if Key Usage includes signing
if( ( (keyUsageSign.integer & keyUsage.integer) != 0
&& !IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign))
// OR the 'decrypt' attribute is Set if Key Usage includes decryption uses
|| ( (keyUsageDecrypt.integer & keyUsage.integer) != 0
&& !IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt))
// OR that 'fixedTPM' is SET if Key Usage is non-repudiation
|| ( IS_ATTRIBUTE(keyUsage.x509, TPMA_X509_KEY_USAGE, nonrepudiation)
&& !IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM))
// OR that 'restricted' is SET if Key Usage is key agreement
|| ( IS_ATTRIBUTE(keyUsage.x509, TPMA_X509_KEY_USAGE, keyAgreement)
&& !IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted))
)
return TPM_RCS_ATTRIBUTES;
}
else
// The KeyUsage extension is required
return TPM_RCS_VALUE;
@ -308,6 +320,10 @@ X509PushAlgorithmIdentifierSequence(
const BYTE *OID
)
{
// An algorithm ID sequence is:
// SEQUENCE
// OID
// NULL
ASN1StartMarshalContext(ctx); // hash algorithm
ASN1PushNull(ctx);
ASN1PushOID(ctx, OID);