⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chk_chn.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 3 页
字号:
			}

		/* 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 + -