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

📄 certchk.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 4 页
字号:
	   already been done at a lower level */
	if( subjectCertInfoPtr->maxCheckLevel < CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL && \
		subjectCertInfoPtr->type != CRYPT_CERTTYPE_ATTRIBUTE_CERT )
		{
		status = checkKeyUsageFlags( subjectCertInfoPtr, complianceLevel,
									 errorLocus, errorType );
		if( cryptStatusError( status ) )
			return( status );
        }

	/* If we're not doing at least partial PKIX checking, we're done */
	if( complianceLevel < CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL )
		{
		if( subjectCertInfoPtr->maxCheckLevel < complianceLevel )
			subjectCertInfoPtr->maxCheckLevel = complianceLevel;
		return( CRYPT_OK );
		}

	/* Check various CA vs. non-CA restrictions: Name, policy, and path-
	   length constraints can only be present in CA certs */
	if( !subjectIsCA )
		{
		if( checkAttributePresent( subjectAttributes, \
								   CRYPT_CERTINFO_NAMECONSTRAINTS ) )
			{
			setErrorValues( CRYPT_CERTINFO_CA, CRYPT_ERRTYPE_CONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}
		if( checkAttributePresent( subjectAttributes, \
								   CRYPT_CERTINFO_POLICYCONSTRAINTS ) )
			{
			setErrorValues( CRYPT_CERTINFO_CA, CRYPT_ERRTYPE_CONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}
		if( findAttributeField( subjectAttributes,
								CRYPT_CERTINFO_PATHLENCONSTRAINT, 
								CRYPT_ATTRIBUTE_NONE ) )
			{
			setErrorValues( CRYPT_CERTINFO_CA, CRYPT_ERRTYPE_CONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}
		}
	if( !issuerIsCA )
		{
		if( checkAttributePresent( issuerAttributes, \
								   CRYPT_CERTINFO_NAMECONSTRAINTS ) )
			{
			setErrorValues( CRYPT_CERTINFO_CA, CRYPT_ERRTYPE_ISSUERCONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}
		if( checkAttributePresent( issuerAttributes, \
								   CRYPT_CERTINFO_POLICYCONSTRAINTS ) )
			{
			setErrorValues( CRYPT_CERTINFO_CA, 
							CRYPT_ERRTYPE_ISSUERCONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}
		if( findAttributeField( issuerAttributes,
								CRYPT_CERTINFO_PATHLENCONSTRAINT, 
								CRYPT_ATTRIBUTE_NONE ) )
			{
			setErrorValues( CRYPT_CERTINFO_CA, CRYPT_ERRTYPE_ISSUERCONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}
		}

	/* If there's a path length constraint present and set to zero, make 
	   sure that the subject is a non-CA cert */
	attributeListPtr = findAttributeField( issuerAttributes,
										   CRYPT_CERTINFO_PATHLENCONSTRAINT, 
										   CRYPT_ATTRIBUTE_NONE );
	if( attributeListPtr != NULL && attributeListPtr->intValue <= 0 && \
		!selfSigned && subjectIsCA )
		{
		setErrorValues( CRYPT_CERTINFO_PATHLENCONSTRAINT,
						CRYPT_ERRTYPE_ISSUERCONSTRAINT );
		return( CRYPT_ERROR_INVALID );
		}

	/* If we're not doing full PKIX checking, we're done */
	if( complianceLevel < CRYPT_COMPLIANCELEVEL_PKIX_FULL )
		{
		if( subjectCertInfoPtr->maxCheckLevel < complianceLevel )
			subjectCertInfoPtr->maxCheckLevel = complianceLevel;
		return( CRYPT_OK );
		}

	/* If the cert isn't self-signed and an issuer altname is present, check 
	   that it chains correctly.  No-one can quite agree on how chaining of 
	   altNames is really supposed to work, it's only their rarity that 
	   prevents this from being much of a problem */
	if( !selfSigned && \
		subjectCertInfoPtr->type != CRYPT_CERTTYPE_ATTRIBUTE_CERT )
		{
		const BOOLEAN boolean1 = checkAttributePresent( issuerAttributes,
											CRYPT_CERTINFO_SUBJECTALTNAME );
		const BOOLEAN boolean2 = checkAttributePresent( subjectAttributes,
											CRYPT_CERTINFO_ISSUERALTNAME );

		/* If present, the attribute must be present and match in both 
		   certs */
		if( boolean1 && !boolean2 )
			{ 
			setErrorValues( CRYPT_CERTINFO_ISSUERALTNAME, 
							CRYPT_ERRTYPE_CONSTRAINT ); 
			return( CRYPT_ERROR_INVALID );
			}
		if( boolean2 && !boolean1 )
			{
			setErrorValues( CRYPT_CERTINFO_SUBJECTALTNAME, 
							CRYPT_ERRTYPE_ISSUERCONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}
		if( boolean1 && boolean2 )
			{
			const CRYPT_ATTRIBUTE_TYPE altNameComponent = \
										compareAltNames( subjectAttributes, 
														 issuerAttributes );
			if( altNameComponent != CRYPT_ATTRIBUTE_NONE )
				{
				setErrorValues( altNameComponent, 
								CRYPT_ERRTYPE_CONSTRAINT );
				return( CRYPT_ERROR_INVALID );
				}
			}
		}

	/* If the issuing cert has name constraints and isn't self-signed, make 
	   sure that the subject name and altName falls within the constrained 
	   subtrees.  Since excluded subtrees override permitted subtrees, we 
	   check these first */
	if( !selfSigned )
		{
		attributeListPtr = findAttributeField( issuerAttributes, 
											   CRYPT_CERTINFO_EXCLUDEDSUBTREES,
											   CRYPT_ATTRIBUTE_NONE );
		if( attributeListPtr != NULL )
			{
			if( cryptStatusError( \
				checkNameConstraints( subjectCertInfoPtr, attributeListPtr, 
									  TRUE, errorLocus, errorType ) ) )
				return( CRYPT_ERROR_INVALID );
			}
		attributeListPtr = findAttributeField( issuerAttributes, 
											   CRYPT_CERTINFO_PERMITTEDSUBTREES,
											   CRYPT_ATTRIBUTE_NONE );
		if( attributeListPtr != NULL )
			{
			if( cryptStatusError( \
				checkNameConstraints( subjectCertInfoPtr, attributeListPtr, 
									  FALSE, errorLocus, errorType ) ) )
				return( CRYPT_ERROR_INVALID );
			}
		}

	/* If there's a policy constraint present and the skip count is set to 
	   zero (i.e. the constraint applies to the current cert), check the 
	   issuer constraints against the subject */
	attributeListPtr = findAttributeField( issuerAttributes,
										   CRYPT_CERTINFO_REQUIREEXPLICITPOLICY,
										   CRYPT_ATTRIBUTE_NONE );
	if( attributeListPtr != NULL && attributeListPtr->intValue <= 0 )
		{
		status = checkPolicyConstraints( subjectCertInfoPtr,
										 issuerAttributes,
										 errorLocus, errorType );
		if( cryptStatusError( status ) )
			return( status );
		}

	if( subjectCertInfoPtr->maxCheckLevel < complianceLevel )
		subjectCertInfoPtr->maxCheckLevel = complianceLevel;
	return( CRYPT_OK );
	}

/* Check that a certificate is valid for a particular purpose.  This is used
   mainly to check that contexts and certs are valid for key exchange/sig.
   generation/cert signing, and isn't as rigorous as the cert/issuer cert 
   check in checkCert().  In some instances we need to check for specific 
   types of usage that are dependant on the peculiarities of object types, 
   so if it's available we pass in the exact requested cryptlib-level usage 
   as well */

int checkCertUsage( const CERT_INFO *certInfoPtr, const int keyUsage,
					const MESSAGE_CHECK_TYPE exactUsage,
					CRYPT_ATTRIBUTE_TYPE *errorLocus, 
					CRYPT_ERRTYPE_TYPE *errorType )
	{
	ATTRIBUTE_LIST *attributeListPtr;
	const BOOLEAN isV1selfSigned = \
		( certInfoPtr->version == 1 && \
		  ( certInfoPtr->flags & CERT_FLAG_SELFSIGNED ) ) ? TRUE : FALSE;
	int complianceLevel, status;

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

	/* PKCS #10 cert requests are special-case objects in that the key they 
	   contain is usable only for signature checking of the self-signature 
	   on the object (it can't be used for general-purpose usages, which 
	   would make it equivalent to a trusted self-signed cert).  This is 
	   problematic because the keyUsage may indicate that the key is valid 
	   for other things as well, or not valid for signature checking.  To 
	   get around this, we indicate that the key has a single trusted usage, 
	   signature checking, and disallow any other usage regardless of what 
	   the keyUsage says.  The actual keyUsage usage is only valid once the 
	   request has been converted into a cert */
	if( certInfoPtr->type == CRYPT_CERTTYPE_CERTREQUEST )
		{
		if( exactUsage == MESSAGE_CHECK_PKC_SIGCHECK )
			return( CRYPT_OK );
		setErrorValues( CRYPT_CERTINFO_TRUSTED_USAGE, 
						CRYPT_ERRTYPE_CONSTRAINT );
		return( CRYPT_ERROR_INVALID );
		}

	/* 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 we're looking for a CA cert, make sure that either the 
	   basicConstraints CA flag is set and the keyUsage indicates a CA usage,
	   or if there's no basicConstraints/keyUsage present that it's a v1 
	   self-signed cert (PKIX sections 4.2.1.3 and 4.2.1.10) */
	if( exactUsage == MESSAGE_CHECK_CA && \
		complianceLevel >= CRYPT_COMPLIANCELEVEL_REDUCED && \
		!isV1selfSigned )
		{
		attributeListPtr = findAttributeField( certInfoPtr->attributes,
											   CRYPT_CERTINFO_CA, 
											   CRYPT_ATTRIBUTE_NONE );
		if( attributeListPtr == NULL || !attributeListPtr->intValue )
			{
			setErrorValues( CRYPT_CERTINFO_CA, CRYPT_ERRTYPE_CONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}
		attributeListPtr = findAttributeField( certInfoPtr->attributes,
											   CRYPT_CERTINFO_KEYUSAGE, 
											   CRYPT_ATTRIBUTE_NONE );
		if( attributeListPtr == NULL || \
			!( attributeListPtr->intValue & certInfoPtr->trustedUsage & \
				( CRYPT_KEYUSAGE_CRLSIGN | CRYPT_KEYUSAGE_KEYCERTSIGN ) ) )
			{
			setErrorValues( CRYPT_CERTINFO_KEYUSAGE, 
							CRYPT_ERRTYPE_CONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}
		}

	/* Check and enforce the keyUsage if required */
	if( keyUsage != CRYPT_UNUSED )
		{
		attributeListPtr = findAttributeField( certInfoPtr->attributes,
											   CRYPT_CERTINFO_KEYUSAGE, 
											   CRYPT_ATTRIBUTE_NONE );
		if( attributeListPtr != NULL )
			{
			const int trustedUsage = \
						attributeListPtr->intValue & certInfoPtr->trustedUsage;
			BOOLEAN usageOK = FALSE;

			/* If it's a key agreement usage the checking gets a bit complex, 
			   we have to make sure it's both a permitted usage and not an 
			   excluded usage */
			if( complianceLevel >= CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL && \
				( keyUsage == CRYPT_KEYUSAGE_ENCIPHERONLY || \
				  keyUsage == CRYPT_KEYUSAGE_DECIPHERONLY ) )
				{
				const int excludedUsage = \
					( keyUsage == CRYPT_KEYUSAGE_ENCIPHERONLY ) ? \
					CRYPT_KEYUSAGE_DECIPHERONLY : CRYPT_KEYUSAGE_ENCIPHERONLY;

				if( ( trustedUsage & keyUsage ) && \
					!( trustedUsage & excludedUsage ) )
					usageOK = TRUE;
				}
			else
				/* Conventional usage flag, do a straight check */
				if( trustedUsage & keyUsage )
					usageOK = TRUE;
			if( !usageOK )
				{
				setErrorValues( ( attributeListPtr->intValue & keyUsage ) ? \
									CRYPT_CERTINFO_TRUSTED_USAGE : \
									CRYPT_CERTINFO_KEYUSAGE,
								CRYPT_ERRTYPE_CONSTRAINT );
				return( CRYPT_ERROR_INVALID );
				}
			}
		else
			{
			/* There is one special case in which a cert with no explicit 
			   key usage can't be used for a particular purpose and that's 
			   when the cert is explicitly not trusted for the purpose */
			if( !( certInfoPtr->trustedUsage & keyUsage ) )
				{
				setErrorValues( CRYPT_CERTINFO_TRUSTED_USAGE, 
								CRYPT_ERRTYPE_CONSTRAINT );
				return( CRYPT_ERROR_INVALID );
				}
			}
		}

	/* If we're not doing at least partial PKIX checking, we're done */
	if( complianceLevel < CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL )
		return( CRYPT_OK );

	/* If we're being asked for a private-key op, check and enforce the 
	   privateKeyUsage attribute if there's one present */
	if( ( exactUsage == MESSAGE_CHECK_PKC_PRIVATE || \
		  exactUsage == MESSAGE_CHECK_PKC_DECRYPT || \
		  exactUsage == MESSAGE_CHECK_PKC_SIGN ) && \
		findAttributeField( certInfoPtr->attributes,
							CRYPT_CERTINFO_PRIVATEKEYUSAGEPERIOD, 
							CRYPT_ATTRIBUTE_NONE ) != NULL )
		{
		const time_t currentTime = getTime();

		if( currentTime < MIN_TIME_VALUE )
			{
			/* Time is broken, we can't reliably check for expiry times */
			setErrorValues( CRYPT_CERTINFO_PRIVATEKEY_NOTBEFORE, 
							CRYPT_ERRTYPE_CONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}
		attributeListPtr = findAttributeField( certInfoPtr->attributes,
											   CRYPT_CERTINFO_PRIVATEKEY_NOTBEFORE, 
											   CRYPT_ATTRIBUTE_NONE );
		if( attributeListPtr != NULL && \
			currentTime < *( ( time_t * ) attributeListPtr->value ) )
			{
			setErrorValues( CRYPT_CERTINFO_PRIVATEKEY_NOTBEFORE,
							CRYPT_ERRTYPE_CONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}
		attributeListPtr = findAttributeField( certInfoPtr->attributes,
											   CRYPT_CERTINFO_PRIVATEKEY_NOTAFTER, 
											   CRYPT_ATTRIBUTE_NONE );
		if( attributeListPtr != NULL && \
			currentTime > *( ( time_t * ) attributeListPtr->value ) )
			{
			setErrorValues( CRYPT_CERTINFO_PRIVATEKEY_NOTAFTER,
							CRYPT_ERRTYPE_CONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}
		}

	return( CRYPT_OK );
	}

⌨️ 快捷键说明

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