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

📄 chk_use.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 3 页
字号:
	   was made explicit in RFC 3280.  If we're running at a reduced 
	   compliance level then the settings will have been adjusted as 
	   required earlier on */
	if( flags & CHECKKEY_FLAG_CA )
		{
		if( !isCA )
			{
			setErrorValues( CRYPT_CERTINFO_CA, CRYPT_ERRTYPE_CONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}
		if( !( caKeyUsage & specificUsage ) )
			{
			setErrorValues( CRYPT_CERTINFO_KEYUSAGE, 
							CRYPT_ERRTYPE_CONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}
		}

	/* There is one universal case in which a key is regarded as invalid for
	   the requested use and that's when it's explicitly not trusted for the 
	   purpose */
	if( specificUsage != CRYPT_KEYUSAGE_NONE && \
		trustedUsage != CRYPT_UNUSED && !( specificUsage & keyUsage ) )
		{
		setErrorValues( CRYPT_CERTINFO_TRUSTED_USAGE,
						CRYPT_ERRTYPE_CONSTRAINT );
		return( CRYPT_ERROR_INVALID );
		}

	/* If we're doing a reduced level of checking, we're done */
	if( complianceLevel < CRYPT_COMPLIANCELEVEL_STANDARD )
		return( CRYPT_OK );

	/* If we're being asked to check for private-key constraints, check and 
	   enforce the privateKeyUsage attribute if there's one present */
	if( ( flags & CHECKKEY_FLAG_PRIVATEKEY ) && \
		checkAttributePresent( certInfoPtr->attributes,
							   CRYPT_CERTINFO_PRIVATEKEYUSAGEPERIOD ) )
		{
		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 );
			}
		}

	/* If we're just performing a key-usability check rather than a general
	   check that the key usage is in order, we're done */
	if( !isGeneralCheck )
		return( CRYPT_OK );

	/* Phase 3: Consistency check */

	/* 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.  In other words this
	   check tests for an XOR relation, ( CA && kU ) || ( !CA && !kU ).
	   
	   The CA flag is actually a leftover from an early v3 certificate 
	   concept and is made entirely redundant by the keyUsage flags but we 
	   have to check it regardless (PKIX sections 4.2.1.3 and 4.2.1.10).  
	   RFC 2459 left this open, it was made explicit in RFC 3280 */
	if( isCA )
		{
		/* It's a CA certificate, make sure that a CA keyUsage is set */
		if( !( caKeyUsage | extKeyUsage ) )
			{
			setErrorValues( CRYPT_CERTINFO_KEYUSAGE, 
							CRYPT_ERRTYPE_CONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}
		}	
	else
		{
		/* It's a non-CA certificate, make sure that no CA keyUsage is set */
		if( ( caKeyUsage | extKeyUsage ) & ( CRYPT_KEYUSAGE_CRLSIGN | \
											 CRYPT_KEYUSAGE_KEYCERTSIGN ) )
			{
			setErrorValues( CRYPT_CERTINFO_CA, CRYPT_ERRTYPE_CONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}
		}

	/* Check and enforce the keyUsage if required (PKIX section 4.2.1.3).  
	   RFC 2459 included some waffly text about critical vs. non-critical 
	   usage, RFC 3280 made this explicit regardless of criticality */
	if( specificUsage != CRYPT_KEYUSAGE_NONE )
		{
		BOOLEAN usageOK = FALSE;

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

			if( ( keyUsage & specificUsage ) && !( keyUsage & excludedUsage ) )
				usageOK = TRUE;
			}
		else
			{
			/* Conventional usage flag, do a straight check */
			if( keyUsage & specificUsage )
				usageOK = TRUE;
			}
		if( !usageOK )
			{
			setErrorValues( ( rawKeyUsage & specificUsage ) ? \
								CRYPT_CERTINFO_TRUSTED_USAGE : \
								CRYPT_CERTINFO_KEYUSAGE,
							CRYPT_ERRTYPE_CONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}
		}

	/* Switch back to the original usage values (before adjustment by 
	   trusted-usage values) because after this point we're performing 
	   consistency checks on the values and need to check all of the bits */
	keyUsage = rawKeyUsage;
	extKeyUsage = rawExtKeyUsage;
	   		
	/* Make sure that mutually exclusive flags aren't set (RFC 3279 section 
	   2.3.3) */
	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.  RFC 2459 included some waffly text
	   about critical vs. non-critical usage, RFC 3280 made this explicit
	   regardless of criticality, although the details were actually moved
	   into RFC 3279, which specifies the algorithms used in PKIX */
	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. certificate signing, which 
	   doesn't occur in extended key usages and has already been checked 
	   above) */
	keyUsage &= ~USAGE_MASK_NONRELEVANT;
	extKeyUsage &= ~USAGE_MASK_NONRELEVANT;

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

	/* If the CA key usages are set then an encryption key usage shouldn't 
	   be set (RFC 3279 section 2.3.1) */
	if( isCA && \
		( keyUsage & extKeyUsage & ( CRYPT_KEYUSAGE_KEYENCIPHERMENT | \
									 CRYPT_KEYUSAGE_DATAENCIPHERMENT ) ) )
		{
		setErrorValues( CRYPT_CERTINFO_KEYUSAGE, CRYPT_ERRTYPE_CONSTRAINT );
		return( CRYPT_ERROR_INVALID );
		}

	/* 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 (PKIX section 4.2.1.13).  To 
	   perform this check we first check for situations where we *don't* 
	   have to perform the check and only if none of these occur do we 
	   perform the actual check.
	   
	   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 certificate.  This is done for two reasons, firstly 
	   because an unsigned certificate 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 certificates, 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 there's no critical key usage present we can exit without
		   performing further checks */
		if( !keyUsageCritical )
			return( CRYPT_OK );

		/* If we find an extended key usage and it's non-critical (which 
		   means that all extended usages are non-critical since they're
		   all in the same extension), return */
		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 ) )
				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 );
		}

	/* If the encipherOnly or decipherOnly bits are set then the 
	   keyAgreement bit most also be set (PKIX section 4.2.1.3).  Actually 
	   the spec merely says "undefined" but we interpret this to mean that 
	   they should be consistent.  This situation occurs because the 
	   encipher/decipher-only usages were tacked on as modifiers long after 
	   keyAgreement was defined and make it entirely redundant, in the same 
	   way that the CA keyUsages make the basicConstraints CA flag 
	   redundant */
	if( ( keyUsage & ( CRYPT_KEYUSAGE_ENCIPHERONLY | \
					   CRYPT_KEYUSAGE_DECIPHERONLY ) ) && \
		!( keyUsage & CRYPT_KEYUSAGE_KEYAGREEMENT ) )
		{
		setErrorValues( CRYPT_CERTINFO_KEYUSAGE, CRYPT_ERRTYPE_ATTR_VALUE );
		return( CRYPT_ERROR_INVALID );
		}

	return( CRYPT_OK );
	}

⌨️ 快捷键说明

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