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

📄 certchk.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 4 页
字号:
	constrainedAttributeListPtr = findAttributeField( subjectAttributes,
			CRYPT_CERTINFO_SUBJECTALTNAME, CRYPT_CERTINFO_RFC822NAME );
	if( attributeListPtr != NULL && constrainedAttributeListPtr != NULL && \
		wildcardMatch( constrainedAttributeListPtr, attributeListPtr,
					   FALSE ) == matchValue )
		status = CRYPT_ERROR_INVALID;
	attributeListPtr = findAttributeField( issuerAttributes,
							constraintType, CRYPT_CERTINFO_DNSNAME );
	constrainedAttributeListPtr = findAttributeField( subjectAttributes,
			CRYPT_CERTINFO_SUBJECTALTNAME, CRYPT_CERTINFO_DNSNAME );
	if( attributeListPtr != NULL && constrainedAttributeListPtr != NULL && \
		wildcardMatch( constrainedAttributeListPtr, attributeListPtr,
					   FALSE ) == matchValue )
		status = CRYPT_ERROR_INVALID;
	attributeListPtr = findAttributeField( issuerAttributes,
							constraintType, CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER );
	constrainedAttributeListPtr = findAttributeField( subjectAttributes,
			CRYPT_CERTINFO_SUBJECTALTNAME, CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER );
	if( attributeListPtr != NULL && constrainedAttributeListPtr != NULL && \
		wildcardMatch( constrainedAttributeListPtr, attributeListPtr,
					   FALSE ) == matchValue )
		status = CRYPT_ERROR_INVALID;
	if( cryptStatusError( status ) )
		{
		setErrorValues( CRYPT_CERTINFO_SUBJECTALTNAME, 
						CRYPT_ERRTYPE_CONSTRAINT );
		return( status );
		}

	return( CRYPT_OK );
	}

/* Check policy constraints placed by an issuer, checked if complianceLevel 
   >= CRYPT_COMPLIANCELEVEL_PKIX_FULL */

int checkPolicyConstraints( const CERT_INFO *subjectCertInfoPtr,
							const ATTRIBUTE_LIST *issuerAttributes,
							CRYPT_ATTRIBUTE_TYPE *errorLocus, 
							CRYPT_ERRTYPE_TYPE *errorType )
	{
	ATTRIBUTE_LIST *attributeListPtr, *constrainedAttributeListPtr;

	assert( isReadPtr( subjectCertInfoPtr, CERT_INFO ) );
	assert( isReadPtr( issuerAttributes, ATTRIBUTE_LIST ) );

	/* Compare the issuer and subject policies if constraints exist */
	attributeListPtr = findAttributeField( issuerAttributes,
										   CRYPT_CERTINFO_CERTPOLICYID, 
										   CRYPT_ATTRIBUTE_NONE );
	if( attributeListPtr == NULL )
		return( CRYPT_OK );
	constrainedAttributeListPtr = \
				findAttributeField( subjectCertInfoPtr->attributes,
									CRYPT_CERTINFO_CERTPOLICYID, 
									CRYPT_ATTRIBUTE_NONE );
	if( constrainedAttributeListPtr == NULL )
		{
		setErrorValues( CRYPT_CERTINFO_CERTPOLICYID, CRYPT_ERRTYPE_CONSTRAINT );
		return( CRYPT_ERROR_INVALID );
		}
	if( attributeListPtr->valueLength != \
								constrainedAttributeListPtr->valueLength || \
		memcmp( attributeListPtr->value, constrainedAttributeListPtr->value, 
				attributeListPtr->valueLength ) )
		{
		setErrorValues( CRYPT_CERTINFO_CERTPOLICYID, CRYPT_ERRTYPE_CONSTRAINT );
		return( CRYPT_ERROR_INVALID );
		}

	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*						Check for Constraint Violations						*
*																			*
****************************************************************************/

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

static int checkCRL( const CERT_INFO *crlInfoPtr,
					 const CERT_INFO *issuerCertInfoPtr,
					 const int complianceLevel,
					 CRYPT_ATTRIBUTE_TYPE *errorLocus, 
					 CRYPT_ERRTYPE_TYPE *errorType )
	{
	ATTRIBUTE_LIST *attributeListPtr;

	/* 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 );

	/* There is one universal case in which a cert is regarded as an invalid 
	   issuer cert regardless of any special-case considerations for self-
	   signed/v1 certs, and that's when the cert is explicitly not trusted 
	   for this purpose */
	if( issuerCertInfoPtr->trustedUsage != CRYPT_ERROR && \
		!( issuerCertInfoPtr->trustedUsage & CRYPT_KEYUSAGE_CRLSIGN ) )
		{
		setErrorValues( CRYPT_CERTINFO_TRUSTED_USAGE, 
						CRYPT_ERRTYPE_ISSUERCONSTRAINT );
		return( CRYPT_ERROR_INVALID );
		}

	/* If the issuer is a v1 cert, we can't do any checking of issuer 
	   attributes/capabilities */
	if( issuerCertInfoPtr->version <= 2 )
		return( CRYPT_OK );

	/* If it's an oblivious check, we're done */
	if( complianceLevel <= CRYPT_COMPLIANCELEVEL_OBLIVIOUS )
		return( CRYPT_OK );

	/* Make sure that the issuer has a key usage attribute present and can 
	   sign certs (PKIX section 4.2.1.3) */
	attributeListPtr = findAttributeField( issuerCertInfoPtr->attributes,
										   CRYPT_CERTINFO_KEYUSAGE, 
										   CRYPT_ATTRIBUTE_NONE  );
	if( attributeListPtr == NULL || \
		!( attributeListPtr->intValue & CRYPT_KEYUSAGE_CRLSIGN ) )
		{
		/* The issuer can't sign CRLs */
		setErrorValues( CRYPT_CERTINFO_KEYUSAGE,
						CRYPT_ERRTYPE_ISSUERCONSTRAINT );
		return( CRYPT_ERROR_INVALID );
		}

	/* Make sure that there's a basicConstraints attribute present and that 
	   the issuer is a CA (PKIX section 4.2.1.10) */
	attributeListPtr = findAttributeField( issuerCertInfoPtr->attributes,
										   CRYPT_CERTINFO_CA, 
										   CRYPT_ATTRIBUTE_NONE );
	if( attributeListPtr == NULL || !attributeListPtr->intValue )
		{
		setErrorValues( CRYPT_CERTINFO_CA, CRYPT_ERRTYPE_ISSUERCONSTRAINT );
		return( CRYPT_ERROR_INVALID );
		}

	return( CRYPT_OK );
	}

/* Check the validity of a subject cert based on an issuer cert, with the 
   level of checking performed depending on the complianceLevel setting */

int checkCert( CERT_INFO *subjectCertInfoPtr,
			   const CERT_INFO *issuerCertInfoPtr,
			   const BOOLEAN shortCircuitCheck,
			   CRYPT_ATTRIBUTE_TYPE *errorLocus, 
			   CRYPT_ERRTYPE_TYPE *errorType )
	{
	const ATTRIBUTE_LIST *subjectAttributes = subjectCertInfoPtr->attributes;
	const ATTRIBUTE_LIST *issuerAttributes = \
			( issuerCertInfoPtr != NULL ) ? issuerCertInfoPtr->attributes : NULL;
	ATTRIBUTE_LIST *attributeListPtr;
	const BOOLEAN selfSigned = ( subjectCertInfoPtr->flags & CERT_FLAG_SELFSIGNED );
	BOOLEAN subjectIsCA = FALSE, issuerIsCA = FALSE;
	const time_t currentTime = getTime();
	int complianceLevel, status;

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

	/* If it's some form of certificate request or an OCSP object (which means
	   it isn't signed by an issuer in the normal sense), there's nothing to 
	   check (yet) */
	if( subjectCertInfoPtr->type == CRYPT_CERTTYPE_CERTREQUEST || \
		subjectCertInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT || \
		subjectCertInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION || \
		subjectCertInfoPtr->type == CRYPT_CERTTYPE_RTCS_REQUEST || \
		subjectCertInfoPtr->type == CRYPT_CERTTYPE_RTCS_RESPONSE || \
		subjectCertInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST || \
		subjectCertInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE )
		return( CRYPT_OK );

	/* It's an issuer-signed object, there must be an issuer cert present
	   unless its a standalone single CRL entry that acts purely as a 
	   container for revocation data */
	assert( subjectCertInfoPtr->type == CRYPT_CERTTYPE_CRL || \
			isReadPtr( issuerCertInfoPtr, CERT_INFO ) );

	/* Determine how much checking we need to perform */
	status = krnlSendMessage( subjectCertInfoPtr->ownerHandle, 
							  IMESSAGE_GETATTRIBUTE, &complianceLevel, 
							  CRYPT_OPTION_CERT_COMPLIANCELEVEL );
	if( cryptStatusError( status ) )
		return( status );

	/* If we're checking a CRL, call the special-case routine for this */
	if( subjectCertInfoPtr->type == CRYPT_CERTTYPE_CRL )
		return( checkCRL( subjectCertInfoPtr, issuerCertInfoPtr, 
						  complianceLevel, errorLocus, errorType ) );

	/* There is one universal case in which a cert is regarded as an invalid 
	   issuer cert regardless of any special-case considerations for self-
	   signed/v1 certs, and that's when the cert is explicitly not trusted 
	   for this purpose */
	if( issuerCertInfoPtr->trustedUsage != CRYPT_ERROR && \
		!( issuerCertInfoPtr->trustedUsage & CRYPT_KEYUSAGE_KEYCERTSIGN ) )
		{
		/* The issuer can sign certs but is explicitly not trusted to do 
		   so */
		setErrorValues( CRYPT_CERTINFO_TRUSTED_USAGE,
						CRYPT_ERRTYPE_ISSUERCONSTRAINT );
		return( CRYPT_ERROR_INVALID );
		}
	if( selfSigned )
		{
		/* Check whether the issuer (== subject) is explicitly not trusted 
		   to sign itself */
		if( subjectCertInfoPtr->trustedUsage != CRYPT_ERROR && \
			!( subjectCertInfoPtr->trustedUsage & CRYPT_KEYUSAGE_KEYCERTSIGN ) )
			{
			setErrorValues( CRYPT_CERTINFO_TRUSTED_USAGE, 
							CRYPT_ERRTYPE_CONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}
		}

	/* If we're not running in oblivious mode, we're done */
	if( complianceLevel < CRYPT_COMPLIANCELEVEL_REDUCED )
		return( CRYPT_OK );

	/* Check that the validity period is in order.  If we're checking an 
	   existing cert then the start time has to be valid, if we're creating
	   a new cert then it doesn't have to be valid since the cert could be
	   created for use in the future */
	if( currentTime < MIN_TIME_VALUE )
		{
		/* Time is broken, we can't reliably check for expiry times */
		setErrorValues( CRYPT_CERTINFO_VALIDFROM, CRYPT_ERRTYPE_CONSTRAINT );
		return( CRYPT_ERROR_INVALID );
		}
	if( subjectCertInfoPtr->startTime >= subjectCertInfoPtr->endTime || \
		( subjectCertInfoPtr->certificate != NULL && \
		  currentTime < subjectCertInfoPtr->startTime ) )
		{
		setErrorValues( CRYPT_CERTINFO_VALIDFROM, CRYPT_ERRTYPE_CONSTRAINT );
		return( CRYPT_ERROR_INVALID );
		}
	if( currentTime > subjectCertInfoPtr->endTime )
		{
		setErrorValues( CRYPT_CERTINFO_VALIDTO, CRYPT_ERRTYPE_CONSTRAINT );
		return( CRYPT_ERROR_INVALID );
		}

	/* If it's a self-signed cert or we're doing a short-circuit check of a 
	   cert in a chain that has already been checked, and we've already 
	   checked it at the appropriate level, there's no need to perform any 
	   further checks */
	if( ( selfSigned || shortCircuitCheck ) && \
		( subjectCertInfoPtr->maxCheckLevel >= complianceLevel ) )
		return( CRYPT_OK );

	/* If the cert isn't self-signed, check name chaining */
	if( !selfSigned )
		{
		/* Check that the subject issuer and issuer subject names chain
		   properly.  If the DNs are present in pre-encoded form, we do
		   a binary comparison, which is faster than calling compareDN() */
		if( subjectCertInfoPtr->certificate != NULL )
			{
			if( subjectCertInfoPtr->issuerDNsize != \
									issuerCertInfoPtr->subjectDNsize || \
				memcmp( subjectCertInfoPtr->issuerDNptr, 
						issuerCertInfoPtr->subjectDNptr, 
						subjectCertInfoPtr->issuerDNsize ) )
				{
				setErrorValues( CRYPT_CERTINFO_ISSUERNAME, 
								CRYPT_ERRTYPE_CONSTRAINT );
				return( CRYPT_ERROR_INVALID );
				}
			}
		else
			if( !compareDN( subjectCertInfoPtr->issuerName,
							issuerCertInfoPtr->subjectName, FALSE ) )
				{
				setErrorValues( CRYPT_CERTINFO_ISSUERNAME, 
								CRYPT_ERRTYPE_CONSTRAINT );
				return( CRYPT_ERROR_INVALID );
				}
		}

	/* Determine whether the subject or issuer are CA certs */
	attributeListPtr = findAttributeField( subjectAttributes, 
										   CRYPT_CERTINFO_CA, 
										   CRYPT_ATTRIBUTE_NONE );
	if( attributeListPtr != NULL )
		subjectIsCA = attributeListPtr->intValue;
	attributeListPtr = findAttributeField( issuerAttributes,
										   CRYPT_CERTINFO_CA, 
										   CRYPT_ATTRIBUTE_NONE );
	if( attributeListPtr != NULL )
		issuerIsCA = attributeListPtr->intValue;

	/* If the issuer is a non self-signed v3 cert, check the issuer 
	   attributes/capabilities.  Note that this means that a self-signed 
	   cert has an implicitly permitted usage of keyCertSign for itself even 
	   if it's a non-CA cert (a Smith and Wesson beats four aces) */
	if( !selfSigned && issuerCertInfoPtr->version > 2 )
		{
		/* Make sure that the issuer has a key usage attribute present and 
		   can sign certs (PKIX section 4.2.1.3) */
		attributeListPtr = findAttributeField( issuerAttributes,
											   CRYPT_CERTINFO_KEYUSAGE, 
											   CRYPT_ATTRIBUTE_NONE );
		if( attributeListPtr == NULL || \
			!( attributeListPtr->intValue & CRYPT_KEYUSAGE_KEYCERTSIGN ) )
			{
			/* The issuer can't sign certs */
			setErrorValues( CRYPT_CERTINFO_KEYUSAGE, 
							CRYPT_ERRTYPE_ISSUERCONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}

		/* Make sure that there's a basicConstraints attribute present/the
		   issuer is a CA (PKIX section 4.2.1.10) */
		if( !issuerIsCA )
			{
			setErrorValues( CRYPT_CERTINFO_CA, CRYPT_ERRTYPE_ISSUERCONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}
		}

	/* If we're doing a reduced level of checking, we're done */
	if( complianceLevel < CRYPT_COMPLIANCELEVEL_STANDARD )
		{
		if( subjectCertInfoPtr->maxCheckLevel < complianceLevel )
			subjectCertInfoPtr->maxCheckLevel = complianceLevel;
		return( CRYPT_OK );
		}

	/* Check that the cert usage flags are present and consistent.  The key 
	   usage checking level ranges from CRYPT_COMPLIANCELEVEL_STANDARD to
	   CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL so we re-do the check even if it's

⌨️ 快捷键说明

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