/* Notes:
*
* 1) Your project's include directories must include the Platform SDK
* include directory.
*
* 2) You must link against 'crypt32.lib', also in from the Platform SDK
*
*/
#include "stdafx.h"
/* Function to dump out a useful string from error codes returned
* by the Windows 'GetLastError()'. Stolen from a MSDN example.
*/
void dumpErrorMessage(DWORD errorCode)
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
errorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL);
printf("%s", lpMsgBuf);
}
void parseKeyValues(BYTE* data)
{
BYTE* ptrNow = data;
BLOBHEADER* blobheader;
RSAPUBKEY* rsapubkey;
DWORD bitLength;
DWORD publicExponent;
BYTE modulus[1024/8];
BYTE p_prime[1024/16];
BYTE q_prime[1024/16];
BYTE exponent1[1024/16];
BYTE exponent2[1024/16];
BYTE coefficient[1024/16];
BYTE privateExponent[1024/8];
blobheader = (BLOBHEADER *)ptrNow;
ptrNow += sizeof(BLOBHEADER);
rsapubkey = (RSAPUBKEY *)ptrNow;
ptrNow += sizeof(RSAPUBKEY);
bitLength = rsapubkey->bitlen;
publicExponent = rsapubkey->pubexp;
printf("b/l = %i pubExp = 0x%x ", bitLength, publicExponent);
/*
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];
*/
}
/* Main()
*
*/
int main(int argc, char* argv[])
{
//@ First, becaue M$ provides no easy way to do this, we go
//@ straight to the registry to figure out for ourselves what
//@ keys are installed
LONG result;
HKEY returnedKey;
result = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\SystemCertificates\\My",
// subkey
0, // reserved
KEY_READ, // security access mask
&returnedKey // handle to open key
);
if (result != ERROR_SUCCESS)
{ dumpErrorMessage(result);
return 1;
}
printf("Successfully opened registry key\n");
//@ Now, becaue M$ provides no easy way to do this, we FORCE
//@ it to recognize the system certs that IIS uses by sticking
//@ its nose right in the registry and telling it to open it
HCERTSTORE hSysStore;
hSysStore = CertOpenStore(
CERT_STORE_PROV_REG, // The store provider type.
0, // The encoding type is not needed from registry
NULL, // Use the default HCRYPTPROV.
CERT_STORE_OPEN_EXISTING_FLAG,
returnedKey
);
if (hSysStore == 0)
{ printf("Failure calling 'CertOpenStore()' - can't access certs in registry\n");
return 1;
}
printf("Successfully accessed system cert store\n");
//@ Next we walk through the certs one by one.
//@
//@
PCCERT_CONTEXT pCertContext=NULL;
char pszNameString[256];
DWORD cbData;
CRYPT_KEY_PROV_INFO *pCryptKeyProvInfo;
while(pCertContext= CertEnumCertificatesInStore(
hSysStore,
pCertContext))
{
//@ Though not necessary, we parse out the name of the cert
//@ for possible debugging/diagnostic purposes
if(!CertGetNameString(
pCertContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
0,
NULL,
pszNameString,
128))
{
printf("Parsing certificate '???'...",pszNameString);
}
else
{ printf("Parsing certificate '%s'...",pszNameString);
}
//@ Now we try and get the container name. First see if
//@ we can get the 'CERT_KEY_PROV_INFO_PROP_ID' property.
//@ At the same time, see how many bytes we need for the
//@ struct. This technique was largely based on a
//@ MSDN example.
if (!CertGetCertificateContextProperty(
pCertContext,
CERT_KEY_PROV_INFO_PROP_ID,
NULL, // NULL on the first call to get the
// length.
&cbData)) // The number of bytes that must be
// allocated for the structure.
{
printf("FAILED! cert doesn't have provider info property!\n");
}
else
{ pCryptKeyProvInfo = (CRYPT_KEY_PROV_INFO *)malloc(cbData);
if(pCryptKeyProvInfo == NULL)
{ printf("Can't allocate memory for CRYPT_KEY_PROV_INFO stuct\n");
return 1;
}
//@ We can now really get the information for the
//@ 'CERT_KEY_PROV_INFO_PROP_ID' property.
if(!CertGetCertificateContextProperty(
pCertContext,
CERT_KEY_PROV_INFO_PROP_ID,
pCryptKeyProvInfo,
&cbData))
{
//@ this should never happen!
printf("FAILED! somehow can't read provider info property!\n");
}
else
{
LPCTSTR test2 = (LPCTSTR)pCryptKeyProvInfo->pwszContainerName;
char out[2000];
if (!WideCharToMultiByte(
CP_ACP,
0,
pCryptKeyProvInfo->pwszContainerName,
-1,
out,
2000,
NULL,
NULL))
{
printf("Can't convert key container from unicode.\n", out);
dumpErrorMessage(GetLastError());
}
else
{
//@ Now, since we know the container name we can get
//@ a context to the CSP provider !FOR THIS KEY!
HCRYPTPROV hProv;
if (!CryptAcquireContext(
&hProv,
out,
"Microsoft RSA SChannel Cryptographic Provider",
PROV_RSA_SCHANNEL,
CRYPT_MACHINE_KEYSET))
{
printf("FAILED! Can't get handle to CSP for this key!\n");
dumpErrorMessage(GetLastError());
}
else
{ HCRYPTKEY phUserKey;
if (!CryptGetUserKey(
hProv,
AT_KEYEXCHANGE,
&phUserKey))
{
printf("FAILED! Can't get user key!\n");
dumpErrorMessage(GetLastError());
}
else
{
BYTE data[2000];
DWORD dataLen = 2000;
if (!CryptExportKey(
phUserKey,
0,
PRIVATEKEYBLOB,
0,
data,
&dataLen))
{
printf("FAILED! Can't export user key! %i\n", dataLen);
dumpErrorMessage(GetLastError());
//printf("Hot darn!");
}
else
{
parseKeyValues(data);
printf("OK!\n");
}
}
}
}
}
}
}
/*
HCRYPTPROV hProv; // handle to the provider returned by CryptoAPI
if (!CryptAcquireContext(
&hProv,
NULL,
// "Microsoft Internet Information Server",
"Microsoft RSA SChannel Cryptographic Provider", // provider
PROV_RSA_SCHANNEL,
// CRYPT_MACHINE_KEYSET ))
CRYPT_MACHINE_KEYSET | CRYPT_VERIFYCONTEXT))
{
// Bail
printf("Can't get handle to SCHannel CSP: \n ");
dumpErrorMessage(GetLastError());
printf("\n");
return 1;
}
printf("SCHannel CSP Opened OK!\n");
BYTE rcvdData[2000];
DWORD rcvdDataLen;
HCRYPTKEY phUserKey;
// Walk through the key containers
if(!CryptGetProvParam(
hProv,
PP_ENUMCONTAINERS,
rcvdData,
&rcvdDataLen,
CRYPT_FIRST))
{
printf("Can't get provider container name: ");
dumpErrorMessage(GetLastError());
return 1;
}
printf("Container: %s\n", rcvdData);
while(CryptGetProvParam(
hProv,
PP_ENUMCONTAINERS,
rcvdData,
&rcvdDataLen,
0))
{
printf("Container: %s\n", rcvdData);
/*if (!CryptAcquireContext(
&hProv,
(const char*) rcvdData,
"Microsoft RSA SChannel Cryptographic Provider", // provider
PROV_RSA_SCHANNEL,
CRYPT_MACHINE_KEYSET ))
//CRYPT_MACHINE_KEYSET | CRYPT_VERIFYCONTEXT))
{
// Bail
printf("Can't get handle to SCHannel CSP: \n ");
dumpErrorMessage(GetLastError());
printf("\n");
//return 1;
}
}
if (!CryptGetUserKey(
hProv,
AT_KEYEXCHANGE,
&phUserKey))
{
// Bail
printf("Can't get handle to User Key: \n ");
dumpErrorMessage(GetLastError());
printf("\n");
//return 1;
}
printf("User Key accessed OK!");
BYTE data[2000];
DWORD dataDW;
DWORD dataLen;
if (!CryptExportKey(
phUserKey,
0,
PRIVATEKEYBLOB,
0,
data,
&dataLen))
{
// Bail
printf("Can't export User Key: \n ");
dumpErrorMessage(GetLastError());
printf("\n");
//return 1;
}
printf("User Key exported OK!");
//*/
/* if (CryptAcquireContext(
&phProv,
"2a9238e4a2c9ad3b4224fd6bc4be5de8_52402037-ca58-4653-8549-5d3a8d8121e2",
//"1c147ff611891d95ed67debc8b9e0051_52402037-ca58-4653-8549-5d3a8d8121e2",
"Microsoft RSA SChannel Cryptographic Provider", // provider
PROV_RSA_SCHANNEL,// PROV_RSA_FULL,
CRYPT_MACHINE_KEYSET))
{
*/
return 0;
}
--
MattWalsh - 18 Dec 2001