📄 chk_chn.c
字号:
}
/* Check that the current certificate in the chain obeys the
constraints set by the overall issuer, possibly modified by other
certificates in the chain */
if( hasExcludedSubtrees && \
cryptStatusError( checkNameConstraints( subjectCertInfoPtr,
nameConstraintPtr, TRUE,
&subjectCertInfoPtr->errorLocus,
&subjectCertInfoPtr->errorType ) ) )
status = CRYPT_ERROR_INVALID;
if( cryptStatusOK( status ) && hasPermittedSubtrees && \
cryptStatusError( checkNameConstraints( subjectCertInfoPtr,
nameConstraintPtr, FALSE,
&subjectCertInfoPtr->errorLocus,
&subjectCertInfoPtr->errorType ) ) )
status = CRYPT_ERROR_INVALID;
if( cryptStatusOK( status ) && hasPolicy && \
cryptStatusError( checkPolicyConstraints( subjectCertInfoPtr,
issuerCertInfoPtr->attributes, policyType,
&subjectCertInfoPtr->errorLocus,
&subjectCertInfoPtr->errorType ) ) )
status = CRYPT_ERROR_INVALID;
if( cryptStatusOK( status ) && hasPathLength && \
cryptStatusError( checkPathConstraints( subjectCertInfoPtr,
&pathAttributeList,
&subjectCertInfoPtr->errorLocus,
&subjectCertInfoPtr->errorType ) ) )
status = CRYPT_ERROR_INVALID;
if( cryptStatusError( status ) )
{
/* Remember which certificate caused the problem */
*errorCertIndex = certIndex;
}
/* If there are length constraints, decrement them for each
certificate. At this point we run into another piece of PKIX
weirdness: If there's a path-kludge certificate present it's not
counted for path-length constraint purposes but the exception
only holds for path-length constraint purposes and not for
require/inhibit policy constraint purposes. This is an error in
the spec, sections 4.2.1.12 (policy constraints) and 4.2.1.15
(path constraints) don't permit path-kludge certificate
exceptions while section 6.1.4(h) does. On the other hand given
the confusion in the pseudocode and the fact that it diverges
from the body of the spec in other places as well we treat it as
an error in the (non-authoritative) pseudocode rather than the
(authoritative) spec.
Unfortunately there's no easy way to tell just from looking at a
certificate whether it's one of these kludge certificates or not
because it looks identical to a CA root certificate (even the
path-building code has to handle this speculatively, falling back
to alternatives if the initial attempt to construct a path fails).
However, for chain-internal kludge certificates the
chain-assembly code can determine whether it's a path-kludge by
the presence of further certificates higher up in the chain
(although it can't tell whether the chain ends in a path-kludge
or a true CA root certificate because they appear identical). In
the case where the chain-assembly code has been able to identify
the certificate as a path-kludge we can skip it for path length
constraint purposes */
if( hasPathLength && \
( !( subjectCertInfoPtr->flags & CERT_FLAG_PATHKLUDGE ) ) )
pathAttributeList.intValue--;
if( hasExplicitPolicy )
requireExplicitPolicyLevel--;
if( hasInhibitPolicyMap )
inhibitPolicyMapLevel--;
if( hasInhibitAnyPolicy )
inhibitAnyPolicyLevel--;
/* Release the certificate again unless it's the chain certificate
itself, which is returned by getCertInfo() as the last
certificate in the chain */
if( certInfoPtr != subjectCertInfoPtr )
krnlReleaseObject( subjectCertInfoPtr->objectHandle );
}
ENSURES( iterationCount < MAX_CHAINLENGTH );
return( status );
}
/* Walk down a chain checking each certificate */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int checkCertChain( INOUT CERT_INFO *certInfoPtr )
{
CRYPT_CERTIFICATE iIssuerCert;
CERT_CERT_INFO *certChainInfo = certInfoPtr->cCertCert;
CERT_INFO *issuerCertInfoPtr, *subjectCertInfoPtr;
BOOLEAN explicitPolicy = TRUE;
int certIndex, complianceLevel, iterationCount, status;
assert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );
/* Determine how much checking we need to perform */
status = krnlSendMessage( certInfoPtr->ownerHandle, IMESSAGE_GETATTRIBUTE,
&complianceLevel,
CRYPT_OPTION_CERT_COMPLIANCELEVEL );
if( cryptStatusError( status ) )
return( status );
if( complianceLevel >= CRYPT_COMPLIANCELEVEL_PKIX_FULL )
{
int value;
status = krnlSendMessage( certInfoPtr->ownerHandle,
IMESSAGE_GETATTRIBUTE, &value,
CRYPT_OPTION_CERT_REQUIREPOLICY );
if( cryptStatusOK( status ) && !value )
explicitPolicy = FALSE;
}
/* Try and find a trust anchor for the chain */
status = findTrustAnchor( certInfoPtr, &certIndex, &iIssuerCert );
if( status == OK_SPECIAL )
{
/* The leaf is implicitly trusted, there's nothing more to do */
return( CRYPT_OK );
}
if( cryptStatusError( status ) )
{
CRYPT_ATTRIBUTE_TYPE attributeType;
const int lastCertIndex = certChainInfo->chainEnd - 1;
int value;
/* Select the certificate that caused the problem, which is the
highest-level certificate in the chain */
certChainInfo->chainPos = lastCertIndex;
/* We couldn't find a trust anchor, either there's a missing link in
the chain (CRYPT_ERROR_STUART) and it was truncated before we got
to a trusted certificate or it goes to a root certificate but it
isn't trusted. Returning error information on this is a bit
complex since we've selected the certificate that caused the
problem, which means that any attempt to read error status
information will read it from this certificate rather than the
encapsulating chain object. To get around this we set the error
information for the selected certificate rather than the chain */
status = krnlSendMessage( certChainInfo->chain[ lastCertIndex ],
IMESSAGE_GETATTRIBUTE, &value,
CRYPT_CERTINFO_SELFSIGNED );
if( cryptStatusOK( status ) && value > 0 )
{
/* We got a root certificate but it's not trusted */
attributeType = CRYPT_CERTINFO_TRUSTED_IMPLICIT;
}
else
{
/* There's a missing link in the chain and it stops at this
certificate */
attributeType = CRYPT_CERTINFO_CERTIFICATE;
}
status = getCertInfo( certInfoPtr, &subjectCertInfoPtr,
lastCertIndex );
if( cryptStatusOK( status ) )
{
setErrorInfo( subjectCertInfoPtr, attributeType,
CRYPT_ERRTYPE_ATTR_ABSENT );
krnlReleaseObject( subjectCertInfoPtr->objectHandle );
}
return( CRYPT_ERROR_INVALID );
}
status = krnlAcquireObject( iIssuerCert, OBJECT_TYPE_CERTIFICATE,
( void ** ) &issuerCertInfoPtr,
CRYPT_ERROR_SIGNALLED );
if( cryptStatusError( status ) )
return( status );
/* Check the trust anchor. Since this is the start of the chain there
aren't any constraints placed on it by higher-level certificates so
all that we need to check at this point is the certificate itself and
its signature if it's self-signed */
if( certIndex >= certChainInfo->chainEnd )
{
CRYPT_ATTRIBUTE_TYPE dummyLocus;
CRYPT_ERRTYPE_TYPE dummyType;
/* The issuer certificate info is coming from the certificate trust
database, don't modify its state when we check it */
status = checkCertDetails( issuerCertInfoPtr, issuerCertInfoPtr,
( issuerCertInfoPtr->iPubkeyContext != CRYPT_ERROR ) ? \
issuerCertInfoPtr->iPubkeyContext : CRYPT_UNUSED,
NULL, TRUE, TRUE, &dummyLocus, &dummyType );
}
else
{
/* The issuer certificate is contained in the chain, update its state
when we check it */
status = checkCertDetails( issuerCertInfoPtr, issuerCertInfoPtr,
( issuerCertInfoPtr->iPubkeyContext != CRYPT_ERROR ) ? \
issuerCertInfoPtr->iPubkeyContext : CRYPT_UNUSED,
NULL, TRUE, TRUE, &issuerCertInfoPtr->errorLocus,
&issuerCertInfoPtr->errorType );
}
if( cryptStatusError( status ) )
{
krnlReleaseObject( issuerCertInfoPtr->objectHandle );
if( certIndex < certChainInfo->chainEnd )
certChainInfo->chainPos = certIndex;
return( status );
}
/* We've checked the trust anchor, move on to the next certificate */
certIndex--;
/* Walk down the chain from the trusted certificate checking each link
in turn */
for( iterationCount = 0;
cryptStatusOK( status ) && certIndex >= -1 && \
( status = getCertInfo( certInfoPtr, &subjectCertInfoPtr,
certIndex ) ) == CRYPT_OK && \
iterationCount < MAX_CHAINLENGTH;
certIndex--, iterationCount++ )
{
/* Check the certificate details and signature */
status = checkCertDetails( subjectCertInfoPtr, issuerCertInfoPtr,
( issuerCertInfoPtr->iPubkeyContext != CRYPT_ERROR ) ? \
issuerCertInfoPtr->iPubkeyContext : CRYPT_UNUSED,
NULL, FALSE, TRUE, &subjectCertInfoPtr->errorLocus,
&subjectCertInfoPtr->errorType );
if( status == CRYPT_ARGERROR_NUM1 )
{
/* If there's a problem with the issuer's public key we'll get
a parameter error, the most appropriate standard error code
that we can translate this to is a standard signature error */
status = CRYPT_ERROR_SIGNATURE;
}
/* Check any constraints that the issuer certificate may place on
the rest of the chain */
if( cryptStatusOK( status ) && \
complianceLevel >= CRYPT_COMPLIANCELEVEL_PKIX_FULL )
{
int errorCertIndex = DUMMY_INIT; /* Needed for gcc */
status = checkConstraints( certInfoPtr, certIndex,
issuerCertInfoPtr, &errorCertIndex,
explicitPolicy );
if( cryptStatusError( status ) )
certIndex = errorCertIndex;
}
/* Move on to the next certificate */
krnlReleaseObject( issuerCertInfoPtr->objectHandle );
issuerCertInfoPtr = subjectCertInfoPtr;
}
ENSURES( iterationCount < MAX_CHAINLENGTH );
/* If we stopped before we processed all the certificates in the chain,
select the one that caused the problem. We also have to unlock the
last certificate that we got to if it wasn't the leaf, which
corresponds to the chain itself */
if( cryptStatusError( status ) )
{
certChainInfo->chainPos = certIndex + 1;
if( issuerCertInfoPtr != certInfoPtr )
krnlReleaseObject( issuerCertInfoPtr->objectHandle );
}
return( status );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -