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

📄 chk_chn.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 3 页
字号:
/****************************************************************************
*																			*
*					  Certificate Chain Checking Routines					*
*						Copyright Peter Gutmann 1996-2004					*
*																			*
****************************************************************************/

/* This module and chk_cert.c implement the following PKIX checks (* =
   unhandled, see the code comments.  Currently only policy mapping is
   unhandled, this is optional in PKIX and given the nature of the
   kitchenSink extension no-one really knows how to apply it anyway).  For
   simplicity we use the more compact form of RFC 2459 rather than the 18
   page long one from RFC 3280.

	General:

	(a) Verify the basic certificate information:
		(1) The certificate signature is valid.
		(2a) The certificate has not expired.
		(2b) If present, the private key usage period is satisfied.
		(3) The certificate has not been revoked.
		(4a) The subject and issuer name chains correctly.
		(4b) If present, the subjectAltName and issuerAltName chains
			 correctly.

	NameConstraints:

	(b) Verify that the subject name or critical subjectAltName is consistent
		with the constrained subtrees.

	(c) Verify that the subject name or critical subjectAltName is consistent
		with the excluded subtrees.

	Policy Constraints:

	(d) Verify that policy info.is consistent with the initial policy set:
		(1) If the require explicit policy state variable is less than or 
			equal to n, a policy identifier in the certificate must be in 
			the initial policy set.
*		(2) If the policy mapping state variable is less than or equal to n, 
			the policy identifier may not be mapped.
		(3) RFC 3280 addition: If the inhibitAnyPolicy state variable is 
			less than or equal to n, the anyPolicy policy is no longer 
			considered a match (this also extends into (e) and (g) below).

	(e) Verify that policy info.is consistent with the acceptable policy set:
		(1) If the policies extension is marked critical, the policies
			extension must lie within the acceptable policy set.
		(2) The acceptable policy set is assigned the resulting intersection
			as its new value.

	(g) Verify that the intersection of the acceptable policy set and the
		initial policy set is non-null (this is covered by chaining of e(1)).

	Other Constraints:

	(f) Step (f) is missing in the original, it should probably be: Verify 
		that the current path length is less than the path length constraint.  
		If a path length constraint is present in the certificate, update it 
		as for policy constraints in (l).  RFC 3280 addition: If the cert is 
		a PKIX path kludge cert, it doesn't count for path length constraint
		purposes.

	(h) Recognize and process any other critical extension present in the
		certificate.

	(i) Verify that the certificate is a CA certificate.

	Update of state:

	(j) If permittedSubtrees is present in the certificate, set the
		constrained subtrees state variable to the intersection of its
		previous value and the value indicated in the extension field.

	(k) If excludedSubtrees is present in the certificate, set the excluded
		subtrees state variable to the union of its previous value and the
		value indicated in the extension field.

	(l) If a policy constraints extension is included in the certificate,
		modify the explicit policy and policy mapping state variables as
		follows:

		For any of { requireExplicitPolicy, inhibitPolicyMapping, 
		inhibitAnyPolicy }, if the constraint value is present and has value 
		r, the state variable is set to the minimum of (a) its current value 
		and (b) the sum of r and n (the current certificate in the 
		sequence) 

	(m) If a key usage extension is marked critical, ensure that the 
		keyCertSign bit is set */

#include <stdlib.h>
#include <string.h>
#if defined( INC_ALL ) ||  defined( INC_CHILD )
  #include "cert.h"
#else
  #include "cert/cert.h"
#endif /* Compiler-specific includes */

/* Prototypes for functions in sign.c */

int checkX509signature( const void *signedObject, const int signedObjectLength,
						void **object, int *objectLength, 
						const CRYPT_CONTEXT sigCheckContext,
						const int formatInfo );

/****************************************************************************
*																			*
*								Utility Functions							*
*																			*
****************************************************************************/

/* Get certificate information for a cert in the chain */

static int getCertInfo( const CERT_INFO *certInfoPtr,
						CERT_INFO **certChainPtr, const int certChainIndex )
	{
	assert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );
	assert( certChainIndex >= -2 && \
			certChainIndex < certInfoPtr->cCertCert->chainEnd );

	/* If it's an index into the cert chain, return info for the cert at 
	   that position */
	if( certChainIndex >= 0 && \
		certChainIndex < certInfoPtr->cCertCert->chainEnd )
		return( krnlAcquireObject( certInfoPtr->cCertCert->chain[ certChainIndex ], 
								   OBJECT_TYPE_CERTIFICATE, 
								   ( void ** ) certChainPtr, 
								   CRYPT_ERROR_SIGNALLED ) );

	/* The -1th cert is the leaf itself */
	if( certChainIndex == -1 )
		{
		*certChainPtr = ( CERT_INFO * ) certInfoPtr;
		return( CRYPT_OK );
		}

	/* We've reached the end of the chain */
	*certChainPtr = NULL;
	return( CRYPT_ERROR_NOTFOUND );
	}

/* Find the trust anchor in a cert chain.  The definition of a "trusted 
   cert" is somewhat ambiguous and can have at least two different
   interpretations:

	1. Trust the identified cert in the chain and only verify from there on
	   down.

	2. Trust the root of the chain that contains the identified cert (for 
	   the purposes of verifying that particular chain only) and verify the
	   whole chain.

   Situation 1 is useful where there's a requirement that things go up to an
   external CA somewhere but no-one particularly cares about (or trusts) the
   external CA.  This is probably the most common situation in general PKC 
   usage, in which the external CA requirement is more of an inconvenience
   than anything else.  In this case the end user can choose to trust the
   path at the point where it comes under their control (a local CA or 
   directly trusting the leaf certs) without having to bother about the 
   external CA.

   Situation 2 is useful where there's a requirement to use the full PKI 
   model.  This can be enabled by having the user mark the root CA as
   trusted, although this means that all certs issued by that CA also have
   to be trusted, removing user control over certificate use.  This is 
   required by orthodox PKI theology, followed by all manner of hacks and
   kludges down the chain to limit what can actually be done with the 
   cert(s) */

static int findTrustAnchor( CERT_INFO *certInfoPtr, int *trustAnchorIndexPtr, 
							CRYPT_CERTIFICATE *trustAnchorCertPtr )
	{
	CRYPT_CERTIFICATE iIssuerCert;
	CERT_CERT_INFO *certChainInfo = certInfoPtr->cCertCert;
	SELECTION_STATE savedState;
	int trustAnchorIndex = 0, status;

	/* Clear return value */
	*trustAnchorIndexPtr = CRYPT_ERROR;
	*trustAnchorCertPtr = CRYPT_ERROR;

	/* If the leaf cert is implicitly trusted, exit.  To perform this check 
	   we have to explicitly select the leaf cert by making it appear that 
	   the cert chain is empty.  This is required in order to ensure that we 
	   check the leaf rather than the currently-selected cert */
	saveSelectionState( savedState, certInfoPtr );
	certChainInfo->chainPos = CRYPT_ERROR;
	status = krnlSendMessage( certInfoPtr->ownerHandle, IMESSAGE_SETATTRIBUTE,
							  &certInfoPtr->objectHandle, 
							  CRYPT_IATTRIBUTE_CERT_CHECKTRUST );
	restoreSelectionState( savedState, certInfoPtr );
	if( cryptStatusOK( status ) )
		/* Indicate that the leaf is trusted and there's nothing further to 
		   do */
		return( OK_SPECIAL );

	/* Walk up the chain looking for a trusted cert.  Note that the 
	   evaluated trust anchor cert position is one past the current cert 
	   position, since we're looking for the issuer of the current cert at
	   position n, which will be located at position n+1.  This means that 
	   it may end up pointing past the end of the chain if the trust anchor 
	   is present in the trust database but not in the chain */
	iIssuerCert = certInfoPtr->objectHandle;
	status = krnlSendMessage( certInfoPtr->ownerHandle, IMESSAGE_SETATTRIBUTE, 
							  &iIssuerCert, CRYPT_IATTRIBUTE_CERT_TRUSTEDISSUER );
	while( cryptStatusError( status ) && \
		   trustAnchorIndex < certChainInfo->chainEnd )
		{
		iIssuerCert = certChainInfo->chain[ trustAnchorIndex++ ];
		status = krnlSendMessage( certInfoPtr->ownerHandle, 
								  IMESSAGE_SETATTRIBUTE, &iIssuerCert, 
								  CRYPT_IATTRIBUTE_CERT_TRUSTEDISSUER );
		}
	if( cryptStatusError( status ) || \
		trustAnchorIndex > certChainInfo->chainEnd )
		return( CRYPT_ERROR_NOTFOUND );
	*trustAnchorCertPtr = iIssuerCert;
	*trustAnchorIndexPtr = trustAnchorIndex;

	/* If there are more certs in the chain beyond the one that we stopped 
	   at, check to see whether the next cert is the same as the trust 
	   anchor.  If it is, we use the copy of the cert in the chain rather 
	   than the external one from the trust database */
	if( trustAnchorIndex < certChainInfo->chainEnd - 1 )
		{
		status = krnlSendMessage( certChainInfo->chain[ trustAnchorIndex ],
								  IMESSAGE_COMPARE, &iIssuerCert, 
								  MESSAGE_COMPARE_CERTOBJ );
		if( cryptStatusOK( status ) )
			*trustAnchorCertPtr = certChainInfo->chain[ trustAnchorIndex ];
		}
	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*							Verify a Certificate Chain						*
*																			*
****************************************************************************/

/* Check constraints along a cert chain in certInfoPtr from startCertIndex 
   on down, checked if complianceLevel >= CRYPT_COMPLIANCELEVEL_PKIX_FULL.  
   There are three types of constraints that can cover multiple certs: path 
   constraints, name constraints, and policy constraints.

   Path constraints are the easiest to check, just make sure that the number 

⌨️ 快捷键说明

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