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

📄 ca_misc.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************
*																			*
*					cryptlib DBMS CA Certificate Misc Interface				*
*						Copyright Peter Gutmann 1996-2007					*
*																			*
****************************************************************************/

#include <stdio.h>		/* For snprintf() */
#if defined( INC_ALL )
  #include "crypt.h"
  #include "keyset.h"
  #include "dbms.h"
  #include "asn1.h"
#else
  #include "crypt.h"
  #include "keyset/keyset.h"
  #include "keyset/dbms.h"
  #include "misc/asn1.h"
#endif /* Compiler-specific includes */

#ifdef USE_DBMS

/****************************************************************************
*																			*
*								Utility Functions							*
*																			*
****************************************************************************/

#if 0

/* Get the ultimate successor certificate for one that's been superseded */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
static int getSuccessorCert( INOUT DBMS_INFO *dbmsInfo,
							 OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate,
							 IN_BUFFER( initialCertIDlength ) \
								const char *initialCertID,
							 IN_LENGTH_SHORT const int initialCertIDlength )
	{
	char certID[ ENCODED_DBXKEYID_SIZE + 8 ];
	int chainingLevel, status;

	assert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );
	assert( isWritePtr( *iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );
	assert( isReadPtr( initialCertID, initialCertIDlength ) );

	/* Walk through the chain of renewals in the certificate store log until 
	   we find the ultimate successor certificate to the current one */
	memcpy( certID, initialCertID, initialCertIDlength );
	for( chainingLevel = 0, status = CRYPT_ERROR_NOTFOUND;
		 status == CRYPT_ERROR_NOTFOUND && \
			chainingLevel < FAILSAFE_ITERATIONS_MED;
		 chainingLevel++ )
		{
		BYTE keyCertID[ DBXKEYID_SIZE + 8 ];
		char certData[ MAX_QUERY_RESULT_SIZE + 8 ];
		int certDataLength, length, dummy;

		/* Find the request to renew this certificate */
		status = dbmsQuery(
			"SELECT certID FROM certLog WHERE subjCertID = ? "
			"AND action = " TEXT_CERTACTION_REQUEST_RENEWAL,
							certData, &certDataLength, certID,
							strlen( certID ), 0, DBMS_CACHEDQUERY_NONE,
							DBMS_QUERY_NORMAL );
		if( cryptStatusError( status ) )
			return( status );

		/* Find the resulting certificate */
		memcpy( certID, certData,
				min( certDataLength, ENCODED_DBXKEYID_SIZE + 1 ) );
		certID[ MAX_ENCODED_DBXKEYID_SIZE ] = '\0';
		status = dbmsQuery(
			"SELECT certID FROM certLog WHERE reqCertID = ? "
				"AND action = " TEXT_CERTACTION_CERT_CREATION,
							certData, &certDataLength, certID,
							strlen( certID ), 0, DBMS_CACHEDQUERY_NONE,
							DBMS_QUERY_NORMAL );
		if( cryptStatusOK( status ) )
			{
			status = length = \
				base64decode( keyCertID, certData,
							  min( certDataLength, ENCODED_DBXKEYID_SIZE ),
							  CRYPT_CERTFORMAT_NONE );
			assert( !cryptStatusError( status ) );
			}
		if( cryptStatusError( status ) )
			return( status );

		/* Try and get the replacement certificate */
		status = getItemData( dbmsInfo, iCertificate, &dummy,
							  getKeyName( CRYPT_IKEYID_CERTID ),
							  keyCertID, length, KEYMGMT_ITEM_PUBLICKEY,
							  KEYMGMT_FLAG_NONE, errorInfo );
		}
	if( chainingLevel >= FAILSAFE_ITERATIONS_MED )
		{
		/* We've chained through too many entries, bail out */
		return( CRYPT_ERROR_OVERFLOW );
		}

	return( status );
	}
#endif /* 0 */

/****************************************************************************
*																			*
*								Logging Functions							*
*																			*
****************************************************************************/

/* Add an entry to the CA log */

RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int updateCertLog( INOUT DBMS_INFO *dbmsInfo, 
				   IN_ENUM( CRYPT_CERTACTION ) const CRYPT_CERTACTION_TYPE action, 
				   IN_BUFFER_OPT( certIDlength ) const char *certID, 
				   IN_LENGTH_SHORT_Z const int certIDlength,
				   IN_BUFFER_OPT( reqCertIDlength ) const char *reqCertID, 
				   IN_LENGTH_SHORT_Z const int reqCertIDlength,
				   IN_BUFFER_OPT( subjCertIDlength ) const char *subjCertID, 
				   IN_LENGTH_SHORT_Z const int subjCertIDlength,
				   IN_BUFFER_OPT( dataLength ) const void *data, 
				   IN_LENGTH_SHORT_Z const int dataLength, 
				   IN_ENUM( DBMS_UPDATE ) const DBMS_UPDATE_TYPE updateType )
	{
	BOUND_DATA boundData[ BOUND_DATA_MAXITEMS ], *boundDataPtr = boundData;
	char sqlBuffer[ MAX_SQL_QUERY_SIZE + 8 ];
	char certIDbuffer[ ENCODED_DBXKEYID_SIZE + 8 ];
	char encodedCertData[ MAX_ENCODED_CERT_SIZE + 8 ];
	const time_t boundDate = getApproxTime();
	int localCertIDlength = certIDlength, sqlOffset, sqlLength, boundDataIndex;

	assert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );
	assert( ( certID == NULL && certIDlength == 0 ) || \
			isReadPtr( certID, certIDlength ) );
	assert( ( reqCertID == NULL && reqCertIDlength == 0 ) || \
			isReadPtr( reqCertID, reqCertIDlength ) );
	assert( ( subjCertID == NULL && subjCertIDlength == 0 ) || \
			isReadPtr( subjCertID, subjCertIDlength ) );
	assert( ( data == NULL && dataLength == 0 ) || \
			isReadPtr( data, dataLength ) );
	
	REQUIRES( action > CRYPT_CERTACTION_NONE && \
			  action < CRYPT_CERTACTION_LAST );
	REQUIRES( ( certID == NULL && certIDlength == 0 ) || \
			  ( certID != NULL && \
				certIDlength > 0 && \
				certIDlength < MAX_INTLENGTH_SHORT ) );
	REQUIRES( ( reqCertID == NULL && reqCertIDlength == 0 ) || \
			  ( reqCertID != NULL && \
				reqCertIDlength > 0 && \
				reqCertIDlength < MAX_INTLENGTH_SHORT ) );
	REQUIRES( ( subjCertID == NULL && subjCertIDlength == 0 ) || \
			  ( subjCertID != NULL && \
				subjCertIDlength > 0 && \
				subjCertIDlength < MAX_INTLENGTH_SHORT ) );
	REQUIRES( ( data == NULL && dataLength == 0 ) || \
			  ( data != NULL && \
				dataLength > 0 && \
				dataLength < MAX_INTLENGTH_SHORT ) );
	REQUIRES( updateType > DBMS_UPDATE_NONE && \
			  updateType < DBMS_UPDATE_LAST );

	/* Build up the necessary SQL format string required to insert the log
	   entry.  This is complicated somewhat by the fact that some of the
	   values may be NULL so we have to insert them by naming the columns
	   (some databases allow the use of the DEFAULT keyword but this isn't
	   standardised enough to be safe) */
	strlcpy_s( sqlBuffer, MAX_SQL_QUERY_SIZE,
			  "INSERT INTO certLog (action, actionTime, certID" );
	if( reqCertID != NULL )
		strlcat_s( sqlBuffer, MAX_SQL_QUERY_SIZE, ", reqCertID" );
	if( subjCertID != NULL )
		strlcat_s( sqlBuffer, MAX_SQL_QUERY_SIZE, ", subjCertID" );
	if( data != NULL )
		strlcat_s( sqlBuffer, MAX_SQL_QUERY_SIZE, ", certData" );
	strlcat_s( sqlBuffer, MAX_SQL_QUERY_SIZE, ") VALUES (" );
	sqlOffset = strlen( sqlBuffer );
	sqlLength = MAX_SQL_QUERY_SIZE - sqlOffset;
	sprintf_s( sqlBuffer + sqlOffset, sqlLength, "%d, ?, ?", action );
	if( reqCertID != NULL )
		strlcat_s( sqlBuffer + sqlOffset, sqlLength, ", ?" );
	if( subjCertID != NULL )
		strlcat_s( sqlBuffer + sqlOffset, sqlLength, ", ?" );
	if( data != NULL )
		strlcat_s( sqlBuffer + sqlOffset, sqlLength, ", ?" );
	strlcat_s( sqlBuffer + sqlOffset, sqlLength, ")" );

	/* If we're not worried about the certID we just insert a nonce value
	   which is used to meet the constraints for a unique entry.  In order
	   to ensure that it doesn't clash with a real certID we set the first
	   four characters to an out-of-band value */
	if( certID == NULL )
		{
		MESSAGE_DATA msgData;
		BYTE nonce[ KEYID_SIZE + 8 ];
		int status;

		setMessageData( &msgData, nonce, KEYID_SIZE );
		status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );
		if( cryptStatusOK( status ) )
			status = base64encode( certIDbuffer, ENCODED_DBXKEYID_SIZE, 
								   &localCertIDlength, nonce, DBXKEYID_SIZE, 
								   CRYPT_CERTTYPE_NONE );
		if( cryptStatusError( status ) )
			{
			/* Normally this is a should-never-occur error, however if
			   cryptlib has been shut down from another thread the kernel
			   will fail all non shutdown-related calls with a permission
			   error.  To avoid false alarms, we mask out failures due to
			   permission errors */
			assert( ( status == CRYPT_ERROR_PERMISSION ) || DEBUG_WARN );
			return( status );
			}
		memset( certIDbuffer, '-', 4 );
		certID = certIDbuffer;
		}

	/* Set up the parameter information and update the certificate store 
	   log */
	initBoundData( boundDataPtr );
	setBoundDataDate( boundDataPtr, 0, &boundDate );
	setBoundData( boundDataPtr, 1, certID, localCertIDlength );
	boundDataIndex = 2;
	if( reqCertID != NULL )
		setBoundData( boundDataPtr, boundDataIndex++, reqCertID, 
					  reqCertIDlength );
	if( subjCertID != NULL )
		setBoundData( boundDataPtr, boundDataIndex++, subjCertID, 
					  subjCertIDlength );
	if( data != NULL )
		{
		if( hasBinaryBlobs( dbmsInfo ) )
			{
			setBoundDataBlob( boundDataPtr, boundDataIndex, 
							  data, dataLength );
			}
		else
			{
			int encodedDataLength, status;

			status = base64encode( encodedCertData, MAX_ENCODED_CERT_SIZE,
								   &encodedDataLength, data, dataLength, 
								   CRYPT_CERTTYPE_NONE );
			if( cryptStatusError( status ) )
				{
				assert( DEBUG_WARN );
				return( status );
				}
			setBoundData( boundDataPtr, boundDataIndex, 
						  encodedCertData, encodedDataLength );
			}
		}
	return( dbmsUpdate( sqlBuffer, boundDataPtr, updateType ) );
	}

RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
int updateCertErrorLog( INOUT DBMS_INFO *dbmsInfo, 
						IN_ERROR const int errorStatus,
						IN_STRING const char *errorString, 
						IN_BUFFER_OPT( certIDlength ) const char *certID, 
						IN_LENGTH_SHORT_Z const int certIDlength,
						IN_BUFFER_OPT( reqCertIDlength ) const char *reqCertID, 
						IN_LENGTH_SHORT_Z const int reqCertIDlength,
						IN_BUFFER_OPT( subjCertIDlength ) const char *subjCertID, 
						IN_LENGTH_SHORT_Z const int subjCertIDlength,
						IN_BUFFER_OPT( dataLength ) const void *data, 
						IN_LENGTH_SHORT_Z const int dataLength )
	{
	STREAM stream;
	BYTE errorData[ 64 + MAX_CERT_SIZE + 8 ];
	const int errorStringLength = strlen( errorString );
	int errorDataLength = DUMMY_INIT, status;

	assert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );
	assert( ( certID == NULL && certIDlength == 0 ) || \
			isReadPtr( certID, certIDlength ) );
	assert( ( reqCertID == NULL && reqCertIDlength == 0 ) || \
			isReadPtr( reqCertID, reqCertIDlength ) );
	assert( ( subjCertID == NULL && subjCertIDlength == 0 ) || \
			isReadPtr( subjCertID, subjCertIDlength ) );
	assert( ( data == NULL && dataLength == 0 ) || \
			isReadPtr( data, dataLength ) );

	REQUIRES( cryptStatusError( errorStatus ) );
	REQUIRES( errorString != NULL );
	REQUIRES( ( certID == NULL && certIDlength == 0 ) || \
			  ( certID != NULL && \
				certIDlength > 0 && \
				certIDlength < MAX_INTLENGTH_SHORT ) );
	REQUIRES( ( reqCertID == NULL && reqCertIDlength == 0 ) || \
			  ( reqCertID != NULL && \
				reqCertIDlength > 0 && \
				reqCertIDlength < MAX_INTLENGTH_SHORT ) );
	REQUIRES( ( subjCertID == NULL && subjCertIDlength == 0 ) || \
			  ( subjCertID != NULL && \
				subjCertIDlength > 0 && \
				subjCertIDlength < MAX_INTLENGTH_SHORT ) );
	REQUIRES( ( data == NULL && dataLength == 0 ) || \
			  ( data != NULL && \
				dataLength > 0 && \
				dataLength < MAX_INTLENGTH_SHORT ) );

	/* Encode the error information:

		SEQUENCE {
			errorStatus	INTEGER,
			errorString	UTF8String,
			certData	ANY OPTIONAL
			} 

	   Note that the buffer we use is slightly larger than MAX_CERT_SIZE in 
	   order to accomodate the error status information alongside the 
	   largest possible certificate, in theory this means that if the database
	   back-end doesn't support binary blobs there won't be enough room in
	   the logging code to text-encode this worst-case scenario, but the use
	   of non-binary-blob capable database should be fairly rare so it's 
	   easier to just rely on the logging code to catch this unlikely 
	   scenario than to try and special-case around it */
	sMemOpen( &stream, errorData, 64 + MAX_CERT_SIZE );
	writeSequence( &stream, sizeofShortInteger( -errorStatus ) + \
							( int ) sizeofObject( errorStringLength ) + \
							dataLength );
	writeShortInteger( &stream, -errorStatus, DEFAULT_TAG );
	status = writeCharacterString( &stream, errorString, errorStringLength,
								   BER_STRING_UTF8 );
	if( dataLength > 0 )
		status = swrite( &stream, data, dataLength );
	if( cryptStatusOK( status ) )
		errorDataLength = stell( &stream );
	sMemDisconnect( &stream );
	if( cryptStatusError( status ) )

⌨️ 快捷键说明

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