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

📄 certsig.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 3 页
字号:
		   Optimising the query strategy is complicated by the fact that
		   although in theory the most common status will be not-revoked, we
		   could also get a large number of unknown queries, for example if
		   a widely-deployed implementation which is pointed at a cryptlib-
		   based server gets its ID-hashing wrong and submits huge numbers of
		   queries with IDs which match no known cert.  The best we can do is
		   assume that a not-revoked status will be the most common, and if 
		   that fails fall back to a revoked status check */
		setMessageKeymgmtInfo( &getkeyInfo, 
					( revocationInfo->type == CRYPT_CERTINFO_FINGERPRINT ) ? \
						CRYPT_IKEYID_CERTID : CRYPT_IKEYID_ISSUERID, 
					revocationInfo->dataPtr, KEYID_SIZE, NULL, 0,
					KEYMGMT_FLAG_CHECK_ONLY );
		status = krnlSendMessage( cryptKeyset, RESOURCE_IMESSAGE_KEY_GETKEY,
								  &getkeyInfo, KEYMGMT_ITEM_PUBLICKEY );
		if( cryptStatusOK( status ) )
			{
			/* The cert is present and not revoked, we're done */
			revocationInfo->status = CRYPT_OCSPSTATUS_NOTREVOKED;
			continue;
			}

		/* There cert isn't a currently active cert, if it weren't for the 
		   need to return the CRL-based OCSP status values we could just 
		   return not-OK now, but as it is we have to differentiate between
		   revoked and unknown, so we perform a second query, this time of
		   the revocation information */
		setMessageKeymgmtInfo( &getkeyInfo, 
					( revocationInfo->type == CRYPT_CERTINFO_FINGERPRINT ) ? \
						CRYPT_IKEYID_CERTID : CRYPT_IKEYID_ISSUERID, 
					revocationInfo->dataPtr, KEYID_SIZE, NULL, 0,
					KEYMGMT_FLAG_CHECK_ONLY );
		status = krnlSendMessage( cryptKeyset, RESOURCE_IMESSAGE_KEY_GETKEY,
								  &getkeyInfo, KEYMGMT_ITEM_REVOCATIONINFO );
		if( cryptStatusError( status ) )
			{
			/* No revocation information found, status is unknown */
			revocationInfo->status = CRYPT_OCSPSTATUS_UNKNOWN;
			continue;
			}

		/* The cert has been revoked, fetch revocation information */
/*	set rev.date as for CRL;
	set rev.status as _iattr_revstatus;
	(set reasoncode if nec); */
		revocationInfo->status = CRYPT_OCSPSTATUS_REVOKED;
		isRevoked = TRUE;
		}

	/* If at least one cert was revoked, indicate this to the caller.  Note
	   that if there are multiple certs present in the query, it's up to the
	   caller to step through the list to find out which ones were revoked */
	return( isRevoked ? CRYPT_ERROR_INVALID : CRYPT_OK );
	}

/* Check a certificate against a CRL */

static int checkCRL( CERT_INFO *certInfoPtr, const CRYPT_CERTIFICATE cryptCRL )
	{
	CERT_INFO *crlInfoPtr;
	int i, status;

	/* Check that the CRL is a full, signed CRL and not a newly-created CRL
	   object */
	getCheckResource( cryptCRL, crlInfoPtr, OBJECT_TYPE_CERTIFICATE,
					  CRYPT_ARGERROR_VALUE );
	if( crlInfoPtr->certificate == NULL )
		return( CRYPT_ERROR_NOTINITED );

	/* Check the base cert against the CRL.  If it's been revoked or there's
	   only a single cert present, exit */
	status = checkRevocation( certInfoPtr, crlInfoPtr );
	if( cryptStatusError( status ) || \
		certInfoPtr->type != CRYPT_CERTTYPE_CERTCHAIN )
		unlockResourceExit( crlInfoPtr, status );

	/* It's a cert chain, check every remaining cert in the chain against the
	   CRL */
	for( i = 0; i < certInfoPtr->certChainEnd; i++ )
		{
		CERT_INFO *certChainInfoPtr;

		/* Check this cert agains the CRL */
		getCheckInternalResource( certInfoPtr->certChain[ i ],
								  certChainInfoPtr, OBJECT_TYPE_CERTIFICATE );
		status = checkRevocation( certChainInfoPtr, crlInfoPtr );
		unlockResource( certChainInfoPtr );

		/* If the cert has been revoked, set the currently selected cert to
		   the revoked one */
		if( cryptStatusError( status ) )
			{
			certInfoPtr->certChainPos = i;
			break;
			}
		}

	unlockResourceExit( crlInfoPtr, status );
	}

/* Check the validity of a cert object, either against an issuing key/
   certificate or against a CRL */

int checkCertValidity( CERT_INFO *certInfoPtr, const CRYPT_HANDLE sigCheckKey )
	{
	CRYPT_CONTEXT cryptContext;
	CRYPT_CERTTYPE_TYPE sigCheckKeyType = CRYPT_ERROR;
	CERT_INFO *issuerCertInfoPtr = NULL;
	OBJECT_TYPE type;
	int status;

	/* If there's no signature checking key supplied, the cert must be self-
	   signed, either an implicitly self-signed object like a cert chain or
	   an explicitly self-signed object like a cert request or self-signed
	   cert */
	if( sigCheckKey == CRYPT_UNUSED )
		{
		/* If it's a cert chain, it's a (complex) self-signed object 
		   containing more than one cert so we need a special function to check 
		   the entire chain.  If not, it has to be explicitly self-signed */
		if( certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN )
			return( checkCertChain( certInfoPtr ) );
		if( !( certInfoPtr->flags & CERT_FLAG_SELFSIGNED ) )
			return( CRYPT_ARGERROR_VALUE );

		/* Check the signer details and signature */
		status = checkCert( certInfoPtr, certInfoPtr );	/* Issuer = subject */
		if( cryptStatusError( status ) )
			return( status );
		if( checkCertTrusted( certInfoPtr ) )
			/* It's an implicitly trusted cert, we don't need to go any 
			   further */
			return( CRYPT_OK );
		return( checkX509signature( certInfoPtr->certificate, 
									certInfoPtr->certificateSize, NULL, NULL,
									certInfoPtr->iCryptContext ) );
		}

	/* Find out what the sig.check object is */
	status = krnlSendMessage( sigCheckKey, RESOURCE_IMESSAGE_GETATTRIBUTE,
							  &type, CRYPT_IATTRIBUTE_TYPE );
	if( cryptStatusError( status ) )
		return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
				CRYPT_ARGERROR_VALUE : status );
	if( type == OBJECT_TYPE_CERTIFICATE )
		krnlSendMessage( sigCheckKey, RESOURCE_IMESSAGE_GETATTRIBUTE, 
						 &sigCheckKeyType, CRYPT_CERTINFO_CERTTYPE );

	/* Perform a general validity check on the object being checked and the
	   associated verification object.  This is somewhat more strict than 
	   the kernel checks since the kernel only knows about valid subtypes 
	   but not that some subtypes are only valid in combination with some 
	   types of object being checked */
	switch( type )
		{
		case OBJECT_TYPE_CERTIFICATE:
		case OBJECT_TYPE_CONTEXT:
			break;

		case OBJECT_TYPE_KEYSET:
			/* A keyset can only be used as a source of revocation 
			   information for checking a certificate or to populate the
			   revocation status fields of an OCSP response */
			if( certInfoPtr->type != CRYPT_CERTTYPE_CERTIFICATE && \
				certInfoPtr->type != CRYPT_CERTTYPE_ATTRIBUTE_CERT && \
				certInfoPtr->type != CRYPT_CERTTYPE_CERTCHAIN && \
				certInfoPtr->type != CRYPT_CERTTYPE_OCSP_RESPONSE )
				return( CRYPT_ARGERROR_VALUE );
			break;

		default:
			return( CRYPT_ARGERROR_VALUE );
		}

	/* If the checking key is a CRL or keyset which may contain a CRL then 
	   this is a revocation check which works rather differently from a 
	   straight signature check */
	if( type == OBJECT_TYPE_CERTIFICATE && \
		sigCheckKeyType == CRYPT_CERTTYPE_CRL )
		return( checkCRL( certInfoPtr, sigCheckKey ) );
	if( type == OBJECT_TYPE_KEYSET )
		{
		BYTE issuerID[ CRYPT_MAX_HASHSIZE ];

		/* If it's an OCSP response, use the certificate store to fill in the
		   revocation information fields */
		if( certInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE )
			return( checkOCSPResponse( certInfoPtr, sigCheckKey ) );

		assert( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \
				certInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \
				certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN );

		/* Generate the issuerID for this cert and check whether it's present 
		   in the CRL.  Since all we're interested in is a yes/no answer, we 
		   tell the keyset to perform a check only */
		status = generateCertID( certInfoPtr->issuerName, 
				certInfoPtr->serialNumber, certInfoPtr->serialNumberLength,
				issuerID );
		if( cryptStatusOK( status ) )
			{
			MESSAGE_KEYMGMT_INFO getkeyInfo;

			setMessageKeymgmtInfo( &getkeyInfo, CRYPT_IKEYID_ISSUERID, issuerID, 
								   KEYID_SIZE, NULL, 0, KEYMGMT_FLAG_CHECK_ONLY );
			status = krnlSendMessage( sigCheckKey, RESOURCE_IMESSAGE_KEY_GETKEY,
									  &getkeyInfo, KEYMGMT_ITEM_REVOCATIONINFO );

			/* Reverse the results of the check: OK -> certificate revoked, 
			   not found -> certificate not revoked */
			if( cryptStatusOK( status ) )
				status = CRYPT_ERROR_INVALID;
			else
				if( status == CRYPT_ERROR_NOTFOUND )
					status = CRYPT_OK;
			}

		return( status );
		}

	/* If we've been given a self-signed cert, make sure the sig check key is 
	   the same as the cert.  To test this we have to compare both the 
	   signing key and, if the sig check object is a cert, the cert */
	if( certInfoPtr->flags & CERT_FLAG_SELFSIGNED )
		{
		RESOURCE_DATA msgData;
		BYTE keyID[ KEYID_SIZE ];

		/* Check that the key in the cert and the key in the sig.check object 
		   are identical */
		setResourceData( &msgData, keyID, KEYID_SIZE );
		status = krnlSendMessage( sigCheckKey, RESOURCE_IMESSAGE_GETATTRIBUTE_S, 
								  &msgData, CRYPT_IATTRIBUTE_KEYID );
		if( cryptStatusOK( status ) )
			status = krnlSendMessage( certInfoPtr->objectHandle, 
									  RESOURCE_IMESSAGE_COMPARE, &msgData,
									  RESOURCE_MESSAGE_COMPARE_KEYID );
		if( cryptStatusError( status ) )
			return( CRYPT_ARGERROR_VALUE );

		/* If the sig.check object is a cert, check that it's identical to the
		   cert.  This may be somewhat stricter than required, but it'll weed
		   out technically valid but questionable combinations like a cert
		   request being used to validate a cert and misleading ones such as 
		   one cert chain being used to check a second chain */
		if( type == OBJECT_TYPE_CERTIFICATE )
			{
			status = krnlSendMessage( certInfoPtr->objectHandle, 
						RESOURCE_IMESSAGE_COMPARE, ( void * ) &sigCheckKey, 
						RESOURCE_MESSAGE_COMPARE_FINGERPRINT );
			if( cryptStatusError( status ) )
				return( CRYPT_ARGERROR_VALUE );
			}

		/* If it's a cert chain, it's a (complex) self-signed object 
		   containing more than one cert so we need a special function to check 
		   the entire chain */
		if( certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN )
			return( checkCertChain( certInfoPtr ) );

		/* Check the signer details and signature */
		status = checkCert( certInfoPtr, certInfoPtr );	/* Issuer = subject */
		if( cryptStatusError( status ) )
			return( status );
		if( checkCertTrusted( certInfoPtr ) )
			/* It's an implicitly trusted cert, we don't need to go any 
			   further */
			return( CRYPT_OK );
		return( checkX509signature( certInfoPtr->certificate, 
									certInfoPtr->certificateSize, NULL, NULL,
									certInfoPtr->iCryptContext ) );
		}

	/* The signature check key may be a certificate or a context.  If it's 
	   a cert, we get the issuer cert info and extract the context from it 
	   before continuing */
	if( type == OBJECT_TYPE_CERTIFICATE )
		{
		/* Get the context from the issuer certificate */
		status = krnlSendMessage( sigCheckKey, 
								  RESOURCE_IMESSAGE_GETDEPENDENT, 
								  &cryptContext, OBJECT_TYPE_CONTEXT );
		if( cryptStatusError( status ) )
			return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
					CRYPT_ARGERROR_VALUE : status );

		/* Lock the issuer certificate info */
		getCheckInternalResource2( sigCheckKey, issuerCertInfoPtr,
								   OBJECT_TYPE_CERTIFICATE, certInfoPtr );
		}
	else
		{
		CRYPT_CERTIFICATE localCert;

		cryptContext = sigCheckKey;

		/* It's a context, we may have a certificate present in it so we try 
		   to extract that and use it as the issuer certificate if possible.  
		   If the issuer cert isn't present this isn't an error, since it 
		   could be just a raw context */
		status = krnlSendMessage( sigCheckKey, RESOURCE_IMESSAGE_GETDEPENDENT,
								  &localCert, OBJECT_TYPE_CERTIFICATE );
		if( cryptStatusOK( status ) )
			getCheckInternalResource2( localCert, issuerCertInfoPtr,
									   OBJECT_TYPE_CERTIFICATE, certInfoPtr );
		}

	/* If there's an issuer certificate present, check the validity of the
	   subject cert based on it */
	if( issuerCertInfoPtr != NULL )
		{
		status = checkCert( certInfoPtr, issuerCertInfoPtr );
		unlockResource( issuerCertInfoPtr );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Check the signature */
	if( checkCertTrusted( certInfoPtr ) || \
		( certInfoPtr->flags & CERT_FLAG_SIGCHECKED ) )
		/* It's an implicitly trusted cert, we don't need to go any 
		   further */
		return( CRYPT_OK );
	status = checkX509signature( certInfoPtr->certificate, 
								 certInfoPtr->certificateSize, NULL, NULL,
								 cryptContext );
	if( cryptStatusOK( status ) )
		/* The signature is OK, we don't need to check it again */
		certInfoPtr->flags |= CERT_FLAG_SIGCHECKED;
	return( status );
	}

⌨️ 快捷键说明

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