mirror of
https://github.com/stefanberger/libtpms
synced 2026-08-13 04:45:12 +00:00
tpm2: Some x509 related fixes
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
This commit is contained in:
parent
baa5b3995d
commit
db1d01526a
@ -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_
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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() */
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user