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

📄 cryptcrt.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 3 页
字号:
	if( cryptStatusError( status ) )
		{
		krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
		return( status );
		}
	*iPubkeyContext = createInfo.cryptHandle;
	assert( cryptStatusError( \
				krnlSendMessage( createInfo.cryptHandle, IMESSAGE_CHECK, 
								 NULL, MESSAGE_CHECK_PKC_PRIVATE ) ) );
	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*						Certificate Management API Functions				*
*																			*
****************************************************************************/

/* Handle data sent to or read from a cert object */

static int processCertData( CERT_INFO *certInfoPtr,
						    const MESSAGE_TYPE message,
							void *messageDataPtr, const int messageValue )
	{
	RESOURCE_DATA *msgData = ( RESOURCE_DATA * ) messageDataPtr;
	int *valuePtr = ( int * ) messageDataPtr;

	/* Process get/set/delete attribute messages */
	if( message == MESSAGE_GETATTRIBUTE )
		{
		if( messageValue == CRYPT_ATTRIBUTE_ERRORTYPE )
			{
			*valuePtr = certInfoPtr->errorType;
			return( CRYPT_OK );
			}
		if( messageValue == CRYPT_ATTRIBUTE_ERRORLOCUS )
			{
			*valuePtr = certInfoPtr->errorLocus;
			return( CRYPT_OK );
			}
		return( getCertComponent( certInfoPtr, messageValue, valuePtr, NULL ) );
		}
	if( message == MESSAGE_GETATTRIBUTE_S )
		return( getCertComponent( certInfoPtr, messageValue, 
								  msgData->data, &msgData->length ) );
	if( message == MESSAGE_SETATTRIBUTE )
		{
		const BOOLEAN validCursorPosition = \
			( certInfoPtr->type == CRYPT_CERTTYPE_CMS_ATTRIBUTES ) ? \
			messageValue >= CRYPT_CERTINFO_FIRST_CMS && \
								messageValue <= CRYPT_CERTINFO_LAST_CMS : \
			messageValue >= CRYPT_CERTINFO_FIRST_EXTENSION && \
								messageValue <= CRYPT_CERTINFO_LAST_EXTENSION;

		/* If it's a completed certificate, we can only add a restricted 
		   class of component selection control values to the object */
		assert( certInfoPtr->certificate == NULL || \
				isDNSelectionComponent( messageValue ) || \
				isGeneralNameSelectionComponent( messageValue ) || \
				isCursorComponent( messageValue ) || \
				isControlComponent( messageValue ) || \
				messageValue == CRYPT_IATTRIBUTE_INITIALISED || \
				messageValue == CRYPT_IATTRIBUTE_PKIUSERINFO );

		/* If it's an initialisation message, there's nothing to do (we get 
		   these when importing a cert, when the import is complete the 
		   import code sends this message to move the cert into the high
		   state because it's already signed) */
		if( messageValue == CRYPT_IATTRIBUTE_INITIALISED )
			return( CRYPT_OK );

		/* If the passed-in value is a cursor-positioning code, make sure 
		   that it's valid */
		if( *valuePtr < 0 && *valuePtr != CRYPT_UNUSED && \
			( *valuePtr > CRYPT_CURSOR_FIRST || *valuePtr < CRYPT_CURSOR_LAST ) &&
			!validCursorPosition && messageValue != CRYPT_CERTINFO_SELFSIGNED )
			return( CRYPT_ARGERROR_NUM1 );

		return( addCertComponent( certInfoPtr, messageValue, valuePtr, 
								  CRYPT_UNUSED ) );
		}
	if( message == MESSAGE_SETATTRIBUTE_S )
		return( addCertComponent( certInfoPtr, messageValue, msgData->data, 
								  msgData->length ) );
	if( message == MESSAGE_DELETEATTRIBUTE )
		return( deleteCertComponent( certInfoPtr, messageValue ) );

	assert( NOTREACHED );
	return( CRYPT_ERROR );	/* Get rid of compiler warning */
	}

/* Handle a message sent to a certificate context */

static int certificateMessageFunction( const void *objectInfoPtr,
									   const MESSAGE_TYPE message,
									   void *messageDataPtr,
									   const int messageValue )
	{
	CERT_INFO *certInfoPtr = ( CERT_INFO * ) objectInfoPtr;

	/* Process destroy object messages */
	if( message == MESSAGE_DESTROY )
		{
		/* Clear the encoded certificate and miscellaneous components if
		   necessary.  Note that there's no need to clear the associated
		   encryption context (if any) since this is a dependent object of
		   the cert and is destroyed by the kernel when the cert is 
		   destroyed */
		if( certInfoPtr->certificate != NULL )
			{
			zeroise( certInfoPtr->certificate, certInfoPtr->certificateSize );
			clFree( "certificateMessageFunction", certInfoPtr->certificate );
			}
		if( certInfoPtr->serialNumber != NULL && \
			certInfoPtr->serialNumber != certInfoPtr->serialNumberBuffer )
			clFree( "certificateMessageFunction", certInfoPtr->serialNumber );
		if( certInfoPtr->subjectUniqueID != NULL )
			clFree( "certificateMessageFunction", certInfoPtr->subjectUniqueID );
		if( certInfoPtr->issuerUniqueID != NULL )
			clFree( "certificateMessageFunction", certInfoPtr->issuerUniqueID );
		if( certInfoPtr->publicKeyData != NULL )
			clFree( "certificateMessageFunction", certInfoPtr->publicKeyData  );
		if( certInfoPtr->subjectDNdata != NULL )
			clFree( "certificateMessageFunction", certInfoPtr->subjectDNdata );
		if( certInfoPtr->issuerDNdata != NULL )
			clFree( "certificateMessageFunction", certInfoPtr->issuerDNdata );
		if( certInfoPtr->responderUrl != NULL )
			clFree( "certificateMessageFunction", certInfoPtr->responderUrl );

		/* Clear the DN's if necessary */
		if( certInfoPtr->issuerName != NULL )
			deleteDN( &certInfoPtr->issuerName );
		if( certInfoPtr->subjectName != NULL )
			deleteDN( &certInfoPtr->subjectName );

		/* Clear the attributes and CRL's if necessary */
		if( certInfoPtr->attributes != NULL )
			deleteAttributes( &certInfoPtr->attributes );
		if( certInfoPtr->revocations != NULL )
			deleteRevocationEntries( &certInfoPtr->revocations );

		/* Clear the cert chain if necessary */
		if( certInfoPtr->certChainEnd )
			{
			int i;

			for( i = 0; i < certInfoPtr->certChainEnd; i++ )
				krnlSendNotifier( certInfoPtr->certChain[ i ],
								  IMESSAGE_DECREFCOUNT );
			}

		/* Delete the object itself */
		zeroise( certInfoPtr, sizeof( CERT_INFO ) );
		clFree( "certificateMessageFunction", certInfoPtr );

		return( CRYPT_OK );
		}

	/* Process attribute get/set/delete messages */
	if( isAttributeMessage( message ) )
		{
		/* If it's a cert chain, lock the currently selected cert in the 
		   chain unless the message being processed is a certificate cursor 
		   movement command or something specifically directed at the entire 
		   chain (for example a get type or self-signed status command - we 
		   want to get the type/status of the chain, not of the certs within 
		   it) */
		if( certInfoPtr->certChainPos >= 0 && \
			!( ( message == MESSAGE_SETATTRIBUTE ) && \
			   ( messageValue == CRYPT_CERTINFO_CURRENT_CERTIFICATE ) ) && \
			!( ( message == MESSAGE_GETATTRIBUTE ) && \
			   ( messageValue == CRYPT_CERTINFO_CERTTYPE || \
				 messageValue == CRYPT_CERTINFO_SELFSIGNED ) ) )
			{
			CERT_INFO *certChainInfoPtr;
			int status;

			status = krnlGetObject( certInfoPtr->certChain[ certInfoPtr->certChainPos ], 
									OBJECT_TYPE_CERTIFICATE, 
									( void ** ) &certChainInfoPtr,
									CRYPT_ARGERROR_OBJECT );
			if( cryptStatusError( status ) )
				return( status );
			status = processCertData( certChainInfoPtr, message, messageDataPtr, 
									  messageValue );
			krnlReleaseObject( certChainInfoPtr->objectHandle );
			return( status );
			}

		return( processCertData( certInfoPtr, message, messageDataPtr, 
								 messageValue ) );
		}

	/* Process messages that compare the object */
	if( message == MESSAGE_COMPARE )
		return( compareCertInfo( certInfoPtr, messageValue, 
								 messageDataPtr ) );

	/* Process messages that check a certificate */
	if( message == MESSAGE_CHECK )
		{
		const int certCheckValue = \
			( messageValue == MESSAGE_CHECK_PKC_ENCRYPT || \
              messageValue == MESSAGE_CHECK_PKC_DECRYPT ) ? \
				CRYPT_KEYUSAGE_KEYENCIPHERMENT : \
			( messageValue == MESSAGE_CHECK_PKC_SIGN || \
              messageValue == MESSAGE_CHECK_PKC_SIGCHECK ) ? \
				( CRYPT_KEYUSAGE_DIGITALSIGNATURE | \
				  CRYPT_KEYUSAGE_NONREPUDIATION | \
				  CRYPT_KEYUSAGE_KEYCERTSIGN | CRYPT_KEYUSAGE_CRLSIGN ) : \
			( messageValue == MESSAGE_CHECK_PKC_KA_EXPORT ) ? \
				CRYPT_KEYUSAGE_ENCIPHERONLY : \
			( messageValue == MESSAGE_CHECK_PKC_KA_IMPORT ) ? \
				CRYPT_KEYUSAGE_DECIPHERONLY : \
			( messageValue == MESSAGE_CHECK_CA ) ? \
				CRYPT_KEYUSAGE_KEYCERTSIGN : 0;
			/* enc/decOnly usage falls back to plain keyAgree if necessary */
		int status;

		/* If we're not checking for a specific type of functionality 
		   restriction set by the cert then any kind of usage is OK */
		if( !certCheckValue )
			return( CRYPT_OK );

		status = checkCertUsage( certInfoPtr, certCheckValue, messageValue,
						&certInfoPtr->errorLocus, &certInfoPtr->errorType );
		status = cryptStatusError( status ) ? \
				 CRYPT_ARGERROR_OBJECT : CRYPT_OK;	/* Convert to correct form */
		return( status );
		}

	/* Process internal notification messages */
	if( message == MESSAGE_CHANGENOTIFY )
		{
		/* If the object has been locked/unlocked, save/restore the internal 
		   state */
		if( messageValue == CRYPT_IATTRIBUTE_LOCKED )
			{
			if( messageDataPtr == MESSAGE_VALUE_TRUE )
				{
				/* Save the current volatile state so that any changes made 
				   while the object is locked aren't reflected back to the 
				   caller */
				saveSelectionState( certInfoPtr->selectionState, 
									certInfoPtr );
				}
			else
				{
				/* Restore the volatile state from before the object was 
				   locked */
				restoreSelectionState( certInfoPtr->selectionState, 
									   certInfoPtr );
				}

			return( CRYPT_OK );
			}

		assert( NOTREACHED );
		return( CRYPT_ERROR );	/* Get rid of compiler warning */
		}

	/* Process object-specific messages */
	if( message == MESSAGE_CRT_SIGN )
		{
		int status;

		assert( certInfoPtr->certificate == NULL );

		/* Make sure that the signing object can actually be used for 
		   signing */
		status = krnlSendMessage( messageValue, IMESSAGE_CHECK, NULL,
								  MESSAGE_CHECK_PKC_SIGN );
		if( cryptStatusError( status ) )
			{
			/* The only time we can use a signing object that can't sign is
			   when we have a CRMF request, which can be created with an
			   encryption-only key if the private key POP is performed via 
			   an out-of-band mechanism.  If this is the case, we make sure
			   that the key can decrypt, which is the other way of performing 
			   POP if a signing key isn't available */
			if( certInfoPtr->type != CRYPT_CERTTYPE_REQUEST_CERT )
				return( CRYPT_ARGERROR_VALUE );
			status = krnlSendMessage( messageValue, IMESSAGE_CHECK, NULL,
									  MESSAGE_CHECK_PKC_DECRYPT );
			if( cryptStatusError( status ) )
				return( CRYPT_ARGERROR_VALUE );
			}

		/* We're changing data in a certificate, clear the error 
		   information */
		clearErrorInfo( certInfoPtr );

		return( signCert( certInfoPtr, messageValue ) );
		}
	if( message == MESSAGE_CRT_SIGCHECK )
		{
		assert( certInfoPtr->certificate != NULL || \
				certInfoPtr->type == CRYPT_CERTTYPE_RTCS_RESPONSE || \
				certInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE );

		/* We're checking data in a certificate, clear the error 
		   information */
		clearErrorInfo( certInfoPtr );

		return( checkCertValidity( certInfoPtr, messageValue ) );
		}
	if( message == MESSAGE_CRT_EXPORT )
		{
		RESOURCE_DATA *msgData = ( RESOURCE_DATA * ) messageDataPtr;
		int status;

		assert( messageValue > CRYPT_CERTFORMAT_NONE && \
				messageValue < CRYPT_CERTFORMAT_LAST );

		/* Unsigned object types like CMS attributes aren't signed like other 
		   cert.objects so they aren't pre-encoded when we sign them, and 
		   have the potential to change on each use if the same CMS 
		   attributes are reused for multiple signatures.  Because of this 
		   we write them out on export rather than copying the pre-encoded 
		   form from an internal buffer */
		if( certInfoPtr->type == CRYPT_CERTTYPE_CMS_ATTRIBUTES )
			{
			STREAM stream;
			int i;

			assert( messageValue == CRYPT_ICERTFORMAT_DATA );

			for( i = 0; \
				 certWriteTable[ i ].type != CRYPT_CERTTYPE_CMS_ATTRIBUTES && \
				 certWriteTable[ i ].type != CRYPT_CERTTYPE_NONE; i++ );
			if( certWriteTable[ i ].type == CRYPT_CERTTYPE_NONE )
				{
				assert( NOTREACHED );
				return( CRYPT_ERROR_NOTAVAIL );
				}
			sMemOpen( &stream, msgData->data, msgData->length );
			status = certWriteTable[ i ].writeFunction( &stream, certInfoPtr,
														NULL, CRYPT_UNUSED );
			msgData->length = stell( &stream );
			sMemDisconnect( &stream );

			return( status );
			}

		/* Some objects aren't signed, or are pseudo-signed or optionally 
		   signed, and have to be handled specially.  RTCS requests and
		   responses are never signed (they're pure data containers like
		   CMS attributes, with protection being provided by CMS).  OCSP 
		   requests can be optionally signed but usually aren't, so if 
		   we're fed an OCSP request without any associated encoded data we 
		   pseudo-sign it to produce encoded data.  PKI user data is never 
		   signed but needs to go through a one-off setup process to 
		   initialise the user data fields so it has the same semantics as a 
		   pseudo-signed object.  CRMF revocation requests are never signed 
		   (thus ruling out suicide-note revocations) */
		if( ( certInfoPtr->type == CRYPT_CERTTYPE_RTCS_REQUEST || \
			  certInfoPtr->type == CRYPT_CERTTYPE_RTCS_RESPONSE || \
			  certInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST || \
			  certInfoPtr->type == CRYPT_CERTTYPE_PKIUSER || \
			  certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION ) && \
			certInfoPtr->certificate == NULL )
			{
			status = signCert( certInfoPtr, CRYPT_UNUSED );
			if( cryptStatusError( status ) )
				return( status );
			}

		/* If we're exporting a single cert from a chain, lock the currently 
		   selected cert in the chain and export that */
		if( certInfoPtr->certChainPos >= 0 && \
			( messageValue == CRYPT_CERTFORMAT_CERTIFICATE || \
			  messageValue == CRYPT_CERTFORMAT_TEXT_CERTIFICATE || \
			  messageValue == CRYPT_CERTFORMAT_XML_CERTIFICATE ) )
			{
			CERT_INFO *certChainInfoPtr;

			status = krnlGetObject( certInfoPtr->certChain[ certInfoPtr->certChainPos ], 
									OBJECT_TYPE_CERTIFICATE, 
									( void ** ) &certChainInfoPtr,
									CRYPT_ARGERROR_OBJECT );
			if( cryptStatusError( status ) )
				return( status );
			status = exportCert( msgData->data, &msgData->length, 
								 messageValue, certChainInfoPtr, 
								 msgData->length );
			krnlReleaseObject( certChainInfoPtr->objectHandle );
			return( status );
			}

		assert( ( ( certInfoPtr->flags & CERT_FLAG_CERTCOLLECTION ) && \
				  certInfoPtr->certificate == NULL ) || \
				certInfoPtr->certificate != NULL );

		return( exportCert( msgData->data, &msgData->length, 
							messageValue, certInfoPtr, msgData->length ) );
		}

	assert( NOTREACHED );
	return( CRYPT_ERROR );	/* Get rid of compiler warning */
	}

/* Create a certificate object, returning a pointer to the locked cert info 
   ready for further initialisation */

int createCertificateInfo( CERT_INFO **certInfoPtrPtr, 
						   const CRYPT_USER cryptOwner,
						   const CRYPT_CERTTYPE_TYPE certType )
	{

⌨️ 快捷键说明

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