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

📄 ms_capi.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 5 页
字号:
			status = capiToCryptlibContext( cryptoapiInfo, hKey, 
											iCryptContext );
			pCryptDestroyKey( hKey ); 
			return( status );
			}
		}
	else
		{
		assert( !( flags & KEYMGMT_FLAG_LABEL_ONLY ) );

		/* We don't have a definite private key ID indicator, go via the
		   certificate instead */
		status = getCertificate( cryptoapiInfo, keyIDtype, keyID, keyIDlength,
								 &pCertContext );
		if( cryptStatusError( status ) )
			return( status );

		/* If we're only doing a presence check, we don't need the key and 
		   can exit */
		if( flags & KEYMGMT_FLAG_CHECK_ONLY )
			{
			pCertFreeCertificateContext( pCertContext );
			return( CRYPT_OK );
			}

		/* If we're after a private key, try and find the one corresponding
		   to the certificate */
		if( itemType == KEYMGMT_ITEM_PRIVATEKEY )
			{
#if 1
			CERT_KEY_CONTEXT certKeyContext;
			DWORD certKeyContextSize = sizeof( CERT_KEY_CONTEXT );

			if( !pCertGetCertificateContextProperty( pCertContext, 
									CERT_KEY_CONTEXT_PROP_ID,
									&certKeyContext, &certKeyContextSize ) || \
				!pCryptGetUserKey( certKeyContext.hCryptProv, 
								   certKeyContext.dwKeySpec, &hKey ) )
				return( mapError( cryptoapiInfo, CRYPT_ERROR_NOTFOUND ) );

#else		/* Need to uncomment gPKFC() above */
			status = getPrivKeyFromCertificate( cryptoapiInfo, pCertContext, 
												&hKey );
#endif
			if( cryptStatusError( status ) )
				{
				pCertFreeCertificateContext( pCertContext );
				return( status );
				}
			}
		}

	/* If we've got a priavte key, create a device context for it */
	if( hKey != 0 )
		{
		status = createPrivkeyContext( deviceInfo, iCryptContext, 
									   &cryptAlgo, hKey, label );
		if( cryptStatusError( status ) )
			{
			if( pCertContext != NULL )
				pCertFreeCertificateContext( pCertContext );
			return( status );
			}
		}

	/* If there's no certificate available for the key, we're done */
	if( pCertContext == NULL )
		return( CRYPT_OK );

	/* We've got a key and certificate, try and get the rest of the chain 
	   for the certificate */
{
BOOLEAN publicComponentsOnly = FALSE;

	status = iCryptImportCertIndirect( &iCryptCert,
								deviceInfo->objectHandle, keyIDtype, keyID,
								keyIDlength, publicComponentsOnly ? \
									KEYMGMT_FLAG_NONE : \
									KEYMGMT_FLAG_DATAONLY_CERT );
}

	if( cryptStatusOK( status ) )
		{
		/* If we're getting a public key, the returned info is the 
		   certificate chain */
		if( itemType == KEYMGMT_ITEM_PUBLICKEY )
			*iCryptContext = iCryptCert;
		else
			{
			/* If we're getting a private key, attach the certificate chain 
			   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 */
			status = krnlSendMessage( *iCryptContext, IMESSAGE_SETDEPENDENT, 
									   &iCryptCert, SETDEP_OPTION_NOINCREF );
			}
		}
	
	/* Clean up */
	pCertFreeCertificateContext( pCertContext );
	pCertFreeCertificateChain( pChainContext );
	return( status );

#if 0
		{
		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 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( 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 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( 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,
	   determine the key size, and find its capabilities */
	keyTypeTemplate.pValue = &keyType;
	C_GetAttributeValue( cryptoapiInfo->hProv, 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( cryptoapiInfo->hProv, 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 certificate object found in issuerAndSerialNumber search
			create native data-only certificate object
			attach certificate object to key
		else
			if public key
				if certificate
					create native certificate (+context) object
				else
					create device pubkey object, mark as "key loaded"
			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 )
		{
		/* We've already got the certificate object handle, instantiate a 
		   native data-only certificate 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 certificate 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 certificate then not 
			   finding anything is also an error */
			if( cryptStatus != CRYPT_ERROR_NOTFOUND || certViaPrivateKey )
				return( cryptStatus );
			}
		else
			{
			/* We got the certificate, 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 );
				}
			}
		}
#endif
	}

/* Update a device with a certificate */

static int setItemFunction( DEVICE_INFO *deviceInfo, 
							const CRYPT_HANDLE iCryptHandle )
	{
	CRYPTOAPI_INFO *cryptoapiInfo = deviceInfo->deviceCryptoAPI;
	HCRYPTKEY hKey;
	DWORD dwKeySpec = 0;
	CRYPT_CERTIFICATE iCryptCert;
	BOOLEAN seenNonDuplicate = FALSE;
	int iterationCount = 0, status;

	/* Lock the certificate for our exclusive use (in case it's a 
	   certificate chain, we also select the first certificate in the 
	   chain), update the device with the certificate, 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 );

	/* Check whether the leaf certificate matches any of the user's private 
	   keys */
	if( pCryptGetUserKey( cryptoapiInfo->hProv, AT_KEYEXCHANGE, &hKey ) )
		{
		if( isCertKey( cryptoapiInfo, hKey, iCryptCert ) )
			dwKeySpec = AT_KEYEXCHANGE;
		pCryptDestroyKey( hKey ); 
		}
	else
		{
		if( pCryptGetUserKey( cryptoapiInfo->hProv, AT_SIGNATURE, &hKey ) )
			{
			if( isCertKey( cryptoapiInfo, hKey, iCryptCert ) )
				dwKeySpec = AT_SIGNATURE;
			pCryptDestroyKey( hKey ); 
			}
		}

	/* Add each certificate in the chain to the store */
	do
		{
		DYNBUF certDB;
		BOOL result = FALSE;

		/* Get the certificate data and add it to the store */
		status = dynCreate( &certDB, iCryptHandle, 
							CRYPT_CERTFORMAT_CERTIFICATE );
		if( cryptStatusError( status ) )
			return( status );

		/* If the certificate corresponds to one of the user's private keys 
		   and a binding between the key and a certificate isn't already 
		   established, establish one now */
		if( dwKeySpec != 0 )
			{
			PCCERT_CONTEXT pCertContext;
			CERT_KEY_CONTEXT certKeyContext;
			DWORD certKeyContextSize = sizeof( CERT_KEY_CONTEXT );

			/* Check whether the certificate is already bound to a key and 
			   if not, bind it to the appropriate private key */
			pCertContext = pCertCreateCertificateContext( X509_ASN_ENCODING, 
									dynData( certDB ), dynLength( certDB ) );
			if( pCertContext != NULL && \
				

⌨️ 快捷键说明

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