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

📄 dev_pk11.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 5 页
字号:
								  &idTemplate, 1 );
	if( status == CKR_OK )
		{
		if( idTemplate.ulValueLen > MAX_BUFFER_SIZE && \
			( bufPtr = clAlloc( "findCertFromObject", \
						( size_t ) ( idTemplate.ulValueLen ) ) ) == NULL )
			return( CRYPT_ERROR_MEMORY );
		idTemplate.pValue = bufPtr;
		status = C_GetAttributeValue( pkcs11Info->hSession, hObject,
									  &idTemplate, 1 );
		}
	if( status != CKR_OK )
		{
		if( bufPtr != buffer )
			clFree( "findCertFromObject", bufPtr );
		return( mapError( pkcs11Info, status, CRYPT_ERROR_NOTFOUND ) );
		}

	/* Look for a certificate with the same ID as the key */
	cryptStatus = findCertFromID( pkcs11Info, bufPtr, 
								  idTemplate.ulValueLen, iCryptCert,
								  findAction );
	if( bufPtr != buffer )
		clFree( "findCertFromObject", bufPtr );
	return( cryptStatus );
	}

static int findCertFromTemplate( PKCS11_INFO *pkcs11Info,
								 const CK_ATTRIBUTE *findTemplate,
								 const int templateCount,
								 CRYPT_CERTIFICATE *iCryptCert,
								 const FINDCERT_ACTION findAction )
	{
	CK_OBJECT_HANDLE hCertificate;
	int cryptStatus;

	*iCryptCert = CRYPT_ERROR;

	/* Try and find the cert from the given template */
	cryptStatus = findObject( pkcs11Info, &hCertificate, findTemplate, 
							  templateCount );
	if( cryptStatusError( cryptStatus ) )
		return( cryptStatus );
	if( findAction == FINDCERT_P11OBJECT )
		{
		*iCryptCert = hCertificate;
		return( CRYPT_OK );
		}

	return( instantiateCert( pkcs11Info, hCertificate, iCryptCert, 
							 ( findAction == FINDCERT_NORMAL ) ? \
							 TRUE : FALSE ) );
	}

/* Find an object from a source object by matching ID's.  This is used to
   find a key matching a cert, a public key matching a private key, or
   other objects with similar relationships */

static int findObjectFromObject( PKCS11_INFO *pkcs11Info,
								 const CK_OBJECT_HANDLE hSourceObject, 
								 const CK_OBJECT_CLASS objectClass,
								 CK_OBJECT_HANDLE *hObject )
	{
	CK_ATTRIBUTE keyTemplate[] = {
		{ CKA_CLASS, ( CK_VOID_PTR ) &objectClass, sizeof( CK_OBJECT_CLASS ) },
		{ CKA_ID, NULL_PTR, 0 }
		};
	CK_ATTRIBUTE idTemplate = \
		{ CKA_ID, NULL_PTR, 0 };
	CK_RV status;
	BYTE buffer[ MAX_BUFFER_SIZE ], *bufPtr = buffer;
	int cryptStatus;

	*hObject = CRYPT_ERROR;

	/* We're looking for a key whose ID matches that of the source object, 
	   read its cert ID.  We can't use a dynBuf for this because it's a 
	   PKCS #11 attribute rather than a cryptlib attribute */
	status = C_GetAttributeValue( pkcs11Info->hSession, hSourceObject, 
								  &idTemplate, 1 );
	if( status == CKR_OK )
		{
		if( idTemplate.ulValueLen > MAX_BUFFER_SIZE && \
			( bufPtr = clAlloc( "findObjectFromObject", \
						( size_t ) ( idTemplate.ulValueLen ) ) ) == NULL )
			return( CRYPT_ERROR_MEMORY );
		idTemplate.pValue = bufPtr;
		status = C_GetAttributeValue( pkcs11Info->hSession, hSourceObject,
									  &idTemplate, 1 );
		}
	if( status != CKR_OK )
		{
		if( bufPtr != buffer )
			clFree( "findObjectFromObject", bufPtr );
		return( mapError( pkcs11Info, status, CRYPT_ERROR_NOTFOUND ) );
		}

	/* Find the key object with the given ID */
	keyTemplate[ 1 ].pValue = bufPtr;
	keyTemplate[ 1 ].ulValueLen = idTemplate.ulValueLen;
	cryptStatus = findObject( pkcs11Info, hObject, keyTemplate, 2 );
	if( bufPtr != buffer )
		clFree( "findObjectFromObject", bufPtr );
	return( cryptStatus );
	}

/* Read a flag for an object.  An absent value is treated as FALSE */

static BOOLEAN readFlag( PKCS11_INFO *pkcs11Info, 
						 const CK_OBJECT_HANDLE hObject,
						 const CK_ATTRIBUTE_TYPE flagType )
	{
	CK_BBOOL bFlag = FALSE;
	CK_ATTRIBUTE flagTemplate = { flagType, &bFlag, sizeof( CK_BBOOL ) };

	/* Some buggy implementations return CKR_OK but forget to set the
	   data value in the template (!!!) so we have to initialise bFlag
	   to a default of FALSE to handle this */
	return( ( C_GetAttributeValue( pkcs11Info->hSession, hObject,
								   &flagTemplate, 1 ) == CKR_OK && bFlag ) ? \
			TRUE : FALSE );
	}
		
/* 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).  If the
   value being read is a public key and there's a certificate attached, the
   instantiated object is a native cryptlib object rather than a device
   object with a native certificate object attached because there doesn't 
   appear to be any good reason to create the public-key object in the device, 
   for most devices the cryptlib native object will be faster anyway, and 
   some apps see the public key as redundant and delete it, so only the cert
   will be present */

static int rsaSetPublicComponents( PKCS11_INFO *pkcs11Info,
								   const CRYPT_CONTEXT iCryptContext,
								   const CK_OBJECT_HANDLE hRsaKey );

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 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 keyTypeTemplate = \
		{ CKA_KEY_TYPE, NULL_PTR, sizeof( CK_KEY_TYPE ) };
	CK_ATTRIBUTE keySizeTemplate = \
		{ 0, NULL_PTR, 0 };
	CK_ATTRIBUTE keyLabelTemplate = \
		{ CKA_LABEL, NULL_PTR, 0 };
	CK_OBJECT_HANDLE hObject, hCertificate;
	CK_KEY_TYPE keyType;
	CRYPT_CERTIFICATE iCryptCert;
	CRYPT_ALGO_TYPE cryptAlgo;
	PKCS11_INFO *pkcs11Info = deviceInfo->devicePKCS11;
	RESOURCE_DATA msgData;
	BOOLEAN certViaPrivateKey = FALSE, privateKeyViaCert = FALSE;
	BOOLEAN certPresent = FALSE;
	BOOLEAN cryptAllowed = FALSE, sigAllowed = FALSE;
	char label[ CRYPT_MAX_TEXTSIZE ];
	int keySize, actionFlags = 0, labelLength, cryptStatus;

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

	/* If we're looking for something based on an issuerAndSerialNumber, set 
	   up the search template.  Because Netscape incorrectly uses the raw
	   serial number and other apps copy this, we also set up an alternative 
	   template with the serial number in this alternative form that we fall 
	   back to if a search using the correct form fails */
	if( keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER )
		{
		STREAM stream;
		int length;

		sMemConnect( &stream, keyID, keyIDlength );
		readSequence( &stream, NULL );
		iAndSTemplate[ 2 ].pValue = sMemBufPtr( &stream );
		readSequence( &stream, &length );		/* Issuer DN */
		iAndSTemplate[ 2 ].ulValueLen = ( int ) sizeofObject( length );
		sSkip( &stream, length );
		iAndSTemplate[ 3 ].pValue = sMemBufPtr( &stream );
		readGenericHole( &stream, &length, BER_INTEGER );/* Serial number */
		iAndSTemplate[ 3 ].ulValueLen = ( int ) sizeofObject( length );
		memcpy( iAndSTemplateAlt, iAndSTemplate, sizeof( iAndSTemplate ) );
		iAndSTemplateAlt[ 3 ].pValue = sMemBufPtr( &stream );
		iAndSTemplateAlt[ 3 ].ulValueLen = length;
		assert( sStatusOK( &stream ) );
		sMemDisconnect( &stream );
		}

	/* If we're looking for a public key, try for a cert first.  Some non-
	   crypto-capable devices don't have an explicit CKO_PUBLIC_KEY but only 
	   a CKO_CERTIFICATE and some apps delete the public key since it's
	   redundant, so we try to create a cert object before we try anything 
	   else.  If the keyID type is an ID or label, this won't necessarily 
	   locate the cert since it could be unlabelled or have a different 
	   label/ID, so if this fails we try again by going via the private key 
	   with the given label/ID */
	if( itemType == KEYMGMT_ITEM_PUBLICKEY )
		{
		const FINDCERT_ACTION findAction = \
			( flags & ( KEYMGMT_FLAG_CHECK_ONLY | KEYMGMT_FLAG_LABEL_ONLY ) ) ? \
			FINDCERT_P11OBJECT : FINDCERT_NORMAL;

		if( keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER )
			{
			cryptStatus = findCertFromTemplate( pkcs11Info, iAndSTemplate, 4, 
												&iCryptCert, findAction );
			if( cryptStatus == CRYPT_ERROR_NOTFOUND )
				cryptStatus = findCertFromTemplate( pkcs11Info, iAndSTemplateAlt, 4, 
													&iCryptCert, findAction );
			}
		else
			if( keyIDtype == CRYPT_IKEYID_KEYID )
				cryptStatus = findCertFromID( pkcs11Info, keyID, keyIDlength, 
											  &iCryptCert, findAction );
			else
				{
				cryptStatus = findCertFromLabel( pkcs11Info, keyID, keyIDlength, 
												 &iCryptCert, findAction );
				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 */
					cryptStatus = findCertFromID( pkcs11Info, keyID, keyIDlength, 
												  &iCryptCert, findAction );
				}
		if( cryptStatusOK( cryptStatus ) )
			{
			/* If we're just checking whether an object exists, return now.  
			   If all we want is the key label, copy it back to the caller 
			   and exit */
			if( flags & KEYMGMT_FLAG_CHECK_ONLY )
				return( CRYPT_OK );
			if( flags & KEYMGMT_FLAG_LABEL_ONLY )
				return( getObjectLabel( pkcs11Info, 
										( CK_OBJECT_HANDLE ) iCryptCert, 
										auxInfo, auxInfoLength ) );

			*iCryptContext = iCryptCert;
			return( CRYPT_OK );
			}
		else
			/* If we're looking for a specific match on a certificate (rather 
			   than just a general public key) and we don't find anything, 
			   exit now */
			if( keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER )
				return( cryptStatus );
		}

	/* Either there were no certs found or we're looking for a private key 
	   (or, somewhat unusually, a raw public key).  At this point we can 
	   approach the problem from one of two sides, if we've got an 
	   issuerAndSerialNumber we have to find the matching cert and get the 
	   key from that, otherwise we find the key and get the cert from that */
	if( keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER )
		{
		/* Try and find the cert from the given template */
		cryptStatus = findObject( pkcs11Info, &hCertificate, 
								  iAndSTemplate, 4 );
		if( cryptStatus == CRYPT_ERROR_NOTFOUND )
			cryptStatus = findObject( pkcs11Info, &hCertificate, 
									  iAndSTemplateAlt, 4 );
		if( cryptStatusOK( cryptStatus ) )
			{
			/* We found the cert, use it to find the corresponding private 
			   key */
			cryptStatus = findObjectFromObject( pkcs11Info, hCertificate, 
												CKO_PRIVATE_KEY, &hObject );
			if( cryptStatusError( cryptStatus ) )
				return( cryptStatus );
	
			/* Remember that we've already got a cert to attach to the private
			   key */
			privateKeyViaCert = TRUE;
			}
		else
			/* If we didn't find anything, it may be because whoever set up
			   the token didn't set the iAndS rather than because there's no
			   key there, so we only bail out if we got some unexpected type 
			   of error */
			if( cryptStatus != CRYPT_ERROR_NOTFOUND )
				return( cryptStatus );
		}
	else
		{
		const int keyTemplateCount = ( keyID == NULL ) ? 1 : 2;

		/* Try and find the object with the given label/ID, or the first 
		   object of the given class if no ID is given */
		keyTemplate[ 0 ].pValue = ( CK_VOID_PTR ) \
								  ( ( itemType == KEYMGMT_ITEM_PUBLICKEY ) ? \
								  &pubkeyClass : &privkeyClass );
		if( keyIDtype != CRYPT_KEYID_NONE )
			{
			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, 
								  keyTemplateCount );
		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, 
									  keyTemplateCount );
			keyTemplate[ 1 ].type = CKA_LABEL;
			}
		if( cryptStatus == CRYPT_ERROR_NOTFOUND && \
			itemType == KEYMGMT_ITEM_PUBLICKEY )
			{
			/* Some devices may only contain private key objects with 
			   associated certificates that can't be picked out of the other 
			   cruft that's present without going via the private key, so if 
			   we're looking for a public key and d

⌨️ 快捷键说明

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