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

📄 pkcs15_get.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************
*																			*
*					   cryptlib PKCS #15 Get-item Routines					*
*						Copyright Peter Gutmann 1996-2007					*
*																			*
****************************************************************************/

#if defined( INC_ALL )
  #include "crypt.h"
  #include "keyset.h"
  #include "pkcs15.h"
  #include "asn1.h"
#else
  #include "crypt.h"
  #include "keyset/keyset.h"
  #include "keyset/pkcs15.h"
  #include "misc/asn1.h"
#endif /* Compiler-specific includes */

#ifdef USE_PKCS15

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

/* Set any optional attributes that may be associated with a key */

CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
static int setKeyAttributes( IN_HANDLE const CRYPT_HANDLE iCryptHandle,
							 INOUT const PKCS15_INFO *pkcs15infoPtr,
							 IN_FLAGS_Z( ACTION_PERM ) const int actionFlags )
	{
	int status;

	assert( isReadPtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );

	REQUIRES( isHandleRangeValid( iCryptHandle ) );
	REQUIRES( actionFlags >= ACTION_PERM_FLAG_NONE && \
			  actionFlags < ACTION_PERM_FLAG_MAX );
			  /* This check is a bit odd because normally an action flag 
			     value of ACTION_PERM_FLAG_NONE would indicate that the 
				 object can't be used, but setting it to CRYPT_UNUSED would 
				 create a value outside the normal allowed range so we use 
				 _NONE to indicate a don't-care value */

	if( actionFlags != 0 )
		{
		status = krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE,
								  ( void * ) &actionFlags,
								  CRYPT_IATTRIBUTE_ACTIONPERMS );
		if( cryptStatusError( status ) )
			return( status );
		}
	if( pkcs15infoPtr->openPGPKeyIDlength > 0 )
		{
		MESSAGE_DATA msgData;

		setMessageData( &msgData, ( void * ) pkcs15infoPtr->openPGPKeyID,
						pkcs15infoPtr->openPGPKeyIDlength );
		status = krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE_S,
								  &msgData, CRYPT_IATTRIBUTE_KEYID_OPENPGP );
		if( cryptStatusError( status ) )
			return( status );
		}
	if( pkcs15infoPtr->validFrom > MIN_TIME_VALUE )
		{
		MESSAGE_DATA msgData;

		/* This isn't really used for anything but is required to generate
		   the OpenPGP keyID, which includes the key creation time in the
		   ID-generation process */
		setMessageData( &msgData, ( void * ) &pkcs15infoPtr->validFrom,
						sizeof( time_t ) );
		status = krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE_S,
								  &msgData, CRYPT_IATTRIBUTE_PGPVALIDITY );
		if( cryptStatusError( status ) )
			return( status );
		}

	return( CRYPT_OK );
	}

/* Get an encoded trusted certificate */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \
static int getTrustedCert( IN_ARRAY( noPkcs15objects ) \
							const PKCS15_INFO *pkcs15info,
						   IN_LENGTH_SHORT const int noPkcs15objects,
						   OUT_BUFFER( dataMaxLength, *dataLength ) void *data, 
						   IN_LENGTH_SHORT_MIN( 16 ) const int dataMaxLength, 
						   OUT_LENGTH_SHORT_Z int *dataLength, 
						   const BOOLEAN resetCertIndex )
	{
	static int trustedCertIndex;
	const PKCS15_INFO *pkcs15infoPtr;
	int certStartOffset, certDataTotalSize;

	assert( isReadPtr( pkcs15info, \
					   sizeof( PKCS15_INFO ) * noPkcs15objects ) );
	assert( isWritePtr( data, dataMaxLength ) );
	assert( isWritePtr( dataLength, sizeof( int ) ) );

	REQUIRES( noPkcs15objects > 0 && noPkcs15objects < MAX_INTLENGTH_SHORT );
	REQUIRES( dataMaxLength >= 16 && dataMaxLength < MAX_INTLENGTH_SHORT );

	/* Clear return values */
	memset( data, 0, min( 16, dataMaxLength ) );
	*dataLength = 0;

	/* If this is the first certificate, reset the index value.  This is 
	   pretty ugly since this sort of state-information value should be 
	   stored with the caller, however there's no way to pass this back and 
	   forth in a MESSAGE_DATA without resorting to an even uglier hack and 
	   it's safe since this attribute is only ever read by the init thread 
	   when it reads the configuration data at startup */
	if( resetCertIndex )
		trustedCertIndex = 0;
	else
		{
		/* Move on to the next certificate */
		if( trustedCertIndex >= noPkcs15objects - 1 )
			return( CRYPT_ERROR_NOTFOUND );
		trustedCertIndex++;	
		}

	/* Find the next trusted certificate */
	for( pkcs15infoPtr = NULL; 
		 trustedCertIndex < noPkcs15objects && \
			trustedCertIndex < FAILSAFE_ITERATIONS_MED; trustedCertIndex++ )
		{
		if( pkcs15info[ trustedCertIndex ].implicitTrust )
			{
			pkcs15infoPtr = &pkcs15info[ trustedCertIndex ];
			break;
			}
		}
	ENSURES( trustedCertIndex < FAILSAFE_ITERATIONS_MED );
	if( pkcs15infoPtr == NULL )
		return( CRYPT_ERROR_NOTFOUND );
	certStartOffset = pkcs15infoPtr->certOffset;
	certDataTotalSize = pkcs15infoPtr->certDataSize;

	/* Return the data to the caller */
	REQUIRES( rangeCheck( certStartOffset, 
						  certDataTotalSize - certStartOffset,
						  certDataTotalSize ) );
	return( attributeCopyParams( data, dataMaxLength, dataLength,
					( BYTE * ) pkcs15infoPtr->certData + certStartOffset,
					certDataTotalSize - certStartOffset ) );
	}

/* Get an encoded configuration item */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \
static int getConfigItem( IN_ARRAY( noPkcs15objects ) \
							const PKCS15_INFO *pkcs15info,
						  IN_LENGTH_SHORT const int noPkcs15objects,
						  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE dataType,
						  OUT_BUFFER_OPT( dataMaxLength, *dataLength ) void *data, 
						  IN_LENGTH_SHORT_Z const int dataMaxLength, 
						  OUT_LENGTH_SHORT_Z int *dataLength )
	{
	const PKCS15_INFO *pkcs15infoPtr;
	int dataStartOffset, dataTotalSize, i;

	assert( isReadPtr( pkcs15info, \
					   sizeof( PKCS15_INFO ) * noPkcs15objects ) );
	assert( ( data == NULL && dataMaxLength == 0 ) || \
			isWritePtr( data, dataMaxLength ) );
	assert( isWritePtr( dataLength, sizeof( int ) ) );

	REQUIRES( noPkcs15objects > 0 && noPkcs15objects < MAX_INTLENGTH_SHORT );
	REQUIRES( dataType == CRYPT_IATTRIBUTE_CONFIGDATA || \
			  dataType == CRYPT_IATTRIBUTE_USERINDEX || \
			  dataType == CRYPT_IATTRIBUTE_USERINFO );
	REQUIRES( ( data == NULL && dataMaxLength == 0 ) || \
			  ( data != NULL && \
				dataMaxLength >= 16 && \
				dataMaxLength < MAX_INTLENGTH_SHORT ) );

	/* Clear return values */
	*dataLength = 0;
	if( data != NULL )
		memset( data, 0, min( 16, dataMaxLength ) );

	/* Find the particular data type that we're looking for */
	for( pkcs15infoPtr = NULL, i = 0; 
		 i < noPkcs15objects && i < FAILSAFE_ITERATIONS_MED; i++ )
		{
		if( ( pkcs15info[ i ].type == PKCS15_SUBTYPE_DATA && \
			  pkcs15info[ i ].dataType == dataType ) )
			{
			pkcs15infoPtr = &pkcs15info[ i ];
			break;
			}
		}
	ENSURES( i < FAILSAFE_ITERATIONS_MED );
	if( pkcs15infoPtr == NULL )
		return( CRYPT_ERROR_NOTFOUND );
	dataStartOffset = pkcs15infoPtr->dataOffset;
	dataTotalSize = pkcs15infoPtr->dataDataSize;

	/* If it's just a length check, we're done */
	if( data == NULL )
		{
		*dataLength = dataTotalSize - dataStartOffset;
		return( CRYPT_OK );
		}

	/* Return the data to the caller */
	REQUIRES( rangeCheck( dataStartOffset, 
						  dataTotalSize - dataStartOffset,
						  dataTotalSize ) );
	return( attributeCopyParams( data, dataMaxLength, dataLength,
					( BYTE * ) pkcs15infoPtr->dataData + dataStartOffset,
					dataTotalSize - dataStartOffset ) );
	}

/****************************************************************************
*																			*
*									Get a Key								*
*																			*
****************************************************************************/

/* Read key data from a PKCS #15 collection */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5 ) ) \
static int getItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,
							OUT_HANDLE_OPT CRYPT_HANDLE *iCryptHandle,
							IN_ENUM( KEYMGMT_ITEM ) \
								const KEYMGMT_ITEM_TYPE itemType,
							IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,
							IN_BUFFER( keyIDlength ) const void *keyID, 
							IN_LENGTH_KEYID const int keyIDlength,
							IN_OPT void *auxInfo, 
							INOUT_OPT int *auxInfoLength,
							IN_FLAGS_Z( KEYMGMT ) const int flags )
	{
	CRYPT_CERTIFICATE iDataCert = CRYPT_ERROR;
	CRYPT_CONTEXT iCryptContext;
	const PKCS15_INFO *pkcs15infoPtr;
	MESSAGE_DATA msgData;
	const BOOLEAN publicComponentsOnly = \
					( itemType != KEYMGMT_ITEM_PRIVATEKEY ) ? TRUE : FALSE;
	const int auxInfoMaxLength = *auxInfoLength;
	int pubkeyActionFlags = 0, privkeyActionFlags = 0, status;

	assert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );
	assert( isWritePtr( iCryptHandle, sizeof( CRYPT_HANDLE ) ) );
	assert( isReadPtr( keyID, keyIDlength ) );
	assert( ( auxInfo == NULL && auxInfoMaxLength == 0 ) || \
			isReadPtr( auxInfo, auxInfoMaxLength ) );

	REQUIRES( keysetInfoPtr->type == KEYSET_FILE && \
			  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 );
	REQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY || \
			  itemType == KEYMGMT_ITEM_PRIVATEKEY );
	REQUIRES( keyIDtype == CRYPT_KEYID_NAME || \
			  keyIDtype == CRYPT_KEYID_URI || \
			  keyIDtype == CRYPT_IKEYID_KEYID || \
			  keyIDtype == CRYPT_IKEYID_PGPKEYID || \
			  keyIDtype == CRYPT_IKEYID_ISSUERID );
	REQUIRES( keyIDlength >= MIN_NAME_LENGTH && \
			  keyIDlength < MAX_ATTRIBUTE_SIZE );
	REQUIRES( ( auxInfo == NULL && *auxInfoLength == 0 ) || \
			  ( auxInfo != NULL && \
				*auxInfoLength > 0 && \
				*auxInfoLength < MAX_INTLENGTH_SHORT ) );
	REQUIRES( flags >= KEYMGMT_FLAG_NONE && flags < KEYMGMT_FLAG_MAX );

	/* Clear return values */
	*iCryptHandle = CRYPT_ERROR;

	/* Locate the appropriate object in the PKCS #15 collection and make 
	   sure that the components that we need are present: Either a public 
	   key or a certificate for any type of read, and a private key as well 
	   for a private-key read */
	pkcs15infoPtr = findEntry( keysetInfoPtr->keyData, 
							   keysetInfoPtr->keyDataNoObjects, keyIDtype,
							   keyID, keyIDlength, flags );
	if( pkcs15infoPtr == NULL )
		{
		retExt( CRYPT_ERROR_NOTFOUND, 
				( CRYPT_ERROR_NOTFOUND, KEYSET_ERRINFO, 
				  "No information present for this ID" ) );
		}
	if( pkcs15infoPtr->pubKeyData == NULL && \
		pkcs15infoPtr->certData == NULL )
		{
		/* There's not enough information present to get a public key or the
		   public portions of a private key */
		retExt( CRYPT_ERROR_NOTFOUND, 
				( CRYPT_ERROR_NOTFOUND, KEYSET_ERRINFO, 
				  "No public key or certificate data present for this ID" ) );
		}
	if( !publicComponentsOnly && pkcs15infoPtr->privKeyData == NULL )
		{
		/* There's not enough information present to get a private key */
		retExt( CRYPT_ERROR_NOTFOUND, 
				( CRYPT_ERROR_NOTFOUND, KEYSET_ERRINFO, 
				  "No private key data present for this ID" ) );
		}

	/* If we're just checking whether an object exists, return now.  If all
	   that we want is the key label, copy it back to the caller and exit */
	if( flags & KEYMGMT_FLAG_CHECK_ONLY )
		return( CRYPT_OK );
	if( flags & KEYMGMT_FLAG_LABEL_ONLY )
		{
		return( attributeCopyParams( auxInfo, auxInfoMaxLength, 
									 auxInfoLength, pkcs15infoPtr->label, 
									 pkcs15infoPtr->labelLength ) );
		}

	/* If we're reading the private key, make sure that the user has
	   supplied a password.  This is checked by the kernel but we perform
	   another check here just to be safe*/
	if( !publicComponentsOnly && auxInfo == NULL )
		return( CRYPT_ERROR_WRONGKEY );

	/* Read the public components */
	status = readPublicKeyComponents( pkcs15infoPtr, keysetInfoPtr->objectHandle,
									  keyIDtype, keyID, keyIDlength, 
									  publicComponentsOnly,
									  &iCryptContext, &iDataCert,
									  &pubkeyActionFlags, 
									  &privkeyActionFlags, KEYSET_ERRINFO );
	if( cryptStatusError( status ) )
		return( status );

	/* If we're only interested in the public components, set the key
	   permissions and exit */
	if( publicComponentsOnly )
		{
		status = setKeyAttributes( iCryptContext, pkcs15infoPtr,
								   ( pkcs15infoPtr->pubKeyData != NULL ) ? \
									 pubkeyActionFlags : 0 );
		if( cryptStatusError( status ) )
			{
			krnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );
			retExt( status, 
					( status, KEYSET_ERRINFO, 

⌨️ 快捷键说明

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