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

📄 certchk.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 3 页
字号:

	/* Enforce validity period nesting if necessary */
	krnlSendMessage( subjectCertInfoPtr->ownerHandle, 
					 RESOURCE_IMESSAGE_GETATTRIBUTE, &validityNesting, 
					 CRYPT_OPTION_CERT_DECODE_VALIDITYNESTING );
	if( validityNesting )
		{
		if( subjectCertInfoPtr->startTime < issuerCertInfoPtr->startTime )
			{
			setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_VALIDFROM,
						  CRYPT_ERRTYPE_CONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}
		if( subjectCertInfoPtr->endTime > issuerCertInfoPtr->endTime )
			{
			setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_VALIDTO,
						  CRYPT_ERRTYPE_CONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}
		}

	/* Check that the cert usage flags are consistent */
	if( !( subjectCertInfoPtr->flags & CERT_FLAG_CERTCHECKED ) && \
		subjectCertInfoPtr->type != CRYPT_CERTTYPE_ATTRIBUTE_CERT )
		{
		status = checkKeyUsageFlags( subjectCertInfoPtr );
		if( cryptStatusError( status ) )
			return( status );
        }

	/* If the cert isn't self-signed, check name and altName chaining */
	if( !( subjectCertInfoPtr->flags & CERT_FLAG_SELFSIGNED ) )
		{
		/* Check that the subject issuer and issuer subject names chain
		   properly  */
		if( !compareDN( subjectCertInfoPtr->issuerName,
						issuerCertInfoPtr->subjectName, FALSE ) )
			{
			setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_ISSUERNAME,
						  CRYPT_ERRTYPE_CONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}

		/* If an issuer altname is present, check that it chains correctly */
		if( subjectCertInfoPtr->type != CRYPT_CERTTYPE_ATTRIBUTE_CERT )
			{
			boolean1 = ( findAttribute( issuerAttributes,
					CRYPT_CERTINFO_SUBJECTALTNAME ) != NULL ) ? TRUE : FALSE;
			boolean2 = ( findAttribute( subjectAttributes,
					CRYPT_CERTINFO_ISSUERALTNAME ) != NULL ) ? TRUE : FALSE;
			if( boolean1 ^ boolean2 )
				{
				/* The altName must be present in both certs */
				if( boolean1 )
					{
					setErrorInfo( subjectCertInfoPtr,
								  CRYPT_CERTINFO_ISSUERALTNAME, 
								  CRYPT_ERRTYPE_CONSTRAINT );
					}
				else
					setErrorInfo( subjectCertInfoPtr,
								  CRYPT_CERTINFO_SUBJECTALTNAME, 
								  CRYPT_ERRTYPE_ISSUERCONSTRAINT );
				return( CRYPT_ERROR_INVALID );
				}
			if( boolean1 && boolean2 )
				{
				subjectCertInfoPtr->errorLocus = compareAltNames( subjectAttributes,
														  issuerAttributes );
				if( subjectCertInfoPtr->errorLocus != CRYPT_ATTRIBUTE_NONE )
					return( CRYPT_ERROR_INVALID );
				}
			}
		}

	/* If there's a path length constraint present, make sure the cert is a
	   CA cert.  If the issuer path length is set to zero, make sure the
	   subject is a non-CA cert */
	attributeListPtr = findAttributeField( issuerAttributes,
					CRYPT_CERTINFO_PATHLENCONSTRAINT, CRYPT_ATTRIBUTE_NONE );
	if( attributeListPtr != NULL )
		{
		if( !issuerIsCA )
			{
			setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_CA,
						  CRYPT_ERRTYPE_ISSUERCONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}
		if( !( subjectCertInfoPtr->flags & CERT_FLAG_SELFSIGNED ) && \
			!attributeListPtr->value && subjectIsCA )
			{
			setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_PATHLENCONSTRAINT,
						  CRYPT_ERRTYPE_ISSUERCONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}
		}
	if( !( subjectCertInfoPtr->flags & CERT_FLAG_CERTCHECKED ) && \
		findAttributeField( subjectAttributes,
				CRYPT_CERTINFO_PATHLENCONSTRAINT, CRYPT_ATTRIBUTE_NONE ) && \
		!subjectIsCA )
		{
		setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_CA,
					  CRYPT_ERRTYPE_CONSTRAINT );
		return( CRYPT_ERROR_INVALID );
		}

	/* If there's a name constraint present, make sure the cert is a CA
	   cert */
	if( !( subjectCertInfoPtr->flags & CERT_FLAG_CERTCHECKED ) && \
		findAttribute( subjectAttributes, CRYPT_CERTINFO_NAMECONSTRAINTS ) && \
		!subjectIsCA )
		{
		setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_CA,
					  CRYPT_ERRTYPE_CONSTRAINT );
		return( CRYPT_ERROR_INVALID );
		}
	if( findAttribute( issuerAttributes, CRYPT_CERTINFO_NAMECONSTRAINTS ) && \
		!issuerIsCA )
		{
		setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_CA,
					  CRYPT_ERRTYPE_ISSUERCONSTRAINT );
		return( CRYPT_ERROR_INVALID );
		}

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

	/* If there's a policy constraint present, make sure the cert is a CA
	   cert.  If the skip count is set to zero (ie the constraint applies to
	   the current cert), check the issuer constraints against the subject */
	if( !( subjectCertInfoPtr->flags & CERT_FLAG_CERTCHECKED ) && \
		findAttribute( subjectAttributes, CRYPT_CERTINFO_POLICYCONSTRAINTS ) && \
		!subjectIsCA )
		{
		setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_CA,
					  CRYPT_ERRTYPE_CONSTRAINT );
		return( CRYPT_ERROR_INVALID );
		}
	if( findAttribute( issuerAttributes, CRYPT_CERTINFO_POLICYCONSTRAINTS ) )
		{
		if( !issuerIsCA )
			{
			setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_CA,
						  CRYPT_ERRTYPE_ISSUERCONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}

		/* Make sure the skip count is set to zero, which means the constraint
		   applies to the subject */
		attributeListPtr = findAttribute( issuerAttributes,
									CRYPT_CERTINFO_REQUIREEXPLICITPOLICY );
		if( attributeListPtr != NULL && attributeListPtr->value == 0 )
			{
			status = checkPolicyConstraints( subjectCertInfoPtr,
											 issuerAttributes );
			if( cryptStatusError( status ) )
				return( status );
			}
		}

	/* If it's not a self-signed cert, make sure that the issuer cert is of
	   the appropriate type */
	if( !( subjectCertInfoPtr->flags & CERT_FLAG_SELFSIGNED ) )
		{
		/* If there's a key usage attribute present, make sure the issuer can 
		   sign certs */
		attributeListPtr = findAttribute( issuerAttributes,
										  CRYPT_CERTINFO_KEYUSAGE );
		if( attributeListPtr != NULL )
			{
			if( !( attributeListPtr->value & issuerCertInfoPtr->trustedUsage & \
				   CRYPT_KEYUSAGE_KEYCERTSIGN ) )
				{
				setErrorInfo( subjectCertInfoPtr, 
						  ( attributeListPtr->value & CRYPT_KEYUSAGE_KEYCERTSIGN ) ? \
							CRYPT_CERTINFO_TRUSTED_USAGE : CRYPT_CERTINFO_KEYUSAGE,
						  CRYPT_ERRTYPE_ISSUERCONSTRAINT );
				return( CRYPT_ERROR_INVALID );
				}
			}
		else
			/* There's no key usage present, make sure the issuer is at least 
			   trusted to sign certs */
			if( !( issuerCertInfoPtr->trustedUsage & CRYPT_KEYUSAGE_KEYCERTSIGN ) )
				{
				setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_TRUSTED_USAGE,
							  CRYPT_ERRTYPE_ISSUERCONSTRAINT );
				return( CRYPT_ERROR_INVALID );
				}

		/* If a basic constraints attribute is present, make sure the issuer 
		   is a CA */
		if( findAttribute( issuerAttributes, CRYPT_CERTINFO_CA ) != NULL && \
			!issuerIsCA )
			{
			setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_CA,
						  CRYPT_ERRTYPE_ISSUERCONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}
		}
	else
		/* There is one special case in which a self-signed cert is regarded 
		   as an invalid issuer cert and that's when the cert is explicitly 
		   not trusted for this purpose */
		if( !( subjectCertInfoPtr->trustedUsage & CRYPT_KEYUSAGE_KEYCERTSIGN ) )
			{
			setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_TRUSTED_USAGE,
						  CRYPT_ERRTYPE_CONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}

	/* Remember that we've passed all the checks so we can avoid performing 
	   as many as possible again in the future */
	subjectCertInfoPtr->flags |= CERT_FLAG_CERTCHECKED;
	return( CRYPT_OK );
	}

/* Check that a key cert 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 which 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 RESOURCE_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;

	/* 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.  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 keyUsage usage is 
	   only valid once the request has been converted into a cert */
	if( certInfoPtr->type == CRYPT_CERTTYPE_CERTREQUEST )
		{
		if( exactUsage == RESOURCE_MESSAGE_CHECK_PKC_SIGCHECK )
			return( CRYPT_OK );
		if( errorLocus != NULL )
			{
			/* PKCS #10 requests have a single implicit trusted usage which
			   is sig-checking the self-signature on the object */
			*errorLocus = CRYPT_CERTINFO_TRUSTED_USAGE;
			*errorType = CRYPT_ERRTYPE_CONSTRAINT;
			}
		return( CRYPT_ERROR_INVALID );
		}

	/* If we're looking for a CA cert, make sure that either the 
	   basicConstraints CA flag is set or if there's no basicConstraints
	   present that it's a v1 self-signed cert.  We can't do a relatively
	   straightforward yes/no check for a self-signed v1 cert (which by 
	   convention is a CA root cert) because there are some (theoretically 
	   illegal) variations such as the presence of v3 extensions which can 
	   modify this, so we have to treat it as a special case of a v3 cert */
	if( exactUsage == RESOURCE_MESSAGE_CHECK_CA )
		{
		attributeListPtr = findAttributeField( certInfoPtr->attributes,
							CRYPT_CERTINFO_CA, CRYPT_ATTRIBUTE_NONE );
		if( attributeListPtr != NULL && \
			!( attributeListPtr->value || isV1selfSigned ) )
			{
			if( errorLocus != NULL )
				{
				*errorLocus = CRYPT_CERTINFO_CA;
				*errorType = CRYPT_ERRTYPE_CONSTRAINT;
				}
			return( CRYPT_ERROR_INVALID );
			}
		}

	/* Check and enforce the keyUsage attribute if there's one present */
	attributeListPtr = findAttributeField( certInfoPtr->attributes,
							CRYPT_CERTINFO_KEYUSAGE, CRYPT_ATTRIBUTE_NONE );
	if( attributeListPtr != NULL && keyUsage != CRYPT_UNUSED )
		{
		const int trustedUsage = \
					attributeListPtr->value & 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( 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 )
			{
			if( errorLocus != NULL )
				{
				*errorLocus = ( attributeListPtr->value & keyUsage ) ? \
					CRYPT_CERTINFO_TRUSTED_USAGE : CRYPT_CERTINFO_KEYUSAGE;
				*errorType = 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( keyUsage != CRYPT_UNUSED && \
			!( certInfoPtr->trustedUsage & keyUsage ) )
			{
			*errorLocus = CRYPT_CERTINFO_TRUSTED_USAGE;
			*errorType = CRYPT_ERRTYPE_CONSTRAINT;
			return( CRYPT_ERROR_INVALID );
			}

		/* If we're looking for a CA and there's no keyUsage attribute 
		   present, the cert either has to be v1 self-signed or an unsigned
		   (ie not-yet-completed) cert for which the appropriate key usage
		   will be added when the cert is signed */
		if( exactUsage == RESOURCE_MESSAGE_CHECK_CA && \
			!( isV1selfSigned || certInfoPtr->certificate == NULL ) )
			{
			if( errorLocus != NULL )
				{
				*errorLocus = CRYPT_CERTINFO_KEYUSAGE;
				*errorType = CRYPT_ERRTYPE_CONSTRAINT;
				}
			return( CRYPT_ERROR_INVALID );
			}
		}

	/* Check and enforce the privateKeyUsage attribute if there's one
	   present */
	if( findAttributeField( certInfoPtr->attributes,
			CRYPT_CERTINFO_PRIVATEKEYUSAGEPERIOD, CRYPT_ATTRIBUTE_NONE ) != NULL )
		{
		const time_t currentTime = time( NULL );

		attributeListPtr = findAttributeField( certInfoPtr->attributes,
				CRYPT_CERTINFO_PRIVATEKEY_NOTBEFORE, CRYPT_ATTRIBUTE_NONE );
		if( attributeListPtr != NULL && \
			currentTime < *( ( time_t * ) attributeListPtr->smallData ) )
			{
			*errorLocus = CRYPT_CERTINFO_PRIVATEKEY_NOTBEFORE;
			*errorType = 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->smallData ) )
			{
			if( errorLocus != NULL )
				{
				*errorLocus = CRYPT_CERTINFO_PRIVATEKEY_NOTAFTER;
				*errorType = CRYPT_ERRTYPE_CONSTRAINT;
				}
			return( CRYPT_ERROR_INVALID );
			}
		}

	return( CRYPT_OK );
	}

⌨️ 快捷键说明

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