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

📄 ms_capi.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 5 页
字号:
	while( length > 0 && nPtr[ length ] == 0 )
		length--;
	copyMPI( n, nPtr, length, length );
	*nLen = length;
	length = ( exponent <= 0xFF ) ? 1 : \
			 ( exponent <= 0xFFFF ) ? 2 : \
			 ( exponent <= 0xFFFFFFL ) ? 3 : 4;
	mputLong( bufPtr, exponent );
	memcpy( e, buffer + ( 4 - length ), length );
	*eLen = length;

	return( CRYPT_OK );
	}

static int capiToCryptlibContext( CRYPTOAPI_INFO *cryptoapiInfo,
								  const HCRYPTKEY hKey, 
								  CRYPT_CONTEXT *cryptContextPtr )
	{
	CRYPT_PKCINFO_RSA rsaKey;
	MESSAGE_CREATEOBJECT_INFO createInfo;
	RESOURCE_DATA msgData;
	BYTE n[ CRYPT_MAX_PKCSIZE ], e[ CRYPT_MAX_PKCSIZE ];
	int nLen, eLen, status;

	/* Clear return value */
	*cryptContextPtr = CRYPT_ERROR;

	/* Extract the public-key components from the CryptoAPI context */
	status = getPubkeyComponents( cryptoapiInfo, hKey, n, &nLen, e, &eLen );
	if( cryptStatusError( status ) )
		return( status );

	/* Copy the public-key components into the cryptlib format */
	cryptInitComponents( &rsaKey, CRYPT_KEYTYPE_PUBLIC );
	cryptSetComponent( ( &rsaKey )->n, n, bytesToBits( nLen ) );
	cryptSetComponent( ( &rsaKey )->e, e, bytesToBits( eLen ) );
	zeroise( n, CRYPT_MAX_PKCSIZE );
	zeroise( e, CRYPT_MAX_PKCSIZE );

	/* Create the RSA context */
	setMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_RSA );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,
							  &createInfo, OBJECT_TYPE_CONTEXT );
	if( cryptStatusError( status ) )
		{
		cryptDestroyComponents( &rsaKey );
		return( status );
		}

	/* Load the key into the context */
	setMessageData( &msgData, "CryptoAPI RSA key", 17 );
	status = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE_S,
							  &msgData, CRYPT_CTXINFO_LABEL );
	if( cryptStatusOK( status ) )
		{
		setMessageData( &msgData, &rsaKey, sizeof( CRYPT_PKCINFO_RSA ) );
		status = krnlSendMessage( createInfo.cryptHandle,
								  IMESSAGE_SETATTRIBUTE_S, &msgData,
								  CRYPT_CTXINFO_KEY_COMPONENTS );
		}
	cryptDestroyComponents( &rsaKey );
	if( cryptStatusError( status ) )
		{
		assert( NOTREACHED );
		krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
		return( status );
		}

	*cryptContextPtr = createInfo.cryptHandle;
	return( CRYPT_OK );
	}

/* Compare a CryptoAPI private key with a certificate to check whether the
   cert corresponds to the key */

static BOOLEAN isCertKey( const CRYPTOAPI_INFO *cryptoapiInfo,
						  const HCRYPTKEY hKey, 
						  const CRYPT_CERTIFICATE iCryptCert )
	{
	return( TRUE );
	}

/* Get a certificate using a key/certificate identifier */

static int getCertificate( const CRYPTOAPI_INFO *cryptoapiInfo,
						   const CRYPT_KEYID_TYPE keyIDtype,
						   const void *keyID, const int keyIDlength,
						   PCCERT_CONTEXT *pCertContextPtr )
	{
	PCCERT_CONTEXT pCertContext = NULL;

	switch( keyIDtype )
		{
		case CRYPT_KEYID_NAME:
			{
			CERT_RDN certRDN;
			CERT_RDN_ATTR certRDNAttr;

			/* Find a cert by CN */
			memset( &certRDNAttr, 0, sizeof( CERT_RDN_ATTR ) );
			certRDNAttr.pszObjId = szOID_COMMON_NAME;
			certRDNAttr.dwValueType = CERT_RDN_ANY_TYPE;
			certRDNAttr.Value.pbData = ( void * ) keyID;
			certRDNAttr.Value.cbData = keyIDlength;
			memset( &certRDN, 0, sizeof( CERT_RDN ) );
			certRDN.rgRDNAttr = &certRDNAttr;
			certRDN.cRDNAttr = 1;
			pCertContext = \
				pCertFindCertificateInStore( cryptoapiInfo->hCertStore,
							X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_ATTR,
							&certRDN, NULL );
			break;
			}

		case CRYPT_KEYID_URI:
			{
			CERT_RDN certRDN;
			CERT_RDN_ATTR certRDNAttr;

			/* There doesn't appear to be any way to locate a cert using the 
			   email address in an altName, so we have to restrict ourselves 
			   to the most commonly-used OID for certs in DNs */
			memset( &certRDNAttr, 0, sizeof( CERT_RDN_ATTR ) );
			certRDNAttr.pszObjId = szOID_RSA_emailAddr ;
			certRDNAttr.dwValueType = CERT_RDN_ANY_TYPE;
			certRDNAttr.Value.pbData = ( void * ) keyID;
			certRDNAttr.Value.cbData = keyIDlength;
			memset( &certRDN, 0, sizeof( CERT_RDN ) );
			certRDN.rgRDNAttr = &certRDNAttr;
			certRDN.cRDNAttr = 1;
			pCertContext = \
				pCertFindCertificateInStore( cryptoapiInfo->hCertStore,
							X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_ATTR,
							&certRDN, NULL );
			break;
			}

		case CRYPT_IKEYID_CERTID:
			{
			CRYPT_DATA_BLOB cryptDataBlob;

			memset( &cryptDataBlob, 0, sizeof( CRYPT_DATA_BLOB ) );
			cryptDataBlob.pbData = ( void * ) keyID;
			cryptDataBlob.cbData = keyIDlength;
			pCertContext = \
				pCertFindCertificateInStore( cryptoapiInfo->hCertStore,
							X509_ASN_ENCODING, 0, CERT_FIND_SHA1_HASH,
							&cryptDataBlob, NULL );
			break;
			}

		case CRYPT_IKEYID_KEYID:
			{
#if 0
			CERT_ID certID;

			certID.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
			certID.KeyId.pbData = ( void * ) keyID;
			certID.KeyId.cbData = keyIDlength;
			pCertContext = \
				pCertFindCertificateInStore( cryptoapiInfo->hCertStore,
							X509_ASN_ENCODING, 0, CERT_FIND_CERT_ID,
							&certID, NULL );
#else
			CRYPT_HASH_BLOB hashBlob;

			hashBlob.pbData = ( void * ) keyID;
			hashBlob.cbData = keyIDlength;
			pCertContext = \
				pCertFindCertificateInStore( cryptoapiInfo->hCertStore,
							X509_ASN_ENCODING, 0, CERT_FIND_KEY_IDENTIFIER,
							&hashBlob, NULL );
#endif /* 0 */
			break;
			}

		case CRYPT_IKEYID_ISSUERANDSERIALNUMBER:
			{
			CERT_INFO certInfo;
			STREAM stream;
			int length;

			memset( &certInfo, 0, sizeof( CERT_INFO ) );
			sMemConnect( &stream, keyID, keyIDlength );
			readSequence( &stream, NULL );
			certInfo.Issuer.pbData = sMemBufPtr( &stream );
			readSequence( &stream, &length );		/* Issuer DN */
			certInfo.Issuer.cbData = ( int ) sizeofObject( length );
			sSkip( &stream, length );
			certInfo.SerialNumber.pbData = sMemBufPtr( &stream );
			readGenericHole( &stream, &length, BER_INTEGER );/* Serial number */
			certInfo.SerialNumber.cbData = ( int ) sizeofObject( length );
			assert( sStatusOK( &stream ) );
			sMemDisconnect( &stream );
			pCertContext = \
				pCertGetSubjectCertificateFromStore( cryptoapiInfo->hCertStore,
							X509_ASN_ENCODING, &certInfo );
			}

		default:
			assert( NOTREACHED );
		}

	if( pCertContext == NULL )
		return( CRYPT_ERROR_NOTFOUND );
	*pCertContextPtr = pCertContext;
	return( CRYPT_OK );
	}

/* Get a certificate chain from a leaf certificate */

static int getCertificateChain( CRYPTOAPI_INFO *cryptoapiInfo,
								const PCCERT_CONTEXT pCertContext,
								PCCERT_CHAIN_CONTEXT *pChainContextPtr )
	{
	CERT_CHAIN_PARA chainPara;
	CERT_USAGE_MATCH certUsage;
	CERT_ENHKEY_USAGE enhkeyUsage;
	PCCERT_CHAIN_CONTEXT pChainContext;

	/* Clear return value */
	*pChainContextPtr = NULL;

	/* Get the chain from the supplied cert up to a root cert */
	memset( &enhkeyUsage, 0, sizeof( CERT_ENHKEY_USAGE ) );
	enhkeyUsage.cUsageIdentifier = 0;
	enhkeyUsage.rgpszUsageIdentifier = NULL;
	memset( &certUsage, 0, sizeof( CERT_USAGE_MATCH ) );
	certUsage.dwType = USAGE_MATCH_TYPE_AND;
	certUsage.Usage = enhkeyUsage;
	memset( &chainPara, 0, sizeof( CERT_CHAIN_PARA ) );
	chainPara.cbSize = sizeof( CERT_CHAIN_PARA );
	chainPara.RequestedUsage = certUsage;
	if( !pCertGetCertificateChain( NULL, pCertContext, NULL, NULL, &chainPara,
								   CERT_CHAIN_CACHE_END_CERT | \
								   CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY, 
								   NULL, &pChainContext ) )
		return( mapError( cryptoapiInfo, CRYPT_ERROR_NOTFOUND ) );
	*pChainContextPtr = pChainContext;
	return( CRYPT_OK );
	}

/* Get a certificate from a public/private key and vice versa */

static int getCertificateFromKey( CRYPTOAPI_INFO *cryptoapiInfo,
								  const HCRYPTKEY hKey,
								  const BOOLEAN isSigningKey,
								  PCCERT_CONTEXT *pCertContextPtr )
	{
	PCCERT_CONTEXT pCertContext;
	CERT_PUBLIC_KEY_INFO pubKeyInfo;
	BYTE keyBlob[ 1024 + CRYPT_MAX_PKCSIZE ];
	int keyBlobLen = 1024 + CRYPT_MAX_PKCSIZE;

	/* Clear return value */
	*pCertContextPtr = NULL;

	/* Extract the public-key components from the public or private key */
	if( !pCryptExportKey( hKey, 0, PUBLICKEYBLOB, 0, keyBlob, &keyBlobLen ) )
		{
		pCryptDestroyKey( hKey );
		return( CRYPT_ERROR_NOTFOUND );
		}

	/* Get the cert for the context's public key */
	memset( &pubKeyInfo, 0, sizeof( CERT_PUBLIC_KEY_INFO ) );
	pubKeyInfo.Algorithm.pszObjId = isSigningKey ? \
									CERT_DEFAULT_OID_PUBLIC_KEY_SIGN : \
									CERT_DEFAULT_OID_PUBLIC_KEY_XCHG;
	pubKeyInfo.PublicKey.pbData = keyBlob;
	pubKeyInfo.PublicKey.cbData = keyBlobLen;
	pCertContext = \
		pCertFindCertificateInStore( cryptoapiInfo->hCertStore,
						X509_ASN_ENCODING, 0, CERT_FIND_PUBLIC_KEY,
						&pubKeyInfo, NULL );
	if( pCertContext == NULL )
		return( mapError( cryptoapiInfo, CRYPT_ERROR_NOTFOUND ) );
	*pCertContextPtr = pCertContext;
	return( CRYPT_OK );
	}

#if 0

static int getPrivKeyFromCertificate( CRYPTOAPI_INFO *cryptoapiInfo,
									  const PCCERT_CONTEXT pCertContext,
									  HCRYPTKEY *hKeyPtr )
	{
	HCRYPTPROV hProv;
	HCRYPTKEY hKey;
	DWORD dwKeySpec;
	BOOL fCallerFreeProv;

	/* Clear return value */
	*hKeyPtr = 0;

	/* Get the provider and key-type from the cert and use that to get the
	   key */
	if( !pCryptAcquireCertificatePrivateKey( pCertContext, 
									CRYPT_ACQUIRE_CACHE_FLAG, NULL,
									&hProv, &dwKeySpec, &fCallerFreeProv ) )
		return( mapError( cryptoapiInfo, CRYPT_ERROR_NOTFOUND ) );
	if( !pCryptGetUserKey( hProv, dwKeySpec, &hKey ) )
		return( mapError( cryptoapiInfo, CRYPT_ERROR_NOTFOUND ) );
	*hKeyPtr = hKey;
	return( CRYPT_OK );
	}
#endif /* 0 */

/* Create a private-key context using a CryptoAPI native key */

static int createPrivkeyContext( DEVICE_INFO *deviceInfo,
								 CRYPT_CONTEXT *iCryptContext,
								 CRYPT_ALGO_TYPE *cryptAlgo,
								 const HCRYPTKEY hKey,
								 const char *label )
	{
	ALG_ID algID;
	DWORD dwDataLen = sizeof( ALG_ID );
	const CAPABILITY_INFO *capabilityInfoPtr = NULL;
	RESOURCE_DATA msgData;
	int status;

	/* Clear return values */
	*iCryptContext = CRYPT_ERROR;
	*cryptAlgo = CRYPT_ALGO_NONE;

	/* Get the algorithm type and look up the corresponding capability 
	   info */
	if( !pCryptGetKeyParam( hKey, KP_ALGID, ( BYTE * ) &algID, &dwDataLen, 
							0 ) || \
		( *cryptAlgo = capiToCryptlibID( algID ) ) == CRYPT_ALGO_NONE )
		return( CRYPT_ERROR_NOTAVAIL );
	capabilityInfoPtr = findCapabilityInfo( deviceInfo->capabilityInfoList, 
											*cryptAlgo );
	if( capabilityInfoPtr == NULL )
		return( CRYPT_ERROR_NOTAVAIL );

	/* 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, and mark it as initialised (i.e. with a key loaded) */
	status = createContextFromCapability( iCryptContext, 
								deviceInfo->ownerHandle, capabilityInfoPtr, 
								CREATEOBJECT_FLAG_DUMMY );
	if( cryptStatusError( status ) )
		return( status );
	krnlSendMessage( *iCryptContext, IMESSAGE_SETDEPENDENT,
					 &deviceInfo->objectHandle, SETDEP_OPTION_INCREF );
	krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE, 
					 ( void * ) &hKey, CRYPT_IATTRIBUTE_DEVICEOBJECT );
	setMessageData( &msgData, ( void * ) label, strlen( label ) );
	krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE_S,
					 &msgData, CRYPT_CTXINFO_LABEL );
#if 0
	if( cryptAlgo == CRYPT_ALGO_RSA )

⌨️ 快捷键说明

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