📄 dev_capi.c
字号:
#define USE_CRYPTOAPI
void *hCertStore; // CAPI dev-specific entry for device_info */
/****************************************************************************
* *
* cryptlib CryptoAPI Routines *
* Copyright Peter Gutmann 1998-2003 *
* *
****************************************************************************/
#include <stdlib.h>
#include <string.h>
#if defined( INC_ALL )
#include "crypt.h"
#include "device.h"
#include "asn1_rw.h"
#include "context.h"
#elif defined( INC_CHILD )
#include "../crypt.h"
#include "device.h"
#include "../misc/asn1_rw.h"
#include "../misc/context.h"
#else
#include "crypt.h"
#include "device/device.h"
#include "misc/asn1_rw.h"
#include "misc/context.h"
#endif /* Compiler-specific includes */
/* Occasionally we need to read things into host memory from a device in a
manner that can't be handled by a dynBuf since the data is coming from a
device rather than a cryptlib object. The following value defines the
maximum size of the on-stack buffer, if the data is larger than this we
dynamically allocate the buffer (this almost never occurs) */
#define MAX_BUFFER_SIZE 1024
/* Prototypes for functions in cryptcap.c */
const void FAR_BSS *findCapabilityInfo( const void FAR_BSS *capabilityInfoPtr,
const CRYPT_ALGO_TYPE cryptAlgo );
#ifdef USE_CRYPTOAPI
/* The following define is needed to enable crypto functions in the include
file. This would probably be defined by the compiler since it's not
defined in any header file, but it doesn't seem to be enabled by
default */
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0500
#endif /* _WIN32_WINNT */
/* cryptlib.h includes a trap for inclusion of wincrypt.h before cryptlib.h
which results in a compiler error if both files are included. To disable
this, we need to undefine the CRYPT_MODE_ECB defined in cryptlib.h */
#undef CRYPT_MODE_ECB
#include <wincrypt.h>
/* CryptoAPI uses the same mode names as cryptlib but different values,
fortunately this is done with #defines so we can remove them at this
point */
#undef CRYPT_MODE_ECB
#undef CRYPT_MODE_CBC
#undef CRYPT_MODE_CFB
#undef CRYPT_MODE_OFB
/****************************************************************************
* *
* Init/Shutdown Routines *
* *
****************************************************************************/
/* Global function pointers. These are necessary because the functions need
to be dynamically linked since not all systems contain the necessary
DLL's. Explicitly linking to them will make cryptlib unloadable on some
systems */
#define NULL_HINSTANCE ( HINSTANCE ) NULL
static HINSTANCE hCryptoAPI = NULL_HINSTANCE;
static HINSTANCE hAdvAPI32 = NULL_HINSTANCE;
typedef BOOL ( WINAPI *CERTADDENCODEDCERTIFICATETOSTORE )( HCERTSTORE hCertStore,
DWORD dwCertEncodingType, const BYTE *pbCertEncoded,
DWORD cbCertEncoded, DWORD dwAddDisposition,
PCCERT_CONTEXT *ppCertContext );
typedef BOOL ( WINAPI *CERTCLOSESTORE )( HCERTSTORE hCertStore, DWORD dwFlags );
typedef BOOL ( WINAPI *CERTDELETECERTIFICATEFROMSTORE )( PCCERT_CONTEXT pCertContext );
typedef PCCERT_CONTEXT ( WINAPI *CERTFINDCERTIFICATEINSTORE )( HCERTSTORE hCertStore,
DWORD dwCertEncodingType, DWORD dwFindFlags,
DWORD dwFindType, const void *pvFindPara,
PCCERT_CONTEXT pPrevCertContext );
typedef BOOL ( WINAPI *CERTFREECERTIFICATECONTEXT )( PCCERT_CONTEXT pCertContext );
typedef PCCERT_CONTEXT ( WINAPI *CERTGETSUBJECTCERTIFICATEFROMSTORE )( HCERTSTORE hCertStore,
DWORD dwCertEncodingType, PCERT_INFO pCertId );
typedef HCERTSTORE ( WINAPI *CERTOPENSTORE )( LPCSTR lpszStoreProvider,
DWORD dwEncodingType, HCRYPTPROV hCryptProv,
DWORD dwFlags, const void *pvPara );
typedef BOOL ( WINAPI *CRYPTACQUIRECONTEXTA )( HCRYPTPROV *phProv, LPCSTR pszContainer,
LPCSTR pszProvider, DWORD dwProvType, DWORD dwFlags );
typedef BOOL ( WINAPI *CRYPTDECRYPT )( HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen );
typedef BOOL ( WINAPI *CRYPTDESTROYHASH )( HCRYPTHASH hHash );
typedef BOOL ( WINAPI *CRYPTDESTROYKEY )( HCRYPTKEY hKey );
typedef BOOL ( WINAPI *CRYPTENCRYPT )( HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen, DWORD dwBufLen );
typedef BOOL ( WINAPI *CRYPTEXPORTKEY )( HCRYPTKEY hKey, HCRYPTKEY hExpKey,
DWORD dwBlobType, DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen );
typedef BOOL ( WINAPI *CRYPTGENKEY )( HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags,
HCRYPTKEY *phKey );
typedef BOOL ( WINAPI *CRYPTGENRANDOM )( HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer );
typedef BOOL ( WINAPI *CRYPTGETPROVPARAM )( HCRYPTPROV hProv, DWORD dwParam,
BYTE *pbData, DWORD *pdwDataLen, DWORD dwFlags );
typedef BOOL ( WINAPI *CRYPTHASHDATA )( HCRYPTHASH hHash, BYTE *pbData, DWORD dwDataLen,
DWORD dwFlags );
typedef BOOL ( WINAPI *CRYPTIMPORTKEY )( HCRYPTPROV hProv, CONST BYTE *pbData,
DWORD dwDataLen, HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY *phKey );
typedef BOOL ( WINAPI *CRYPTRELEASECONTEXT )( HCRYPTPROV hProv, DWORD dwFlags );
typedef BOOL ( WINAPI *CRYPTSETKEYPARAM )( HCRYPTKEY hKey, DWORD dwParam,
BYTE *pbData, DWORD dwFlags );
static CERTADDENCODEDCERTIFICATETOSTORE pCertAddEncodedCertificateToStore = NULL;
static CERTDELETECERTIFICATEFROMSTORE pCertDeleteCertificateFromStore = NULL;
static CERTCLOSESTORE pCertCloseStore = NULL;
static CERTFINDCERTIFICATEINSTORE pCertFindCertificateInStore = NULL;
static CERTFREECERTIFICATECONTEXT pCertFreeCertificateContext = NULL;
static CERTGETSUBJECTCERTIFICATEFROMSTORE pCertGetSubjectCertificateFromStore = NULL;
static CERTOPENSTORE pCertOpenStore = NULL;
static CRYPTACQUIRECONTEXTA pCryptAcquireContextA = NULL;
static CRYPTDECRYPT pCryptDecrypt = NULL;
static CRYPTDESTROYHASH pCryptDestroyHash = NULL;
static CRYPTDESTROYKEY pCryptDestroyKey = NULL;
static CRYPTENCRYPT pCryptEncrypt = NULL;
static CRYPTEXPORTKEY pCryptExportKey = NULL;
static CRYPTGENKEY pCryptGenKey = NULL;
static CRYPTGENRANDOM pCryptGenRandom = NULL;
static CRYPTGETPROVPARAM pCryptGetProvParam = NULL;
static CRYPTHASHDATA pCryptHashData = NULL;
static CRYPTIMPORTKEY pCryptImportKey = NULL;
static CRYPTRELEASECONTEXT pCryptReleaseContext = NULL;
static CRYPTSETKEYPARAM pCryptSetKeyParam = NULL;
/* Dynamically load and unload any necessary DBMS libraries */
int deviceInitCryptoAPI( void )
{
/* If the CryptoAPI module is already linked in, don't do anything */
if( hCryptoAPI != NULL_HINSTANCE )
return( CRYPT_OK );
/* Obtain handles to the modules containing the CryptoAPI functions */
if( ( hAdvAPI32 = GetModuleHandle( "AdvAPI32.DLL" ) ) == NULL )
return( CRYPT_ERROR );
if( ( hCryptoAPI = LoadLibrary( "Crypt32.dll" ) ) == NULL_HINSTANCE )
return( CRYPT_ERROR );
/* Get pointers to the crypt functions */
pCryptAcquireContextA = ( CRYPTACQUIRECONTEXTA ) GetProcAddress( hAdvAPI32, "CryptAcquireContextA" );
pCryptDecrypt = ( CRYPTDECRYPT ) GetProcAddress( hAdvAPI32, "CryptDecrypt" );
pCryptDestroyHash = ( CRYPTDESTROYHASH ) GetProcAddress( hAdvAPI32, "CryptDestroyHash" );
pCryptDestroyKey = ( CRYPTDESTROYKEY ) GetProcAddress( hAdvAPI32, "CryptDestroyKey" );
pCryptEncrypt = ( CRYPTENCRYPT ) GetProcAddress( hAdvAPI32, "CryptEncrypt" );
pCryptExportKey = ( CRYPTEXPORTKEY ) GetProcAddress( hAdvAPI32, "CryptExportKey" );
pCryptGenKey = ( CRYPTGENKEY ) GetProcAddress( hAdvAPI32, "CryptGenKey" );
pCryptGenRandom = ( CRYPTGENRANDOM ) GetProcAddress( hAdvAPI32, "CryptGenRandom" );
pCryptGetProvParam = ( CRYPTGETPROVPARAM ) GetProcAddress( hAdvAPI32, "CryptGetProvParam" );
pCryptHashData = ( CRYPTHASHDATA ) GetProcAddress( hAdvAPI32, "CryptHashData" );
pCryptImportKey = ( CRYPTIMPORTKEY ) GetProcAddress( hAdvAPI32, "CryptImportKey" );
pCryptReleaseContext = ( CRYPTRELEASECONTEXT ) GetProcAddress( hAdvAPI32, "CryptReleaseContext" );
pCryptSetKeyParam = ( CRYPTSETKEYPARAM ) GetProcAddress( hAdvAPI32, "CryptSetKeyParam" );
/* Get pointers to the cert functions */
pCertAddEncodedCertificateToStore = ( CERTADDENCODEDCERTIFICATETOSTORE ) GetProcAddress( hCryptoAPI, "CertAddEncodedCertificateToStore" );
pCertDeleteCertificateFromStore = ( CERTDELETECERTIFICATEFROMSTORE ) GetProcAddress( hCryptoAPI, "CertDeleteCertificateFromStore" );
pCertCloseStore = ( CERTCLOSESTORE ) GetProcAddress( hCryptoAPI, "CertCloseStore" );
pCertFindCertificateInStore = ( CERTFINDCERTIFICATEINSTORE ) GetProcAddress( hCryptoAPI, "CertFindCertificateInStore" );
pCertFreeCertificateContext = ( CERTFREECERTIFICATECONTEXT ) GetProcAddress( hCryptoAPI, "CertFreeCertificateContext" );
pCertGetSubjectCertificateFromStore = ( CERTGETSUBJECTCERTIFICATEFROMSTORE ) GetProcAddress( hCryptoAPI, "CertGetSubjectCertificateFromStore" );
pCertOpenStore = ( CERTOPENSTORE ) GetProcAddress( hCryptoAPI, "CertOpenStore" );
/* Make sure that we got valid pointers for every CryptoAPI function */
if( pCertAddEncodedCertificateToStore == NULL ||
pCertDeleteCertificateFromStore == NULL ||
pCertCloseStore == NULL || pCertFindCertificateInStore == NULL ||
pCertFreeCertificateContext == NULL ||
pCertGetSubjectCertificateFromStore == NULL || pCertOpenStore == NULL ||
pCryptAcquireContextA == NULL || pCryptDecrypt == NULL ||
pCryptEncrypt == NULL || pCryptExportKey == NULL ||
pCryptDestroyHash == NULL || pCryptDestroyKey == NULL ||
pCryptGenKey == NULL || pCryptGenRandom == NULL ||
pCryptGetProvParam == NULL || pCryptHashData == NULL ||
pCryptImportKey == NULL || pCryptReleaseContext == NULL ||
pCryptSetKeyParam == NULL )
{
/* Free the library reference and reset the handle */
FreeLibrary( hCryptoAPI );
hCryptoAPI = NULL_HINSTANCE;
return( CRYPT_ERROR );
}
return( CRYPT_OK );
}
void deviceEndCryptoAPI( void )
{
if( hCryptoAPI != NULL_HINSTANCE )
FreeLibrary( hCryptoAPI );
hCryptoAPI = NULL_HINSTANCE;
}
/****************************************************************************
* *
* Utility Routines *
* *
****************************************************************************/
/* Map a CryptoAPI-specific error to a cryptlib error */
static int mapError( CRYPTOAPI_INFO *cryptoapiInfo, const int defaultError )
{
const DWORD errorCode = GetLastError();
cryptoapiInfo->errorCode = ( int ) errorCode;
FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, errorCode, 0,
cryptoapiInfo->errorMessage, MAX_ERRMSG_SIZE - 1, 0 );
switch( errorCode )
{
case CRYPT_E_UNKNOWN_ALGO:
return( CRYPT_ERROR_NOTAVAIL );
case ERROR_BUSY:
return( CRYPT_ERROR_TIMEOUT );
case ERROR_MORE_DATA:
return( CRYPT_ERROR_OVERFLOW );
case ERROR_NO_MORE_ITEMS:
return( CRYPT_ERROR_COMPLETE );
case CRYPT_E_EXISTS:
case NTE_EXISTS:
return( CRYPT_ERROR_DUPLICATE );
case ERROR_NOT_ENOUGH_MEMORY:
case NTE_NO_MEMORY:
return( CRYPT_ERROR_MEMORY );
case CRYPT_E_SECURITY_SETTINGS:
case NTE_PERM:
return( CRYPT_ERROR_PERMISSION );
case NTE_BAD_SIGNATURE:
return( CRYPT_ERROR_SIGNATURE );
case CRYPT_E_NO_MATCH:
case CRYPT_E_NOT_FOUND:
case NTE_KEYSET_NOT_DEF:
case NTE_NOT_FOUND:
case NTE_PROV_DLL_NOT_FOUND:
case NTE_PROV_TYPE_NO_MATCH:
case NTE_PROV_TYPE_NOT_DEF:
return( CRYPT_ERROR_NOTFOUND );
}
return( defaultError );
}
static int mapDeviceError( CONTEXT_INFO *contextInfoPtr, const int defaultError )
{
CRYPT_DEVICE iCryptDevice;
DEVICE_INFO *deviceInfo;
int status;
/* Get the device associated with this context, set the error information
in it, and exit */
status = krnlSendMessage( contextInfoPtr->objectHandle, IMESSAGE_GETDEPENDENT,
&iCryptDevice, OBJECT_TYPE_DEVICE );
if( cryptStatusOK( status ) )
status = krnlGetObject( iCryptDevice, OBJECT_TYPE_DEVICE,
( void ** ) &deviceInfo,
CRYPT_ERROR_SIGNALLED );
if( cryptStatusError( status ) )
return( status );
status = mapError( deviceInfo->deviceCryptoAPI, defaultError );
krnlReleaseObject( deviceInfo->objectHandle );
return( status );
}
/* Create the special-case RSA key with e=1 needed to allow direct key
import and export */
static int createExportKey( const HCRYPTPROV hProv, HCRYPTKEY *hPrivateKey,
int *privateKeySize )
{
BLOBHEADER *blobHeaderPtr;
RSAPUBKEY *pubKeyPtr;
BYTE keyBlob[ 1024 ], *keyBlobPtr;
int bitLen16, keyBlobLen = 1024, status;
/* Generate a private key and export it as a private key blob:
Ofs Value
0 PUBLICKEYSTRUC publickeystruc {
0 BYTE bType;
1 BYTE bVersion;
2 WORD reserved;
4 ALG_ID aiKeyAlg; }
8 RSAPUBKEY rsapubkey {
8 DWORD magic;
12 DWORD bitlen;
16 DWORD pubexp; }
20 BYTE modulus[ rsapubkey.bitlen / 8 ];
BYTE prime1[ rsapubkey.bitlen / 16 ];
BYTE prime2[ rsapubkey.bitlen / 16 ];
BYTE exponent1[ rsapubkey.bitlen / 16 ];
BYTE exponent2[ rsapubkey.bitlen / 16 ];
BYTE coefficient[ rsapubkey.bitlen / 16 ];
BYTE privateExponent[ rsapubkey.bitlen / 8 ]; */
if( !pCryptGenKey( hProv, AT_KEYEXCHANGE, CRYPT_EXPORTABLE, hPrivateKey ) || \
!pCryptExportKey( *hPrivateKey, 0, PRIVATEKEYBLOB, 0, keyBlob, &keyBlobLen ) || \
!pCryptDestroyKey( *hPrivateKey ) )
return( CRYPT_ERROR );
/* Perform a general sanity check on the returned data */
blobHeaderPtr = ( BLOBHEADER * ) keyBlob;
if( blobHeaderPtr->bType != PRIVATEKEYBLOB || \
blobHeaderPtr->bVersion != 2 || \
blobHeaderPtr->aiKeyAlg != CALG_RSA_KEYX )
{
pCryptDestroyKey( *hPrivateKey );
return( CRYPT_ERROR );
}
/* Set the public exponent to 1 (little-endian 32-bit value) and skip to
the private exponents */
pubKeyPtr = ( RSAPUBKEY * ) ( keyBlob + 8 );
bitLen16 = ( pubKeyPtr->bitlen / 16 );
pubKeyPtr->pubexp = 1;
keyBlobPtr = keyBlob + 20 + ( pubKeyPtr->bitlen / 8 ) + bitLen16 + bitLen16;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -