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

📄 pkcs11.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 5 页
字号:
		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_GetSlotInfo == 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_DRIVER_INFO ) );
		return( CRYPT_ERROR );
		}

	/* Initialise the PKCS #11 library and get info on the device.  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 
	   that 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 = pC_Initialize( NULL_PTR ) & 0xFFFF;
	if( status == CKR_OK || status == CKR_CRYPTOKI_ALREADY_INITIALIZED )
		{
		isInitialised = TRUE;
		status = pC_GetInfo( &info ) & 0xFFFF;
		}
	if( status == CKR_OK && info.cryptokiVersion.major <= 1 )
		/* It's v1, we can't work with it */
		status = CKR_FUNCTION_NOT_SUPPORTED;
	if( status != CKR_OK )
		{
		if( isInitialised )
			pkcs11Info->pC_Finalize( NULL_PTR );
		DynamicUnload( pkcs11Info->hPKCS11 );
		memset( pkcs11Info, 0, sizeof( PKCS11_DRIVER_INFO ) );
		return( CRYPT_ERROR );
		}
#else
	/* Get the access information for the PKCS #11 library, initialise it, 
	   and get info on the device.  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 that 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 */
	pC_GetFunctionList = ( CK_C_GetFunctionList ) DynamicBind( pkcs11Info->hPKCS11, "C_GetFunctionList" );
	if( pC_GetFunctionList == NULL )
		status = CKR_GENERAL_ERROR;
	else
		status = pC_GetFunctionList( &pkcs11Info->functionListPtr ) & 0xFFFF;
	if( status != CKR_OK )
		{
		/* Free the library reference and clear the info */
		DynamicUnload( pkcs11Info->hPKCS11 );
		memset( pkcs11Info, 0, sizeof( PKCS11_DRIVER_INFO ) );
		return( CRYPT_ERROR );
		}
	status = C_Initialize( NULL_PTR ) & 0xFFFF;
	if( status == CKR_OK || status == CKR_CRYPTOKI_ALREADY_INITIALIZED )
		{
		isInitialised = TRUE;
		status = C_GetInfo( &info ) & 0xFFFF;
		}
	if( status == CKR_OK && info.cryptokiVersion.major <= 1 )
		/* It's v1, we can't work with it */
		status = CKR_FUNCTION_NOT_SUPPORTED;
	if( status != CKR_OK )
		{
		if( isInitialised )
			C_Finalize( NULL_PTR );
		DynamicUnload( pkcs11Info->hPKCS11 );
		memset( pkcs11Info, 0, sizeof( PKCS11_DRIVER_INFO ) );
		return( CRYPT_ERROR );
		}
#endif /* USE_EXPLICIT_LINKING */

	/* Copy out the device driver's name so that 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 > 0 && ( pkcs11Info->name[ i - 1 ] == ' ' || \
					  !pkcs11Info->name[ i - 1 ] ) )
		i--;
	pkcs11Info->name[ i ] = '\0';

	return( CRYPT_OK );
	}

void deviceEndPKCS11( void )
	{
	int i;

	if( pkcs11Initialised )
		for( i = 0; i < MAX_PKCS11_DRIVERS; i++ )
			{
			if( pkcs11InfoTbl[ i ].hPKCS11 != NULL_INSTANCE )
				{
#ifdef USE_EXPLICIT_LINKING
				pkcs11InfoTbl[ i ].pC_Finalize( NULL_PTR );
#else
				PKCS11_DRIVER_INFO *pkcs11Info = &pkcs11InfoTbl[ i ];

				C_Finalize( NULL_PTR );
#endif /* USE_EXPLICIT_LINKING */
				DynamicUnload( pkcs11InfoTbl[ i ].hPKCS11 );
				}
			pkcs11InfoTbl[ i ].hPKCS11 = NULL_INSTANCE;
			}
	pkcs11Initialised = FALSE;
	}

int deviceInitPKCS11( void )
	{
	int tblIndex = 0, optionIndex;

	/* If we've previously tried to init the drivers, don't try it again */
	if( pkcs11Initialised )
		return( CRYPT_OK );
	memset( pkcs11InfoTbl, 0, sizeof( pkcs11InfoTbl ) );

	/* Try and link in each driver specified in the config options.  Since
	   this is a general systemwide config option, we always query the built-
	   in default user object */
	for( optionIndex = 0; optionIndex < MAX_PKCS11_DRIVERS; optionIndex++ )
		{
		RESOURCE_DATA msgData;
		char deviceDriverName[ MAX_PATH_LENGTH + 1 ];
		int status;

		setMessageData( &msgData, deviceDriverName, MAX_PATH_LENGTH );
		status = krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE, 
						IMESSAGE_GETATTRIBUTE_S, &msgData, 
						optionIndex + CRYPT_OPTION_DEVICE_PKCS11_DVR01 );
		if( cryptStatusError( status ) )
			continue;
		deviceDriverName[ msgData.length ] = '\0';
		status = loadPKCS11driver( &pkcs11InfoTbl[ tblIndex ], 
								   deviceDriverName );
		if( cryptStatusOK( status ) )
			{
			tblIndex++;
			pkcs11Initialised = TRUE;
			}
		}
	
	return( pkcs11Initialised ? CRYPT_OK : CRYPT_ERROR );
	}

#else

int deviceInitPKCS11( void )
	{
	int status;

	/* If we've previously tried to init the drivers, don't try it again */
	if( pkcs11Initialised )
		return( CRYPT_OK );

	status = C_Initialize( NULL_PTR );
	if( status != CKR_OK && status != CKR_CRYPTOKI_ALREADY_INITIALIZED )
		return( CRYPT_ERROR );
	pkcs11Initialised = TRUE;
	return( CRYPT_OK );
	}

void deviceEndPKCS11( void )
	{
	if( pkcs11Initialised )
		C_Finalize( NULL_PTR );
	pkcs11Initialised = FALSE;
	}
#endif /* DYNAMIC_LOAD */

/****************************************************************************
*																			*
*						 		Utility Routines							*
*																			*
****************************************************************************/

/* Map a PKCS #11-specific error to a cryptlib error */

static int mapError( PKCS11_INFO *pkcs11Info, const CK_RV errorCode,
					 const int defaultError )
	{
	pkcs11Info->errorCode = ( int ) errorCode;
	switch( ( int ) errorCode )
		{
		case CKR_OK:
			return( CRYPT_OK );

		case CKR_HOST_MEMORY:
		case CKR_DEVICE_MEMORY:
			return( CRYPT_ERROR_MEMORY );

		case CKR_DEVICE_ERROR:
		case CKR_DEVICE_REMOVED:
		case CKR_TOKEN_NOT_PRESENT:
			return( CRYPT_ERROR_SIGNALLED );

		case CKR_PIN_INCORRECT:
		case CKR_PIN_INVALID:
		case CKR_PIN_LEN_RANGE:
		case CKR_PIN_EXPIRED:
		case CKR_PIN_LOCKED:
			return( CRYPT_ERROR_WRONGKEY );

		case CKR_DATA_INVALID:
		case CKR_ENCRYPTED_DATA_INVALID:
		case CKR_WRAPPED_KEY_INVALID:
			return( CRYPT_ERROR_BADDATA );

		case CKR_SIGNATURE_INVALID:
			return( CRYPT_ERROR_SIGNATURE );

		case CKR_KEY_NOT_WRAPPABLE:
		case CKR_KEY_UNEXTRACTABLE:
		case CKR_TOKEN_WRITE_PROTECTED:
		case CKR_INFORMATION_SENSITIVE:
			return( CRYPT_ERROR_PERMISSION );

		case CKR_DATA_LEN_RANGE:
		case CKR_ENCRYPTED_DATA_LEN_RANGE:
		case CKR_SIGNATURE_LEN_RANGE:
		case CKR_UNWRAPPING_KEY_SIZE_RANGE:
		case CKR_WRAPPING_KEY_SIZE_RANGE:
		case CKR_WRAPPED_KEY_LEN_RANGE:
			return( CRYPT_ERROR_OVERFLOW );

		case CKR_SESSION_EXISTS:
		case CKR_SESSION_READ_ONLY_EXISTS:
		case CKR_SESSION_READ_WRITE_SO_EXISTS:
		case CKR_USER_ALREADY_LOGGED_IN:
		case CKR_USER_ANOTHER_ALREADY_LOGGED_IN:
		case CKR_CRYPTOKI_NOT_INITIALIZED:
			return( CRYPT_ERROR_INITED );

		case CKR_USER_NOT_LOGGED_IN:
		case CKR_USER_PIN_NOT_INITIALIZED:
		case CKR_CRYPTOKI_ALREADY_INITIALIZED:
			return( CRYPT_ERROR_NOTINITED );

		case CKR_RANDOM_NO_RNG:
			return( CRYPT_ERROR_RANDOM );

		case CKR_OPERATION_ACTIVE:
			return( CRYPT_ERROR_TIMEOUT );

		case CKR_TOKEN_NOT_RECOGNIZED:
			return( CRYPT_ERROR_NOTFOUND );
		}

	return( defaultError );
	}

/* Extract the time from a PKCS #11 tokenInfo structure */

static time_t getTokenTime( CK_TOKEN_INFO *tokenInfo )
	{
	STREAM stream;
	BYTE buffer[ 32 ];
	time_t theTime = MIN_TIME_VALUE + 1;
	int length, status;

	/* Convert the token time to an ASN.1 time string that we can read using
	   the standard ASN.1 routines by writing a dummy time value and inserting 
	   the token's time string in its place */
	sMemOpen( &stream, buffer, 32 );
	writeGeneralizedTime( &stream, theTime, DEFAULT_TAG );
	length = stell( &stream );
	sMemDisconnect( &stream );
	memcpy( buffer + 2, tokenInfo->utcTime, 14 );
	sMemConnect( &stream, buffer, length );
	status = readGeneralizedTime( &stream, &theTime );
	sMemDisconnect( &stream );
	
	return( ( cryptStatusOK( status ) ) ? theTime : 0 );
	}

/* Find an object based on a given template.  There are two variations of 
   this, one that finds one and only one object, and the other that returns 
   the first object it finds without treating the presence of multiple 
   objects as an error.
   
   The way in which this call works has special significance, there are PKCS
   #11 implementations that don't allow any other calls during the init/find/
   final sequence, so the code is structured to always call them one after 
   the other without any intervening calls.  In addition some drivers are
   confused over whether they're 1.x or 2.x and may or may not implement
   C_FindObjectsFinal().  Because of this we call it if it exists, if it 
   doesn't we assume that the driver can handle cleanup itself (this 
   situation shouldn't occur because we've checked for 1.x drivers earlier, 
   but there are one or two drivers where it does happen) */

static int findDeviceObjects( PKCS11_INFO *pkcs11Info, 
							  CK_OBJECT_HANDLE *hObject,
							  const CK_ATTRIBUTE *objectTemplate,
							  const CK_ULONG templateCount,
							  const BOOLEAN onlyOne )
	{
	CK_OBJECT_HANDLE hObjectArray[ 2 ];
	CK_ULONG ulObjectCount;

⌨️ 快捷键说明

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