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

📄 certsig.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 4 页
字号:
   issuerID, which is an SHA-1 hash of the IssuerAndSerialNumber and is used 
   for CRLs and CMS */

static int generateCertID( const void *dn, const int dnLength,
						   const void *serialNumber,
						   const int serialNumberLength, BYTE *certID )
	{
	HASHFUNCTION hashFunction;
	HASHINFO hashInfo;
	STREAM stream;
	BYTE buffer[ MAX_SERIALNO_SIZE + 8 ];
	int status;

	assert( isReadPtr( dn, dnLength ) );
	assert( ( serialNumber == NULL && serialNumberLength == 0 ) || \
			( isReadPtr( serialNumber, serialNumberLength ) && \
			  serialNumberLength <= MAX_SERIALNO_SIZE ) );

	/* Get the hash algorithm information */
	getHashParameters( CRYPT_ALGO_SHA, &hashFunction, NULL );

	/* If it's a pure DN hash, we don't have to perform any encoding */
	if( serialNumber == NULL )
		{
		hashFunction( NULL, certID, dn, dnLength, HASH_ALL );
		return( CRYPT_OK );
		}

	/* Write the relevant information to a buffer and hash the data to get
	   the ID */
	sMemOpen( &stream, buffer, MAX_SERIALNO_SIZE + 8 );
	writeSequence( &stream, dnLength + \
							sizeofInteger( serialNumber, serialNumberLength ) );
	hashFunction( hashInfo, NULL, buffer, stell( &stream ), HASH_START );
	hashFunction( hashInfo, NULL, dn, dnLength, HASH_CONTINUE );
	sseek( &stream, 0 );
	status = writeInteger( &stream, serialNumber, serialNumberLength, 
						   DEFAULT_TAG );
	hashFunction( hashInfo, certID, buffer, stell( &stream ), HASH_END );
	sMemClose( &stream );

	return( status );
	}

/* Check the entries in an RTCS or OCSP response object against a cert 
   store.  The semantics for this one are a bit odd, the source information 
   for the check is from a request, but the destination information is in a 
   response, since we don't have a copy-and-verify function we do the 
   checking from the response even though, technically, it's the request 
   data which is being checked */

int checkRTCSResponse( CERT_INFO *certInfoPtr, 
					   const CRYPT_KEYSET cryptKeyset )
	{
	VALIDITY_INFO *validityInfo;
	BOOLEAN isInvalid = FALSE;

	/* Walk down the list of validity entries fetching status information 
	   on each one from the cert store */
	for( validityInfo = certInfoPtr->validityInfo;
		 validityInfo != NULL; validityInfo = validityInfo->next )
		{
		MESSAGE_KEYMGMT_INFO getkeyInfo;
		int status;

		/* Determine the validity of the object */
		setMessageKeymgmtInfo( &getkeyInfo, CRYPT_IKEYID_CERTID, 
							   validityInfo->data, KEYID_SIZE, NULL, 0,
							   KEYMGMT_FLAG_CHECK_ONLY );
		status = krnlSendMessage( cryptKeyset, IMESSAGE_KEY_GETKEY,
								  &getkeyInfo, KEYMGMT_ITEM_PUBLICKEY );
		if( cryptStatusOK( status ) )
			{
			/* The cert is present and OK, we're done */
			validityInfo->status = TRUE;
			validityInfo->extStatus = CRYPT_CERTSTATUS_VALID;
			}
		else
			{
			/* The cert isn't present/OK, record the fact that we've seen at 
			   least one invalid cert */
			validityInfo->status = FALSE;
			validityInfo->extStatus = CRYPT_CERTSTATUS_NOTVALID;
			isInvalid = TRUE;
			}
		}

	/* If at least one cert was invalid, 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 invalid */
	return( isInvalid ? CRYPT_ERROR_INVALID : CRYPT_OK );
	}

int checkOCSPResponse( CERT_INFO *certInfoPtr, 
					   const CRYPT_KEYSET cryptKeyset )
	{
	REVOCATION_INFO *revocationInfo;
	BOOLEAN isRevoked = FALSE;

	/* Walk down the list of revocation entries fetching status information 
	   on each one from the cert store */
	for( revocationInfo = certInfoPtr->revocations;
		 revocationInfo != NULL; revocationInfo = revocationInfo->next )
		{
		MESSAGE_KEYMGMT_INFO getkeyInfo;
		CERT_INFO *crlEntryInfoPtr;
		REVOCATION_INFO *crlRevocationInfo;
		int status;

		assert( revocationInfo->type == CRYPT_KEYID_NONE || \
				revocationInfo->type == CRYPT_IKEYID_CERTID || \
				revocationInfo->type == CRYPT_IKEYID_ISSUERID );

		/* If it's an OCSPv1 ID, we can't really do anything with it because
		   the one-way hashing process required by the standard destroys the 
		   information */
		if( revocationInfo->type == CRYPT_KEYID_NONE )
			{
			revocationInfo->status = CRYPT_OCSPSTATUS_UNKNOWN;
			continue;
			}

		/* Determine the revocation status of the object.  Unfortunately
		   because of the way OCSP returns status information we can't just
		   return a yes/no response but have to perform multiple queries to
		   determine whether a cert is not revoked, revoked, or unknown.
		   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 that 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,
							   revocationInfo->dataPtr, KEYID_SIZE, NULL, 0,
							   KEYMGMT_FLAG_CHECK_ONLY );
		status = krnlSendMessage( cryptKeyset, IMESSAGE_KEY_GETKEY,
								  &getkeyInfo, KEYMGMT_ITEM_PUBLICKEY );
		if( cryptStatusOK( status ) )
			{
			/* The cert is present and not revoked/OK, we're done */
			revocationInfo->status = CRYPT_OCSPSTATUS_NOTREVOKED;
			continue;
			}

		/* The 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, 
							   revocationInfo->dataPtr, KEYID_SIZE, NULL, 0,
							   KEYMGMT_FLAG_NONE );
		status = krnlSendMessage( cryptKeyset, 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, copy the revocation information across
		   from the CRL entry.  We don't check for problems in copying the
		   attributes since bailing out at this late stage is worse than
		   missing a few obscure annotations to the revocation */
		status = krnlGetObject( getkeyInfo.cryptHandle, 
								OBJECT_TYPE_CERTIFICATE, 
								( void ** ) &crlEntryInfoPtr, 
								CRYPT_ERROR_SIGNALLED );
		if( cryptStatusError( status ) )
			return( status );
		crlRevocationInfo = crlEntryInfoPtr->revocations;
		if( crlRevocationInfo != NULL )
			{
			revocationInfo->revocationTime = \
									crlRevocationInfo->revocationTime;
			if( crlRevocationInfo->attributes != NULL )
				copyRevocationAttributes( &revocationInfo->attributes,
						crlRevocationInfo->attributes, 
						&certInfoPtr->errorLocus, &certInfoPtr->errorType );
			}
		krnlReleaseObject( crlEntryInfoPtr->objectHandle );
		krnlSendNotifier( getkeyInfo.cryptHandle, IMESSAGE_DECREFCOUNT );

		/* Record the fact that we've seen at least one revoked cert */
		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 using an RTCS or OCSP responder */

static int checkResponder( CERT_INFO *certInfoPtr, 
						   const CRYPT_SESSION cryptSession )
	{
	CRYPT_CERTIFICATE cryptResponse;
	MESSAGE_CREATEOBJECT_INFO createInfo;
	int type, status;

	status = krnlSendMessage( cryptSession, IMESSAGE_GETATTRIBUTE, &type,
							  CRYPT_IATTRIBUTE_SUBTYPE );
	if( cryptStatusError( status ) )
		return( status );

	assert( ( type == SUBTYPE_SESSION_RTCS ) || \
			( type == SUBTYPE_SESSION_OCSP ) );

	/* Create the request, add the certificate, and add the request to the 
	   session */
	setMessageCreateObjectInfo( &createInfo, 
							    ( type == SUBTYPE_SESSION_RTCS ) ? \
									CRYPT_CERTTYPE_RTCS_REQUEST : \
									CRYPT_CERTTYPE_OCSP_REQUEST );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,
							  &createInfo, OBJECT_TYPE_CERTIFICATE );
	if( cryptStatusError( status ) )
		return( status );
	status = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE,
					&certInfoPtr->objectHandle, CRYPT_CERTINFO_CERTIFICATE );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( cryptSession, IMESSAGE_SETATTRIBUTE,
					&createInfo.cryptHandle, CRYPT_SESSINFO_REQUEST );
	krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
	if( cryptStatusError( status ) )
		return( status );

	/* Activate the session and get the response info */
	status = krnlSendMessage( cryptSession, IMESSAGE_SETATTRIBUTE,
							  MESSAGE_VALUE_TRUE, CRYPT_SESSINFO_ACTIVE );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( cryptSession, IMESSAGE_GETATTRIBUTE,
								  &cryptResponse, CRYPT_SESSINFO_RESPONSE );
	if( cryptStatusError( status ) )
		return( status );
	if( type == SUBTYPE_SESSION_RTCS )
		{
		int certStatus;

		status = krnlSendMessage( cryptResponse, IMESSAGE_GETATTRIBUTE, 
								  &certStatus, CRYPT_CERTINFO_CERTSTATUS );
		if( cryptStatusOK( status ) && \
			( certStatus != CRYPT_CERTSTATUS_VALID ) )
			status = CRYPT_ERROR_INVALID;
		}
	else
		{
		int revocationStatus;

		status = krnlSendMessage( cryptResponse, IMESSAGE_GETATTRIBUTE, 
								  &revocationStatus, 
								  CRYPT_CERTINFO_REVOCATIONSTATUS );
		if( cryptStatusOK( status ) && \
			( revocationStatus != CRYPT_OCSPSTATUS_NOTREVOKED ) )
			status = CRYPT_ERROR_INVALID;
		}
	krnlSendNotifier( cryptResponse, IMESSAGE_DECREFCOUNT );

	return( status );
	}

/* 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 complete, signed CRL and not a newly-created 
	   CRL object */
	status = krnlGetObject( cryptCRL, OBJECT_TYPE_CERTIFICATE, 
							( void ** ) &crlInfoPtr, CRYPT_ARGERROR_VALUE );
	if( cryptStatusError( status ) )
		return( status );
	if( crlInfoPtr->certificate == NULL )
		{
		krnlReleaseObject( crlInfoPtr->objectHandle );
		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 )
		{
		krnlReleaseObject( crlInfoPtr->objectHandle );
		return( status );
		}

	/* It's a cert chain, check every remaining cert in the chain against the
	   CRL.  In theory this is pointless because a CRL can only contain 
	   information for a single cert in the chain, however the caller may 
	   have passed us a CRL for an intermediate cert (in which case the check
	   for the leaf cert was pointless).  In any case it's easier to just do
	   the check for all certs than to determine which cert the CRL applies 
	   to, so we check for all certs */
	for( i = 0; i < certInfoPtr->certChainEnd; i++ )
		{
		CERT_INFO *certChainInfoPtr;

		/* Check this cert against the CRL */
		status = krnlGetObject( certInfoPtr->certChain[ i ], 
								OBJECT_TYPE_CERTIFICATE, 
								( void ** ) &certChainInfoPtr, 
								CRYPT_ERROR_SIGNALLED );
		if( cryptStatusOK( status ) )
			{
			status = checkRevocation( certChainInfoPtr, crlInfoPtr );
			krnlReleaseObject( certChainInfoPtr->objectHandle );
			}

		/* If the cert has been revoked, remember which one is the revoked
		   cert and exit */
		if( cryptStatusError( status ) )
			{
			certInfoPtr->certChainPos = i;
			krnlReleaseObject( crlInfoPtr->objectHandle );
			return( status );
			}
		}

	krnlReleaseObject( crlInfoPtr->objectHandle );
	return( CRYPT_OK );
	}

/* Check a self-signed certificate like a cert request or a self-signed 
   cert */

static int checkSelfSignedCert( CERT_INFO *certInfoPtr, 
								const int formatInfo )
	{
	CRYPT_CONTEXT iCryptContext;
	CERT_INFO *issuerCertInfoPtr;

⌨️ 快捷键说明

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