/* 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

Topic revision: r1 - 18 Dec 2001 - MattWalsh
 
This site is powered by the TWiki collaboration platformCopyright © 2008-2012 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback