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

📄 chk_cert.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 3 页
字号:
	   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 cert 
			   present */
			assert( isReadPtr( issuerCertInfoPtr, sizeof( CERT_INFO ) ) );
			if( subjectCertInfoPtr->flags & CERT_FLAG_CERTCOLLECTION )
				{
				/* Cert collections are pure container objects for which the 
				   base cert object doesn't correspond to an actual cert */
				assert( NOTREACHED );
				return( CRYPT_ERROR_INVALID );
				}
			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 cert 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 cert 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:
			assert( NOTREACHED );
			return( CRYPT_ERROR_INVALID );

		case CRYPT_CERTTYPE_RTCS_REQUEST:
		case CRYPT_CERTTYPE_RTCS_RESPONSE:
		case CRYPT_CERTTYPE_OCSP_REQUEST:
		case CRYPT_CERTTYPE_OCSP_RESPONSE:
			/* These aren't normal cert types, there's nothing to check - we
			   can't even check the issuer since they're not normally issued 
			   by CAs */
			return( CRYPT_OK );

		default:
			assert( NOTREACHED );
			return( CRYPT_ERROR_INVALID );
		}

	/* There is one universal case in which a cert is regarded as invalid 
	   and that's when it's explicitly not trusted for the purpose.  We
	   perform the check at this point in oblivious mode to ensure that only 
	   the basic trusted usage gets checked */
	if( issuerCertInfoPtr->cCertCert->trustedUsage != CRYPT_ERROR )
		{
		status = checkKeyUsage( issuerCertInfoPtr, CHECKKEY_FLAG_CA, 
								CRYPT_KEYUSAGE_KEYCERTSIGN,
								CRYPT_COMPLIANCELEVEL_OBLIVIOUS, 
								errorLocus, errorType );
		if( cryptStatusError( status ) )
			{
			/* There was a problem with the issuer cert, convert the problem 
			   to an issuer constraint */
			*errorType = CRYPT_ERRTYPE_ISSUERCONSTRAINT;
			return( status );
			}
		}

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

	/* If the cert isn't self-signed, check name chaining */
	if( !subjectSelfSigned )
		{
		/* Check that the subject issuer name and issuer subject name 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 we're doing a reduced level of checking, we're done */
	if( complianceLevel < CRYPT_COMPLIANCELEVEL_STANDARD )
		{
		if( subjectCertInfoPtr->cCertCert->maxCheckLevel < complianceLevel )
			subjectCertInfoPtr->cCertCert->maxCheckLevel = complianceLevel;
		return( CRYPT_OK );
		}

	/* Check that the cert usage flags are present and consistent.  The key 
	   usage checking level ranges up to CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL 
	   so we re-do the check even if it's already been done at a lower 
	   level */
	if( subjectCertInfoPtr->cCertCert->maxCheckLevel < CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL && \
		subjectCertInfoPtr->type != CRYPT_CERTTYPE_ATTRIBUTE_CERT )
		{
		status = checkKeyUsage( subjectCertInfoPtr, CHECKKEY_FLAG_GENCHECK, 
								CRYPT_UNUSED, complianceLevel, 
								errorLocus, errorType );
		if( cryptStatusError( status ) )
			return( status );
        }

	/* If the cert isn't self-signed, check that issuer is a CA */
	if( !subjectSelfSigned )
		{
		status = checkKeyUsage( issuerCertInfoPtr, CHECKKEY_FLAG_CA, 
								CRYPT_KEYUSAGE_KEYCERTSIGN, complianceLevel, 
								errorLocus, errorType );
		if( cryptStatusError( status ) )
			{
			/* There was a problem with the issuer cert, convert the problem 
			   to an issuer constraint */
			*errorType = CRYPT_ERRTYPE_ISSUERCONSTRAINT;
			return( status );
			}
		}

	/* Check all the blob (unrecognised) attributes to see if any are marked 
	   critical.  We only do this if it's an existing cert that we've
	   imported rather than one that we've just created, since applying this 
	   check to the latter would make it impossible to create certs with
	   unrecognised critical extensions */
	if( subjectCertInfoPtr->certificate != NULL )
		{
		for( attributeListPtr = subjectAttributes; \
			 attributeListPtr != NULL && !isBlobAttribute( attributeListPtr ); \
			 attributeListPtr = attributeListPtr->next );
		while( attributeListPtr != NULL )
			{
			/* If we've found an unrecognised critical extension, reject the 
			   cert (PKIX section 4.2).  The one exception to this is if the
			   attribute was recognised but has been ignored at this 
			   compliance level, in which case it's treated as a blob
			   attribute */
			if( ( attributeListPtr->flags & ATTR_FLAG_CRITICAL ) && \
				!( attributeListPtr->flags & ATTR_FLAG_IGNORED ) )
				{
				setErrorValues( CRYPT_ATTRIBUTE_NONE, 
								CRYPT_ERRTYPE_CONSTRAINT );
				return( CRYPT_ERROR_INVALID );
				}
			attributeListPtr = attributeListPtr->next;
			}
		}

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

	/* Constraints can only be present in CA certs.  The issuer may not be 
	   a proper CA if it's a self-signed end entity cert or an X.509v1 CA 
	   cert, which is why we also check for !issuerIsCA */
	if( !subjectIsCA && invalidAttributesPresent( subjectAttributes, FALSE, 
												  errorLocus, errorType ) )
		return( CRYPT_ERROR_INVALID );
	if( !issuerIsCA && invalidAttributesPresent( subjectAttributes, TRUE, 
												 errorLocus, errorType ) )
		return( CRYPT_ERROR_INVALID );

	/*  From this point onwards if we're doing a short-circuit check of 
	    certs in a chain we don't apply constraint checks.  This is because 
		the cert-chain code has already performed far more complete checks 
		of the various constraints set by all the certs in the chain rather 
		than just the current cert issuer : subject pair */

	/* If there's a path length constraint present, apply it */
	attributeListPtr = findAttributeField( issuerAttributes,
										   CRYPT_CERTINFO_PATHLENCONSTRAINT, 
										   CRYPT_ATTRIBUTE_NONE );
	if( attributeListPtr != NULL && !shortCircuitCheck )
		{
		status = checkPathConstraints( subjectCertInfoPtr, attributeListPtr,
									   complianceLevel, errorLocus, 
									   errorType );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* In order to dig itself out of a hole caused by a circular definition, 
	   RFC 3280 added a new extKeyUsage anyExtendedKeyUsage (rather than the
	   more obvious fix of removing the problematic definition).  
	   Unfortunately this causes more problems than it solves because the exact
	   semantics of this new usage aren't precisely defined.  To fix this 
	   problem we invent some plausible ones ourselves: If the only eKU is 
	   anyKU, we treat the overall extKeyUsage as empty, i.e. there are no
	   particular restrictions on usage.  If any other usage is present the 
	   extension has become self-contradictory, so we treat the anyKU as
	   being absent.  See the comment for getExtendedKeyUsageFlags() for how
	   this is handled */
	attributeListPtr = findAttributeField( subjectAttributes,
										   CRYPT_CERTINFO_EXTKEY_ANYKEYUSAGE, 
										   CRYPT_ATTRIBUTE_NONE );
	if( attributeListPtr != NULL && \
		( attributeListPtr->flags & ATTR_FLAG_CRITICAL ) )
		{
		/* If anyKU is present the extension must be non-critical 
		   (PKIX section 4.2.1.13) */
		setErrorValues( CRYPT_CERTINFO_EXTKEY_ANYKEYUSAGE, 
						CRYPT_ERRTYPE_CONSTRAINT );
		return( CRYPT_ERROR_INVALID );
		}

	/* If we're not doing full PKIX checking, we're done.  In addition since 
	   all of the remaining checks are constraint checks we can exit at this
	   point if we're doing a short-circuit check */
	if( complianceLevel < CRYPT_COMPLIANCELEVEL_PKIX_FULL || \
		shortCircuitCheck )
		{
		if( subjectCertInfoPtr->cCertCert->maxCheckLevel < complianceLevel )
			subjectCertInfoPtr->cCertCert->maxCheckLevel = complianceLevel;
		return( CRYPT_OK );
		}

	/* 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( !subjectSelfSigned )
		{
		attributeListPtr = findAttributeField( issuerAttributes, 
											   CRYPT_CERTINFO_EXCLUDEDSUBTREES,
											   CRYPT_ATTRIBUTE_NONE );
		if( attributeListPtr != NULL && \
			cryptStatusError( \
				checkNameConstraints( subjectCertInfoPtr, attributeListPtr, 
									  TRUE, errorLocus, errorType ) ) )
			return( CRYPT_ERROR_INVALID );
		attributeListPtr = findAttributeField( issuerAttributes, 
											   CRYPT_CERTINFO_PERMITTEDSUBTREES,
											   CRYPT_ATTRIBUTE_NONE );
		if( attributeListPtr != NULL && \
			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 )
		{
		POLICY_TYPE policyType = POLICY_SUBJECT;

		/* Check whether use of the the wildcard anyPolicy has been 
		   disallowed */
		attributeListPtr = findAttribute( issuerCertInfoPtr->attributes, \
										  CRYPT_CERTINFO_INHIBITANYPOLICY, 
										  TRUE );
		if( attributeListPtr != NULL && attributeListPtr->intValue <= 0 )
			policyType = POLICY_SUBJECT_SPECIFIC;

		/* Apply the appropriate policy constraint */
		status = checkPolicyConstraints( subjectCertInfoPtr,
										 issuerAttributes, policyType,
										 errorLocus, errorType );
		if( cryptStatusError( status ) )
			return( status );
		}

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

⌨️ 快捷键说明

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