📄 chk_cert.c
字号:
check - we can't even check the issuer since they're not
normally issued by CAs */
return( CRYPT_OK );
default:
retIntError();
}
ENSURES( issuerCertInfoPtr != NULL );
/* There is one universal case in which a certificate is regarded as
invalid and that's when it's explicitly not trusted for the purpose.
We perform the check at this point in oblivious mode to ensure that
only the basic trusted usage gets checked */
if( issuerCertInfoPtr->cCertCert->trustedUsage != CRYPT_ERROR )
{
status = checkKeyUsage( issuerCertInfoPtr, CHECKKEY_FLAG_CA,
CRYPT_KEYUSAGE_KEYCERTSIGN,
CRYPT_COMPLIANCELEVEL_OBLIVIOUS,
errorLocus, errorType );
if( cryptStatusError( status ) )
{
/* There was a problem with the issuer certificate, convert the
error to an issuer constraint */
*errorType = CRYPT_ERRTYPE_ISSUERCONSTRAINT;
return( status );
}
}
/* If we're running in oblivious mode, we're done */
if( complianceLevel < CRYPT_COMPLIANCELEVEL_REDUCED )
return( CRYPT_OK );
/* Check that the validity period is in order. If we're checking an
existing certificate then the start time has to be valid, if we're
creating a new certificate then it doesn't have to be valid since the
certificate could be created for use in the future */
if( currentTime <= MIN_TIME_VALUE )
{
/* Time is broken, we can't reliably check for expiry times */
setErrorValues( CRYPT_CERTINFO_VALIDFROM, CRYPT_ERRTYPE_CONSTRAINT );
return( CRYPT_ERROR_INVALID );
}
if( subjectCertInfoPtr->startTime >= subjectCertInfoPtr->endTime || \
( subjectCertInfoPtr->certificate != NULL && \
currentTime < subjectCertInfoPtr->startTime ) )
{
setErrorValues( CRYPT_CERTINFO_VALIDFROM, CRYPT_ERRTYPE_CONSTRAINT );
return( CRYPT_ERROR_INVALID );
}
if( currentTime > subjectCertInfoPtr->endTime )
{
setErrorValues( CRYPT_CERTINFO_VALIDTO, CRYPT_ERRTYPE_CONSTRAINT );
return( CRYPT_ERROR_INVALID );
}
/* If it's a self-signed certificate or if we're doing a short-circuit
check of a certificate in a chain that's already been checked and
we've already checked it at the appropriate level then there's no
need to perform any further checks */
if( ( subjectSelfSigned || shortCircuitCheck ) && \
( subjectCertInfoPtr->cCertCert->maxCheckLevel >= complianceLevel ) )
return( CRYPT_OK );
/* If the certificate isn't self-signed, check name chaining */
if( !subjectSelfSigned )
{
/* Check that the subject issuer name and issuer subject name chain
properly. If the DNs are present in pre-encoded form we do a
binary comparison, which is faster than calling compareDN() */
if( subjectCertInfoPtr->certificate != NULL )
{
if( subjectCertInfoPtr->issuerDNsize != \
issuerCertInfoPtr->subjectDNsize || \
memcmp( subjectCertInfoPtr->issuerDNptr,
issuerCertInfoPtr->subjectDNptr,
subjectCertInfoPtr->issuerDNsize ) )
{
setErrorValues( CRYPT_CERTINFO_ISSUERNAME,
CRYPT_ERRTYPE_CONSTRAINT );
return( CRYPT_ERROR_INVALID );
}
}
else
{
if( !compareDN( subjectCertInfoPtr->issuerName,
issuerCertInfoPtr->subjectName, FALSE ) )
{
setErrorValues( CRYPT_CERTINFO_ISSUERNAME,
CRYPT_ERRTYPE_CONSTRAINT );
return( CRYPT_ERROR_INVALID );
}
}
}
/* Determine whether the subject or issuer are CA certificates */
attributeListPtr = findAttributeField( subjectAttributes,
CRYPT_CERTINFO_CA,
CRYPT_ATTRIBUTE_NONE );
if( attributeListPtr != NULL )
subjectIsCA = attributeListPtr->intValue;
attributeListPtr = findAttributeField( issuerAttributes,
CRYPT_CERTINFO_CA,
CRYPT_ATTRIBUTE_NONE );
if( attributeListPtr != NULL )
issuerIsCA = attributeListPtr->intValue;
/* If we're doing a reduced level of checking, we're done */
if( complianceLevel < CRYPT_COMPLIANCELEVEL_STANDARD )
{
if( subjectCertInfoPtr->cCertCert->maxCheckLevel < complianceLevel )
subjectCertInfoPtr->cCertCert->maxCheckLevel = complianceLevel;
return( CRYPT_OK );
}
/* Check that the certificate usage flags are present and consistent.
The key usage checking level ranges up to
CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL so we re-do the check even if it's
already been done at a lower level */
if( subjectCertInfoPtr->cCertCert->maxCheckLevel < CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL && \
subjectCertInfoPtr->type != CRYPT_CERTTYPE_ATTRIBUTE_CERT )
{
status = checkKeyUsage( subjectCertInfoPtr, CHECKKEY_FLAG_GENCHECK,
CRYPT_KEYUSAGE_NONE, complianceLevel,
errorLocus, errorType );
if( cryptStatusError( status ) )
return( status );
}
/* If the certificate isn't self-signed check that issuer is a CA */
if( !subjectSelfSigned )
{
status = checkKeyUsage( issuerCertInfoPtr, CHECKKEY_FLAG_CA,
CRYPT_KEYUSAGE_KEYCERTSIGN, complianceLevel,
errorLocus, errorType );
if( cryptStatusError( status ) )
{
/* There was a problem with the issuer certificate, convert the
error to an issuer constraint */
*errorType = CRYPT_ERRTYPE_ISSUERCONSTRAINT;
return( status );
}
}
/* Check all the blob (unrecognised) attributes to see if any are marked
critical. We only do this if it's an existing certificate that we've
imported rather than one that we've just created since applying this
check to the latter would make it impossible to create certificates
with unrecognised critical extensions */
if( subjectCertInfoPtr->certificate != NULL )
{
int iterationCount;
for( attributeListPtr = subjectAttributes, iterationCount = 0;
attributeListPtr != NULL && \
!isBlobAttribute( attributeListPtr ) && \
iterationCount < FAILSAFE_ITERATIONS_LARGE;
attributeListPtr = attributeListPtr->next, iterationCount++ );
ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
for( ; attributeListPtr != NULL && \
iterationCount < FAILSAFE_ITERATIONS_LARGE;
attributeListPtr = attributeListPtr->next, iterationCount++ )
{
/* If we've found an unrecognised critical extension, reject the
certificate (PKIX section 4.2). The one exception to this is
if the attribute was recognised but has been ignored at this
compliance level, in which case it's treated as a blob
attribute */
if( ( attributeListPtr->flags & ATTR_FLAG_CRITICAL ) && \
!( attributeListPtr->flags & ATTR_FLAG_IGNORED ) )
{
setErrorValues( CRYPT_ATTRIBUTE_NONE,
CRYPT_ERRTYPE_CONSTRAINT );
return( CRYPT_ERROR_INVALID );
}
}
ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
}
/* If we're not doing at least partial PKIX checking, we're done */
if( complianceLevel < CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL )
{
if( subjectCertInfoPtr->cCertCert->maxCheckLevel < complianceLevel )
subjectCertInfoPtr->cCertCert->maxCheckLevel = complianceLevel;
return( CRYPT_OK );
}
/* Constraints can only be present in CA certificates. The issuer may
not be a proper CA if it's a self-signed end entity certificate or
an X.509v1 CA certificate, which is why we also check for
!issuerIsCA */
if( subjectAttributes != NULL )
{
if( !subjectIsCA && invalidAttributesPresent( subjectAttributes, FALSE,
errorLocus, errorType ) )
return( CRYPT_ERROR_INVALID );
if( !issuerIsCA && invalidAttributesPresent( subjectAttributes, TRUE,
errorLocus, errorType ) )
return( CRYPT_ERROR_INVALID );
}
/* From this point onwards if we're doing a short-circuit check of
certificates in a chain we don't apply constraint checks. This is
because the certificate-chain code has already performed far more
complete checks of the various constraints set by all the
certificates in the chain rather than just the current certificate
issuer : subject pair */
/* If there's a path length constraint present, apply it */
attributeListPtr = findAttributeField( issuerAttributes,
CRYPT_CERTINFO_PATHLENCONSTRAINT,
CRYPT_ATTRIBUTE_NONE );
if( attributeListPtr != NULL && !shortCircuitCheck )
{
status = checkPathConstraints( subjectCertInfoPtr, attributeListPtr,
errorLocus, errorType );
if( cryptStatusError( status ) )
return( status );
}
/* In order to dig itself out of a hole caused by a circular definition,
RFC 3280 added a new extKeyUsage anyExtendedKeyUsage (rather than the
more obvious fix of removing the problematic definition).
Unfortunately this causes more problems than it solves because the exact
semantics of this new usage aren't precisely defined. To fix this
problem we invent some plausible ones ourselves: If the only eKU is
anyKU we treat the overall extKeyUsage as empty, i.e. there are no
particular restrictions on usage. If any other usage is present the
extension has become self-contradictory so we treat the anyKU as
being absent. See the comment for getExtendedKeyUsageFlags() for how
this is handled */
attributeListPtr = findAttributeField( subjectAttributes,
CRYPT_CERTINFO_EXTKEY_ANYKEYUSAGE,
CRYPT_ATTRIBUTE_NONE );
if( attributeListPtr != NULL && \
( attributeListPtr->flags & ATTR_FLAG_CRITICAL ) )
{
/* If anyKU is present the extension must be non-critical
(PKIX section 4.2.1.13) */
setErrorValues( CRYPT_CERTINFO_EXTKEY_ANYKEYUSAGE,
CRYPT_ERRTYPE_CONSTRAINT );
return( CRYPT_ERROR_INVALID );
}
/* If we're not doing full PKIX checking, we're done. In addition since
all of the remaining checks are constraint checks we can exit at this
point if we're doing a short-circuit check */
if( complianceLevel < CRYPT_COMPLIANCELEVEL_PKIX_FULL || \
shortCircuitCheck )
{
if( subjectCertInfoPtr->cCertCert->maxCheckLevel < complianceLevel )
subjectCertInfoPtr->cCertCert->maxCheckLevel = complianceLevel;
return( CRYPT_OK );
}
/* If the issuing certificate has name constraints and isn't
self-signed make sure that the subject name and altName falls within
the constrained subtrees. Since excluded subtrees override permitted
subtrees we check these first */
if( !subjectSelfSigned )
{
attributeListPtr = findAttributeField( issuerAttributes,
CRYPT_CERTINFO_EXCLUDEDSUBTREES,
CRYPT_ATTRIBUTE_NONE );
if( attributeListPtr != NULL && \
cryptStatusError( \
checkNameConstraints( subjectCertInfoPtr, attributeListPtr,
TRUE, errorLocus, errorType ) ) )
return( CRYPT_ERROR_INVALID );
attributeListPtr = findAttributeField( issuerAttributes,
CRYPT_CERTINFO_PERMITTEDSUBTREES,
CRYPT_ATTRIBUTE_NONE );
if( attributeListPtr != NULL && \
cryptStatusError( \
checkNameConstraints( subjectCertInfoPtr, attributeListPtr,
FALSE, errorLocus, errorType ) ) )
return( CRYPT_ERROR_INVALID );
}
/* If there's a policy constraint present and the skip count is set to
zero (i.e. the constraint applies to the current certificate) check
the issuer constraints against the subject */
attributeListPtr = findAttributeField( issuerAttributes,
CRYPT_CERTINFO_REQUIREEXPLICITPOLICY,
CRYPT_ATTRIBUTE_NONE );
if( attributeListPtr != NULL && attributeListPtr->intValue <= 0 )
{
POLICY_TYPE policyType = POLICY_SUBJECT;
/* Check whether use of the the wildcard anyPolicy has been
disallowed */
attributeListPtr = findAttribute( issuerCertInfoPtr->attributes, \
CRYPT_CERTINFO_INHIBITANYPOLICY,
TRUE );
if( attributeListPtr != NULL && attributeListPtr->intValue <= 0 )
policyType = POLICY_SUBJECT_SPECIFIC;
/* Apply the appropriate policy constraint */
status = checkPolicyConstraints( subjectCertInfoPtr,
issuerAttributes, policyType,
errorLocus, errorType );
if( cryptStatusError( status ) )
return( status );
}
if( subjectCertInfoPtr->cCertCert->maxCheckLevel < complianceLevel )
subjectCertInfoPtr->cCertCert->maxCheckLevel = complianceLevel;
return( CRYPT_OK );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -