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

📄 certchn.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 4 页
字号:
	   length */
	attributeListPtr = findAttributeField( issuerCertInfoPtr->attributes,
					CRYPT_CERTINFO_PATHLENCONSTRAINT, CRYPT_ATTRIBUTE_NONE );
	if( attributeListPtr != NULL && \
		!( issuerCertInfoPtr->flags & CERT_FLAG_SELFSIGNED ) && \
		attributeListPtr->value <= certIndex )
		{
		setErrorInfo( certInfoPtr, CRYPT_CERTINFO_PATHLENCONSTRAINT,
					  CRYPT_ERRTYPE_ISSUERCONSTRAINT );
		return( CRYPT_ERROR_INVALID );
		}

	/* If there's a name or policy constraint present, check that it's
	   satisfied for all certs below this one.  We don't have to perform this
	   check if the constraint appears in the 0-th cert since the check for
	   (leaf, [0]) is performed by checkCert() */
	if( certIndex >= 0 && \
		!( issuerCertInfoPtr->flags & CERT_FLAG_SELFSIGNED ) && \
		( ( nameAttributeListPtr = findAttribute( issuerCertInfoPtr->attributes, \
							CRYPT_CERTINFO_NAMECONSTRAINTS ) ) != NULL ) || \
		( ( policyAttributeListPtr = findAttribute( issuerCertInfoPtr->attributes, \
							CRYPT_CERTINFO_POLICYCONSTRAINTS ) ) != NULL ) )
		{
		const BOOLEAN hasExcludedSubtrees = findAttribute( nameAttributeListPtr, \
								CRYPT_CERTINFO_EXCLUDEDSUBTREES ) != NULL;
		const BOOLEAN hasPermittedSubtrees = findAttribute( nameAttributeListPtr, \
								CRYPT_CERTINFO_PERMITTEDSUBTREES ) != NULL;
		const BOOLEAN hasPolicy = findAttribute( policyAttributeListPtr, \
								CRYPT_CERTINFO_CERTPOLICYID ) != NULL;
		BOOLEAN requireExplicitPolicyPresent = FALSE;
		int requireExplicitPolicyLevel = CRYPT_ERROR;
		CERT_INFO *subjectCertInfoPtr;

		/* Check whether there's a requireExplicitPolicy attribute.  The
		   handling of this is very ambiguous since other parts of the path
		   validation requirements stipulate that policies should be checked
		   anyway (even if requireExplicitPolicy isn't set), and no-one knows
		   what to do if multiple requireExplicitPolicy settings are present
		   in a chain (for example due to reparenting).  This implementation
		   handles it by returning an error if a second requireExplicitPolicy
		   attribute which contradicts the first one is encountered */
		attributeListPtr = findAttribute( policyAttributeListPtr,
									CRYPT_CERTINFO_REQUIREEXPLICITPOLICY );
		if( attributeListPtr != NULL )
			{
			requireExplicitPolicyLevel = ( int ) attributeListPtr->value;
			requireExplicitPolicyPresent = TRUE;
			}

		/* Walk down the chain checking each cert against the issuer */
		do
			{
			/* Get the next cert in the chain */
			certIndex--;
			status = getNextCert( certInfoPtr, &subjectCertInfoPtr, 
								  certIndex );
			if( status == OK_SPECIAL )
				/* We've reached the end of the chain, exit */
				break;

			/* If there's a second policy constraint present further down the
			   chain, make sure it doesn't contradict the current one */
			attributeListPtr = findAttribute( certInfoPtr->attributes,
									CRYPT_CERTINFO_REQUIREEXPLICITPOLICY );
			if( attributeListPtr != NULL && requireExplicitPolicyPresent && \
				attributeListPtr->value != requireExplicitPolicyLevel )
				{
				setErrorInfo( certInfoPtr, CRYPT_CERTINFO_REQUIREEXPLICITPOLICY,
							  CRYPT_ERRTYPE_ISSUERCONSTRAINT );
				status = CRYPT_ERROR_INVALID;
				break;
				}

			/* If there's a requireExplicitPolicy skip count, decrement it
			   for each cert */
			if( requireExplicitPolicyLevel != CRYPT_ERROR )
				requireExplicitPolicyLevel--;

			/* Check that the current cert obeys the constraints set by the
			   issuer */
			if( hasExcludedSubtrees && \
				cryptStatusError( checkNameConstraints( subjectCertInfoPtr,
											nameAttributeListPtr, TRUE ) ) )
				status = CRYPT_ERROR_INVALID;
			if( hasPermittedSubtrees && \
				cryptStatusError( checkNameConstraints( subjectCertInfoPtr,
											nameAttributeListPtr, FALSE ) ) )
				status = CRYPT_ERROR_INVALID;
			if( hasPolicy && requireExplicitPolicyLevel == CRYPT_ERROR && \
				cryptStatusError( checkPolicyConstraints( subjectCertInfoPtr,
											policyAttributeListPtr ) ) )
				status = CRYPT_ERROR_INVALID;
			unlockResource( subjectCertInfoPtr );
			}
		while( cryptStatusOK( status ) );
		}
	if( status == CRYPT_OK || status == OK_SPECIAL )
		return( CRYPT_OK );

	/* Remember which cert in the chain caused the problem */
	*subjectCertIndex = certIndex;
	return( status );
	}

/* Walk down a chain checking each certificate */

int checkCertChain( CERT_INFO *certInfoPtr )
	{
	CRYPT_CONTEXT iCryptContext;
	CERT_INFO *issuerCertInfoPtr = certInfoPtr, *subjectCertInfoPtr;
	BOOLEAN isTrusted = TRUE;
	int certIndex = certInfoPtr->certChainEnd - 1, i, status = CRYPT_OK;

	assert( isWritePtr( certInfoPtr, CERT_INFO ) );

	/* If the leaf cert is implicitly trusted, there's nothing to do */
	if( checkCertTrusted( certInfoPtr ) )
		return( CRYPT_OK );

	/* If the leaf cert's issuer is implicitly trusted, we only need to check
	   the signature on the leaf cert */
	iCryptContext = findTrustedCert( certInfoPtr->issuerDNptr,
									 certInfoPtr->issuerDNsize );
	if( !cryptStatusError( iCryptContext ) )
		certIndex = CRYPT_ERROR;	/* No need to check the cert chain */
	else
		{
		/* Walk up the chain from the leaf cert's issuer to the root checking
		   for an implicitly trusted cert */
		for( i = 0; i <= certIndex; i++ )
			{
			getCheckInternalResource( certInfoPtr->certChain[ i ],
									  issuerCertInfoPtr, OBJECT_TYPE_CERTIFICATE );
			iCryptContext = findTrustedCert( issuerCertInfoPtr->issuerDNptr,
											 issuerCertInfoPtr->issuerDNsize );
			if( !cryptStatusError( iCryptContext ) )
				break;
			if( i != certIndex )
				unlockResource( issuerCertInfoPtr );
			}
		certIndex = i;	/* Remember how far we got */

		/* If we didn't end up at an implicitly trusted cert, check whether
		   we should implicitly trust a self-signed root */
		if( cryptStatusError( iCryptContext ) )
			{
			int trustChainRoot;

			krnlSendMessage( certInfoPtr->ownerHandle, 
							 RESOURCE_IMESSAGE_GETATTRIBUTE, &trustChainRoot, 
							 CRYPT_OPTION_CERT_TRUSTCHAINROOT );
			if( ( issuerCertInfoPtr->flags & CERT_FLAG_SELFSIGNED ) && \
				trustChainRoot )
				/* There's a self-signed root present but it's not implicitly
				   trusted, continue without the trust flag set */
				isTrusted = FALSE;
			else
				{
				/* We didn't end up at an implicitly or explicitly trusted
				   key, 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 */
				certInfoPtr->certChainPos = certInfoPtr->certChainEnd - 1;
				if( issuerCertInfoPtr->flags & CERT_FLAG_SELFSIGNED )
					{
					/* We got a root cert but it's not trusted */
					setErrorInfo( issuerCertInfoPtr, 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 );
				unlockResource( issuerCertInfoPtr );

				return( CRYPT_ERROR_INVALID );
				}
			}
		}

	/* Walk down the chain from the trusted cert checking each link in turn */
	subjectCertInfoPtr = ( CERT_INFO * ) issuerCertInfoPtr;
	do
		{
		/* If the issuing cert for this one isn't implicitly trusted, check
		   the chaining from issuer to subject */
		if( !isTrusted )
			{
			iCryptContext = issuerCertInfoPtr->iCryptContext;
			status = checkCert( subjectCertInfoPtr, issuerCertInfoPtr );
			}
		isTrusted = FALSE;

		/* 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 we can have a data-only chain is when we're reading
		   from an (implicitly trusted) private key store */
		if( cryptStatusOK( status ) && !cryptStatusError( iCryptContext ) )
			status = checkX509signature( subjectCertInfoPtr->certificate, 
										 subjectCertInfoPtr->certificateSize,
										 NULL, NULL, iCryptContext );

		/* Check any constraints the issuer cert may place on the rest of the
		   chain */
		if( cryptStatusOK( status ) && issuerCertInfoPtr != subjectCertInfoPtr )
			status = checkConstraints( certInfoPtr, issuerCertInfoPtr,
									   &certIndex );

		/* Move on to the next cert */
		if( issuerCertInfoPtr != subjectCertInfoPtr )
			unlockResource( issuerCertInfoPtr );
		issuerCertInfoPtr = subjectCertInfoPtr;
		certIndex--;
		}
	while( cryptStatusOK( status ) && \
		   ( status = getNextCert( certInfoPtr, &subjectCertInfoPtr,
								   certIndex ) ) == CRYPT_OK );
	if( status != OK_SPECIAL )
		{
		/* We stopped before we processed all the certs in the chain, if
		   the last cert we processed wasn't the leaf, unlock it and
		   select the one which caused the problem */
		if( issuerCertInfoPtr != certInfoPtr )
			unlockResource( issuerCertInfoPtr );
		certInfoPtr->certChainPos = certIndex + 1;
		}
	else
		/* We successfully reached the end of the chain */
		status = CRYPT_OK;

	return( status );
	}

/****************************************************************************
*																			*
*						Read Certificate-bagging Records					*
*																			*
****************************************************************************/

/* Read a collection of certs in a cert chain into a cert object */

static int buildCertChain( CRYPT_CERTIFICATE *iLeafCert, 
						   CRYPT_CERTIFICATE *iCertChain, int certChainEnd,
						   const CRYPT_KEYID_TYPE keyIDtype,
						   const void *keyID, const int keyIDlength )
	{
	CERTCHAIN_INFO certChainInfo[ MAX_CHAINLENGTH ];
	CERT_INFO *certChainPtr;
	CHAINING_INFO chainingInfo;
	int leafNodePos, selfSigned, status;

	assert( certChainEnd > 0 && certChainEnd < MAX_CHAINLENGTH );
	assert( isWritePtrEx( certChainInfo, CERTCHAIN_INFO, certChainEnd ) );
	assert( isReadPtrEx( iCertChain, CRYPT_CERTIFICATE, certChainEnd ) );

	/* We've now got a collection of certs in unknown order (although in most
	   cases the first cert is the leaf).  Extract the chaining info and
	   search the chain for the leaf node */
	status = buildCertChainInfo( certChainInfo, iCertChain, certChainEnd );
	if( cryptStatusError( status ) )
		{
		freeCertChain( iCertChain, certChainEnd );
		return( status );
		}
	if( keyID != NULL )
		leafNodePos = findIdentifiedLeafNode( certChainInfo, certChainEnd,
											  keyIDtype, keyID,keyIDlength );
	else
		leafNodePos = findLeafNode( certChainInfo, certChainEnd );
	if( cryptStatusError( leafNodePos ) )
		return( leafNodePos );

	/* Now that we have the leaf node, clear its entry in the chain (to make
	   sure it isn't used for further processing), order the remaining certs
	   up to the root, and discard any unneeded certs */
	*iLeafCert = iCertChain[ leafNodePos ];
	getIssuerChainingInfo( &chainingInfo, &certChainInfo[ leafNodePos ] );
	memset( &certChainInfo[ leafNodePos ], 0, sizeof( CERTCHAIN_INFO ) );
	status = sortCertChain( iCertChain, certChainInfo, certChainEnd,
							CRYPT_UNUSED, &chainingInfo );
	if( cryptStatusError( status ) )
		{
		krnlSendNotifier( *iLeafCert, RESOURCE_IMESSAGE_DECREFCOUNT );
		freeCertChain( iCertChain, certChainEnd );
		return( status );
		}
	certChainEnd = status;
	if( !certChainEnd )
		/* There's only one cert in the chain, either due to it only having 
		   one cert to begin with or due to all other certs being discarded, 
		   leave it as a standalone cert rather than turning it into a 
		   chain */
		return( CRYPT_OK );

	/* Finally, we've got the leaf cert and a chain up to the root.  Make the
	   leaf a cert-chain type and copy in the chain.  */
	getCheckInternalResource( *iLeafCert, certChainPtr,
							  OBJECT_TYPE_CERTIFICATE );
	memcpy( certChainPtr->certChain, iCertChain,
			certChainEnd * sizeof( CRYPT_CERTIFICATE ) );
	certChainPtr->certChainEnd = certChainEnd;
	certChainPtr->type = CRYPT_CERTTYPE_CERTCHAIN;

	/* If the root is self-signed, the entire chain counts as self-

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -