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

📄 chk_cert.c

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

	/* If there's no requirement for a policy and there's none set, we're 
	   done */
	if( policyType == POLICY_NONE && constrainedAttributeListPtr == NULL )
		return( CRYPT_OK );

	/* Check the subject policy */
	if( !checkPolicyType( constrainedAttributeListPtr, &subjectHasPolicy,
						  &subjectHasAnyPolicy, 
						  ( policyType == POLICY_NONE_SPECIFIC || \
							policyType == POLICY_SUBJECT_SPECIFIC || \
							policyType == POLICY_BOTH_SPECIFIC ) ? \
							TRUE : FALSE ) )
		{
		setErrorValues( CRYPT_CERTINFO_CERTPOLICYID, 
						CRYPT_ERRTYPE_CONSTRAINT );
		return( CRYPT_ERROR_INVALID );
		}

	/* If there's no requirement for an issuer policy and there's none set 
	   by the issuer, we're done */
	if( ( ( policyType == POLICY_SUBJECT ) || \
		  ( policyType == POLICY_SUBJECT_SPECIFIC ) ) && \
		attributeListPtr == NULL )
		return( CRYPT_OK );

	/* Check the subject policy */
	if( !checkPolicyType( attributeListPtr , &issuerHasPolicy,
						  &issuerHasAnyPolicy, 
						  ( policyType == POLICY_BOTH_SPECIFIC ) ? \
							TRUE : FALSE ) )
		{
		setErrorValues( CRYPT_CERTINFO_CERTPOLICYID, 
						CRYPT_ERRTYPE_CONSTRAINT );
		return( CRYPT_ERROR_INVALID );
		}

	/* Both the issuer and subject have some sort of policy, if either are 
	   anyPolicy wildcards (introduced in RFC 3280 section 4.2.1.5) then 
	   it's considered a match */
	if( subjectHasAnyPolicy || issuerHasAnyPolicy )
		return( CRYPT_OK );

	/* An explicit policy is required, make sure that at least one of the 
	   issuer policies matches at least one of the subject policies.  Note
	   that there's no exception for PKIX path-kludge certificates, this is 
	   an error in the RFC for which the text at this point is unchanged 
	   from RFC 2459.  In fact this contradicts the path-processing 
	   pesudocode but since that in turn contradicts the main text in a 
	   number of places we take the main text as definitive, not the buggy 
	   pseudocode */
	for( attributeCursor = ( ATTRIBUTE_LIST * ) attributeListPtr, \
			iterationCount = 0;
		 attributeCursor != NULL && \
			iterationCount < FAILSAFE_ITERATIONS_MAX; 
		 attributeCursor = findNextFieldInstance( attributeCursor ), \
			iterationCount++ )
		{
		ATTRIBUTE_LIST *constrainedAttributeCursor;	
		int innerIterationCount;

		ENSURES( attributeCursor->fieldID == CRYPT_CERTINFO_CERTPOLICYID );

		for( constrainedAttributeCursor = \
					( ATTRIBUTE_LIST * ) constrainedAttributeListPtr, \
				innerIterationCount = 0;
			 constrainedAttributeCursor != NULL && \
				innerIterationCount < FAILSAFE_ITERATIONS_MAX; 
			 constrainedAttributeCursor = \
					findNextFieldInstance( constrainedAttributeCursor ), \
				innerIterationCount++ )
			{
			assert( constrainedAttributeCursor->fieldID == \
					CRYPT_CERTINFO_CERTPOLICYID );

			if( attributeCursor->valueLength == \
							constrainedAttributeCursor->valueLength && \
				!memcmp( attributeCursor->value, 
						 constrainedAttributeCursor->value, 
						 attributeCursor->valueLength ) )
				return( CRYPT_OK );
			}
		ENSURES( innerIterationCount < FAILSAFE_ITERATIONS_MAX );
		}
	ENSURES( iterationCount < FAILSAFE_ITERATIONS_MAX );

	/* We couldn't find a matching policy, report an error */
	setErrorValues( CRYPT_CERTINFO_CERTPOLICYID, CRYPT_ERRTYPE_CONSTRAINT );
	return( CRYPT_ERROR_INVALID );
	}

/* Check path constraints placed by an issuer, checked if complianceLevel 
   >= CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \
int checkPathConstraints( const CERT_INFO *subjectCertInfoPtr,
						  const ATTRIBUTE_LIST *issuerAttributes,
						  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
							CRYPT_ATTRIBUTE_TYPE *errorLocus,
						  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \
							CRYPT_ERRTYPE_TYPE *errorType )
	{
	ATTRIBUTE_LIST *attributeListPtr;

	assert( isReadPtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );
	assert( isReadPtr( issuerAttributes, sizeof( ATTRIBUTE_LIST ) ) );
	assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
	assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );

	/* If this is a PKIX path-kludge certificate then the path length 
	   constraints don't apply to it (PKIX section 4.2.1.10).  This is 
	   required in order to allow extra certificates to be kludged into the 
	   path without violating the name constraint */
	if( isPathKludge( subjectCertInfoPtr ) )
		return( CRYPT_OK );

	/* If the path length constraint hasn't been triggered yet we're OK */
	if( issuerAttributes->intValue > 0 )
		return( CRYPT_OK );

	/* If the certificate is self-signed (i.e. the certificate is applying 
	   the constraint to itself) then a path length constraint of zero is 
	   valid.  Checking only the subject certificate info is safe because 
	   the calling code has guaranteed that if the certificate is 
	   self-signed then the issuer attributes are the attributes from the 
	   subject certificate */
	if( subjectCertInfoPtr->flags & CERT_FLAG_SELFSIGNED )
		return( CRYPT_OK );

	/* The path length constraint is in effect, the next certificate down 
	   the chain must be an end-entity certificate */
	attributeListPtr = findAttributeField( subjectCertInfoPtr->attributes, 
										   CRYPT_CERTINFO_CA, 
										   CRYPT_ATTRIBUTE_NONE );
	if( attributeListPtr != NULL && attributeListPtr->intValue > 0 )
		{
		setErrorValues( CRYPT_CERTINFO_PATHLENCONSTRAINT,
						CRYPT_ERRTYPE_ISSUERCONSTRAINT );
		return( CRYPT_ERROR_INVALID );
		}

	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*							Check a Certificate	Object						*
*																			*
****************************************************************************/

/* Check the validity of a CRL based on an issuer certificate */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 5 ) ) \
static int checkCRL( const CERT_INFO *crlInfoPtr,
					 IN_OPT const CERT_INFO *issuerCertInfoPtr,
					 IN_RANGE( CRYPT_COMPLIANCELEVEL_OBLIVIOUS, \
							 CRYPT_COMPLIANCELEVEL_LAST - 1 ) \
						const int complianceLevel,
					 OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
						CRYPT_ATTRIBUTE_TYPE *errorLocus,
					 OUT_ENUM_OPT( CRYPT_ERRTYPE ) \
						CRYPT_ERRTYPE_TYPE *errorType )
	{
	ATTRIBUTE_LIST *attributeListPtr;

	assert( isReadPtr( crlInfoPtr, sizeof( CERT_INFO ) ) );
	assert( issuerCertInfoPtr == NULL || \
			isReadPtr( issuerCertInfoPtr, sizeof( CERT_INFO ) ) );
	assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
	assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );

	REQUIRES( complianceLevel >= CRYPT_COMPLIANCELEVEL_OBLIVIOUS && \
			  complianceLevel < CRYPT_COMPLIANCELEVEL_LAST );

	/* If it's a delta CRL make sure that the CRL numbers make sense (that 
	   is, that the delta CRL was issued after the full CRL) */
	attributeListPtr = findAttributeField( crlInfoPtr->attributes,
										   CRYPT_CERTINFO_DELTACRLINDICATOR, 
										   CRYPT_ATTRIBUTE_NONE );
	if( attributeListPtr != NULL )
		{
		const int deltaCRLindicator = ( int ) attributeListPtr->intValue;

		attributeListPtr = findAttributeField( crlInfoPtr->attributes,
											   CRYPT_CERTINFO_CRLNUMBER, 
											   CRYPT_ATTRIBUTE_NONE  );
		if( attributeListPtr != NULL && \
			attributeListPtr->intValue >= deltaCRLindicator )
			{
			setErrorValues( CRYPT_CERTINFO_DELTACRLINDICATOR,
							CRYPT_ERRTYPE_CONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}
		}

	/* If it's a standalone CRL entry used purely as a container for 
	   revocation data don't try and perform any issuer-based checking */
	if( issuerCertInfoPtr == NULL )
		return( CRYPT_OK );

	/* Make sure that the issuer can sign CRLs and the issuer certificate 
	   in general is in order */
	return( checkKeyUsage( issuerCertInfoPtr, 
						   CHECKKEY_FLAG_CA | CHECKKEY_FLAG_GENCHECK, 
						   CRYPT_KEYUSAGE_CRLSIGN, complianceLevel, 
						   errorLocus, errorType ) );
	}

/* Check the validity of a subject certificate based on an issuer 
   certificate with the level of checking performed depending on the 
   complianceLevel setting.  If the shortCircuitCheck flag is set (used for 
   certificate issuer : subject pairs that may already have been checked) 
   we skip the constant-result checks if the combination has already been 
   checked at this compliance level */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 5 ) ) \
int checkCert( INOUT CERT_INFO *subjectCertInfoPtr,
			   IN_OPT const CERT_INFO *issuerCertInfoPtr,
			   const BOOLEAN shortCircuitCheck,
			   OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
					CRYPT_ATTRIBUTE_TYPE *errorLocus,
			   OUT_ENUM_OPT( CRYPT_ERRTYPE ) \
					CRYPT_ERRTYPE_TYPE *errorType )
	{
	const ATTRIBUTE_LIST *subjectAttributes = subjectCertInfoPtr->attributes;
	const ATTRIBUTE_LIST *issuerAttributes = \
								( issuerCertInfoPtr != NULL ) ? \
								issuerCertInfoPtr->attributes : NULL;
	const ATTRIBUTE_LIST *attributeListPtr;
	const BOOLEAN subjectSelfSigned = \
					( subjectCertInfoPtr->flags & CERT_FLAG_SELFSIGNED ) ? \
					TRUE : FALSE;
	BOOLEAN subjectIsCA = FALSE, issuerIsCA = FALSE;
	const time_t currentTime = getTime();
	int complianceLevel, status;

	assert( isWritePtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );
	assert( issuerCertInfoPtr == NULL || \
			isReadPtr( issuerCertInfoPtr, sizeof( CERT_INFO ) ) );
	assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE  ) ) );
	assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );

	/* Determine how much checking we need to perform.  If this is a 
	   currently-under-construction certificate we use the maximum 
	   compliance level to ensure that cryptlib never produces broken 
	   certificates */
	if( subjectCertInfoPtr->certificate == NULL )
		complianceLevel = CRYPT_COMPLIANCELEVEL_PKIX_FULL;
	else
		{
		status = krnlSendMessage( subjectCertInfoPtr->ownerHandle, 
								  IMESSAGE_GETATTRIBUTE, &complianceLevel, 
								  CRYPT_OPTION_CERT_COMPLIANCELEVEL );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* If it's some form of certificate request or an OCSP object (which 
	   means that it isn't signed by an issuer in the normal sense) then 
	   there's nothing to check (yet) */
	switch( subjectCertInfoPtr->type )
		{
		case CRYPT_CERTTYPE_CERTIFICATE:
		case CRYPT_CERTTYPE_ATTRIBUTE_CERT:
		case CRYPT_CERTTYPE_CERTCHAIN:
			/* It's an issuer-signed object, there must be an issuer 
			   certificate present */
			assert( isReadPtr( issuerCertInfoPtr, sizeof( CERT_INFO ) ) );
			if( subjectCertInfoPtr->flags & CERT_FLAG_CERTCOLLECTION )
				{
				/* Certificate collections are pure container objects for 
				   which the base certificate object doesn't correspond to 
				   an actual certificate */
				retIntError();
				}
			break;

		case CRYPT_CERTTYPE_CERTREQUEST:
		case CRYPT_CERTTYPE_REQUEST_CERT:
		case CRYPT_CERTTYPE_REQUEST_REVOCATION:
			/* These are merely templates submitted to a CA, there's nothing
			   to check.  For example the template could contain constraints
			   that only make sense once the issuer certificate is 
			   incorporated into a chain or a future-dated validity time or 
			   a CA keyUsage for which the CA provides the appropriate 
			   matching basicConstraints value(s) so we can't really perform 
			   much checking here */
			return( CRYPT_OK );

		case CRYPT_CERTTYPE_CRL:
			/* There must be an issuer certificate present unless we're 
			   checking a standalone CRL entry that acts purely as a 
			   container for revocation data */
			assert( issuerCertInfoPtr == NULL || \
					isReadPtr( issuerCertInfoPtr, sizeof( CERT_INFO ) ) );

			/* CRL checking is handled specially */
			return( checkCRL( subjectCertInfoPtr, issuerCertInfoPtr, 
							  complianceLevel, errorLocus, errorType ) );

		case CRYPT_CERTTYPE_CMS_ATTRIBUTES:
		case CRYPT_CERTTYPE_PKIUSER:
			retIntError();

		case CRYPT_CERTTYPE_RTCS_REQUEST:
		case CRYPT_CERTTYPE_RTCS_RESPONSE:
		case CRYPT_CERTTYPE_OCSP_REQUEST:
		case CRYPT_CERTTYPE_OCSP_RESPONSE:
			/* These aren't normal certificate types, there's nothing to 

⌨️ 快捷键说明

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