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

📄 pkcs11_rw.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 5 页
字号:
		/* If it's just an existence check, return now */
		if( flags & KEYMGMT_FLAG_CHECK_ONLY )
			return( CRYPT_OK );

		/* We found something, map the key type to a cryptlib algorithm ID 
		   and find its capabilities */
		cryptStatus = getMechanismInfo( pkcs11Info, hObject, 
										deviceInfo->capabilityInfoList,
										FALSE, &capabilityInfoPtr,
										&cryptAlgo );
		if( cryptStatusError( cryptStatus ) )
			return( cryptStatus );
		status = C_GetAttributeValue( pkcs11Info->hSession, hObject, 
									  &keySizeTemplate, 1 );
		if( status != CKR_OK )
			return( pkcs11MapError( pkcs11Info, status, 
									CRYPT_ERROR_NOTINITED ) );

		/* Create the object as a device object */
		return( createDeviceObject( pkcs11Info, iCryptContext, hObject, 
								    CRYPT_UNUSED, deviceInfo->ownerHandle, 
								    deviceInfo->objectHandle, capabilityInfoPtr,
								    KEYMGMT_ITEM_SECRETKEY, cryptAlgo, 
									keySize ) );
		}

	/* 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 offset = DUMMY_INIT, length;

		cryptStatus = addIAndSToTemplate( &iAndSTemplate[ 2 ], keyID, 
										  keyIDlength, NULL, CRYPT_UNUSED );
		if( cryptStatusError( cryptStatus ) )
			return( cryptStatus );

		/* Set up the alternate template to the same as the main template, 
		   but with the tag and length stripped from the serial number */
		memcpy( iAndSTemplateAlt, iAndSTemplate, sizeof( iAndSTemplate ) );
		sMemConnect( &stream, iAndSTemplateAlt[ 3 ].pValue, 
					 iAndSTemplateAlt[ 3 ].ulValueLen );
		cryptStatus = readGenericHole( &stream, &length, 1, BER_INTEGER );
		if( cryptStatusOK( cryptStatus ) )
			offset = stell( &stream );
		sMemDisconnect( &stream );
		if( cryptStatusError( cryptStatus ) )
			return( cryptStatus );
		iAndSTemplateAlt[ 3 ].pValue = \
					( BYTE * ) iAndSTemplateAlt[ 3 ].pValue + offset;
		iAndSTemplateAlt[ 3 ].ulValueLen = length;
		}

	/* If we're looking for a public key, try for a certificate 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 certificate object before we try 
	   anything else.  If the keyID type is an ID or label, this won't 
	   necessarily locate the certificate 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, deviceInfo->objectHandle, 
												iAndSTemplate, 4, &iCryptCert, 
												findAction );
			if( cryptStatus == CRYPT_ERROR_NOTFOUND )
				cryptStatus = findCertFromTemplate( pkcs11Info, deviceInfo->objectHandle, 
													iAndSTemplateAlt, 4, &iCryptCert, 
													findAction );
			}
		else
			{
			if( keyIDtype == CRYPT_IKEYID_KEYID )
				cryptStatus = findCertFromID( pkcs11Info, deviceInfo->objectHandle, 
											  keyID, keyIDlength, &iCryptCert, 
											  findAction );
			else
				{
				assert( keyIDtype == CRYPT_KEYID_NAME || \
						keyIDtype == CRYPT_KEYID_URI );

				cryptStatus = findCertFromLabel( pkcs11Info, deviceInfo->objectHandle, 
												 ( keyIDtype == CRYPT_KEYID_NAME ) ? \
													CKA_LABEL : CKA_URL,
												 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, deviceInfo->objectHandle, 
												  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, 
										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 certificates 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 certificate 
	   and get the key from that, otherwise we find the key and get the 
	   certificate from that */
	if( keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER )
		{
		/* Try and find the certificate 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 certificate, 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 certificate 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 don't find one, we try 
			   again for a private key whose sole function is to point to an 
			   associated certificate */
			keyTemplate[ 0 ].pValue = ( CK_VOID_PTR ) &privkeyClass;
			cryptStatus = findObject( pkcs11Info, &hObject, keyTemplate, 
									  keyTemplateCount );
			if( cryptStatusError( cryptStatus ) )
				return( cryptStatus );
		
			/* Remember that although we've got a private key object, we only 
			   need it to find the associated certificate and not finding an 
			   associated certificate is an error */
			certViaPrivateKey = TRUE;
			}
		}

	/* If we're looking for any kind of private key and we either have an
	   explicit certificate ID but couldn't find a certificate for it or we 
	   don't have a proper ID to search on and a generic search found more 
	   than one matching object, chances are we're after a generic decrypt 
	   key.  The former only occurs in misconfigured or limited-memory 
	   tokens, the latter only in rare tokens that store more than one 
	   private key, typically one for signing and one for verification.  
	   
	   If either of these cases occur we try again looking specifically for 
	   a decryption key.  Even this doesn't always work, there's are some
	   >1-key tokens that mark a signing key as a decryption key so we still 
	   get a CRYPT_ERROR_DUPLICATE error.
	   
	   Finally, if we can't find a decryption key either, we look for an
	   unwrapping key.  This may or may not work, depending on whether we 
	   have a decryption key marked as valid for unwrapping but not 
	   decryption, or a key that's genuinely only valid for unwrapping, but
	   at this point we're ready to try anything */
	if( itemType == KEYMGMT_ITEM_PRIVATEKEY && \
		( keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER && \
		  cryptStatus == CRYPT_ERROR_NOTFOUND ) || \
		( cryptStatus == CRYPT_ERROR_DUPLICATE ) )
		{
		static const CK_BBOOL bTrue = TRUE;
		CK_ATTRIBUTE decryptKeyTemplate[] = {
			{ CKA_CLASS, ( CK_VOID_PTR ) &privkeyClass, sizeof( CK_OBJECT_CLASS ) },
			{ CKA_DECRYPT, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) }
			};

		cryptStatus = findObject( pkcs11Info, &hObject, 
								  decryptKeyTemplate, 2 );
		if( cryptStatusError( cryptStatus ) )
			{
			decryptKeyTemplate[ 1 ].type = CKA_UNWRAP;
			cryptStatus = findObject( pkcs11Info, &hObject, 
									  decryptKeyTemplate, 2 );
			}
		}
	if( cryptStatusError( cryptStatus ) )
		return( cryptStatus );

	/* Sanity check that we actually found something */
	if( hObject == CK_OBJECT_NONE )
		retIntError();

	/* 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, hObject, auxInfo, *auxInfoLength,
								auxInfoLength ) );

	/* We found something, map the key type to a cryptlib algorithm ID,
	   determine the key size, and find its capabilities */
	cryptStatus = getMechanismInfo( pkcs11Info, hObject, 
									deviceInfo->capabilityInfoList,
									TRUE, &capabilityInfoPtr, &cryptAlgo );
	if( cryptStatusError( cryptStatus ) )
		return( cryptStatus );
	switch( cryptAlgo )
		{
		case CRYPT_ALGO_RSA:
			keySizeTemplate.type = CKA_MODULUS;
			break;
		case CRYPT_ALGO_DSA:
			keySizeTemplate.type = CKA_PRIME;
			break;
		case CRYPT_ALGO_DH:
			keySizeTemplate.type = CKA_PRIME;
			break;
		default:
			retIntError();
		}
	C_GetAttributeValue( pkcs11Info->hSession, hObject, 
						 &keySizeTemplate, 1 );
	keySize = keySizeTemplate.ulValueLen;

	/* Try and find a certificate which matches the key.  The process is as
	   follows:

		if certificate object found in issuerAndSerialNumber search
			-- Implies key == private key
			create native data-only certificate object
			attach certificate object to key
		else
			if public key read
				if certificate
					create native certificate (+context) object
				else
					create context object
			else
				create device privkey object, mark as "key loaded"
				if certificate
					create native data-only certificate object
					attach certificate object to key

	   The reason for doing things this way is given in the comments earlier
	   on in this function */
	if( privateKeyViaCert )
		{
		/* Sanity check that we actually found a certificate */
		if( hCertificate == CK_OBJECT_NONE )
			retIntError();

		/* We've already got the certificate object handle, instantiate a 
		   native data-only certificate from it */
		cryptStatus = getCertChain( pkcs11Info, deviceInfo->objectHandle, 
									hCertificate, &iCryptCert, FALSE );
		if( cryptStatusError( cryptStatus ) )
			return( cryptStatus );
		certPresent = TRUE;
		}
	else
		{
		cryptStatus = findCertFromObject( pkcs11Info, deviceInfo->objectHandle, 
										  hObject, &iCryptCert, 
										  ( itemType == KEYMGMT_ITEM_PUBLICKEY ) ? \
										  FIN

⌨️ 快捷键说明

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