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

📄 dev_pk11.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 5 页
字号:
void deviceEndPKCS11( void )
	{
	int i;

	for( i = 0; i < MAX_PKCS11_DRIVERS; i++ )
		{
		if( pkcs11InfoTbl[ i ].hPKCS11 != NULL_INSTANCE )
			{
			pkcs11InfoTbl[ i ].pC_Finalize( NULL_PTR );
			DynamicUnload( pkcs11InfoTbl[ i ].hPKCS11 );
			}
		pkcs11InfoTbl[ i ].hPKCS11 = NULL_INSTANCE;
		}
	pkcs11Initialised = FALSE;
	}

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

	/* If we've previously tried to init the drivers, don't try it again */
	if( pkcs11Initialised )
		return;
	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;

		setResourceData( &msgData, deviceDriverName, MAX_PATH_LENGTH );
		status = krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE, 
						RESOURCE_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 ) )
			pkcs11Initialised = TRUE;
		}
	}

#else

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

	if( C_Initialize( NULL_PTR ) != CKR_OK )
		return;
	pkcs11Initialised = TRUE;
	}

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( DEVICE_INFO *deviceInfo, const CK_RV errorCode,
					 const int defaultError )
	{
	deviceInfo->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:
			return( CRYPT_ERROR_SIGNALLED );
		case CKR_PIN_INCORRECT:
		case CKR_PIN_INVALID:
		case CKR_PIN_LEN_RANGE:
			return( CRYPT_ERROR_WRONGKEY );
		case CKR_SIGNATURE_INVALID:
			return( CRYPT_ERROR_SIGNATURE );
		case CKR_TOKEN_WRITE_PROTECTED:
		case CKR_USER_NOT_LOGGED_IN:
		case CKR_INFORMATION_SENSITIVE:
			return( CRYPT_ERROR_PERMISSION );
		case CKR_DATA_LEN_RANGE:
			return( CRYPT_ERROR_OVERFLOW );
		case CKR_USER_ALREADY_LOGGED_IN:
			return( CRYPT_ERROR_INITED );
		case CKR_USER_PIN_NOT_INITIALIZED:
			return( CRYPT_ERROR_NOTINITED );
		}

	return( defaultError );
	}

/* Find an object based on a given template.  There are two variations of 
   this, one which finds one and only one object, and the other which
   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 which 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 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( DEVICE_INFO *deviceInfo, 
							  CK_OBJECT_HANDLE *hObject,
							  const CK_ATTRIBUTE *template,
							  const CK_ULONG templateCount,
							  const BOOLEAN onlyOne )
	{
	CK_OBJECT_HANDLE hObjectArray[ 2 ];
	CK_ULONG ulObjectCount;
	CK_RV status;

	status = C_FindObjectsInit( deviceInfo->deviceHandle,
								( CK_ATTRIBUTE_PTR ) template,
								templateCount );
	if( status == CKR_OK )
		{
		status = C_FindObjects( deviceInfo->deviceHandle, hObjectArray, 
								2, &ulObjectCount );
		if( C_FindObjectsFinal != NULL )
			C_FindObjectsFinal( deviceInfo->deviceHandle );
		}
	if( status != CKR_OK )
		return( mapError( deviceInfo, status, CRYPT_ERROR_NOTFOUND ) );
	if( !ulObjectCount )
		return( CRYPT_ERROR_NOTFOUND );
	if( ulObjectCount > 1 && onlyOne )
		return( CRYPT_ERROR_DUPLICATE );
	if( hObject != NULL )
		*hObject = hObjectArray[ 0 ];

	return( CRYPT_OK );
	}

static int findObject( DEVICE_INFO *deviceInfo, CK_OBJECT_HANDLE *hObject,
					   const CK_ATTRIBUTE *template,
					   const CK_ULONG templateCount )
	{
	return( findDeviceObjects( deviceInfo, hObject, 
							   template, templateCount, TRUE ) );
	}

static int findObjectEx( DEVICE_INFO *deviceInfo, CK_OBJECT_HANDLE *hObject,
						 const CK_ATTRIBUTE *template,
						 const CK_ULONG templateCount )
	{
	return( findDeviceObjects( deviceInfo, hObject, 
							   template, templateCount, FALSE ) );
	}

/* Set up certificate information and load it into the card */

static int updateCertificate( DEVICE_INFO *deviceInfo, 
							  const CRYPT_HANDLE iCryptHandle )
	{
	static const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
	static const CK_OBJECT_CLASS privkeyClass = CKO_PRIVATE_KEY;
	static const CK_OBJECT_CLASS pubkeyClass = CKO_PUBLIC_KEY;
	static const CK_CERTIFICATE_TYPE certType = CKC_X_509;
	static const CK_BBOOL bTrue = TRUE;
	CK_ATTRIBUTE certTemplate[] = {
		{ CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) },
		{ CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) },
		{ CKA_TOKEN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
		{ CKA_ID, NULL_PTR, 0 },
		{ CKA_SUBJECT, NULL_PTR, 0 },
		{ CKA_ISSUER, NULL_PTR, 0 },
		{ CKA_SERIAL_NUMBER, NULL_PTR, 0 },
		{ CKA_VALUE, NULL_PTR, 0 },
		};
	CK_ATTRIBUTE keyTemplate[] = {
		{ CKA_CLASS, ( CK_VOID_PTR ) &privkeyClass, sizeof( CK_OBJECT_CLASS ) },
		{ CKA_ID, NULL_PTR, 0 }
		};
	CK_OBJECT_HANDLE hObject;
	CK_RV status;
	RESOURCE_DATA msgData;
	STREAM stream;
	BYTE keyID[ CRYPT_MAX_HASHSIZE ], certBuffer[ MAX_BUFFER_SIZE ];
	BYTE sBuffer[ MAX_BUFFER_SIZE ], iAndSBuffer[ MAX_BUFFER_SIZE ];
	BYTE *sBufPtr = sBuffer, *iAndSBufPtr = iAndSBuffer;
	BYTE *certBufPtr = certBuffer;
	int length, cryptStatus;

	/* Get the key ID for the cert and use it to locate the corresponding
	   public or private key object.  This is used both as a check to ensure
	   that the certificate corresponds to a key in the device and to allow
	   further attributes used for the certificate to be copied from the key.
	   In theory this would allow us to read the label from the key so that 
	   we can reuse it for the cert, but there doesn't seem to be any good
	   reason for this and it could lead to problems with multiple certs with
	   the same labels so we don't do it */
	setResourceData( &msgData, keyID, CRYPT_MAX_HASHSIZE );
	cryptStatus = krnlSendMessage( iCryptHandle, 
								   RESOURCE_IMESSAGE_GETATTRIBUTE_S,
								   &msgData, CRYPT_IATTRIBUTE_KEYID );
	if( cryptStatusError( cryptStatus ) )
		return( CRYPT_ARGERROR_NUM1 );
	keyTemplate[ 1 ].pValue = msgData.data;
	keyTemplate[ 1 ].ulValueLen = msgData.length;
	cryptStatus = findObject( deviceInfo, &hObject, keyTemplate, 2 );
	if( cryptStatusError( cryptStatus ) )
		{
		/* Couldn't find a private key with this ID, try for a public key */
		keyTemplate[ 0 ].pValue = ( CK_VOID_PTR ) &pubkeyClass;
		cryptStatus = findObject( deviceInfo, &hObject, keyTemplate, 2 );
		}
	if( cryptStatusError( cryptStatus ) )
		return( CRYPT_ERROR_NOTFOUND );
	certTemplate[ 3 ].pValue = msgData.data;
	certTemplate[ 3 ].ulValueLen = msgData.length;

	/* Get the subjectName from the cert */
	setResourceData( &msgData, NULL, 0 );
	cryptStatus = krnlSendMessage( iCryptHandle, 
								   RESOURCE_IMESSAGE_GETATTRIBUTE_S,
								   &msgData, CRYPT_IATTRIBUTE_SUBJECT );
	if( cryptStatusOK( cryptStatus ) && msgData.length > MAX_BUFFER_SIZE && \
	    ( sBufPtr = malloc( msgData.length ) ) == NULL )
		cryptStatus = CRYPT_ERROR_MEMORY;
	if( cryptStatusOK( cryptStatus ) )
		{
		msgData.data = sBufPtr;
		cryptStatus = krnlSendMessage( iCryptHandle, 
									   RESOURCE_IMESSAGE_GETATTRIBUTE_S, 
									   &msgData, CRYPT_IATTRIBUTE_SUBJECT );
		}
	if( cryptStatusError( cryptStatus ) )
		{
		if( sBufPtr != sBuffer && sBufPtr != NULL )
			free( sBufPtr );
		return( cryptStatus );
		}
	certTemplate[ 4 ].pValue = msgData.data;
	certTemplate[ 4 ].ulValueLen = msgData.length;

	/* Get the issuerAndSerialNumber from the cert */
	setResourceData( &msgData, NULL, 0 );
	cryptStatus = krnlSendMessage( iCryptHandle, 
								   RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData, 
								   CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
	if( cryptStatusOK( cryptStatus ) && msgData.length > MAX_BUFFER_SIZE && \
	    ( iAndSBufPtr = malloc( msgData.length ) ) == NULL )
		cryptStatus = CRYPT_ERROR_MEMORY;
	if( cryptStatusOK( cryptStatus ) )
		{
		msgData.data = iAndSBufPtr;
		cryptStatus = krnlSendMessage( iCryptHandle, 
									   RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData, 
									   CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
		}
	if( cryptStatusError( cryptStatus ) )
		{
		if( sBufPtr != sBuffer )
			free( sBufPtr );
		if( iAndSBufPtr != iAndSBuffer && iAndSBufPtr != NULL )
			free( iAndSBufPtr );
		return( cryptStatus );
		}
	sMemConnect( &stream, iAndSBufPtr, msgData.length );
	readSequence( &stream, NULL );
	certTemplate[ 5 ].pValue = sMemBufPtr( &stream );
	readSequence( &stream, &length );
	certTemplate[ 5 ].ulValueLen = ( int ) sizeofObject( length );
	sSkip( &stream, length );
	certTemplate[ 6 ].pValue = sMemBufPtr( &stream );
	readTag( &stream );
	certTemplate[ 6 ].ulValueLen = \
					( int ) sizeofObject( readShortLength( &stream ) );
	assert( sStatusOK( &stream ) );
	sMemDisconnect( &stream );

	/* Get the certificate data */
	setResourceData( &msgData, NULL, 0 );
	cryptStatus = krnlSendMessage( iCryptHandle, 
								   RESOURCE_IMESSAGE_GETATTRIBUTE_S,
								   &msgData, CRYPT_IATTRIBUTE_ENC_CERT );
	if( cryptStatusOK( cryptStatus ) && msgData.length > MAX_BUFFER_SIZE && \
	    ( certBufPtr = malloc( msgData.length ) ) == NULL )
		cryptStatus = CRYPT_ERROR_MEMORY;
	if( cryptStatusOK( cryptStatus ) )
		{
		msgData.data = certBufPtr;
		cryptStatus = krnlSendMessage( iCryptHandle, 
									   RESOURCE_IMESSAGE_GETATTRIBUTE_S,
									   &msgData, CRYPT_IATTRIBUTE_ENC_CERT );
		}
	if( cryptStatusError( cryptStatus ) )
		{
		if( sBufPtr != sBuffer )
			free( sBufPtr );
		if( iAndSBufPtr != iAndSBuffer )
			free( iAndSBufPtr );
		if( certBufPtr != certBuffer && certBufPtr != NULL )
			free( certBufPtr );
		return( cryptStatus );
		}
	certTemplate[ 7 ].pValue = msgData.data;
	certTemplate[ 7 ].ulValueLen = msgData.length;

	/* We've finally got everything available, try and update the device with
	   the certificate data.  In theory we should also set CKA_PRIVATE = FALSE
	   but the Dallas iButton driver doesn't allow this so we have to rely on
	   drivers doing the right thing with the default setting */
#ifndef NO_UPDATE
	status = C_CreateObject( deviceInfo->deviceHandle,
								  ( CK_ATTRIBUTE_PTR ) certTemplate, 8, 
								  &hObject );
	if( status != CKR_OK )
		cryptStatus = mapError( deviceInfo, status, CRYPT_ERROR_FAILED );
#endif /* NO_UPDATE */

	/* Clean up */

⌨️ 快捷键说明

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