📄 ms_capi.c
字号:
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 + -