Re: problem signing CMC request with Enrollment Agent certificate
From: Tory Eneboe (tjeneboe_at_blah.com)
Date: 06/10/04
- Previous message: Pavel Lebedinsky: "Re: Adding a Privilege via LsaAddAccountRights()"
- In reply to: Tory Eneboe: "problem signing CMC request with Enrollment Agent certificate"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]
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, ¬used1, ¬used2);
binaryCMCBeforeData = (BYTE*) malloc(sizeof(BYTE)*binaryCMCBeforeSize);
CryptStringToBinary(base64CMCBeforeData, 0, CRYPT_STRING_BASE64,
binaryCMCBeforeData, &binaryCMCBeforeSize, ¬used1, ¬used2);
//-------------------------------------------------------------------
// 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. > >
- Previous message: Pavel Lebedinsky: "Re: Adding a Privilege via LsaAddAccountRights()"
- In reply to: Tory Eneboe: "problem signing CMC request with Enrollment Agent certificate"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]