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