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

📄 pkcs11.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 4 页
字号:
						  CRYPT_ERRTYPE_ATTR_ABSENT );
			return( CRYPT_ERROR_NOTINITED );
			}

		/* Change the SSO PIN from the init PIN.  Once we've done this we 
		   clear the initial SSO PIN, since it's no longer valid in the new
		   state */
		status = C_SetPIN( pkcs11Info->hSession, pkcs11Info->defaultSSOPin,
						   pkcs11Info->defaultSSOPinLen, 
						   ( CK_CHAR_PTR ) data, ( CK_ULONG ) dataLength );
		zeroise( pkcs11Info->defaultSSOPin, CRYPT_MAX_TEXTSIZE );
		pkcs11Info->defaultSSOPinLen = 0;
		return( pkcs11MapError( pkcs11Info, status, CRYPT_ERROR_FAILED ) );
		}
	if( type == CRYPT_DEVINFO_SET_AUTHENT_USER )
		{
		/* Make sure that the PIN is within range */
		if( dataLength < pkcs11Info->minPinSize || \
			dataLength > pkcs11Info->maxPinSize )
			return( CRYPT_ARGERROR_NUM1 );

		status = C_InitPIN( pkcs11Info->hSession, ( CK_CHAR_PTR ) data, 
							( CK_ULONG ) dataLength );
		return( pkcs11MapError( pkcs11Info, status, CRYPT_ERROR_FAILED ) );
		}

	/* Handle initialisation and zeroisation */
	if( type == CRYPT_DEVINFO_INITIALISE || \
		type == CRYPT_DEVINFO_ZEROISE )
		{
		CK_SESSION_HANDLE hSession;
		CK_CHAR label[ 32 + 8 ];

		/* Make sure that the PIN is within range */
		if( dataLength < pkcs11Info->minPinSize || \
			dataLength > pkcs11Info->maxPinSize )
			return( CRYPT_ARGERROR_NUM1 );

		/* If there's a session active with the device, log out and terminate
		   the session, since the token init will reset this */
		if( pkcs11Info->hSession != CK_OBJECT_NONE )
			{
			C_Logout( pkcs11Info->hSession );
			C_CloseSession( pkcs11Info->hSession );
			pkcs11Info->hSession = CK_OBJECT_NONE;
			}

		/* Initialise/clear the device, setting the initial SSO PIN */
		memset( label, ' ', 32 );
		status = C_InitToken( pkcs11Info->slotID, 
							  ( CK_CHAR_PTR ) data,
							  ( CK_ULONG ) dataLength, label );
		if( status != CKR_OK )
			return( pkcs11MapError( pkcs11Info, status, 
									CRYPT_ERROR_FAILED ) );

		/* Reopen the session with the device */
		status = C_OpenSession( pkcs11Info->slotID,
								CKF_RW_SESSION | CKF_SERIAL_SESSION,
								NULL_PTR, NULL_PTR, &hSession );
		if( status != CKR_OK )
			return( pkcs11MapError( pkcs11Info, status, CRYPT_ERROR_OPEN ) );
		assert( hSession != CK_OBJECT_NONE );
		pkcs11Info->hSession = hSession;

		/* If it's a straight zeroise, we're done */
		if( type == CRYPT_DEVINFO_ZEROISE )
			return( CRYPT_OK );

		/* We're initialising it, log in as supervisor.  In theory we could 
		   also set the initial user PIN to the same as the SSO PIN at this
		   point because the user usually won't be aware of the presence of
		   an SSO role or the need to set a PIN for it, but this can run into
		   problems with tokens that only allow the user PIN to be modified
		   by the SSO after they've set it for the first time, so if the user
		   *is* aware of the existence of an SSO role then once they log in
		   as SSO they can no longer set the user PIN */
		status = C_Login( pkcs11Info->hSession, CKU_SO,
						  ( CK_CHAR_PTR ) data, ( CK_ULONG ) dataLength );
		if( status != CKR_OK )
			{
			C_Logout( pkcs11Info->hSession );
			C_CloseSession( pkcs11Info->hSession );
			pkcs11Info->hSession = CK_OBJECT_NONE;
			return( pkcs11MapError( pkcs11Info, status, CRYPT_ERROR_FAILED ) );
			}

		/* Remember the default SSO PIN for use with a future C_SetPIN() */
		memcpy( pkcs11Info->defaultSSOPin, data, dataLength );
		pkcs11Info->defaultSSOPinLen = dataLength;

		/* We're logged in and ready to go */
		deviceInfo->flags |= DEVICE_LOGGEDIN;
		return( CRYPT_OK );
		}

	/* Handle high-reliability time */
	if( type == CRYPT_IATTRIBUTE_TIME )
		{
		CK_TOKEN_INFO tokenInfo;
		time_t *timePtr = ( time_t * ) data, theTime;

		/* Get the token's time, returned as part of the token info 
		   structure */
		status = C_GetTokenInfo( pkcs11Info->slotID, &tokenInfo );
		if( status != CKR_OK )
			return( pkcs11MapError( pkcs11Info, status, 
									CRYPT_ERROR_SIGNALLED ) );
		if( ( theTime = getTokenTime( &tokenInfo ) ) <= MIN_TIME_VALUE )
			return( CRYPT_ERROR_NOTAVAIL );
		*timePtr = theTime;
		return( CRYPT_OK );
		}

	retIntError();
	}

/****************************************************************************
*																			*
*						 	Capability Interface Routines					*
*																			*
****************************************************************************/

/* Encrypt, decrypt */

static int genericEncrypt( PKCS11_INFO *pkcs11Info, 
						   CONTEXT_INFO *contextInfoPtr,
						   const CK_MECHANISM *pMechanism, void *buffer,
						   const int length, const int outLength )
	{
	CK_ULONG resultLen = outLength;
	CK_RV status;

	status = C_EncryptInit( pkcs11Info->hSession,
							( CK_MECHANISM_PTR ) pMechanism,
							contextInfoPtr->deviceObject );
	if( status == CKR_OK )
		status = C_Encrypt( pkcs11Info->hSession, buffer, length,
							buffer, &resultLen );
	if( status != CKR_OK )
		return( pkcs11MapError( pkcs11Info, status, CRYPT_ERROR_FAILED ) );
	return( CRYPT_OK );
	}

static int genericDecrypt( PKCS11_INFO *pkcs11Info, 
						   CONTEXT_INFO *contextInfoPtr,
						   const CK_MECHANISM *pMechanism, void *buffer,
						   const int length )
	{
	CK_ULONG resultLen = length;
	CK_RV status;

	status = C_DecryptInit( pkcs11Info->hSession,
							( CK_MECHANISM_PTR ) pMechanism,
							contextInfoPtr->deviceObject );
	if( status == CKR_OK )
		status = C_Decrypt( pkcs11Info->hSession, buffer, length,
							buffer, &resultLen );
	if( status != CKR_OK )
		return( pkcs11MapError( pkcs11Info, status, CRYPT_ERROR_FAILED ) );
	return( CRYPT_OK );
	}

/* Clean up the object associated with a context */

int genericEndFunction( CONTEXT_INFO *contextInfoPtr )
	{
	CRYPT_DEVICE iCryptDevice;
	PKCS11_INFO *pkcs11Info;
	int cryptStatus;

	/* Since the device object that corresponds to the cryptlib object is
	   created on-demand, it may not exist yet if the action that triggers
	   the on-demand creation hasn't been taken yet.  If no device object
	   exists, we're done */
	if( contextInfoPtr->deviceObject == CRYPT_ERROR )
		return( CRYPT_OK );

	/* Get the info for the device associated with this context */
	cryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle, 
										&iCryptDevice, &pkcs11Info );
	if( cryptStatusError( cryptStatus ) )
		return( cryptStatus );

	/* If we're deleting an object that's in the middle of a multi-stage 
	   operation, record the fact that the operation has now ended.  We
	   have to perform this tracking explicitly since PKCS #11 only allows
	   one multi-stage operation per session */
	if( pkcs11Info->hActiveSignObject == contextInfoPtr->deviceObject )
		pkcs11Info->hActiveSignObject = CK_OBJECT_NONE;

	/* If this is a persistent object, we can't destroy it.  This is a bit
	   problematic since PKCS #11 doesn't differentiate between releasing
	   an object handle and destroying (deleting) it, which means that
	   repeatedly instantiating a persistent object (via getItemFunction())
	   and then destroying it leaks a PKCS #11 handle each time.  
	   Unfortunately there's nothing that we can do about this since the
	   problem lies at the PKCS #11 level */
	if( contextInfoPtr->flags & CONTEXT_FLAG_PERSISTENT )
		{
		krnlReleaseObject( iCryptDevice );
		return( CRYPT_OK );
		}

	/* Destroy the object */
	C_DestroyObject( pkcs11Info->hSession, contextInfoPtr->deviceObject );
	if( contextInfoPtr->altDeviceObject != CK_OBJECT_NONE )
		C_DestroyObject( pkcs11Info->hSession, 
						 contextInfoPtr->altDeviceObject );
	krnlReleaseObject( iCryptDevice );
	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*					Conventional Crypto/MAC Key Load Functions				*
*																			*
****************************************************************************/

/* Get a PKCS #11 mechanism corresponding to a cryptlib algorithm and 
   optional mode */

typedef enum { MECH_NONE, MECH_CONV, MECH_MAC, MECH_CONV_KEYGEN, 
			   MECH_MAC_KEYGEN, MECH_LAST } GETMECH_TYPE;

static CK_MECHANISM_TYPE getMechanism( const GETMECH_TYPE mechType,
									   const CRYPT_ALGO_TYPE cryptAlgo,
									   const CRYPT_MODE_TYPE cryptMode );

/* Set up a key template and context info in preparation for creating a 
   device object */

static void adjustKeyParity( BYTE *key, const int length )
	{
	int i;

	assert( isWritePtr( key, length ) );

	/* Adjust a key to have odd parity, needed for DES keys */
	for( i = 0; i < length; i++ )
		{
		BYTE ch = key[ i ];
		
		ch = ( ch & 0x55 ) + ( ( ch >> 1 ) & 0x55 );
		ch = ( ch & 0x33 ) + ( ( ch >> 2 ) & 0x33 );
		if( !( ( ch + ( ch >> 4 ) ) & 0x01 ) )
			key[ i ] ^= 1;
		}
	}

/* Load a key into a device object */

static int initKey( CONTEXT_INFO *contextInfoPtr, CK_ATTRIBUTE *keyTemplate,
					const int templateCount, const void *key, 
					const int keyLength )
	{
	CRYPT_DEVICE iCryptDevice;
	const CRYPT_ALGO_TYPE cryptAlgo = \
				contextInfoPtr->capabilityInfo->cryptAlgo;
	PKCS11_INFO *pkcs11Info;
	CK_OBJECT_HANDLE hObject;
	CK_RV status;
	BYTE *contextKeyPtr;
	int *contextKeyLenPtr;
	int keySize = \
		( cryptAlgo == CRYPT_ALGO_DES || cryptAlgo == CRYPT_ALGO_3DES || \
		  cryptAlgo == CRYPT_ALGO_IDEA || cryptAlgo == CRYPT_ALGO_SKIPJACK ) ? \
		contextInfoPtr->capabilityInfo->keySize : keyLength;
	int cryptStatus;

	assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
	assert( isWritePtr( keyTemplate, \
						templateCount * sizeof( CK_ATTRIBUTE ) ) );
	assert( isReadPtr( key, keyLength ) );

	/* Get the info for the device associated with this context */
	cryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle, 
										&iCryptDevice, &pkcs11Info );
	if( cryptStatusError( cryptStatus ) )
		return( cryptStatus );

	/* Set up pointers to the appropriate object sub-type data */
	if( contextInfoPtr->type == CONTEXT_CONV )
		{
		contextKeyPtr = contextInfoPtr->ctxConv->userKey;
		contextKeyLenPtr = &contextInfoPtr->ctxConv->userKeyLength;
		}
	else
		{
		assert( contextInfoPtr->type == CONTEXT_MAC );

		contextKeyPtr = contextInfoPtr->ctxMAC->userKey;
		contextKeyLenPtr = &contextInfoPtr->ctxMAC->userKeyLength;
		}

	/* Copy the key to internal storage */
	if( contextKeyPtr != key )
		memcpy( contextKeyPtr, key, keyLength );
	*contextKeyLenPtr = keyLength;

	/* Special-case handling for 2-key vs.3-key 3DES */
	if( cryptAlgo == CRYPT_ALGO_3DES )
		{
		/* If the supplied key contains only two DES keys, adjust the key to 
		   make it the equivalent of 3-key 3DES.  In addition since the 
		   nominal keysize is for 2-key 3DES, we have to make the actual 
		   size the maximum size, corresponding to 3-key 3DES */
		if( keyLength <= bitsToBytes( 64 * 2 ) )
			memcpy( contextKeyPtr + bitsToBytes( 64 * 2 ),
					contextKeyPtr, bitsToBytes( 64 ) );
		keySize = contextInfoPtr->capabilityInfo->maxKeySize;
		}

	/* If we're using DES we have to adjust the key parity because the spec 
	   says so, almost all implementations do this anyway but there's always 
	   the odd one out that we have to cater for */
	if( cryptAlgo == CRYPT_ALGO_DES || cryptAlgo == CRYPT_ALGO_3DES )
		adjustKeyParity( contextKeyPtr, keySize );

	/* Set up the key values.  Since the key passed in by the user may be 
	   smaller than the keysize required by algorithms that use fixed-size 
	   keys, we use the (optionally) zero-padded key of the correct length 
	   held in the context rather than the variable-length user-supplied 
	   one */
	keyTemplate[ 7 ].pValue = contextKeyPtr;
	keyTemplate[ 7 ].ulValueLen = keySize;

	/* Load the key into the token */
	status = C_CreateObject( pkcs11Info->hSession, keyTemplate, 
							 templateCount, &hObject );
	cryptStatus = pkcs11MapError( pkcs11Info, status, CRYPT_ERROR_FAILED );
	if( cryptStatusOK( cryptStatus ) )
		{
		assert( hObject != CK_OBJECT_NONE );

		contextInfoPtr->deviceObject = hObject;
		}
	else
		{
		zeroise( contextInfoPtr->ctxConv->userKey, keyLength );
		contextInfoPtr->ctxConv->userKeyLength = 0;
		}
	zeroise( keyTemplate, sizeof( CK_ATTRIBUTE ) * templateCount );
	krnlReleaseObject( iCryptDevice );
	return( cryptStatus );
	}

static int cipherInitKey( CONTEXT_INFO *contextInfoPtr, const void *key, 
						  const int keyLength )
	{
	static const CK_OBJECT_CLASS class = CKO_SECRET_KEY;
	static const CK_BBOOL bFalse = FALSE, bTrue = TRUE;
	const CK_KEY_TYPE type = contextInfoPtr->capabilityInfo->paramKeyType;
	CK_ATTRIBUTE keyTemplate[] = {
		/* General-purpose fields */
		{ CKA_CLASS, ( CK_VOID_PTR ) &class, sizeof( CK_OBJECT_CLASS ) },
		{ CKA_KEY_TYPE, ( CK_VOID_PTR ) &type, sizeof( CK_KEY_TYPE ) },
		{ CKA_TOKEN, ( CK_VOID_PTR ) &bFalse, sizeof( CK_BBOOL ) },
		{ CKA_PRIVATE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
		{ CKA_SENSITIVE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
		{ CKA_ENCRYPT, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
		{ CKA_DECRYPT, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
		{ CKA_VALUE, NULL_PTR, 0 },
		/* Persistent-object only fields */
		{ CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize }
		};
	const int templateCount = \
				( contextInfoPtr->flags & CONTEXT_FLAG_PERSISTENT ) ? 9 : 8;

⌨️ 快捷键说明

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