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

📄 ms_capi.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 5 页
字号:
		return( mapError( cryptoapiInfo, CRYPT_ERROR_NOTFOUND ) );
	if( !pCryptGetUserKey( hProv, dwKeySpec, &hKey ) )
		return( mapError( cryptoapiInfo, CRYPT_ERROR_NOTFOUND ) );
	*hKeyPtr = hKey;
	return( CRYPT_OK );
	}
#endif /* 0 */

/* Create a private-key context using a CryptoAPI native key */

static int createPrivkeyContext( DEVICE_INFO *deviceInfo,
								 CRYPT_CONTEXT *iCryptContext,
								 CRYPT_ALGO_TYPE *cryptAlgo,
								 const HCRYPTKEY hKey,
								 const char *label )
	{
	ALG_ID algID;
	DWORD dwDataLen = sizeof( ALG_ID );
	const CAPABILITY_INFO *capabilityInfoPtr = NULL;
	MESSAGE_DATA msgData;
	int status;

	/* Clear return values */
	*iCryptContext = CRYPT_ERROR;
	*cryptAlgo = CRYPT_ALGO_NONE;

	/* Get the algorithm type and look up the corresponding capability 
	   info */
	if( !pCryptGetKeyParam( hKey, KP_ALGID, ( BYTE * ) &algID, &dwDataLen, 
							0 ) || \
		( *cryptAlgo = capiToCryptlibID( algID ) ) == CRYPT_ALGO_NONE )
		return( CRYPT_ERROR_NOTAVAIL );
	capabilityInfoPtr = findCapabilityInfo( deviceInfo->capabilityInfoList, 
											*cryptAlgo );
	if( capabilityInfoPtr == NULL )
		return( CRYPT_ERROR_NOTAVAIL );

	/* Create a dummy context for the key, remember the device it's 
	   contained in, the handle for the device-internal key, and the 
	   object's label, and mark it as initialised (i.e. with a key loaded) */
	status = createContextFromCapability( iCryptContext, 
								deviceInfo->ownerHandle, capabilityInfoPtr, 
								CREATEOBJECT_FLAG_DUMMY );
	if( cryptStatusError( status ) )
		return( status );
	krnlSendMessage( *iCryptContext, IMESSAGE_SETDEPENDENT,
					 &deviceInfo->objectHandle, SETDEP_OPTION_INCREF );
	krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE, 
					 ( void * ) &hKey, CRYPT_IATTRIBUTE_DEVICEOBJECT );
	setMessageData( &msgData, ( void * ) label, 
					min( strlen( label ), CRYPT_MAX_TEXTSIZE ) );
	krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE_S,
					 &msgData, CRYPT_CTXINFO_LABEL );
#if 0
	if( cryptAlgo == CRYPT_ALGO_RSA )
		/* Send the keying info to the context.  This is only possible for
		   RSA keys since it's not possible to read y from a DSA private
		   key object (see the comments in the DSA code for more on this), 
		   however the only time this is necessary is when a certificate is 
		   being generated for a key that was pre-generated in the device by 
		   someone else, which is typically done in Europe where DSA isn't 
		   used so this shouldn't be a problem */
		// Use getPubkeyComponents()
		cryptStatus = rsaSetPublicComponents( deviceInfo, *iCryptContext, 
											  hObject );
	else
		cryptStatus = krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE, 
									   &keySize, CRYPT_IATTRIBUTE_KEYSIZE );
#endif
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE,
								   MESSAGE_VALUE_UNUSED, 
								   CRYPT_IATTRIBUTE_INITIALISED );
	if( cryptStatusError( status ) )
		{
		krnlSendNotifier( *iCryptContext, IMESSAGE_DECREFCOUNT );
		return( status );
		}

	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*					Device Init/Shutdown/Device Control Routines			*
*																			*
****************************************************************************/

/* Prototypes for functions to get and free device capability information */

static int getCapabilities( DEVICE_INFO *deviceInfo );
static void freeCapabilities( DEVICE_INFO *deviceInfo );

/* Close a previously-opened session with the device.  We have to have this
   before the init function since it may be called by it if the init process
   fails */

static void shutdownFunction( DEVICE_INFO *deviceInfo )
	{
	CRYPTOAPI_INFO *cryptoapiInfo = deviceInfo->deviceCryptoAPI;

	/* Log out and close the session with the device */
	if( deviceInfo->flags & DEVICE_LOGGEDIN )
		{
		if( cryptoapiInfo->hPrivateKey )
			pCryptDestroyKey( cryptoapiInfo->hPrivateKey );
		pCryptReleaseContext( cryptoapiInfo->hProv, 0 );
		}
	if( cryptoapiInfo->hCertStore != NULL )
		{
		pCertCloseStore( cryptoapiInfo->hCertStore, 0 );
		cryptoapiInfo->hCertStore = 0;
		}
	cryptoapiInfo->hProv = HCRYPTPROV_NONE;
	deviceInfo->flags &= ~( DEVICE_ACTIVE | DEVICE_LOGGEDIN );

	/* Free the device capability information */
	freeCapabilities( deviceInfo );
	}

/* Open a session with the device */

static int initFunction( DEVICE_INFO *deviceInfo, const char *name,
						 const int nameLength )
	{
	CRYPTOAPI_INFO *cryptoapiInfo = deviceInfo->deviceCryptoAPI;
	HCRYPTPROV hProv;
	HCERTSTORE hCertStore;
	char providerNameBuffer[ CRYPT_MAX_TEXTSIZE + 1 + 8 ];
	char keysetNameBuffer[ CRYPT_MAX_TEXTSIZE + 1 + 8 ];
	const char *keysetName = NULL;
	DWORD value;
	int i, driverNameLength = nameLength, status;

	/* Check whether a keyset name has been specified */
	strlcpy_s( keysetNameBuffer, CRYPT_MAX_TEXTSIZE, "MY" );/* Default keyset */
	for( i = 1; i < nameLength - 1; i++ )
		{
		if( name[ i ] == ':' && name[ i + 1 ] == ':' )
			{
			const int keysetNameLength = nameLength - ( i + 2 );

			if( i > CRYPT_MAX_TEXTSIZE || keysetNameLength <= 0 || \
				keysetNameLength > CRYPT_MAX_TEXTSIZE )
				return( CRYPT_ARGERROR_STR1 );

			/* We've got a keyset name appended to the provider name, break 
			   out the provider and keyset names */
			memcpy( providerNameBuffer, name, i );
			providerNameBuffer[ i ] = '\0';
			memcpy( keysetNameBuffer, name + i + 2, keysetNameLength );
			keysetNameBuffer[ keysetNameLength ] = '\0';
			name = providerNameBuffer;
			keysetName = keysetNameBuffer;
			break;
			}
		}

	/* If we're auto-detecting the device, try various choices */
	if( driverNameLength == 12 && \
		!strnicmp( "[Autodetect]", name, driverNameLength ) )
		{
		if( CryptAcquireContextA( &hProv, keysetName, MS_ENHANCED_PROV, 
								  PROV_RSA_FULL, 0 ) )
			cryptoapiInfo->hProv = hProv;
		else
			{
			if( CryptAcquireContextA( &hProv, keysetName, MS_DEF_PROV, 
									  PROV_RSA_FULL, 0 ) )
				cryptoapiInfo->hProv = hProv;
			else
				return( mapError( cryptoapiInfo, CRYPT_ERROR_NOTFOUND ) );
			}
		}
	else
		{
		/* Try and find a specific provider */
		if( CryptAcquireContextA( &hProv, keysetName, name, PROV_RSA_FULL, 0 ) )
			cryptoapiInfo->hProv = hProv;
		}

	/* Get information on device-specific capabilities */
	value = CRYPT_MAX_TEXTSIZE + 1;
	if( !CryptGetProvParam( cryptoapiInfo->hProv, PP_NAME, 
							cryptoapiInfo->label, &value, 0 ) )
		return( mapError( cryptoapiInfo, CRYPT_ERROR_NOTFOUND ) );
	cryptoapiInfo->labelLen = value;
	deviceInfo->label = cryptoapiInfo->label;
	deviceInfo->labelLen = cryptoapiInfo->labelLen;
	deviceInfo->flags |= DEVICE_ACTIVE;

	/* Set up the capability information for this device */
	status = getCapabilities( deviceInfo );
	if( cryptStatusError( status ) )
		{
		shutdownFunction( deviceInfo );
		return( ( status == CRYPT_ERROR ) ? CRYPT_ERROR_OPEN : status );
		}

	/* Create the special-purpose key needed to allow symmetric key loads */
	status = createExportKey( cryptoapiInfo->hProv, 
							  &cryptoapiInfo->hPrivateKey, 
							  &cryptoapiInfo->privateKeySize );
	if( cryptStatusError( status ) )
		{
		shutdownFunction( deviceInfo );
		return( status );
		}

	/* Open the certificate store used to store/retrieve certificates */
	hCertStore = pCertOpenSystemStore( cryptoapiInfo->hProv, 
									   keysetNameBuffer );
	if( hCertStore == NULL )
		{
		shutdownFunction( deviceInfo );
		return( CRYPT_ERROR_OPEN );
		}
	cryptoapiInfo->hCertStore = hCertStore;

	return( CRYPT_OK );
	}

/* Handle device control functions */

static int controlFunction( DEVICE_INFO *deviceInfo,
							const CRYPT_ATTRIBUTE_TYPE type,
							const void *data, const int dataLength,
							MESSAGE_FUNCTION_EXTINFO *messageExtInfo )
	{
	retIntError();
	}

/****************************************************************************
*																			*
*						 	Misc.Device Interface Routines					*
*																			*
****************************************************************************/

/* Get random data from the device */

static int getRandomFunction( DEVICE_INFO *deviceInfo, void *buffer,
							  const int length,
							  MESSAGE_FUNCTION_EXTINFO *messageExtInfo )
	{
	CRYPTOAPI_INFO *cryptoapiInfo = deviceInfo->deviceCryptoAPI;

	if( pCryptGenRandom( cryptoapiInfo->hProv, length, buffer ) )
		return( CRYPT_OK );
	return( mapError( cryptoapiInfo, CRYPT_ERROR_FAILED ) );
	}

/* Instantiate an object in a device.  This works like the create context
   function but instantiates a cryptlib object using data already contained
   in the device (for example a stored private key or certificate).  If the
   value being read is a public key and there's a certificate attached, the
   instantiated object is a native cryptlib object rather than a device
   object with a native certificate object attached because there doesn't 
   appear to be any good reason to create the public-key object in the 
   device.

   CryptoAPI doesn't have any concept of multiple private keys, only a 
   default encryption + signature key for the provider as a whole, and an 
   optional additional signature key to complement the encryption (and 
   signature if necessary) one.  In addition the ties between a private key 
   and its associated certificate(s) are rather tenuous, requiring jumping 
   through several levels of indirection in order to get from one to the 
   other.  To handle this, we have to use a meet-in-the-middle approach 
   where we try to go from private key to certificate if the identity of the 
   private key is obvious (the user has specifically asked for a private 
   decryption or signature key), or from certificate to private key in all 
   other cases */

static int getItemFunction( DEVICE_INFO *deviceInfo,
							CRYPT_CONTEXT *iCryptContext,
							const KEYMGMT_ITEM_TYPE itemType,
							const CRYPT_KEYID_TYPE keyIDtype,
							const void *keyID, const int keyIDlength,
							void *auxInfo, int *auxInfoLength, 
							const int flags )
	{
	CRYPTOAPI_INFO *cryptoapiInfo = deviceInfo->deviceCryptoAPI;
//	CRYPT_CERTIFICATE iCryptCert;
	HCRYPTKEY hKey = 0;
	PCCERT_CONTEXT pCertContext = NULL;
	PCCERT_CHAIN_CONTEXT pChainContext = NULL;
	DWORD dwKeySpec = 0;
	CRYPT_CERTIFICATE iCryptCert;
	CRYPT_ALGO_TYPE cryptAlgo = CRYPT_ALGO_NONE;
	const char *label = "Private key";
	int status;

	assert( itemType == KEYMGMT_ITEM_PUBLICKEY || \
			itemType == KEYMGMT_ITEM_PRIVATEKEY );

	/* If we're searching for the key by label and the user has specified 
	   one of the special-case key descriptions, get the appropriate key */
	if( keyIDtype == CRYPT_KEYID_NAME )
		{
		if( keyIDlength == 13 && \
			!memcmp( keyID, "Signature key", 13 ) )
			dwKeySpec = AT_SIGNATURE;
		else
			if( keyIDlength == 14 && \
				!memcmp( keyID, "Encryption key", 14 ) )
				dwKeySpec = AT_KEYEXCHANGE;
		}

	/* If we haven't got a key type from the label and we're looking for a 
	   particular usage, get the appropriate key */
	if( dwKeySpec == 0 && itemType == KEYMGMT_ITEM_PRIVATEKEY )
		{
		if( flags & KEYMGMT_FLAG_USAGE_SIGN ) 
			dwKeySpec = AT_SIGNATURE;
		else
			if( flags & KEYMGMT_FLAG_USAGE_CRYPT ) 
				dwKeySpec = AT_KEYEXCHANGE;
		}

	/* If we still haven't got a key type, try and get the certificate for
	   the given ID */
	if( dwKeySpec != 0 )
		{
		/* Get the required key type */
		if( !pCryptGetUserKey( cryptoapiInfo->hProv, dwKeySpec, &hKey ) )
			return( CRYPT_ERROR_NOTFOUND );
		label = ( dwKeySpec == AT_SIGNATURE ) ? \
				"Signature key" : "Encryption key";

		/* If we're only doing a presence check, we don't need the key and 
		   can exit */
		if( flags & KEYMGMT_FLAG_CHECK_ONLY )
			{
			pCryptDestroyKey( hKey ); 
			return( CRYPT_OK );
			}

		/* Since CryptoAPI doesn't have any concept of key labels, the best 
		   that we can do is provide a generic description of the intended 
		   key usage as a form of pseudo-label */
		if( flags & KEYMGMT_FLAG_LABEL_ONLY )
			{
			strlcpy_s( auxInfo, *auxInfoLength, label );
			*auxInfoLength = strlen( label );
			pCryptDestroyKey( hKey ); 
			return( CRYPT_OK );
			}

		/* We've got the key, try and get the associated certificate */
		status = getCertificateFromKey( cryptoapiInfo, hKey, 
										( flags & KEYMGMT_FLAG_USAGE_SIGN ) ? \
											TRUE : FALSE, &pCertContext );
		if( cryptStatusError( status ) && \
			itemType == KEYMGMT_ITEM_PUBLICKEY ) 
			{
			/* We couldn't get a certificate for the key, if we're after a 
			   public key return it as a native context */

⌨️ 快捷键说明

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