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

📄 dev_pk11.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 5 页
字号:
	   number in this form which we fall back to if a search using the 
	   correct form fails */
	if( keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER )
		{
		STREAM stream;
		int length;

		sMemConnect( &stream, keyID, STREAMSIZE_UNKNOWN );
		readSequence( &stream, NULL );
		iAndSTemplate[ 2 ].pValue = sMemBufPtr( &stream );
		readSequence( &stream, &length );
		iAndSTemplate[ 2 ].ulValueLen = ( int ) sizeofObject( length );
		sSkip( &stream, length );
		iAndSTemplate[ 3 ].pValue = sMemBufPtr( &stream );
		readTag( &stream );
		iAndSTemplate[ 3 ].ulValueLen = \
					( int ) sizeofObject( readShortLength( &stream ) );
		memcpy( iAndSTemplateAlt, iAndSTemplate, sizeof( iAndSTemplate ) );
		iAndSTemplateAlt[ 3 ].pValue = sMemBufPtr( &stream );
		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, 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( deviceInfo, iAndSTemplate, 4, 
												&iCryptCert, findAction );
			if( cryptStatus == CRYPT_ERROR_NOTFOUND )
				cryptStatus = findCertFromTemplate( deviceInfo, iAndSTemplateAlt, 4, 
													&iCryptCert, findAction );
			}
		else
			if( keyIDtype == CRYPT_IKEYID_KEYID )
				cryptStatus = findCertFromID( deviceInfo, keyID, keyIDlength, 
											  &iCryptCert, findAction );
			else
				cryptStatus = findCertFromLabel( deviceInfo, 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( deviceInfo, 
										( 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( deviceInfo, &hCertificate, 
								  iAndSTemplate, 4 );
		if( cryptStatus == CRYPT_ERROR_NOTFOUND )
			cryptStatus = findObject( deviceInfo, &hCertificate, 
									  iAndSTemplateAlt, 4 );
		if( cryptStatusOK( cryptStatus ) )
			{
			/* We found the cert, use it to find the corresponding private 
			   key */
			cryptStatus = findObjectFromObject( deviceInfo, 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( deviceInfo, &hObject, keyTemplate, 
								  keyTemplateCount );
		if( cryptStatus == CRYPT_ERROR_NOTFOUND && \
			itemType == KEYMGMT_ITEM_PUBLICKEY )
			{
			/* Some devices may only contain private key objects with 
			   associated certificates which can't be picked out of the other 
			   cruft which is 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 cert */
			keyTemplate[ 0 ].pValue = ( CK_VOID_PTR ) &privkeyClass;
			cryptStatus = findObject( deviceInfo, &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 cert and not finding an 
			   associated cert is an error */
			certViaPrivateKey = TRUE;
			}
		}

	/* If we're looking for any kind of private key and we either have an
	   explicit cert.ID but couldn't find a cert 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 which 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 at least one 
	   >1-key token which marks 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 which is 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( deviceInfo, &hObject, 
								  decryptKeyTemplate, 2 );
		if( cryptStatusError( cryptStatus ) )
			{
			decryptKeyTemplate[ 1 ].type = CKA_UNWRAP;
			cryptStatus = findObject( deviceInfo, &hObject, 
									  decryptKeyTemplate, 2 );
			}
		}
	if( cryptStatusError( cryptStatus ) )
		return( 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( deviceInfo, hObject, auxInfo, 
								auxInfoLength ) );

	/* We found something, map the key type to a cryptlib algorithm ID and
	   determine the key size, and find its capabilities */
	keyTypeTemplate.pValue = &keyType;
	C_GetAttributeValue( deviceInfo->deviceHandle, hObject, 
						 &keyTypeTemplate, 1 );
	switch( ( int ) keyType )
		{
		case CKK_RSA:
			cryptAlgo = CRYPT_ALGO_RSA;
			keySizeTemplate.type = CKA_MODULUS;
			break;
		case CKK_DSA:
			cryptAlgo = CRYPT_ALGO_DSA;
			keySizeTemplate.type = CKA_PRIME;
			break;
		case CKK_DH:
			cryptAlgo = CRYPT_ALGO_DH;
			keySizeTemplate.type = CKA_PRIME;
			break;
		default:
			return( CRYPT_ERROR_NOTAVAIL );
		}
	C_GetAttributeValue( deviceInfo->deviceHandle, hObject, 
						 &keySizeTemplate, 1 );
	keySize = keySizeTemplate.ulValueLen;
	capabilityInfoPtr = findCapabilityInfo( deviceInfo->capabilityInfo, 
											cryptAlgo );
	if( capabilityInfoPtr == NULL )
		return( CRYPT_ERROR_NOTAVAIL );

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

		if cert object found in issuerAndSerialNumber search
			create native data-only cert object
			attach cert object to key
		else
			if public key
				if cert
					create native cert (+context) object
				else
					create device pubkey object, mark as "key loaded"
			else
				create device privkey object, mark as "key loaded"
				if cert
					create native data-only cert object
					attach cert object to key

	   The reason for doing things this way is given in the comment at the 
	   top of this section */
	if( privateKeyViaCert )
		{
		/* We've already got the cert object handle, instantiate a native
		   data-only cert from it */
		cryptStatus = instantiateCert( deviceInfo, hCertificate, 
									   &iCryptCert, FALSE );
		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.  Since the keys are
	   sensitive (otherwise they wouldn't be held in a crypto device) we
	   don't allow external use */
	if( readFlag( deviceInfo, hObject, CKA_ENCRYPT ) )
		actionFlags |= MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_ENCRYPT, 
									   ACTION_PERM_NONE_EXTERNAL );
	if( readFlag( deviceInfo, hObject, CKA_DECRYPT ) || \
		readFlag( deviceInfo, hObject, CKA_UNWRAP ) )
		actionFlags |= MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_DECRYPT, 
									   ACTION_PERM_NONE_EXTERNAL );
	if( readFlag( deviceInfo, hObject, CKA_SIGN ) )
		actionFlags |= MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_SIGN, 
									   ACTION_PERM_NONE_EXTERNAL );
	if( readFlag( deviceInfo, hObject, CKA_VERIFY ) )
		actionFlags |= MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_SIGCHECK, 
									   ACTION_PERM_NONE_EXTERNAL );
	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, RESOURCE_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 (ie 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, RESOURCE_IMESSAGE_DECREFCOUNT );
		return( cryptStatus );
		}
	krnlSendMessage( *iCryptContext, RESOURCE_IMESSAGE_SETDEPENDENT,
					 &deviceInfo->objectHandle, SETDEP_OPTION_INCREF );
	krnlSendMessage( *iCryptContext, RESOURCE_IMESSAGE_SETATTRIBUTE,
					 &hObject, CRYPT_IATTRIBUTE_DEVICEOBJECT );
	krnlSendMessage( *iCryptContext, RESOURCE_IMESSAGE_SETATTRIBUTE,
					 &actionFlags, CRYPT_IATTRIBUTE_ACTIONPERMS );
	i

⌨️ 快捷键说明

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