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

📄 dev_pk11.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 5 页
字号:
/****************************************************************************
*																			*
*							cryptlib PKCS #11 Routines						*
*						Copyright Peter Gutmann 1998-2002					*
*																			*
****************************************************************************/

#include <stdlib.h>
#include <string.h>
#if defined( INC_ALL )
  #include "crypt.h"
  #include "cryptctx.h"
  #include "asn1.h"
  #include "device.h"
#elif defined( INC_CHILD )
  #include "../crypt.h"
  #include "../cryptctx.h"
  #include "../keymgmt/asn1.h"
  #include "device.h"
#else
  #include "crypt.h"
  #include "cryptctx.h"
  #include "keymgmt/asn1.h"
  #include "misc/device.h"
#endif /* Compiler-specific includes */

/* Uncomment the following to fake out writes to the device.  This makes 
   testing easier since it allows the code to be debugged without messing up 
   data stored on the device when the program is terminated halfway through an 
   update */

/*#define NO_UPDATE	/**/

/* Before we can include the PKCS #11 headers we need to define a few OS-
   specific things which are required by the headers */

#ifdef __WINDOWS__
  #ifdef __WIN16__
	#pragma pack( 1 )					/* Struct packing */
	#define CK_PTR	far *				/* Pointer type */
	#define CK_DEFINE_FUNCTION( returnType, name ) \
								returnType __export _far _pascal name
	#define CK_DECLARE_FUNCTION( returnType, name ) \
								 returnType __export _far _pascal name
	#define CK_DECLARE_FUNCTION_POINTER( returnType, name ) \
								returnType __export _far _pascal (* name)
	#define CK_CALLBACK_FUNCTION( returnType, name ) \
								  returnType (_far _pascal * name)
  #else
	#pragma pack( push, cryptoki, 1 )	/* Struct packing */
	#define CK_PTR	*					/* Pointer type */
	#define CK_DEFINE_FUNCTION( returnType, name ) \
								returnType __declspec( dllexport ) name
	#define CK_DECLARE_FUNCTION( returnType, name ) \
								 returnType __declspec( dllimport ) name
	#define CK_DECLARE_FUNCTION_POINTER( returnType, name ) \
								returnType __declspec( dllimport ) (* name)
	#define CK_CALLBACK_FUNCTION( returnType, name ) \
								  returnType (* name)
  #endif /* Win16 vs Win32 */
#else
  #define CK_PTR	*					/* Pointer type */
  #define CK_DEFINE_FUNCTION( returnType, name ) \
							  returnType name
  #define CK_DECLARE_FUNCTION( returnType, name ) \
							   returnType name
  #define CK_DECLARE_FUNCTION_POINTER( returnType, name ) \
									   returnType (* name)
  #define CK_CALLBACK_FUNCTION( returnType, name ) \
								returnType (* name)
#endif /* __WINDOWS__ */
#ifndef NULL_PTR
  #define NULL_PTR	NULL
#endif /* NULL_PTR */

#if defined( INC_ALL ) || defined( INC_CHILD )
  #include "pkcs11.h"
#else
  #include "misc/pkcs11.h"
#endif /* Compiler-specific includes */

/* The max. number of drivers we can work with and the max.number of slots
   per driver */

#define MAX_PKCS11_DRIVERS		5
#define MAX_PKCS11_SLOTS		16

/* The default slot to look for tokens in */

#define DEFAULT_SLOT			0

/* Occasionally we need to read things into host memory from a device, the
   following value defines the maximum size of the on-stack buffer, if the
   data is larger than this we dynamically allocate the buffer (this almost
   never occurs) */

#define MAX_BUFFER_SIZE			1024

/* Encryption contexts can store extra implementation-dependant parameters,
   the following macros maps these generic parameter names to the PKCS #11
   values */

#define paramKeyType			param1

/* Prototypes for functions in cryptcap.c */

const void FAR_BSS *findCapabilityInfo( const void FAR_BSS *capabilityInfoPtr,
										const CRYPT_ALGO cryptAlgo );

#ifdef DEV_PKCS11

/****************************************************************************
*																			*
*						 		Init/Shutdown Routines						*
*																			*
****************************************************************************/

/* Whether the PKCS #11 library has been initialised or not, this is
   initialised on demand the first time it's accessed */

static BOOLEAN pkcs11Initialised = FALSE;

#ifdef DYNAMIC_LOAD

/* Since we can be using multiple PKCS #11 drivers, we define an array of
   them and access the appropriate one by its name */

typedef struct {
	char name[ 32 + 1 ];			/* Name of device */
	INSTANCE_HANDLE hPKCS11;		/* Handle to driver */
	CK_C_CloseSession pC_CloseSession;	/* Interface function pointers */
	CK_C_CreateObject pC_CreateObject;
	CK_C_Decrypt pC_Decrypt;
	CK_C_DecryptInit pC_DecryptInit;
	CK_C_DestroyObject pC_DestroyObject;
	CK_C_Encrypt pC_Encrypt;
	CK_C_EncryptInit pC_EncryptInit;
	CK_C_Finalize pC_Finalize;
	CK_C_FindObjects pC_FindObjects;
	CK_C_FindObjectsFinal pC_FindObjectsFinal;
	CK_C_FindObjectsInit pC_FindObjectsInit;
	CK_C_GenerateKeyPair pC_GenerateKeyPair;
	CK_C_GenerateRandom pC_GenerateRandom;
	CK_C_GetAttributeValue pC_GetAttributeValue;
	CK_C_GetMechanismInfo pC_GetMechanismInfo;
	CK_C_GetSlotList pC_GetSlotList;
	CK_C_GetTokenInfo pC_GetTokenInfo;
	CK_C_InitPIN pC_InitPIN;
	CK_C_InitToken pC_InitToken;
	CK_C_Login pC_Login;
	CK_C_Logout pC_Logout;
	CK_C_OpenSession pC_OpenSession;
	CK_C_SetAttributeValue pC_SetAttributeValue;
	CK_C_SetPIN pC_SetPIN;
	CK_C_Sign pC_Sign;
	CK_C_SignInit pC_SignInit;
	CK_C_UnwrapKey pC_UnwrapKey;
	CK_C_Verify pC_Verify;
	CK_C_VerifyInit pC_VerifyInit;
	} PKCS11_INFO;

static PKCS11_INFO pkcs11InfoTbl[ MAX_PKCS11_DRIVERS ];

/* The use of dynamically bound function pointers vs statically linked
   functions requires a bit of sleight of hand since we can't give the
   pointers the same names as prototyped functions.  To get around this we
   redefine the actual function names to the names of the pointers */

#define C_CloseSession		pkcs11InfoTbl[ deviceInfo->deviceNo ].pC_CloseSession
#define C_CreateObject		pkcs11InfoTbl[ deviceInfo->deviceNo ].pC_CreateObject
#define C_Decrypt			pkcs11InfoTbl[ deviceInfo->deviceNo ].pC_Decrypt
#define C_DecryptInit		pkcs11InfoTbl[ deviceInfo->deviceNo ].pC_DecryptInit
#define C_DestroyObject		pkcs11InfoTbl[ deviceInfo->deviceNo ].pC_DestroyObject
#define C_Encrypt			pkcs11InfoTbl[ deviceInfo->deviceNo ].pC_Encrypt
#define C_EncryptInit		pkcs11InfoTbl[ deviceInfo->deviceNo ].pC_EncryptInit
#define C_Finalize			pkcs11InfoTbl[ deviceInfo->deviceNo ].pC_Finalize
#define C_FindObjects		pkcs11InfoTbl[ deviceInfo->deviceNo ].pC_FindObjects
#define C_FindObjectsFinal	pkcs11InfoTbl[ deviceInfo->deviceNo ].pC_FindObjectsFinal
#define C_FindObjectsInit	pkcs11InfoTbl[ deviceInfo->deviceNo ].pC_FindObjectsInit
#define C_GenerateKeyPair	pkcs11InfoTbl[ deviceInfo->deviceNo ].pC_GenerateKeyPair
#define C_GenerateRandom	pkcs11InfoTbl[ deviceInfo->deviceNo ].pC_GenerateRandom
#define C_GetAttributeValue	pkcs11InfoTbl[ deviceInfo->deviceNo ].pC_GetAttributeValue
#define C_GetMechanismInfo	pkcs11InfoTbl[ deviceInfo->deviceNo ].pC_GetMechanismInfo
#define C_GetSlotList		pkcs11InfoTbl[ deviceInfo->deviceNo ].pC_GetSlotList
#define C_GetTokenInfo		pkcs11InfoTbl[ deviceInfo->deviceNo ].pC_GetTokenInfo
#define C_Initialize		pkcs11InfoTbl[ deviceInfo->deviceNo ].pC_Initialize
#define C_InitPIN			pkcs11InfoTbl[ deviceInfo->deviceNo ].pC_InitPIN
#define C_InitToken			pkcs11InfoTbl[ deviceInfo->deviceNo ].pC_InitToken
#define C_Login				pkcs11InfoTbl[ deviceInfo->deviceNo ].pC_Login
#define C_Logout			pkcs11InfoTbl[ deviceInfo->deviceNo ].pC_Logout
#define C_OpenSession		pkcs11InfoTbl[ deviceInfo->deviceNo ].pC_OpenSession
#define C_SetAttributeValue	pkcs11InfoTbl[ deviceInfo->deviceNo ].pC_SetAttributeValue
#define C_SetPIN			pkcs11InfoTbl[ deviceInfo->deviceNo ].pC_SetPIN
#define C_Sign				pkcs11InfoTbl[ deviceInfo->deviceNo ].pC_Sign
#define C_SignInit			pkcs11InfoTbl[ deviceInfo->deviceNo ].pC_SignInit
#define C_UnwrapKey			pkcs11InfoTbl[ deviceInfo->deviceNo ].pC_UnwrapKey
#define C_Verify			pkcs11InfoTbl[ deviceInfo->deviceNo ].pC_Verify
#define C_VerifyInit		pkcs11InfoTbl[ deviceInfo->deviceNo ].pC_VerifyInit

/* Dynamically load and unload any necessary PKCS #11 drivers */

static int loadPKCS11driver( PKCS11_INFO *pkcs11Info,
							 const char *driverName )
	{
	CK_C_GetInfo pC_GetInfo;
	CK_C_Initialize pC_Initialize;
	CK_INFO info;
	CK_RV status;
#ifdef __WIN16__
	UINT errorMode;
#endif /* __WIN16__ */
	BOOLEAN isInitialised = FALSE;
	int i = 32;

	/* Obtain a handle to the device driver module */
#ifdef __WIN16__
	errorMode = SetErrorMode( SEM_NOOPENFILEERRORBOX );
	pkcs11Info->hPKCS11 = LoadLibrary( driverName );
	SetErrorMode( errorMode );
	if( pkcs11Info->hPKCS11 < HINSTANCE_ERROR )
		{
		pkcs11Info->hPKCS11 = NULL_HINSTANCE;
		return( CRYPT_ERROR );
		}
#else
	if( ( pkcs11Info->hPKCS11 = DynamicLoad( driverName ) ) == NULL_INSTANCE )
		return( CRYPT_ERROR );
#endif /* OS-specific dynamic load */

	/* Now get pointers to the functions */
	pC_GetInfo = ( CK_C_GetInfo ) DynamicBind( pkcs11Info->hPKCS11, "C_GetInfo" );
	pC_Initialize = ( CK_C_Initialize ) DynamicBind( pkcs11Info->hPKCS11, "C_Initialize" );
	pkcs11Info->pC_CloseSession = ( CK_C_CloseSession ) DynamicBind( pkcs11Info->hPKCS11, "C_CloseSession" );
	pkcs11Info->pC_CreateObject = ( CK_C_CreateObject ) DynamicBind( pkcs11Info->hPKCS11, "C_CreateObject" );
	pkcs11Info->pC_Decrypt = ( CK_C_Decrypt ) DynamicBind( pkcs11Info->hPKCS11, "C_Decrypt" );
	pkcs11Info->pC_DecryptInit = ( CK_C_DecryptInit ) DynamicBind( pkcs11Info->hPKCS11, "C_DecryptInit" );
	pkcs11Info->pC_DestroyObject = ( CK_C_DestroyObject ) DynamicBind( pkcs11Info->hPKCS11, "C_DestroyObject" );
	pkcs11Info->pC_Encrypt = ( CK_C_Encrypt ) DynamicBind( pkcs11Info->hPKCS11, "C_Encrypt" );
	pkcs11Info->pC_EncryptInit = ( CK_C_EncryptInit ) DynamicBind( pkcs11Info->hPKCS11, "C_EncryptInit" );
	pkcs11Info->pC_Finalize = ( CK_C_Finalize ) DynamicBind( pkcs11Info->hPKCS11, "C_Finalize" );
	pkcs11Info->pC_FindObjects = ( CK_C_FindObjects ) DynamicBind( pkcs11Info->hPKCS11, "C_FindObjects" );
	pkcs11Info->pC_FindObjectsFinal = ( CK_C_FindObjectsFinal ) DynamicBind( pkcs11Info->hPKCS11, "C_FindObjectsFinal" );
	pkcs11Info->pC_FindObjectsInit = ( CK_C_FindObjectsInit ) DynamicBind( pkcs11Info->hPKCS11, "C_FindObjectsInit" );
	pkcs11Info->pC_GenerateKeyPair = ( CK_C_GenerateKeyPair ) DynamicBind( pkcs11Info->hPKCS11, "C_GenerateKeyPair" );
	pkcs11Info->pC_GenerateRandom = ( CK_C_GenerateRandom ) DynamicBind( pkcs11Info->hPKCS11, "C_GenerateRandom" );
	pkcs11Info->pC_GetAttributeValue = ( CK_C_GetAttributeValue ) DynamicBind( pkcs11Info->hPKCS11, "C_GetAttributeValue" );
	pkcs11Info->pC_GetMechanismInfo = ( CK_C_GetMechanismInfo ) DynamicBind( pkcs11Info->hPKCS11, "C_GetMechanismInfo" );
	pkcs11Info->pC_GetSlotList = ( CK_C_GetSlotList ) DynamicBind( pkcs11Info->hPKCS11, "C_GetSlotList" );
	pkcs11Info->pC_GetTokenInfo = ( CK_C_GetTokenInfo ) DynamicBind( pkcs11Info->hPKCS11, "C_GetTokenInfo" );
	pkcs11Info->pC_InitPIN = ( CK_C_InitPIN ) DynamicBind( pkcs11Info->hPKCS11, "C_InitPIN" );
	pkcs11Info->pC_InitToken = ( CK_C_InitToken ) DynamicBind( pkcs11Info->hPKCS11, "C_InitToken" );
	pkcs11Info->pC_Login = ( CK_C_Login ) DynamicBind( pkcs11Info->hPKCS11, "C_Login" );
	pkcs11Info->pC_Logout = ( CK_C_Logout ) DynamicBind( pkcs11Info->hPKCS11, "C_Logout" );
	pkcs11Info->pC_OpenSession = ( CK_C_OpenSession ) DynamicBind( pkcs11Info->hPKCS11, "C_OpenSession" );
	pkcs11Info->pC_SetAttributeValue = ( CK_C_SetAttributeValue ) DynamicBind( pkcs11Info->hPKCS11, "C_SetAttributeValue" );
	pkcs11Info->pC_SetPIN = ( CK_C_SetPIN ) DynamicBind( pkcs11Info->hPKCS11, "C_SetPIN" );
	pkcs11Info->pC_Sign = ( CK_C_Sign ) DynamicBind( pkcs11Info->hPKCS11, "C_Sign" );
	pkcs11Info->pC_SignInit = ( CK_C_SignInit ) DynamicBind( pkcs11Info->hPKCS11, "C_SignInit" );
	pkcs11Info->pC_UnwrapKey = ( CK_C_UnwrapKey ) DynamicBind( pkcs11Info->hPKCS11, "C_UnwrapKey" );
	pkcs11Info->pC_Verify = ( CK_C_Verify ) DynamicBind( pkcs11Info->hPKCS11, "C_Verify" );
	pkcs11Info->pC_VerifyInit = ( CK_C_VerifyInit ) DynamicBind( pkcs11Info->hPKCS11, "C_VerifyInit" );

	/* Make sure we got valid pointers for every device function.  
	   C_FindObjectsFinal() wasn't added until 2.x and some drivers don't
	   implement it (a smaller subset of them nevertheless claim to be 2.x 
	   drivers), so we allow this to be null - the code won't call it if it's
	   not present */
	if( pC_GetInfo == NULL || pC_Initialize == NULL ||
		pkcs11Info->pC_CloseSession == NULL ||
		pkcs11Info->pC_CreateObject == NULL ||
		pkcs11Info->pC_Decrypt == NULL ||
		pkcs11Info->pC_DecryptInit == NULL ||
		pkcs11Info->pC_DestroyObject == NULL ||
		pkcs11Info->pC_Encrypt == NULL ||
		pkcs11Info->pC_EncryptInit == NULL ||
		pkcs11Info->pC_Finalize == NULL ||
		pkcs11Info->pC_FindObjects == NULL ||
		pkcs11Info->pC_FindObjectsInit == NULL ||
		pkcs11Info->pC_GenerateRandom == NULL ||
		pkcs11Info->pC_GenerateKeyPair == NULL ||
		pkcs11Info->pC_GetAttributeValue == NULL ||
		pkcs11Info->pC_GetMechanismInfo == NULL ||
		pkcs11Info->pC_GetSlotList == NULL ||
		pkcs11Info->pC_GetTokenInfo == NULL || 
		pkcs11Info->pC_InitPIN == NULL || 
		pkcs11Info->pC_InitToken == NULL || pkcs11Info->pC_Login == NULL ||
		pkcs11Info->pC_Logout == NULL || pkcs11Info->pC_OpenSession == NULL ||
		pkcs11Info->pC_SetAttributeValue == NULL ||
		pkcs11Info->pC_SetPIN == NULL || pkcs11Info->pC_Sign == NULL ||
		pkcs11Info->pC_SignInit == NULL || pkcs11Info->pC_UnwrapKey == NULL || 
		pkcs11Info->pC_Verify == NULL || pkcs11Info->pC_VerifyInit == NULL )
		{
		/* Free the library reference and clear the info */
		DynamicUnload( pkcs11Info->hPKCS11 );
		memset( pkcs11Info, 0, sizeof( PKCS11_INFO ) );
		return( CRYPT_ERROR );
		}

	/* Initialise the PKCS #11 library and get info on the device.  We have 
	   to use some kludges to handle v1-style functions */
	status = pC_Initialize( NULL_PTR ) & 0xFFFF;
	if( status == CKR_OK )
		{
		isInitialised = TRUE;
		status = pC_GetInfo( &info ) & 0xFFFF;
		}
	if( status == CKR_OK && info.cryptokiVersion.major <= 1 )
		/* There are four types of PKCS #11 driver around: v1, v1-like 
		   claiming to be v2, v2-like claiming to be v1, and v2.  cryptlib
		   can in theory handle all of these, however there are some problem
		   areas with v1 (for example v1 uses 16-bit values while v2 uses 32-
		   bit ones, this is usually OK because data is passed around as 32-
		   bit values with the high bits zeroed but some implementations may
		   leave garbage in the high 16 bits which leads to all sorts of 
		   confusion).  Because of this we explicitly fail if something claims
		   to be v1 even though it might work in practice */
		status = CKR_FUNCTION_NOT_SUPPORTED;
	if( status != CKR_OK )
		{
		if( isInitialised )
			pkcs11Info->pC_Finalize( NULL_PTR );
		DynamicUnload( pkcs11Info->hPKCS11 );
		memset( pkcs11Info, 0, sizeof( PKCS11_INFO ) );
		return( CRYPT_ERROR );
		}

	/* Copy out the device driver's name so the user can access it by name.  
	   Some vendors erroneously null-terminate the string so we check for 
	   nulls as well */
	memcpy( pkcs11Info->name, info.libraryDescription, 32 );
	while( i && ( pkcs11Info->name[ i - 1 ] == ' ' || \
				  !pkcs11Info->name[ i - 1 ] ) )
		i--;
	pkcs11Info->name[ i ] = '\0';

	return( CRYPT_OK );
	}

⌨️ 快捷键说明

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