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

📄 pkcs11_rw.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 5 页
字号:
			isLeafCert = FALSE;
		}

	/* Add each certificate in the chain to the device */
	do
		{
		CK_OBJECT_HANDLE hObject;
		DYNBUF iAndSDB;

		/* If the certificate is already present, don't do anything */
		cryptStatus = addIAndSToTemplate( &certTemplate[ 2 ], NULL, 0, 
										  &iAndSDB, iCryptCert );
		if( cryptStatusError( cryptStatus ) )
			{
			/* In theory we could also simply skip any certificates for 
			   which we can't decode the iAndS, but in practice it's 
			   probably better to fail and warn the user than to continue 
			   with only some certificates added */
			return( cryptStatus );
			}
		cryptStatus = findObject( pkcs11Info, &hObject, certTemplate, 4 );
		dynDestroy( &iAndSDB );
		if( cryptStatusOK( cryptStatus ) )
			{
			/* The certificate is already present, we don't need to add it 
			   again */
			continue;
			}

		/* Write the new certificate */
		cryptStatus = updateCertificate( pkcs11Info, iCryptCert, isLeafCert );
		if( cryptStatusError( cryptStatus ) )
			return( cryptStatus );
		isLeafCert = FALSE;
		seenNonDuplicate = TRUE;
		}
	while( krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE, 
							MESSAGE_VALUE_CURSORNEXT,
							CRYPT_CERTINFO_CURRENT_CERTIFICATE ) == CRYPT_OK && \
		   iterationCount++ < FAILSAFE_ITERATIONS_MED );
	if( iterationCount >= FAILSAFE_ITERATIONS_MED )
		retIntError();
	
	return( seenNonDuplicate ? CRYPT_OK : CRYPT_ERROR_DUPLICATE );
	}

/****************************************************************************
*																			*
*						 	Read an Item from a Device						*
*																			*
****************************************************************************/

/* 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) */

int rsaSetPublicComponents( PKCS11_INFO *pkcs11Info,
							const CRYPT_CONTEXT iCryptContext,
							const CK_OBJECT_HANDLE hRsaKey,
							const BOOLEAN nativeContext );
int dsaSetPublicComponents( PKCS11_INFO *pkcs11Info,
							const CRYPT_CONTEXT iCryptContext,
							const CK_OBJECT_HANDLE hDsaKey );

static int createNativeObject( PKCS11_INFO *pkcs11Info,
							   CRYPT_CONTEXT *iCryptContext,
							   const CK_OBJECT_HANDLE hObject,
							   const KEYMGMT_ITEM_TYPE itemType,
							   const CRYPT_ALGO_TYPE cryptAlgo )
	{
	MESSAGE_CREATEOBJECT_INFO createInfo;
	int actionFlags, cryptStatus;

	assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
	assert( isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );
	assert( itemType == KEYMGMT_ITEM_PUBLICKEY || \
			itemType == KEYMGMT_ITEM_PRIVATEKEY || \
			itemType == KEYMGMT_ITEM_SECRETKEY );
	assert( cryptAlgo >= CRYPT_ALGO_FIRST_CONVENTIONAL && \
			cryptAlgo <= CRYPT_ALGO_LAST_MAC ); 

	/* Get the permitted-action flags for the object.  If no usage is 
	   allowed we can't do anything with the object so we don't even try and 
	   create it */
	actionFlags = getActionFlags( pkcs11Info, hObject, itemType, cryptAlgo );
	if( actionFlags == 0 )
		return( CRYPT_ERROR_PERMISSION );

	/* We're creating a public-key context, make it a native context instead 
	   of a device one.  This solves a variety of problems including the 
	   fact that some devices (which function purely as key stores coupled 
	   to modexp accelerators) only support private-key operations, that 
	   performing public-key operations natively is much, much faster than 
	   on any device (around 150us for a 1Kbit RSA key on a 1.7GHz CPU, 
	   which doesn't even cover the device communication overhead), and 
	   finally that if we do it ourselves we can defend against a variety 
	   of RSA padding and timing attacks that have come up since the 
	   device firmware was done */
	setMessageCreateObjectInfo( &createInfo, cryptAlgo );
	cryptStatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, 
								   IMESSAGE_DEV_CREATEOBJECT, &createInfo, 
								   OBJECT_TYPE_CONTEXT );
	if( cryptStatusError( cryptStatus ) )
		return( cryptStatus );
	*iCryptContext = createInfo.cryptHandle;

	/* Send the keying info to the context and set the action flags */
	if( cryptAlgo == CRYPT_ALGO_RSA )
		cryptStatus = rsaSetPublicComponents( pkcs11Info, *iCryptContext, 
											  hObject, TRUE );
	else
		cryptStatus = dsaSetPublicComponents( pkcs11Info, *iCryptContext, 
											  hObject );
	if( cryptStatusOK( cryptStatus ) )
		cryptStatus = krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE, 
									   &actionFlags, 
									   CRYPT_IATTRIBUTE_ACTIONPERMS );
	if( cryptStatusError( cryptStatus ) )
		{
		krnlSendNotifier( *iCryptContext, IMESSAGE_DECREFCOUNT );
		return( cryptStatus );
		}

	return( CRYPT_OK );
	}

static int createDeviceObject( PKCS11_INFO *pkcs11Info,
							   CRYPT_CONTEXT *iCryptContext,
							   const CK_OBJECT_HANDLE hObject,
							   const CRYPT_CERTIFICATE iCryptCert,
							   const CRYPT_USER iOwnerHandle,
							   const CRYPT_DEVICE iDeviceHandle,
							   const CAPABILITY_INFO *capabilityInfoPtr,
							   const KEYMGMT_ITEM_TYPE itemType,
							   const CRYPT_ALGO_TYPE cryptAlgo,
							   const int keySize )
	{
	MESSAGE_DATA msgData;
	char label[ CRYPT_MAX_TEXTSIZE + 8 ];
	int createFlags = CREATEOBJECT_FLAG_DUMMY;
	int actionFlags, labelLength, cryptStatus;

	assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
	assert( isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );
	assert( ( iCryptCert == CRYPT_UNUSED ) || \
			isHandleRangeValid( iCryptCert ) );
	assert( iOwnerHandle == DEFAULTUSER_OBJECT_HANDLE || \
			isHandleRangeValid( iOwnerHandle ) );
	assert( isHandleRangeValid( iDeviceHandle ) );
	assert( isReadPtr( capabilityInfoPtr, sizeof( CAPABILITY_INFO ) ) );
	assert( itemType == KEYMGMT_ITEM_PRIVATEKEY || \
			itemType == KEYMGMT_ITEM_SECRETKEY );
	assert( cryptAlgo >= CRYPT_ALGO_FIRST_CONVENTIONAL && \
			cryptAlgo <= CRYPT_ALGO_LAST_MAC );
	assert( keySize >= MIN_KEYSIZE && keySize <= CRYPT_MAX_PKCSIZE );

	/* Check whether this is a persistent object */
	if( readFlag( pkcs11Info, hObject, CKA_TOKEN ) )
		createFlags |= CREATEOBJECT_FLAG_PERSISTENT;

	/* Get the permitted-action flags for the object */
	actionFlags = getActionFlags( pkcs11Info, hObject, itemType, cryptAlgo );
	if( actionFlags == 0 )
		{
		/* If no usage is allowed, we can't do anything with the object so
		   we don't even try to create it */
		if( iCryptCert != CRYPT_UNUSED )
			krnlSendNotifier( iCryptCert, IMESSAGE_DECREFCOUNT );
		return( CRYPT_ERROR_PERMISSION );
		}

	/* Create a dummy context for the key, remember the device that it's 
	   contained in, and record the handle for the device-internal key */
	cryptStatus = getObjectLabel( pkcs11Info, hObject, label, 
								  CRYPT_MAX_TEXTSIZE, &labelLength );
	if( cryptStatusOK( cryptStatus ) )
		cryptStatus = createContextFromCapability( iCryptContext, 
							iOwnerHandle, capabilityInfoPtr, createFlags );
	if( cryptStatusError( cryptStatus ) )
		{
		if( iCryptCert != CRYPT_UNUSED )
			krnlSendNotifier( iCryptCert, IMESSAGE_DECREFCOUNT );
		return( cryptStatus );
		}
	cryptStatus = krnlSendMessage( *iCryptContext, IMESSAGE_SETDEPENDENT,
								   ( void * ) &iDeviceHandle, 
								   SETDEP_OPTION_INCREF );
	if( cryptStatusOK( cryptStatus ) )
		cryptStatus = krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE, 
									   ( void * ) &hObject, 
									   CRYPT_IATTRIBUTE_DEVICEOBJECT );
	if( cryptStatusOK( cryptStatus ) )
		cryptStatus = krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE, 
									   &actionFlags, 
									   CRYPT_IATTRIBUTE_ACTIONPERMS );
	if( cryptStatusError( cryptStatus ) )
		{
		krnlSendNotifier( *iCryptContext, IMESSAGE_DECREFCOUNT );
		if( iCryptCert != CRYPT_UNUSED )
			krnlSendNotifier( iCryptCert, IMESSAGE_DECREFCOUNT );
		return( cryptStatus );
		}

	/* Set the object's label and mark it as initialised (i.e. with a key 
	   loaded).  Setting the label requires special care because the label 
	   that we're setting matches that of an existing object, so trying to
	   set it as a standard CRYPT_CTXINFO_LABEL will return a 
	   CRYPT_ERROR_DUPLICATE error when the context code checks for the
	   existence of an existing label.  To handle this, we use the
	   attribute CRYPT_IATTRIBUTE_EXISTINGLABEL to indicate that we're 
	   setting a label that matches an existing object in the device */
	if( labelLength <= 0 )
		{
		/* If there's no label present, use a dummy value */
		strlcpy_s( label, CRYPT_MAX_TEXTSIZE, "Label-less PKCS #11 key" );
		labelLength = strlen( label );
		}
	setMessageData( &msgData, label, min( labelLength, CRYPT_MAX_TEXTSIZE ) );
	cryptStatus = krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE_S,
								   &msgData, CRYPT_IATTRIBUTE_EXISTINGLABEL );
	if( cryptStatusOK( cryptStatus ) )
		{
		/* Send the keying info to the context.  For non-PKC contexts we 
		   only need to set the key length to let the user query the key 
		   size, for PKC contexts we also have to set the key components so
		   they can be written into certificates.  Unfortunately we can't do 
		   this for DLP private keys since we can't read y from a DLP 
		   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 */
		if( cryptAlgo == CRYPT_ALGO_RSA )
			cryptStatus = rsaSetPublicComponents( pkcs11Info, *iCryptContext, 
												  hObject, FALSE );
		else
			cryptStatus = krnlSendMessage( *iCryptContext, 
										   IMESSAGE_SETATTRIBUTE, 
										   ( void * ) &keySize, 
										   CRYPT_IATTRIBUTE_KEYSIZE );
		}
	if( cryptStatusOK( cryptStatus ) )
		cryptStatus = krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE,
									   MESSAGE_VALUE_UNUSED, 
									   CRYPT_IATTRIBUTE_INITIALISED );
	if( cryptStatusOK( cryptStatus ) && ( iCryptCert != CRYPT_UNUSED ) )
		{
		/* If it's a public key and there's a certificate present, attach it 
		   to the context.  The certificate is an internal object used only 
		   by the context so we tell the kernel to mark it as owned by the 
		   context only */
		cryptStatus = krnlSendMessage( *iCryptContext, IMESSAGE_SETDEPENDENT, 
									   ( void * ) &iCryptCert, 
									   SETDEP_OPTION_NOINCREF );
		}
	if( cryptStatusError( cryptStatus ) )
		{
		krnlSendNotifier( *iCryptContext, IMESSAGE_DECREFCOUNT );
		if( iCryptCert != CRYPT_UNUSED )
			krnlSendNotifier( iCryptCert, IMESSAGE_DECREFCOUNT );
		}
	return( cryptStatus );
	}

/* Get an item from a device and instantiate either a native or a device 
   object from it */

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 )
	{
	static const CK_OBJECT_CLASS pubkeyClass = CKO_PUBLIC_KEY;
	static const CK_OBJECT_CLASS privkeyClass = CKO_PRIVATE_KEY;
	static const CK_OBJECT_CLASS secKeyClass = CKO_SECRET_KEY;
	static const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
	static const CK_CERTIFICATE_TYPE certType = CKC_X_509;
	const CAPABILITY_INFO *capabilityInfoPtr;
	CK_ATTRIBUTE iAndSTemplate[] = {
		{ CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) },
		{ CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) },
		{ CKA_ISSUER, NULL_PTR, 0 },
		{ CKA_SERIAL_NUMBER, NULL_PTR, 0 }
		}, iAndSTemplateAlt[ 4 ];
	CK_ATTRIBUTE keyTemplate[] = {
		{ CKA_CLASS, NULL_PTR, sizeof( CK_OBJECT_CLASS ) },
		{ CKA_LABEL, NULL_PTR, 0 }
		};
	CK_ATTRIBUTE keySizeTemplate = { 0, NULL, 0 };
	CK_OBJECT_HANDLE hObject = CK_OBJECT_NONE, hCertificate = CK_OBJECT_NONE;
	CRYPT_CERTIFICATE iCryptCert;
	CRYPT_ALGO_TYPE cryptAlgo;
	PKCS11_INFO *pkcs11Info = deviceInfo->devicePKCS11;
	BOOLEAN certViaPrivateKey = FALSE, privateKeyViaCert = FALSE;
	BOOLEAN certPresent = FALSE;
	int keySize, cryptStatus;

	assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );
	assert( isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );
	assert( itemType == KEYMGMT_ITEM_PUBLICKEY || \
			itemType == KEYMGMT_ITEM_PRIVATEKEY || \
			itemType == KEYMGMT_ITEM_SECRETKEY );
	assert( keyIDtype == CRYPT_KEYID_NAME || \
			keyIDtype == CRYPT_KEYID_URI || \
			keyIDtype == CRYPT_IKEYID_KEYID || \
			keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER );
	assert( isReadPtr( keyID, keyIDlength ) );
	assert( ( auxInfo == NULL && *auxInfoLength == 0 ) || \
			isReadPtr( auxInfo, *auxInfoLength ) );

	/* If we're looking for a secret key it's fairly straightforward, we
	   can only have a label as an ID */
	if( itemType == KEYMGMT_ITEM_SECRETKEY )
		{
		CK_ULONG keySize;
		CK_ATTRIBUTE keySizeTemplate = \
			{ CKA_VALUE_LEN, &keySize, sizeof( CK_ULONG ) };
		int status;

		assert( keyIDtype == CRYPT_KEYID_NAME || \
				keyIDtype == CRYPT_IKEYID_KEYID );

		/* Try and find the object with the given label/ID */
		keyTemplate[ 0 ].pValue = ( CK_VOID_PTR ) &secKeyClass;
		if( keyIDtype == CRYPT_IKEYID_KEYID )
			keyTemplate[ 1 ].type = CKA_ID;
		keyTemplate[ 1 ].pValue = ( CK_VOID_PTR ) keyID;
		keyTemplate[ 1 ].ulValueLen = keyIDlength;
		cryptStatus = findObject( pkcs11Info, &hObject, keyTemplate, 2 );
		if( cryptStatus == CRYPT_ERROR_NOTFOUND )
			{
			/* Some devices use the iD in place of the label, if a search by 
			   label fails we try again with the label as the iD */
			keyTemplate[ 1 ].type = CKA_ID;
			cryptStatus = findObject( pkcs11Info, &hObject, keyTemplate, 2 );
			keyTemplate[ 1 ].type = CKA_LABEL;
			}
		if( cryptStatusError( cryptStatus ) )
			return( cryptStatus );

⌨️ 快捷键说明

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