Re: problem signing CMC request with Enrollment Agent certificate

From: Tory Eneboe (tjeneboe_at_blah.com)
Date: 06/10/04

  • Next message: Mr.Prakash: "Re: Install that important pack"
    Date: Wed, 9 Jun 2004 15:02:05 -0700
    
    

    Thank you both for your help! Using your tips, I was able to get the
    enrollment agent working, and have included my signing code below. Other
    things I did that are not included in the code below were:
    1) Added the following statement:
    XEnroll.AddNameValuePairToSignature("RequesterName","SOMEDOMAIN\\SOMEUSERACC
    OUNT");
    before calling XEnroll.CreateRequest to create the orignal CMC request.
    2) Changed the certificate template definition so that the "Issuance
    Requirements" required an authorized signature from a Certificate Request
    Agent.

    Tory.

    #include "stdafx.h"
    #include <stdio.h>
    #include <stdlib.h>
    #include <windows.h>

    #define _WIN32_WINNT 0x0400
    #include <wincrypt.h>

    #define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)

    int main(int argc, char* argv[])
    {

    // --------------------------------------------------------------------
    // Declare and initialize variables.

     // This is the CMC request that will be signed by the enrollment agent.
     // You must add the following:
     //
    XEnroll.AddNameValuePairToSignature("RequesterName","SOMEDOMAIN\\SOMEUSERACC
    OUNT");
     // Before calling the:
     // XEnroll.CreateRequest
     // method to create the CMC request.
     char base64CMCBeforeData[] = "PutYourCMCRequestTextHere";
     HCERTSTORE hMyCertStore;
     PCCERT_CONTEXT pSignerCertContext = NULL;
     HCRYPTMSG hMsg;
     CERT_BLOB CertBlob;
     DWORD HashAlgSize;
     CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm;
     HCRYPTPROV hCSP;
     DWORD dwKeySpec;
     CMSG_SIGNER_ENCODE_INFO SignerEncodeInfo;
     DWORD notused1, notused2;
     DWORD binaryCMCBeforeSize;
     BYTE* binaryCMCBeforeData;
     DWORD binaryCMCAfterSize;
     BYTE* binaryCMCAfterData;
     // The following is the OID for an enrollment agent cert.
     LPSTR pszOIDs[1]={szOID_ENROLLMENT_AGENT};
     CERT_ENHKEY_USAGE stCertUsage = {1,pszOIDs};

    //-------------------------------------------------------------------
    // Open the certificate store to be searched.

     if (hMyCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM,
      0,
      NULL,
      CERT_SYSTEM_STORE_CURRENT_USER,
      L"MY" ))
     {
      printf("CertOpenSystemStore was successful.\n");
     }
     else
     {
      fprintf(stderr, "Error number for the following error is 0x%x\n",
    GetLastError());
      fprintf(stderr, "CertOpenSystemStore FAILED.\n");
      exit(1);
     }

    //-------------------------------------------------------------------
    // Search by enhanced key usage to find the certificate that is the
    enrollment agent cert.

     if(pSignerCertContext = CertFindCertificateInStore(
      hMyCertStore,
      MY_ENCODING_TYPE,
      0,
      CERT_FIND_ENHKEY_USAGE,
      &stCertUsage,
      NULL))
     {
      printf("CertFindCertificateInStore was successful.\n");
     }
     else
     {
      fprintf(stderr, "Error number for the following error is 0x%x\n",
    GetLastError());
      fprintf(stderr, "CertFindCertificateInStore FAILED.\n");
      exit(1);
     }

    //-------------------------------------------------------------------
    // Get a handle to the message.

     if (hMsg = CryptMsgOpenToDecode(MY_ENCODING_TYPE, 0, 0, NULL, NULL, NULL))
     {
      printf("CryptMsgOpenToDecode was successful.\n");
     }
     else
     {
      fprintf(stderr, "Error number for the following error is 0x%x\n",
    GetLastError());
      fprintf(stderr, "CryptMsgOpenToDecode FAILED.\n");
      exit(1);
     }

    //-------------------------------------------------------------------
    // Convert the CMC from a BASE64 encoding to a binary blob.

     CryptStringToBinary(base64CMCBeforeData, 0, CRYPT_STRING_BASE64, NULL,
    &binaryCMCBeforeSize, &notused1, &notused2);
     binaryCMCBeforeData = (BYTE*) malloc(sizeof(BYTE)*binaryCMCBeforeSize);
     CryptStringToBinary(base64CMCBeforeData, 0, CRYPT_STRING_BASE64,
    binaryCMCBeforeData, &binaryCMCBeforeSize, &notused1, &notused2);

    //-------------------------------------------------------------------
    // Update the message.

     if(CryptMsgUpdate(hMsg, binaryCMCBeforeData, binaryCMCBeforeSize, TRUE))
     {
      printf("CryptMsgUpdate was successful.\n");
     }
     else
     {
      fprintf(stderr, "Error number for the following error is 0x%x\n",
    GetLastError());
      fprintf(stderr, "CryptMsgUpdate FAILED.\n");
      exit(1);
     }

    //--------------------------------------------------------------------
    // Initialize the CRYPT_ALGORITHM_IDENTIFIER structure.

     HashAlgSize = sizeof(HashAlgorithm);
     memset(&HashAlgorithm, 0, HashAlgSize); // Initialize to zero,
     HashAlgorithm.pszObjId = szOID_RSA_MD5; // then set the
               // necessary member.

    //--------------------------------------------------------------------
    // Get the Cryptographic Service Provider and KeySpec of the enrollment
    agent cert.

     if(CryptAcquireCertificatePrivateKey(
      pSignerCertContext,
            0,
            NULL,
            &hCSP,
            &dwKeySpec,
            NULL))
     {
      printf("CryptAcquireCertificatePrivateKey was successful.\n");
     }
     else
     {
      fprintf(stderr, "Error number for the following error is 0x%x\n",
    GetLastError());
      fprintf(stderr, "CryptAcquireCertificatePrivateKey FAILED.\n");
      exit(1);
     }

    //--------------------------------------------------------------------
    // Initialize the CMSG_SIGNER_ENCODE_INFO structure.

     memset(&SignerEncodeInfo, 0, sizeof(CMSG_SIGNER_ENCODE_INFO));
     SignerEncodeInfo.cbSize = sizeof(CMSG_SIGNER_ENCODE_INFO);
     SignerEncodeInfo.pCertInfo = pSignerCertContext->pCertInfo;
     SignerEncodeInfo.hCryptProv = hCSP;
     SignerEncodeInfo.dwKeySpec = dwKeySpec;
     SignerEncodeInfo.HashAlgorithm = HashAlgorithm;
     SignerEncodeInfo.pvHashAuxInfo = NULL;

    //--------------------------------------------------------------------
    // Initialize SignedEncodeInfo with the enrollment agent certificate info.

     if(CryptMsgControl(hMsg, 0, CMSG_CTRL_ADD_SIGNER, &SignerEncodeInfo))
     {
      printf("CryptMsgControl was successful.\n");
     }
     else
     {
      fprintf(stderr, "Error number for the following error is 0x%x\n",
    GetLastError());
      fprintf(stderr, "CryptMsgControl FAILED.\n");
      exit(1);
     }

    //--------------------------------------------------------------------
    // Initialize the CertBlob structure.

        CertBlob.cbData = pSignerCertContext->cbCertEncoded;
        CertBlob.pbData = pSignerCertContext->pbCertEncoded;

    //--------------------------------------------------------------------
    // Add the signing cert.

     if (CryptMsgControl(hMsg, 0, CMSG_CTRL_ADD_CERT, &CertBlob))
     {
      printf("CryptMsgControl was successful.\n");
     }
     else
     {
      fprintf(stderr, "Error number for the following error is 0x%x\n",
    GetLastError());
      fprintf(stderr, "CryptMsgControl FAILED.\n");
      exit(1);
     }

    //--------------------------------------------------------------------
    // Get the size of the new CMC request.

     if (CryptMsgGetParam(hMsg, CMSG_ENCODED_MESSAGE, 0, NULL,
    &binaryCMCAfterSize))
     {
      printf("CryptMsgGetParam was successful.\n");
     }
     else
     {
      fprintf(stderr, "Error number for the following error is 0x%x\n",
    GetLastError());
      fprintf(stderr, "CryptMsgGetParam FAILED.\n");
      exit(1);
     }

    //--------------------------------------------------------------------
    // Get back the new CMC request.

     binaryCMCAfterData = (BYTE*) malloc(sizeof(BYTE)*binaryCMCAfterSize);
     if (CryptMsgGetParam(hMsg, CMSG_ENCODED_MESSAGE, 0, binaryCMCAfterData,
    &binaryCMCAfterSize))
     {
      printf("CryptMsgGetParam was successful.\n");
     }
     else
     {
      fprintf(stderr, "Error number for the following error is 0x%x\n",
    GetLastError());
      fprintf(stderr, "CryptMsgGetParam FAILED.\n");
      exit(1);
     }

    //--------------------------------------------------------------------
    // Convert the new CMC request from a binary blob to BASE64 encoded.

     DWORD base64CMCAfterSize;
     CryptBinaryToString(binaryCMCAfterData, binaryCMCAfterSize,
    CRYPT_STRING_BASE64HEADER, NULL, &base64CMCAfterSize);
     LPSTR base64CMCAfterData = new char[base64CMCAfterSize];
     CryptBinaryToString(binaryCMCAfterData, binaryCMCAfterSize,
    CRYPT_STRING_BASE64HEADER, base64CMCAfterData, &base64CMCAfterSize);

    //--------------------------------------------------------------------
    // Print the new CMC request.

     printf("The signed request is as follows->\n%s\n",base64CMCAfterData);

    //-------------------------------------------------------------------
    // Clean up.

     if(pSignerCertContext)
      CertFreeCertificateContext(pSignerCertContext);
     if(hMyCertStore)
      CertCloseStore(
       hMyCertStore,
       CERT_CLOSE_STORE_CHECK_FLAG);

     return 0;
    }

    "Tory Eneboe" <tjeneboe@blah.com> wrote in message
    news:OyiMgOpSEHA.3692@TK2MSFTNGP10.phx.gbl...
    > I am trying to use an Enrollment Agent to request certificates on behalf
    of
    > other users. The process I am using is a follows:
    >
    > 1) Issue myself an Enrollment Agent certificate.
    > 2) Create a CMC Request using XEnroll. I set the following XEnroll
    > attribute before calling the XEnroll method that actually creates the
    > request:
    >
    >
    XEnroll.AddNameValuePairToSignature("RequesterName","somedomain\someaccount"
    > );
    > 3) Use the C++ Crypto library to sign the CMC request with the Enrollment
    > Agent cert.
    > 4) Submit the resulting request (PKCS7?) to the CA for processing.
    >
    > I am stuck on step #3. I have included my code below. When my code runs,
    > it fails on the following line:
    > CryptMsgUpdate(hMsg, pbCMCOld, cbCMCOld, TRUE);
    > with the all to common error:
    > 0x8009310B ASN1 bad tag value met
    >
    > Does anyone have any ideas on what I'm doing wrong? Any help would be
    > greatly appreciated! Thanks. Tory.
    >
    > --------------------------------------------------------------------------

    --
    > -----------------
    >
    > // Variable Declaration.
    > HCERTSTORE  hSystemStore;
    > PCCERT_CONTEXT  pSignerCertContext = NULL;
    > HCRYPTMSG hMsg;
    > CERT_BLOB CertBlob;
    >
    > // Here is the original CMC request that XEnroll created for us.
    > BYTE* pbCMCOld = (BYTE*) "-----BEGIN NEW CERTIFICATE
    >
    REQUEST-----MIIFYgYJKoZIhvcNAQcCoIIFUzCCBU8CAQMxCzAJBgUrDgMCGgUAMIID6QYIKwYB
    >
    BQUHDAKgggPbBIID1zCCA9MwgYswWgIBAgYIKwYBBQUHBwgxSzBJAgEAMAMCAQEwPzA9BgkrBgEE
    >
    AYI3FQcEMDAuBiYrBgEEAYI3FQiD1a5UhM74P4b5mwCBjtsFgu2mGRmHr8sohI3MAwIBZAIBCDAt
    >
    AgEDBggrBgEFBQcHEjEeBBxSZXF1ZXN0ZXJOYW1lPUFNUlZNZG5pc2VuYm8mMIIDPaCCAzkCAQEw
    >
    ggMyMIICmwIBADAAMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7t/O9owY88S9FLh7x60b+
    >
    eVO9i3hAg2+t6DoQH/Bs3+WFbwGqEemjRecOY5ZcDe/aGUgfPi3KXOPplQW9tRSAAAo7HZLfscK8
    >
    AdqHUnFD8Vs8XX4up/R/ri0AA8ERuI8a1XGkco/BXgiyVZwC2INNB7Oy9JxDHFuT7TgxCs/saQID
    >
    AQABoIIB8DAaBgorBgEEAYI3DQIDMQwWCjUuMS4yNjAwLjIwUQYJKwYBBAGCNxUUMUQwQgIBAQwh
    >
    dGplbmVib2UtbW9ibDIuYW1yLmNvcnAuaW50ZWwuY29tDAxBTVJcdGplbmVib2UMDGlleHBsb3Jl
    >
    LmV4ZTB9BgkqhkiG9w0BCQ4xcDBuMA4GA1UdDwEB/wQEAwIGwDAdBgNVHQ4EFgQUtuxBrb5BNS7L
    >
    C2IveU0bCZB3lPEwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIg9WuVITO+D+G+ZsAgY7bBYLt
    >
    phkZh6/LKISNzAMCAWQCAQgwgf8GCisGAQQBgjcNAgIxgfAwge0CAQIeXABNAGkAYwByAG8AcwBv
    >
    AGYAdAAgAEUAbgBoAGEAbgBjAGUAZAAgAEMAcgB5AHAAdABvAGcAcgBhAHAAaABpAGMAIABQAHIA
    >
    bwB2AGkAZABlAHIAIAB2ADEALgAwA4GJAJ/4RhOTTKR5uxCCU3ASuY9IBYt2B8iM0dt4ceNEw6Mr
    >
    xUMBbRUbwtOqKT/1PEOK+uEtanHaJv+Xp1hZc9jbjVPnJTq/IRbVGxy89x6D3j6SCvBw0LWaEXlE
    >
    f9aqTXBNzSWDnzo8WTAD0AUkGxl0XiR2fnaPyzkUSGYZhEXYCLANAAAAAAAAAAAwDQYJKoZIhvcN
    >
    AQEFBQADgYEAVHNVdSiXYYpUjfQVEaS+y0E/+3qoWZDtR4j738nAKZs8SD6BYHYQZLw/6mxm2i4S
    >
    RzEj0/68SK39SDgmG3jgV/XJ9it859U1vhFj8oDC/TQWMea3AdzNSQjGqvd0FgMt/dUnIudBvYC9
    >
    /txVmSfEpFNuFe36LPhvD4rFeGviZuQwADAAMYIBTjCCAUoCAQOAFLbsQa2+QTUuywtiL3lNGwmQ
    >
    d5TxMAkGBSsOAwIaBQCggZEwFwYJKoZIhvcNAQkDMQoGCCsGAQUFBwwCMCMGCSqGSIb3DQEJBDEW
    >
    BBSq7MOc4L0MvMljm+6UleKODeqwHjBRBgkrBgEEAYI3FRQxRDBCAgEBDCF0amVuZWJvZS1tb2Js
    >
    Mi5hbXIuY29ycC5pbnRlbC5jb20MDEFNUlx0amVuZWJvZQwMaWV4cGxvcmUuZXhlMA0GCSqGSIb3
    >
    DQEBAQUABIGAgXx/K6iziKUqiXe5VDxe1DdLHqDla+Cn3irH3qSpfHNZKz50rASfQ4meH+KnZB9l
    >
    0nIbLlEgA4GzBrYiMh6Gp4U4CU7OL5JS5rZMUzHYTvU/A9LJ072PxJU+5K6qczuhVhCrd7GKjowt
    > X3tECtAZI37ww4TxQ3ZoHHtrlhydUK4=-----END NEW CERTIFICATE REQUEST-----";
    > DWORD cbCMCOld = strlen((char *) pbCMCOld)+1;
    >
    > // Open the certificate store to be searched.
    > hSystemStore = CertOpenSystemStore(0, "MY");
    >
    > // Since the only cert in my personal store is the
    > // enrollment agent cert, finding the first cert in
    > // the store (CERT_FIND_ANY) works just fine.
    > pSignerCertContext=CertFindCertificateInStore(hSystemStore,
    > MY_ENCODING_TYPE, 0, CERT_FIND_ANY, NULL, NULL);
    >
    > CryptMsgOpenToDecode(MY_ENCODING_TYPE, 0, 0, NULL, NULL, NULL);
    >
    > // >>>>>> This line is where it fails. <<<<<
    > CryptMsgUpdate(hMsg, pbCMCOld, cbCMCOld, TRUE);
    >
    > // Initialize SignedEncodeInfo with the enrollment agent certificate info
    > CryptMsgControl(hMsg, 0, CMSG_CTRL_ADD_SIGNER,
    > pSignerCertContext->pCertInfo);
    >
    > // Add the signing cert.
    > CertBlob.cbData = pSignerCertContext->cbCertEncoded;
    > CertBlob.pbData = pSignerCertContext->pbCertEncoded;
    > CryptMsgControl(hMsg, 0, CMSG_CTRL_ADD_CERT, &CertBlob);
    >
    > // Get the size of the new CMC.
    > DWORD cbCMCNew;
    > CryptMsgGetParam(hMsg, CMSG_ENCODED_MESSAGE, 0, NULL, &cbCMCNew);
    >
    > // Get the new CMC.
    > BYTE* pbCMCNew = (BYTE*) malloc(sizeof(BYTE)*cbCMCNew);
    > CryptMsgGetParam(hMsg, CMSG_ENCODED_MESSAGE, 0, pbCMCNew, &cbCMCNew);
    >
    > // Submit the new CMC to the CA for processing.
    >
    >
    

  • Next message: Mr.Prakash: "Re: Install that important pack"
  • Quantcast