📄 chk_cert.c
字号:
}
/* If there's no requirement for a policy and there's none set, we're
done */
if( policyType == POLICY_NONE && constrainedAttributeListPtr == NULL )
return( CRYPT_OK );
/* Check the subject policy */
if( !checkPolicyType( constrainedAttributeListPtr, &subjectHasPolicy,
&subjectHasAnyPolicy,
( policyType == POLICY_NONE_SPECIFIC || \
policyType == POLICY_SUBJECT_SPECIFIC || \
policyType == POLICY_BOTH_SPECIFIC ) ? \
TRUE : FALSE ) )
{
setErrorValues( CRYPT_CERTINFO_CERTPOLICYID,
CRYPT_ERRTYPE_CONSTRAINT );
return( CRYPT_ERROR_INVALID );
}
/* If there's no requirement for an issuer policy and there's none set
by the issuer, we're done */
if( ( ( policyType == POLICY_SUBJECT ) || \
( policyType == POLICY_SUBJECT_SPECIFIC ) ) && \
attributeListPtr == NULL )
return( CRYPT_OK );
/* Check the subject policy */
if( !checkPolicyType( attributeListPtr , &issuerHasPolicy,
&issuerHasAnyPolicy,
( policyType == POLICY_BOTH_SPECIFIC ) ? \
TRUE : FALSE ) )
{
setErrorValues( CRYPT_CERTINFO_CERTPOLICYID,
CRYPT_ERRTYPE_CONSTRAINT );
return( CRYPT_ERROR_INVALID );
}
/* Both the issuer and subject have some sort of policy, if either are
anyPolicy wildcards (introduced in RFC 3280 section 4.2.1.5) then
it's considered a match */
if( subjectHasAnyPolicy || issuerHasAnyPolicy )
return( CRYPT_OK );
/* An explicit policy is required, make sure that at least one of the
issuer policies matches at least one of the subject policies. Note
that there's no exception for PKIX path-kludge certificates, this is
an error in the RFC for which the text at this point is unchanged
from RFC 2459. In fact this contradicts the path-processing
pesudocode but since that in turn contradicts the main text in a
number of places we take the main text as definitive, not the buggy
pseudocode */
for( attributeCursor = ( ATTRIBUTE_LIST * ) attributeListPtr, \
iterationCount = 0;
attributeCursor != NULL && \
iterationCount < FAILSAFE_ITERATIONS_MAX;
attributeCursor = findNextFieldInstance( attributeCursor ), \
iterationCount++ )
{
ATTRIBUTE_LIST *constrainedAttributeCursor;
int innerIterationCount;
ENSURES( attributeCursor->fieldID == CRYPT_CERTINFO_CERTPOLICYID );
for( constrainedAttributeCursor = \
( ATTRIBUTE_LIST * ) constrainedAttributeListPtr, \
innerIterationCount = 0;
constrainedAttributeCursor != NULL && \
innerIterationCount < FAILSAFE_ITERATIONS_MAX;
constrainedAttributeCursor = \
findNextFieldInstance( constrainedAttributeCursor ), \
innerIterationCount++ )
{
assert( constrainedAttributeCursor->fieldID == \
CRYPT_CERTINFO_CERTPOLICYID );
if( attributeCursor->valueLength == \
constrainedAttributeCursor->valueLength && \
!memcmp( attributeCursor->value,
constrainedAttributeCursor->value,
attributeCursor->valueLength ) )
return( CRYPT_OK );
}
ENSURES( innerIterationCount < FAILSAFE_ITERATIONS_MAX );
}
ENSURES( iterationCount < FAILSAFE_ITERATIONS_MAX );
/* We couldn't find a matching policy, report an error */
setErrorValues( CRYPT_CERTINFO_CERTPOLICYID, CRYPT_ERRTYPE_CONSTRAINT );
return( CRYPT_ERROR_INVALID );
}
/* Check path constraints placed by an issuer, checked if complianceLevel
>= CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \
int checkPathConstraints( const CERT_INFO *subjectCertInfoPtr,
const ATTRIBUTE_LIST *issuerAttributes,
OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
CRYPT_ATTRIBUTE_TYPE *errorLocus,
OUT_ENUM_OPT( CRYPT_ERRTYPE ) \
CRYPT_ERRTYPE_TYPE *errorType )
{
ATTRIBUTE_LIST *attributeListPtr;
assert( isReadPtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );
assert( isReadPtr( issuerAttributes, sizeof( ATTRIBUTE_LIST ) ) );
assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );
/* If this is a PKIX path-kludge certificate then the path length
constraints don't apply to it (PKIX section 4.2.1.10). This is
required in order to allow extra certificates to be kludged into the
path without violating the name constraint */
if( isPathKludge( subjectCertInfoPtr ) )
return( CRYPT_OK );
/* If the path length constraint hasn't been triggered yet we're OK */
if( issuerAttributes->intValue > 0 )
return( CRYPT_OK );
/* If the certificate is self-signed (i.e. the certificate is applying
the constraint to itself) then a path length constraint of zero is
valid. Checking only the subject certificate info is safe because
the calling code has guaranteed that if the certificate is
self-signed then the issuer attributes are the attributes from the
subject certificate */
if( subjectCertInfoPtr->flags & CERT_FLAG_SELFSIGNED )
return( CRYPT_OK );
/* The path length constraint is in effect, the next certificate down
the chain must be an end-entity certificate */
attributeListPtr = findAttributeField( subjectCertInfoPtr->attributes,
CRYPT_CERTINFO_CA,
CRYPT_ATTRIBUTE_NONE );
if( attributeListPtr != NULL && attributeListPtr->intValue > 0 )
{
setErrorValues( CRYPT_CERTINFO_PATHLENCONSTRAINT,
CRYPT_ERRTYPE_ISSUERCONSTRAINT );
return( CRYPT_ERROR_INVALID );
}
return( CRYPT_OK );
}
/****************************************************************************
* *
* Check a Certificate Object *
* *
****************************************************************************/
/* Check the validity of a CRL based on an issuer certificate */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 5 ) ) \
static int checkCRL( const CERT_INFO *crlInfoPtr,
IN_OPT const CERT_INFO *issuerCertInfoPtr,
IN_RANGE( CRYPT_COMPLIANCELEVEL_OBLIVIOUS, \
CRYPT_COMPLIANCELEVEL_LAST - 1 ) \
const int complianceLevel,
OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
CRYPT_ATTRIBUTE_TYPE *errorLocus,
OUT_ENUM_OPT( CRYPT_ERRTYPE ) \
CRYPT_ERRTYPE_TYPE *errorType )
{
ATTRIBUTE_LIST *attributeListPtr;
assert( isReadPtr( crlInfoPtr, sizeof( CERT_INFO ) ) );
assert( issuerCertInfoPtr == NULL || \
isReadPtr( issuerCertInfoPtr, sizeof( CERT_INFO ) ) );
assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );
REQUIRES( complianceLevel >= CRYPT_COMPLIANCELEVEL_OBLIVIOUS && \
complianceLevel < CRYPT_COMPLIANCELEVEL_LAST );
/* If it's a delta CRL make sure that the CRL numbers make sense (that
is, that the delta CRL was issued after the full CRL) */
attributeListPtr = findAttributeField( crlInfoPtr->attributes,
CRYPT_CERTINFO_DELTACRLINDICATOR,
CRYPT_ATTRIBUTE_NONE );
if( attributeListPtr != NULL )
{
const int deltaCRLindicator = ( int ) attributeListPtr->intValue;
attributeListPtr = findAttributeField( crlInfoPtr->attributes,
CRYPT_CERTINFO_CRLNUMBER,
CRYPT_ATTRIBUTE_NONE );
if( attributeListPtr != NULL && \
attributeListPtr->intValue >= deltaCRLindicator )
{
setErrorValues( CRYPT_CERTINFO_DELTACRLINDICATOR,
CRYPT_ERRTYPE_CONSTRAINT );
return( CRYPT_ERROR_INVALID );
}
}
/* If it's a standalone CRL entry used purely as a container for
revocation data don't try and perform any issuer-based checking */
if( issuerCertInfoPtr == NULL )
return( CRYPT_OK );
/* Make sure that the issuer can sign CRLs and the issuer certificate
in general is in order */
return( checkKeyUsage( issuerCertInfoPtr,
CHECKKEY_FLAG_CA | CHECKKEY_FLAG_GENCHECK,
CRYPT_KEYUSAGE_CRLSIGN, complianceLevel,
errorLocus, errorType ) );
}
/* Check the validity of a subject certificate based on an issuer
certificate with the level of checking performed depending on the
complianceLevel setting. If the shortCircuitCheck flag is set (used for
certificate issuer : subject pairs that may already have been checked)
we skip the constant-result checks if the combination has already been
checked at this compliance level */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 5 ) ) \
int checkCert( INOUT CERT_INFO *subjectCertInfoPtr,
IN_OPT const CERT_INFO *issuerCertInfoPtr,
const BOOLEAN shortCircuitCheck,
OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
CRYPT_ATTRIBUTE_TYPE *errorLocus,
OUT_ENUM_OPT( CRYPT_ERRTYPE ) \
CRYPT_ERRTYPE_TYPE *errorType )
{
const ATTRIBUTE_LIST *subjectAttributes = subjectCertInfoPtr->attributes;
const ATTRIBUTE_LIST *issuerAttributes = \
( issuerCertInfoPtr != NULL ) ? \
issuerCertInfoPtr->attributes : NULL;
const ATTRIBUTE_LIST *attributeListPtr;
const BOOLEAN subjectSelfSigned = \
( subjectCertInfoPtr->flags & CERT_FLAG_SELFSIGNED ) ? \
TRUE : FALSE;
BOOLEAN subjectIsCA = FALSE, issuerIsCA = FALSE;
const time_t currentTime = getTime();
int complianceLevel, status;
assert( isWritePtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );
assert( issuerCertInfoPtr == NULL || \
isReadPtr( issuerCertInfoPtr, sizeof( CERT_INFO ) ) );
assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );
/* Determine how much checking we need to perform. If this is a
currently-under-construction certificate we use the maximum
compliance level to ensure that cryptlib never produces broken
certificates */
if( subjectCertInfoPtr->certificate == NULL )
complianceLevel = CRYPT_COMPLIANCELEVEL_PKIX_FULL;
else
{
status = krnlSendMessage( subjectCertInfoPtr->ownerHandle,
IMESSAGE_GETATTRIBUTE, &complianceLevel,
CRYPT_OPTION_CERT_COMPLIANCELEVEL );
if( cryptStatusError( status ) )
return( status );
}
/* If it's some form of certificate request or an OCSP object (which
means that it isn't signed by an issuer in the normal sense) then
there's nothing to check (yet) */
switch( subjectCertInfoPtr->type )
{
case CRYPT_CERTTYPE_CERTIFICATE:
case CRYPT_CERTTYPE_ATTRIBUTE_CERT:
case CRYPT_CERTTYPE_CERTCHAIN:
/* It's an issuer-signed object, there must be an issuer
certificate present */
assert( isReadPtr( issuerCertInfoPtr, sizeof( CERT_INFO ) ) );
if( subjectCertInfoPtr->flags & CERT_FLAG_CERTCOLLECTION )
{
/* Certificate collections are pure container objects for
which the base certificate object doesn't correspond to
an actual certificate */
retIntError();
}
break;
case CRYPT_CERTTYPE_CERTREQUEST:
case CRYPT_CERTTYPE_REQUEST_CERT:
case CRYPT_CERTTYPE_REQUEST_REVOCATION:
/* These are merely templates submitted to a CA, there's nothing
to check. For example the template could contain constraints
that only make sense once the issuer certificate is
incorporated into a chain or a future-dated validity time or
a CA keyUsage for which the CA provides the appropriate
matching basicConstraints value(s) so we can't really perform
much checking here */
return( CRYPT_OK );
case CRYPT_CERTTYPE_CRL:
/* There must be an issuer certificate present unless we're
checking a standalone CRL entry that acts purely as a
container for revocation data */
assert( issuerCertInfoPtr == NULL || \
isReadPtr( issuerCertInfoPtr, sizeof( CERT_INFO ) ) );
/* CRL checking is handled specially */
return( checkCRL( subjectCertInfoPtr, issuerCertInfoPtr,
complianceLevel, errorLocus, errorType ) );
case CRYPT_CERTTYPE_CMS_ATTRIBUTES:
case CRYPT_CERTTYPE_PKIUSER:
retIntError();
case CRYPT_CERTTYPE_RTCS_REQUEST:
case CRYPT_CERTTYPE_RTCS_RESPONSE:
case CRYPT_CERTTYPE_OCSP_REQUEST:
case CRYPT_CERTTYPE_OCSP_RESPONSE:
/* These aren't normal certificate types, there's nothing to
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -