📄 chk_chn.c
字号:
else
policyType = inhibitAnyPolicy ? \
POLICY_NONE_SPECIFIC : POLICY_NONE;
}
/* Check that the current cert in the chain obeys the constraints
set by the overall issuer, possibly modified by other certs 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,
CRYPT_COMPLIANCELEVEL_PKIX_FULL,
&subjectCertInfoPtr->errorLocus,
&subjectCertInfoPtr->errorType ) ) )
status = CRYPT_ERROR_INVALID;
if( cryptStatusError( status ) )
/* Remember which cert caused the problem */
*errorCertIndex = certIndex;
/* If there are length constraints, decrement them for each cert.
At this point we run into another piece of PKIX weirdness: If
there's a path-kludge cert present, it's not counted for path-
length constraint purposes, but the exception only holds for path-
length constraint purposes, 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 cert 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
cert whether it's one of these kludge certs or not, because it
looks identical to a CA root cert (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 certs the chain-assembly code
can determine whether it's a path-kludge by the presence of
further certs higher up in the chain (although it can't tell
whether the chain ends in a path-kludge or a true CA root cert
because they appear identical). In the case where the chain-
assembly code has been able to identify the cert 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 cert again unless it's the chain cert itself, which
is returned by getCertInfo() as the last cert in the chain */
if( certInfoPtr != subjectCertInfoPtr )
krnlReleaseObject( subjectCertInfoPtr->objectHandle );
}
return( status );
}
/* Walk down a chain checking each certificate */
int checkCertChain( CERT_INFO *certInfoPtr )
{
CRYPT_CERTIFICATE iIssuerCert;
CERT_CERT_INFO *certChainInfo = certInfoPtr->cCertCert;
CERT_INFO *issuerCertInfoPtr, *subjectCertInfoPtr;
BOOLEAN explicitPolicy = TRUE;
int certIndex, complianceLevel, 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 ) )
{
int value;
/* 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 cert, or it goes to a root cert but it isn't
trusted */
certChainInfo->chainPos = certChainInfo->chainEnd - 1;
status = krnlSendMessage( certChainInfo->chain[ certChainInfo->chainEnd - 1 ],
IMESSAGE_GETATTRIBUTE, &value,
CRYPT_CERTINFO_SELFSIGNED );
if( cryptStatusOK( status ) && value )
{
/* We got a root cert but it's not trusted */
setErrorInfo( certInfoPtr, CRYPT_CERTINFO_TRUSTED_IMPLICIT,
CRYPT_ERRTYPE_ATTR_ABSENT );
}
else
{
/* There's a missing link in the chain and it stops at this
cert */
setErrorInfo( certInfoPtr, CRYPT_CERTINFO_CERTIFICATE,
CRYPT_ERRTYPE_ATTR_ABSENT );
}
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 certs, so all
that we need to check at this point is the cert itself and its
signature if it's self-signed */
if( certIndex >= certChainInfo->chainEnd )
{
CRYPT_ATTRIBUTE_TYPE dummyLocus;
CRYPT_ERRTYPE_TYPE dummyType;
/* The issuer cert info is coming from the cert trust database,
don't modify its state when we check it */
status = checkCert( issuerCertInfoPtr, issuerCertInfoPtr,
TRUE, &dummyLocus, &dummyType );
}
else
/* The issuer cert is contained in the chain, update its state when
we check it */
status = checkCert( issuerCertInfoPtr, issuerCertInfoPtr,
TRUE, &issuerCertInfoPtr->errorLocus,
&issuerCertInfoPtr->errorType );
if( cryptStatusOK( status ) && \
( issuerCertInfoPtr->flags & CERT_FLAG_SELFSIGNED ) && \
issuerCertInfoPtr->iPubkeyContext != CRYPT_ERROR )
status = checkX509signature( issuerCertInfoPtr->certificate,
issuerCertInfoPtr->certificateSize,
NULL, NULL,
issuerCertInfoPtr->iPubkeyContext,
CRYPT_UNUSED );
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 cert */
certIndex--;
/* Walk down the chain from the trusted cert checking each link in turn */
while( cryptStatusOK( status ) && certIndex >= -1 && \
( status = getCertInfo( certInfoPtr, &subjectCertInfoPtr,
certIndex ) ) == CRYPT_OK )
{
/* Check the chaining from issuer to subject (as well as various
other required bits and pieces such as whether the issuer is
really a CA) */
status = checkCert( subjectCertInfoPtr, issuerCertInfoPtr,
TRUE, &subjectCertInfoPtr->errorLocus,
&subjectCertInfoPtr->errorType );
/* Check the signature on the subject cert unless it's a data-only
cert for which there isn't a context present. This is OK since
the only time that we can have a data-only chain is when we're
reading from an (implicitly trusted) private key store */
if( cryptStatusOK( status ) && \
issuerCertInfoPtr->iPubkeyContext != CRYPT_ERROR )
status = checkX509signature( subjectCertInfoPtr->certificate,
subjectCertInfoPtr->certificateSize,
NULL, NULL,
issuerCertInfoPtr->iPubkeyContext,
CRYPT_UNUSED );
/* Check any constraints that the issuer cert may place on the rest
of the chain */
if( cryptStatusOK( status ) && \
complianceLevel >= CRYPT_COMPLIANCELEVEL_PKIX_FULL )
{
int errorCertIndex;
status = checkConstraints( certInfoPtr, certIndex,
issuerCertInfoPtr, &errorCertIndex,
explicitPolicy );
if( cryptStatusError( status ) )
certIndex = errorCertIndex;
}
/* Move on to the next cert */
krnlReleaseObject( issuerCertInfoPtr->objectHandle );
issuerCertInfoPtr = subjectCertInfoPtr;
certIndex--;
}
/* If we stopped before we processed all the certs in the chain, select
the one that caused the problem. We also have to unlock the last
cert 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 + -