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

📄 certchk.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 4 页
字号:
			/* Some even more broken certs indicate their usage via a 
			   Netscape key usage (even though they use X.509 flags 
			   everywhere else), which means that we fail them if we're 
			   strictly applying the PKIX requirements at a higher compliance
			   level.  At this lower level we try for Netscape usage if we 
			   can't find anything else, and if there's one present, use the 
			   translated values as if they were the X.509 usage */
			if( isCryptAlgo( certInfoPtr->publicKeyAlgo ) )
				algorithmType = ALGO_TYPE_CRYPT;
			if( isSigAlgo( certInfoPtr->publicKeyAlgo ) )
				algorithmType |= ALGO_TYPE_SIGN;
			if( isKeyxAlgo( certInfoPtr->publicKeyAlgo ) )
				algorithmType |= ALGO_TYPE_KEYAGREEMENT;
			netscapeUsage = getNetscapeCertTypeFlags( certInfoPtr->attributes,
													  algorithmType, errorLocus );
			if( netscapeUsage > 0 )
				keyUsage = netscapeUsage;
			}
		}

	/* If the CA flag is set, make sure that there's a keyUsage with one of 
	   the CA usages present.  Conversely, if there are CA key usages 
	   present, make sure that the CA flag is set.  The CA flag is actually a 
	   leftover from an early v3 cert concept and is made entirely redundant 
	   by the keyUsage flags, but we have to check it regardless */
	if( isCA )
		{
		if( !( ( extKeyUsage | keyUsage ) & \
			   ( CRYPT_KEYUSAGE_CRLSIGN | CRYPT_KEYUSAGE_KEYCERTSIGN ) ) )
			{
			setErrorValues( CRYPT_CERTINFO_KEYUSAGE, 
							CRYPT_ERRTYPE_CONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}
		}	
	else
		if( ( extKeyUsage | keyUsage ) & \
			( CRYPT_KEYUSAGE_CRLSIGN | CRYPT_KEYUSAGE_KEYCERTSIGN ) )
			{
			setErrorValues( CRYPT_CERTINFO_CA, CRYPT_ERRTYPE_CONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}
		
	/* Make sure that mutually exclusive flags aren't set */
	if( ( keyUsage & CRYPT_KEYUSAGE_ENCIPHERONLY ) && \
		( keyUsage & CRYPT_KEYUSAGE_DECIPHERONLY ) )
		{
		setErrorValues( CRYPT_CERTINFO_KEYUSAGE, CRYPT_ERRTYPE_ATTR_VALUE );
		return( CRYPT_ERROR_INVALID );
		}

	/* Make sure that the keyUsage flags represent capabilities that the 
	   algorithm is actually capable of */
	if( ( ( keyUsage & USAGE_CRYPT_MASK ) && \
			!isCryptAlgo( certInfoPtr->publicKeyAlgo ) ) || \
		( ( keyUsage & USAGE_SIGN_MASK ) && \
			!isSigAlgo( certInfoPtr->publicKeyAlgo ) ) || \
		( ( keyUsage & USAGE_KEYAGREEMENT_MASK ) && \
			!isKeyxAlgo( certInfoPtr->publicKeyAlgo ) ) )
		{
		setErrorValues( CRYPT_CERTINFO_KEYUSAGE, CRYPT_ERRTYPE_ATTR_VALUE );
		return( CRYPT_ERROR_INVALID );
		}

	/* Mask out any non-relevant usages (e.g. cert signing, which doesn't 
	   occur in extended key usages and has already been checked above) */
	extKeyUsage &= ~USAGE_MASK_NONRELEVANT;
	keyUsage &= ~USAGE_MASK_NONRELEVANT;

	/* If there's no key usage based on extended key usage present or we're 
	   not doing a PKIX-compliant check, there's nothing further to check */
	if( !extKeyUsage || complianceLevel < CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL )
		return( CRYPT_OK );

	/* If the usage and extended usage are critical (but only if both are 
	   critical, because PKIX says so) make sure that the given usage is 
	   consistent with the required usage.  Checking whether the extended 
	   usage is critical is a bit nontrivial, we have to check each possible
	   extended usage since only one of them may be present, so we check the
	   criticality of the basic key usage first to allow quick short-circuit
	   evaluation.
	   
	   In addition to the explicit criticality checks, we also perform an
	   implicit check based on whether this is a freshly-generated, as-yet-
	   unsigned cryptlib cert.  This is done for two reasons, firstly because 
	   an unsigned cert won't have had the criticality flag set by the
	   signing/encoding process so the extension always appears non-critical, 
	   and secondly because we don't want cryptlib to generate inconsistent 
	   certs, whether the extensions are marked critical or not (cryptlib
	   always makes the keyUsage critical, so at least for key usage it's
	   no change from the standard behaviour) */
	if( certInfoPtr->certificate != NULL )
		{
		int attributeID;

		if( !keyUsageCritical )
			/* No critical key usage, return */
			return( CRYPT_OK );
		for( attributeID = CRYPT_CERTINFO_EXTKEYUSAGE + 1; 
			 attributeID < CRYPT_CERTINFO_NS_CERTTYPE; attributeID++ )
			{
			attributeListPtr = findAttributeField( certInfoPtr->attributes,
										attributeID, CRYPT_ATTRIBUTE_NONE );
			if( attributeListPtr != NULL && \
				!( attributeListPtr->flags & ATTR_FLAG_CRITICAL ) )
				/* We found an extended key usage and it's non-critical 
				   (which means that all extended usages are non-critical), 
				   return */
				return( CRYPT_OK );
			}
		}

	/* Make sure that the extended key usage-based key usage is consistent 
	   with the actual key usage */
	if( ( keyUsage & extKeyUsage ) != extKeyUsage )
		{
		setErrorValues( CRYPT_CERTINFO_KEYUSAGE, CRYPT_ERRTYPE_CONSTRAINT );
		return( CRYPT_ERROR_INVALID );
		}

	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*							Name Comparison Routines						*
*																			*
****************************************************************************/

/* Compare two attribute components */

static BOOLEAN compareAttributeComponents( const ATTRIBUTE_LIST *attribute1ptr,
										   const ATTRIBUTE_LIST *attribute2ptr )
	{
	/* Make sure either both are absent or present */
	if( attribute1ptr != NULL )
		{
		if( attribute2ptr == NULL )
			return( FALSE );	/* Both must be present or absent */
		}
	else
		{
		if( attribute2ptr != NULL )
			return( FALSE );	/* Both must be present or absent */
		return( TRUE );
		}

	/* If it's an attribute containing a composite field, use a special-case
	   compare */
	if( attribute1ptr->fieldType == FIELDTYPE_DN )
		return( compareDN( attribute1ptr->value, attribute2ptr->value, FALSE ) );

	/* Compare the data values */
	if( attribute1ptr->valueLength != attribute2ptr->valueLength || \
		memcmp( attribute1ptr->value, attribute2ptr->value, 
				attribute1ptr->valueLength ) )
		return( FALSE );

	return( TRUE );
	}

/* Compare two altNames component by component */

static CRYPT_ATTRIBUTE_TYPE compareAltNames( const ATTRIBUTE_LIST *subjectAttributes,
											 const ATTRIBUTE_LIST *issuerAttributes )
	{
	ATTRIBUTE_LIST *subjectAttributeListPtr, *issuerAttributeListPtr;

	/* Check the otherName */
	subjectAttributeListPtr = findAttributeField( subjectAttributes,
			CRYPT_CERTINFO_ISSUERALTNAME, CRYPT_CERTINFO_OTHERNAME_TYPEID );
	issuerAttributeListPtr = findAttributeField( issuerAttributes,
			CRYPT_CERTINFO_SUBJECTALTNAME, CRYPT_CERTINFO_OTHERNAME_TYPEID );
	if( !compareAttributeComponents( subjectAttributeListPtr,
									 issuerAttributeListPtr ) )
		return( CRYPT_CERTINFO_OTHERNAME_TYPEID );
	subjectAttributeListPtr = findAttributeField( subjectAttributes,
			CRYPT_CERTINFO_ISSUERALTNAME, CRYPT_CERTINFO_OTHERNAME_VALUE );
	issuerAttributeListPtr = findAttributeField( issuerAttributes,
			CRYPT_CERTINFO_SUBJECTALTNAME, CRYPT_CERTINFO_OTHERNAME_VALUE );
	if( !compareAttributeComponents( subjectAttributeListPtr,
									 issuerAttributeListPtr ) )
		return( CRYPT_CERTINFO_OTHERNAME_VALUE );

	/* Check the email address */
	subjectAttributeListPtr = findAttributeField( subjectAttributes,
			CRYPT_CERTINFO_ISSUERALTNAME, CRYPT_CERTINFO_RFC822NAME );
	issuerAttributeListPtr = findAttributeField( issuerAttributes,
			CRYPT_CERTINFO_SUBJECTALTNAME, CRYPT_CERTINFO_RFC822NAME );
	if( !compareAttributeComponents( subjectAttributeListPtr,
									 issuerAttributeListPtr ) )
		return( CRYPT_CERTINFO_RFC822NAME );

	/* Check the DNS name */
	subjectAttributeListPtr = findAttributeField( subjectAttributes,
			CRYPT_CERTINFO_ISSUERALTNAME, CRYPT_CERTINFO_DNSNAME );
	issuerAttributeListPtr = findAttributeField( issuerAttributes,
			CRYPT_CERTINFO_SUBJECTALTNAME, CRYPT_CERTINFO_DNSNAME );
	if( !compareAttributeComponents( subjectAttributeListPtr,
									 issuerAttributeListPtr ) )
		return( CRYPT_CERTINFO_DNSNAME );

	/* Check the directory name */
	subjectAttributeListPtr = findAttributeField( subjectAttributes,
			CRYPT_CERTINFO_ISSUERALTNAME, CRYPT_CERTINFO_DIRECTORYNAME );
	issuerAttributeListPtr = findAttributeField( issuerAttributes,
			CRYPT_CERTINFO_SUBJECTALTNAME, CRYPT_CERTINFO_DIRECTORYNAME );
	if( !compareAttributeComponents( subjectAttributeListPtr,
									 issuerAttributeListPtr ) )
		return( CRYPT_CERTINFO_DIRECTORYNAME );

	/* Check the EDI party name */
	subjectAttributeListPtr = findAttributeField( subjectAttributes,
			CRYPT_CERTINFO_ISSUERALTNAME, CRYPT_CERTINFO_EDIPARTYNAME_NAMEASSIGNER );
	issuerAttributeListPtr = findAttributeField( issuerAttributes,
			CRYPT_CERTINFO_SUBJECTALTNAME, CRYPT_CERTINFO_EDIPARTYNAME_NAMEASSIGNER );
	if( !compareAttributeComponents( subjectAttributeListPtr,
									 issuerAttributeListPtr ) )
		return( CRYPT_CERTINFO_EDIPARTYNAME_NAMEASSIGNER );
	subjectAttributeListPtr = findAttributeField( subjectAttributes,
			CRYPT_CERTINFO_ISSUERALTNAME, CRYPT_CERTINFO_EDIPARTYNAME_PARTYNAME );
	issuerAttributeListPtr = findAttributeField( issuerAttributes,
			CRYPT_CERTINFO_SUBJECTALTNAME, CRYPT_CERTINFO_EDIPARTYNAME_PARTYNAME );
	if( !compareAttributeComponents( subjectAttributeListPtr,
									 issuerAttributeListPtr ) )
		return( CRYPT_CERTINFO_EDIPARTYNAME_PARTYNAME );

	/* Check the URI */
	subjectAttributeListPtr = findAttributeField( subjectAttributes,
			CRYPT_CERTINFO_ISSUERALTNAME, CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER );
	issuerAttributeListPtr = findAttributeField( issuerAttributes,
			CRYPT_CERTINFO_SUBJECTALTNAME, CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER );
	if( !compareAttributeComponents( subjectAttributeListPtr,
									 issuerAttributeListPtr ) )
		return( CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER );

	/* Check the IP address */
	subjectAttributeListPtr = findAttributeField( subjectAttributes,
			CRYPT_CERTINFO_ISSUERALTNAME, CRYPT_CERTINFO_IPADDRESS );
	issuerAttributeListPtr = findAttributeField( issuerAttributes,
			CRYPT_CERTINFO_SUBJECTALTNAME, CRYPT_CERTINFO_IPADDRESS );
	if( !compareAttributeComponents( subjectAttributeListPtr,
									 issuerAttributeListPtr ) )
		return( CRYPT_CERTINFO_IPADDRESS );

	/* Check the registered ID */
	subjectAttributeListPtr = findAttributeField( subjectAttributes,
			CRYPT_CERTINFO_ISSUERALTNAME, CRYPT_CERTINFO_REGISTEREDID );
	issuerAttributeListPtr = findAttributeField( issuerAttributes,
			CRYPT_CERTINFO_SUBJECTALTNAME, CRYPT_CERTINFO_REGISTEREDID );
	if( !compareAttributeComponents( subjectAttributeListPtr,
									 issuerAttributeListPtr ) )
		return( CRYPT_CERTINFO_REGISTEREDID );

	return( CRYPT_ATTRIBUTE_NONE );
	}

/* Perform a wildcarded compare of two strings in attributes */

static BOOLEAN wildcardStringMatch( const char *wildcardString, 
									const char *string )
	{
	while( *wildcardString && *string )
		{
		/* Match a wildcard */
		if( *wildcardString == '*' )
			{
			BOOLEAN isMatch = FALSE;

			/* Skip '*'s and exit if we've reached the end of the pattern */
			while( *wildcardString == '*' )
				wildcardString++;
			if( !*wildcardString )
				return( TRUE );

			/* Match to the next literal, then match the next section with
			   backtracking in case of a mismatch */
			while( *string && *wildcardString != *string )
				string++;
			while( *string && !isMatch )
				{
				isMatch = wildcardStringMatch( wildcardString, string );
				if( !isMatch )
					string++;
				}

			return( isMatch );
			}
		else
			if( *wildcardString != *string )
				return( FALSE );

		wildcardString++;
		string++;
		}

	/* If there are literals left in the wildcard or text string, we haven't
	   found a match yet */
	if( *wildcardString && ( *wildcardString != '*' || *++wildcardString ) )
		return( FALSE );
	return( *string ? FALSE : TRUE );
	}

static BOOLEAN wildcardMatch( const ATTRIBUTE_LIST *constrainedAttribute,
							  const ATTRIBUTE_LIST *attribute,
							  const BOOLEAN errorStatus )
	{
	const char *string = attribute->value;
	int count = 0, i;

	/* Perform a quick damage-control check to prevent excessive recursion:
	   There shouldn't be more than ten wildcard chars present (realistically
	   there shouldn't be more than one) */
	for( i = 0; string[ i ]; i++ )
		if( string[ i ] == '*' )
			count++;
	if( count > 10 )
		return( errorStatus );

	/* Pass the call on to the string matcher (this is recursive so we can't
	   do the match in this function) */
	return( wildcardStringMatch( string, constrainedAttribute->value ) );
	}

/* Check name constraints placed by an issuer, checked if complianceLevel >=
   CRYPT_COMPLIANCELEVEL_PKIX_FULL.  matchValue = TRUE for excluded subtrees 
   (fail on a match), FALSE for included subtrees (fail on a mismatch) */

int checkNameConstraints( const CERT_INFO *subjectCertInfoPtr,
						  const ATTRIBUTE_LIST *issuerAttributes,
						  const BOOLEAN matchValue,
						  CRYPT_ATTRIBUTE_TYPE *errorLocus, 
						  CRYPT_ERRTYPE_TYPE *errorType )
	{
	const ATTRIBUTE_LIST *subjectAttributes = subjectCertInfoPtr->attributes;
	const CRYPT_ATTRIBUTE_TYPE constraintType = matchValue ? \
		CRYPT_CERTINFO_EXCLUDEDSUBTREES : CRYPT_CERTINFO_PERMITTEDSUBTREES;
	ATTRIBUTE_LIST *attributeListPtr, *constrainedAttributeListPtr;
	int status = CRYPT_OK;

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

	/* Compare the DN if a constraint exists */
	attributeListPtr = findAttributeField( issuerAttributes,
							constraintType, CRYPT_CERTINFO_DIRECTORYNAME );
	if( compareDN( subjectCertInfoPtr->subjectName,
				   attributeListPtr->value, TRUE ) == matchValue )
		{
		setErrorValues( CRYPT_CERTINFO_SUBJECTNAME, 
						CRYPT_ERRTYPE_CONSTRAINT );
		return( CRYPT_ERROR_INVALID );
		}

	/* Compare the Internet-related names if constraints exist */
	attributeListPtr = findAttributeField( issuerAttributes,
							constraintType, CRYPT_CERTINFO_RFC822NAME );

⌨️ 快捷键说明

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