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

📄 ms_capi.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 5 页
字号:
	zeroise( keyBlob, blobSize );
	if( !result )
		return( mapDeviceError( errorInfoPtr, CRYPT_ERROR_FAILED ) );

	return( CRYPT_OK );
	}

/* Load a CryptoAPI public key into a cryptlib native context */

static int getPubkeyComponents( CRYPTOAPI_INFO *cryptoapiInfo,
								const HCRYPTKEY hKey, BYTE *n, int *nLen, 
								BYTE *e, int *eLen )
	{
	BLOBHEADER *blobHeaderPtr;
	RSAPUBKEY *pubKeyPtr;
	BYTE keyBlob[ 1024 + CRYPT_MAX_PKCSIZE + 8 ], *nPtr;
	BYTE buffer[ 16 + 8 ], *bufPtr = buffer;
	int keyBlobLen = 1024 + CRYPT_MAX_PKCSIZE, exponent, length;

	/* Clear return values */
	memset( n, 0, 8 );
	memset( e, 0, 8 );
	*nLen = *eLen = 0;

	/* Get the public key components */
	if( !pCryptExportKey( hKey, 0, PUBLICKEYBLOB, 0, keyBlob, &keyBlobLen ) )
		return( mapError( cryptoapiInfo, CRYPT_ERROR_FAILED ) );

	/* Perform a general sanity check on the returned data */
	blobHeaderPtr = ( BLOBHEADER * ) keyBlob;
	if( blobHeaderPtr->bType != PUBLICKEYBLOB || \
		blobHeaderPtr->bVersion != CUR_BLOB_VERSION )
		return( CRYPT_ERROR_FAILED );

	/* Extract the public key components */
	pubKeyPtr = ( RSAPUBKEY * ) ( keyBlob + BLOBHEADER_SIZE );
	exponent = pubKeyPtr->pubexp;
	nPtr = keyBlob + 20;
	length = pubKeyPtr->bitlen / 8;
	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;
	MESSAGE_DATA msgData;
	BYTE n[ CRYPT_MAX_PKCSIZE + 8 ], e[ CRYPT_MAX_PKCSIZE + 8 ];
	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( DEBUG_WARN );
		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
   certificate 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 certificate 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 certificate 
			   using the email address in an altName, so we have to restrict 
			   ourselves to the most commonly-used OID for certificates 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;
			void *dataPtr = DUMMY_INIT_PTR;
			int length, status;

			memset( &certInfo, 0, sizeof( CERT_INFO ) );
			sMemConnect( &stream, keyID, keyIDlength );
			readSequence( &stream, NULL );
			status = getStreamObjectLength( &stream, &length );
			if( cryptStatusOK( status ) )
				status = sMemGetDataBlock( &stream, &dataPtr, length );
			if( cryptStatusError( status ) )
				{
				sMemDisconnect( &stream );
				return( status );
				}
			certInfo.Issuer.pbData = dataPtr;		/* Issuer DN */
			certInfo.Issuer.cbData = length;
			sSkip( &stream, length );
			status = getStreamObjectLength( &stream, &length );
			if( cryptStatusOK( status ) )
				status = sMemGetDataBlock( &stream, &dataPtr, length );
			if( cryptStatusError( status ) )
				return( status );
			certInfo.SerialNumber.pbData = dataPtr;	/* Serial number */
			certInfo.SerialNumber.cbData = length;
			status = sSkip( &stream, length );
			assert( sStatusOK( &stream ) );
			sMemDisconnect( &stream );
			if( cryptStatusError( status ) )
				return( status );
			pCertContext = \
				pCertGetSubjectCertificateFromStore( cryptoapiInfo->hCertStore,
							X509_ASN_ENCODING, &certInfo );
			}

		default:
			retIntError();
		}

	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 certificate up to a root 
	   certificate */
	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 + 8 ];
	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 certificate 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 certificate and use that to 
	   get the key */
	if( !pCryptAcquireCertificatePrivateKey( pCertContext, 
									CRYPT_ACQUIRE_CACHE_FLAG, NULL,
									&hProv, &dwKeySpec, &fCallerFreeProv ) )

⌨️ 快捷键说明

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