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

📄 dev_capi.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 5 页
字号:
		if( cryptStatusError( cryptStatus ) )
			return( cryptStatus );
		certPresent = TRUE;
		}
	else
		{
		cryptStatus = findCertFromObject( deviceInfo, hObject, &iCryptCert, 
										  ( itemType == KEYMGMT_ITEM_PUBLICKEY ) ? \
										  FINDCERT_NORMAL : FINDCERT_DATAONLY );
		if( cryptStatusError( cryptStatus ) )
			{
			/* If we get a CRYPT_ERROR_NOTFOUND this is OK since it means 
			   there's no cert present, however anything else is an error. In 
			   addition if we've got a private key whose only function is to 
			   point to an associated cert then not finding anything is also 
			   an error */
			if( cryptStatus != CRYPT_ERROR_NOTFOUND || certViaPrivateKey )
				return( cryptStatus );
			}
		else
			{
			/* We got the cert, if we're being asked for a public key then
			   we've created a native object to contain it so we return that */
			certPresent = TRUE;
			if( itemType == KEYMGMT_ITEM_PUBLICKEY )
				{
				*iCryptContext = iCryptCert;
				return( CRYPT_OK );
				}
			}
		}

	/* Get the permitted capabilities for the object */
	if( readFlag( deviceInfo, hObject, CKA_ENCRYPT ) || \
		readFlag( deviceInfo, hObject, CKA_UNWRAP ) )
		{
		actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_ALL );
		cryptAllowed = TRUE;
		}
	if( readFlag( deviceInfo, hObject, CKA_DECRYPT ) || \
		readFlag( deviceInfo, hObject, CKA_UNWRAP ) )
		{
		actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, ACTION_PERM_ALL );
		cryptAllowed = TRUE;
		}
	if( readFlag( deviceInfo, hObject, CKA_SIGN ) )
		{
		actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_SIGN, ACTION_PERM_ALL );
		sigAllowed = TRUE;
		}
	if( readFlag( deviceInfo, hObject, CKA_VERIFY ) )
		{
		actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, ACTION_PERM_ALL );
		sigAllowed = TRUE;
		}
	if( cryptAlgo == CRYPT_ALGO_RSA )
		{
		/* If there are any restrictions on the key usage, we have to make it
		   internal-only because of RSA's signature/encryption duality */
		if( !( cryptAllowed && sigAllowed ) )
			actionFlags = MK_ACTION_PERM_NONE_EXTERNAL( actionFlags );
		}
	else
		/* Because of the special-case data formatting requirements for DLP 
		   algorithms, we make the usage internal-only */
		actionFlags = MK_ACTION_PERM_NONE_EXTERNAL( actionFlags );
	if( !actionFlags )
		{
		/* If no usage is allowed, we can't do anything with the object so
		   we don't even try to create it */
		if( certPresent )
			krnlSendNotifier( iCryptCert, IMESSAGE_DECREFCOUNT );
		return( CRYPT_ERROR_PERMISSION );
		}

	/* Create a dummy context for the key, remember the device it's 
	   contained in, the handle for the device-internal key, and the object's
	   label, mark it as initialised (i.e. with a key loaded), and if there's a 
	   cert present attach it to the context.  The cert is an internal object 
	   used only by the context so we tell the kernel to mark it as owned by 
	   the context only */
	cryptStatus = getObjectLabel( deviceInfo, hObject, label, &labelLength );
	if( cryptStatusOK( cryptStatus ) )
		cryptStatus = createContextFromCapability( iCryptContext, 
								deviceInfo->ownerHandle, capabilityInfoPtr, 
								CREATEOBJECT_FLAG_DUMMY );
	if( cryptStatusError( cryptStatus ) )
		{
		if( certPresent )
			krnlSendNotifier( iCryptCert, IMESSAGE_DECREFCOUNT );
		return( cryptStatus );
		}
	krnlSendMessage( *iCryptContext, IMESSAGE_SETDEPENDENT,
					 &deviceInfo->objectHandle, SETDEP_OPTION_INCREF );
	krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE, &hObject, 
					 CRYPT_IATTRIBUTE_DEVICEOBJECT );
	krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE, &actionFlags, 
					 CRYPT_IATTRIBUTE_ACTIONPERMS );
	if( labelLength <= 0 )
		{
		/* If there's no label present, use a dummy value */
		strcpy( label, "Label-less PKCS #11 key" );
		labelLength = strlen( label );
		}
	setMessageData( &msgData, label, labelLength );
	krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE_S,
					 &msgData, CRYPT_CTXINFO_LABEL );
	if( keyType == CKK_RSA )
		/* Send the keying info to the context.  This is only possible for
		   RSA keys since it's not possible to read y from a DSA private
		   key object (see the comments in the DSA code for more on this), 
		   however the only time this is necessary is when a cert 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 */
		cryptStatus = rsaSetPublicComponents( deviceInfo, *iCryptContext, 
											  hObject );
	else
		cryptStatus = krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE, 
									   &keySize, CRYPT_IATTRIBUTE_KEYSIZE );
	if( cryptStatusOK( cryptStatus ) )
		cryptStatus = krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE,
									   MESSAGE_VALUE_UNUSED, 
									   CRYPT_IATTRIBUTE_INITIALISED );
	if( certPresent && cryptStatusOK( cryptStatus ) )
		cryptStatus = krnlSendMessage( *iCryptContext, IMESSAGE_SETDEPENDENT, 
									   &iCryptCert, SETDEP_OPTION_NOINCREF );
	if( cryptStatusError( cryptStatus ) && certPresent )
		krnlSendNotifier( iCryptCert, IMESSAGE_DECREFCOUNT );
	return( cryptStatus );
#endif

	return( CRYPT_ERROR );
	}

/* Update a device with a certificate */

static int setItemFunction( DEVICE_INFO *deviceInfo, 
							const CRYPT_HANDLE iCryptHandle )
	{
	CRYPT_CERTIFICATE iCryptCert;
	int status;

	/* Lock the cert for our exclusive use (in case it's a cert chain, we 
	   also select the first cert in the chain), update the device with the 
	   cert, and unlock it to allow others access */
	krnlSendMessage( iCryptHandle, IMESSAGE_GETDEPENDENT, &iCryptCert, 
					 OBJECT_TYPE_CERTIFICATE );
	krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE, 
					 MESSAGE_VALUE_CURSORFIRST, 
					 CRYPT_CERTINFO_CURRENT_CERTIFICATE );
	status = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE, 
							  MESSAGE_VALUE_TRUE, CRYPT_IATTRIBUTE_LOCKED );
	if( cryptStatusError( status ) )
		return( status );
#if 0
	status = updateCertificate( deviceInfo, iCryptCert );
#endif
	krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE, MESSAGE_VALUE_FALSE, 
					 CRYPT_IATTRIBUTE_LOCKED );

	return( status );
	}

/* Delete an object in a device */

static int deleteItemFunction( DEVICE_INFO *deviceInfo,
							   const KEYMGMT_ITEM_TYPE itemType,
							   const CRYPT_KEYID_TYPE keyIDtype,
							   const void *keyID, const int keyIDlength )
	{
#if 0
	static const CK_OBJECT_CLASS pubkeyClass = CKO_PUBLIC_KEY;
	static const CK_OBJECT_CLASS privkeyClass = CKO_PRIVATE_KEY;
	static const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
	static const CK_CERTIFICATE_TYPE certType = CKC_X_509;
	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_LABEL, ( CK_VOID_PTR ) keyID, keyIDlength }
		};
	CK_ATTRIBUTE keyTemplate[] = {
		{ CKA_CLASS, ( CK_VOID_PTR ) &pubkeyClass, sizeof( CK_OBJECT_CLASS ) },
		{ CKA_LABEL, ( CK_VOID_PTR ) keyID, keyIDlength }
		};
	CK_OBJECT_HANDLE hPrivkey = CRYPT_ERROR, hCertificate = CRYPT_ERROR;
	CK_OBJECT_HANDLE hPubkey = CRYPT_ERROR;
	CK_RV status;
	int cryptStatus;

	assert( itemType == KEYMGMT_ITEM_PUBLICKEY || \
			itemType == KEYMGMT_ITEM_PRIVATEKEY );
	assert( keyIDtype == CRYPT_KEYID_NAME );

	/* Find the object to delete based on the label.  Since we can have 
	   multiple related objects (e.g. a key and a cert) with the same label, 
	   a straight search for all objects with a given label could return
	   CRYPT_ERROR_DUPLICATE so we search for the objects by type as well as 
	   label.  In addition even a search for specific objects can return
	   CRYPT_ERROR_DUPLICATE so we use the Ex version of findObject() to make
	   sure we don't get an error if multiple objects exist.  Although
	   cryptlib won't allow more than one object with a given label to be
	   created, other applications might create duplicate labels.  The correct
	   behaviour in these circumstances is uncertain, what we do for now is
	   delete the first object we find that matches the label.
	   
	   First we try for a cert and use that to find associated keys */
	cryptStatus = findObjectEx( deviceInfo, &hCertificate, certTemplate, 3 );
	if( cryptStatusOK( cryptStatus ) )
		{
		/* We got a cert, if there are associated keys delete them as well */
		cryptStatus = findObjectFromObject( deviceInfo, hCertificate, 
											CKO_PUBLIC_KEY, &hPubkey );
		if( cryptStatusError( cryptStatus ) )
			hPubkey = CRYPT_ERROR;
		cryptStatus = findObjectFromObject( deviceInfo, hCertificate, 
											CKO_PRIVATE_KEY, &hPrivkey );
		if( cryptStatusError( cryptStatus ) )
			hPrivkey = CRYPT_ERROR;
		}
	else
		{
		/* We didn't find a cert with the given label, try for public and
		   private keys */
		cryptStatus = findObjectEx( deviceInfo, &hPubkey, keyTemplate, 2 );
		if( cryptStatusError( cryptStatus ) )
			hPubkey = CRYPT_ERROR;
		keyTemplate[ 0 ].pValue = ( CK_VOID_PTR ) &privkeyClass;
		cryptStatus = findObjectEx( deviceInfo, &hPrivkey, keyTemplate, 2 );
		if( cryptStatusError( cryptStatus ) )
			hPrivkey = CRYPT_ERROR;

		/* There may be an unlabelled cert present, try and find it by 
		   looking for a cert matching the key ID */
		if( hPubkey != CRYPT_ERROR || hPrivkey != CRYPT_ERROR )
			{
			cryptStatus = findObjectFromObject( deviceInfo, 
							( hPrivkey != CRYPT_ERROR ) ? hPrivkey : hPubkey, 
							CKO_CERTIFICATE, &hCertificate );
			if( cryptStatusError( cryptStatus ) )
				hCertificate = CRYPT_ERROR;
			}
		}

	/* If we found a public key with a given label but no private key, try 
	   and find a matching private key by ID, and vice versa */
	if( hPubkey != CRYPT_ERROR && hPrivkey == CRYPT_ERROR )
		{
		cryptStatus = findObjectFromObject( deviceInfo, hPubkey, 
											CKO_PRIVATE_KEY, &hPrivkey );
		if( cryptStatusError( cryptStatus ) )
			hPrivkey = CRYPT_ERROR;
		}
	if( hPrivkey != CRYPT_ERROR && hPubkey == CRYPT_ERROR )
		{
		cryptStatus = findObjectFromObject( deviceInfo, hPrivkey, 
											CKO_PUBLIC_KEY, &hPubkey );
		if( cryptStatusError( cryptStatus ) )
			hPubkey = CRYPT_ERROR;
		}
	if( hPrivkey == CRYPT_ERROR && hPubkey == CRYPT_ERROR )
		return( CRYPT_ERROR_NOTFOUND );

	/* Reset the status values, which may contain error values due to not 
	   finding various objects to delete above */
	cryptStatus = CRYPT_OK;
	status = CKR_OK;

	/* Delete the objects */
	if( hCertificate != CRYPT_ERROR )
		status = C_DestroyObject( cryptoapiInfo->hProv, hCertificate );
	if( hPubkey != CRYPT_ERROR )
		{
		int status2;

		status2 = C_DestroyObject( cryptoapiInfo->hProv, hPubkey );
		if( status2 != CKR_OK && status == CKR_OK )
			status = status2;
		}
	if( hPrivkey != CRYPT_ERROR )
		{
		int status2;

		status2 = C_DestroyObject( cryptoapiInfo->hProv, hPrivkey );
		if( status2 != CKR_OK && status == CKR_OK )
			status = status2;
		}
	if( status != CKR_OK )
		cryptStatus = mapError( deviceInfo, status, CRYPT_ERROR_FAILED );
	return( cryptStatus );
#endif

	return( CRYPT_ERROR );
	}

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

#if 0

/* Sign data, check a signature.  We use Sign and Verify rather than the
   xxxRecover variants because there's no need to use Recover, and because
   many implementations don't do Recover */

static int genericSign( DEVICE_INFO *deviceInfo, CONTEXT_INFO *contextInfoPtr,
						const CK_MECHANISM *pMechanism, 
						const void *inBuffer, const int inLength, 
						void *outBuffer, const int outLength )
	{
	CK_ULONG resultLen = outLength;
	CK_RV status;

	status = C_SignInit( cryptoapiInfo->hProv,
						 ( CK_MECHANISM_PTR ) pMechanism, 
						 contextInfoPtr->deviceObject );
	if( status == CKR_OK )
		status = C_Sign( cryptoapiInfo->hProv, ( CK_BYTE_PTR ) inBuffer, 
						 inLength, outBuffer, &resultLen );
	if( status != CKR_OK )
		return( mapError( deviceInfo, status, CRYPT_ERROR_FAILED ) );

	return( CRYPT_OK );
	}

static int genericVerify( DEVICE_INFO *deviceInfo, CONTEXT_INFO *contextInfoPtr,
						  const CK_MECHANISM *pMechanism, 
						  const void *inBuffer, const int inLength, 
						  void *outBuffer, const int outLength )
	{
	CK_RV status;

	status = C_VerifyInit( cryptoapiInfo->hProv,
						   ( CK_MECHANISM_PTR ) pMechanism,
						   contextInfoPtr->deviceObject );
	if( status == CKR_OK )
		status = C_Verify( cryptoapiInfo->hProv, ( CK_BYTE_PTR ) inBuffer, 
						   inLength, outBuffer, outLength );
	if( status != CKR_OK )
		return( mapError( deviceInfo, status, CRYPT_ERROR_FAILED ) );

	return( CRYPT_OK );
	}
#endif /* 0 */

⌨️ 快捷键说明

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