PKCS#7 request

  • Thread starter Thread starter suscripciones1
  • Start date Start date
S

suscripciones1

I'd like renew client certificates in a standalone CA.
I try to create a pkcs7 request but if fails.

DN = "C=" + Country + ";S=" + State + ";L=" + Locality + ";O=" + Org +
";OU=" + OrgUnit +";CN=" + Nombre + ";Email=" + Email +";T="+"CIF-KM";
IControl.ProviderName = "Microsoft Base Cryptographic Provider
v1.0";
IControl.ProviderType = 1;
IControl.HashAlgorithm = "SHA1";
IControl.GenKeyFlags = 1;
//IControl.UseExistingKeySet = true;
voids "1.3.6.1.5.5.7.3.2";
//,1.3.6.1.5.5.7.3.4,1.3.6.1.5.5.7.3.3,1.3.6.1.5.5.7.3.8";
stringPKCS7=IControl.createRequest(2,DN,voids);

I'd like use the existing keys but it fails too.

Someone can help me , please?
It's very important.
thanks
 
Here is an example from an upcoming MSDN article:

Creating a Renewal Request

It is sometimes necessary to renew an existing certificate as the
certificate may be near expiry. In order to renew a certificate, the renewal
request is signed by a valid existing certificate. The renewal may reuse the
key pair from an existing certificate or may create a new key pair.

The CertOpenStore function is first used to open the certificate store. The
CertFindCertificateInStore function is then be used to search for an
existing certificate that is to be renewed. Typically the store would be
searched looking for certificates that are nearly expired.

After a certificate has been found for renewal, the certificate template
information needs to be obtained to pass in the renewal request. The
CertFindExtension function is called to get a pointer to the V1 or V2
template extension. The template OID or name is decoded using the
CryptDecodeObjectEx function and is then passed when calling the
AddCertTypeToRequestWStr method. The put_RenewalCertificate method call is
the then used to set the renewal certificate for the request.

The code to generate this request is as shown below in C++,

HCERTSTORE hCertStore = NULL;

PCCERT_CONTEXT pEnrollmentCert = NULL;

LPSTR pszOID = "1.3.6.1.4.1.311.10.3.4";

CERT_ENHKEY_USAGE stCertUsage = {1, &pszOID};

LPWSTR TemplateName = NULL;

LPWSTR AllocatedTemplateName = NULL;

CERT_TEMPLATE_EXT* TemplateExt = NULL;

DWORD TemplateExtSiz = 0;

CERT_NAME_VALUE* TemplateExtName = NULL;

DWORD TemplateExtNameSiz = 0;

hCertStore = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
0,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER,
L"MY" );

pEnrollmentCert = CertFindCertificateInStore(
hCertStore,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
0,
CERT_FIND_ENHKEY_USAGE,
&stCertUsage,
NULL );

PCERT_EXTENSION ext = CertFindExtension(
szOID_CERTIFICATE_TEMPLATE,
pEnrollmentCert->pCertInfo->cExtension,
pEnrollmentCert->pCertInfo->rgExtension );

if ( !ext )

{

ext = CertFindExtension(
szOID_ENROLL_CERTTYPE_EXTENSION,
pEnrollmentCert->pCertInfo->cExtension,
pEnrollmentCert->pCertInfo->rgExtension );

CryptDecodeObjectEx(
(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING),
X509_UNICODE_NAME_VALUE,
ext->Value.pbData,
ext->Value.cbData,
CRYPT_DECODE_ALLOC_FLAG,
NULL,
&TemplateExtName,
&TemplateExtNameSiz );

TemplateName = (LPWSTR) TemplateExtName->Value.pbData;

}

else

{

CryptDecodeObjectEx(
(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING),
X509_CERTIFICATE_TEMPLATE,
ext->Value.pbData,
ext->Value.cbData,
CRYPT_DECODE_ALLOC_FLAG,
NULL,
&TemplateExt,
&TemplateExtSiz );

int tmplen = MultiByteToWideChar(
CP_THREAD_ACP, 0, TemplateExt->pszObjId, -1, NULL, 0 );

AllocatedTemplateName = (LPWSTR) LocalAlloc( LPTR,
sizeof(WCHAR) * tmplen );

MultiByteToWideChar( CP_THREAD_ACP, 0,
TemplateExt->pszObjId, -1, AllocatedTemplateName, tmplen );

TemplateName = AllocatedTemplateName;

}

hr=CertEnroll->AddCertTypeToRequestWStr( TemplateName );

hr=CertEnroll->put_RenewalCertificate( pEnrollmentCert );

If the renewal is to re-use an existing key pair then it will be necessary
to call the method put_UseExistingKeySet to make sure the existing key set
is re-used. The provider name and key set name will also need to be set.
These can be obtained from the renewal certificate context by calling
CertGetCertificateContextProperty and then calling methods
put_RenewalCertificate, put_ProviderNameWStr and put_KeySpec.

The code for doing this is as shown below in C++,

CRYPT_KEY_PROV_INFO* ProvInfo = NULL;

DWORD ProvInfoSiz = 0;

CertGetCertificateContextProperty(
pEnrollmentCert,
CERT_KEY_PROV_INFO_PROP_ID,
NULL,
&ProvInfoSiz );

ProvInfo = (CRYPT_KEY_PROV_INFO*) LocalAlloc( LPTR, ProvInfoSiz );

CertGetCertificateContextProperty(
pEnrollmentCert,
CERT_KEY_PROV_INFO_PROP_ID,
ProvInfo,
&ProvInfoSiz );

hr=CertEnroll->put_UseExistingKeySet( TRUE );

hr=CertEnroll->put_ProviderNameWStr(ProvInfo->pwszProvName);

hr=CertEnroll->put_ContainerNameWStr(ProvInfo->pwszContainerName);

hr=CertEnroll->put_KeySpec( ProvInfo->dwKeySpec );
 
0x80090016 Keyset does not exist

Hi all,
This is the code i am using in trying to renew an email certificate.
It fails on creating the request blob:

hr=CertEnroll->createRequestWStr( dwCreateFlags, wszEntityDN, L"", &MyBlob );

giving the error "0x80090016 Keyset does not exist". Can someone please help in pinpointing what it is that i am doing wrong! I find the correct certificate and everything is ok until that point. I need to use the existing keyset.

here comes the code:


#include "stdafx.h"
#include <windows.h>
#include <Xenroll.h>

static DWORD dwProviderType = PROV_RSA_FULL;
static DWORD dwKeyLength = 1024;
static DWORD dwGenKeyFlags = ( dwKeyLength << 16 ) | CRYPT_EXPORTABLE;
static LPCWSTR wszEntityDN = NULL;
static LPCWSTR wszTemplateName = L"MyEFS";

// EKU OIDs : EFS
//static LPSTR szstrCertUsage = "1.3.6.1.4.1.311.10.3.4";
static LPSTR szstrCertUsage = "1.3.6.1.5.5.7.3.4";
static LPCWSTR szReqB64FileName = L"CertRequest.B64";
static LPCTSTR szReqBinaryFileName = _T( "CertRequest.BIN" );
static DWORD dwCreateFlags = XECR_CMC;

static BOOL WriteRequestFile( LPCTSTR Filename, CRYPT_DATA_BLOB* data );

int _tmain(int argc, _TCHAR* argv[])
{
HRESULT hr;
IEnroll4* CertEnroll = NULL;
CRYPT_DATA_BLOB MyBlob = { 0, NULL };
LPWSTR OutputString = NULL;
HCERTSTORE hCertStore = NULL;
PCCERT_CONTEXT pEnrollmentCert = NULL; // Set to NULL for the first call to CertFindCertificateInStore
CERT_ENHKEY_USAGE stCertUsage = {1, &szstrCertUsage };
CRYPT_KEY_PROV_INFO* ProvInfo = NULL;
DWORD ProvInfoSiz = 0;
CRYPT_DATA_BLOB MyB64Blob = { 0, NULL };
LPWSTR TemplateName = NULL;
LPWSTR AllocatedTemplateName = NULL;
CERT_TEMPLATE_EXT* TemplateExt = NULL;
DWORD TemplateExtSiz = 0;
CERT_NAME_VALUE* TemplateExtName = NULL;
DWORD TemplateExtNameSiz = 0;

hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (FAILED(hr))
{
wprintf( L"CoInitializeEx failed: 0x%x\n", hr);
goto error;
}

hr = CoCreateInstance(CLSID_CEnroll,
NULL,
CLSCTX_INPROC_SERVER,
IID_IEnroll4,
(void **)&CertEnroll);
if (FAILED(hr))
{
wprintf( L"CoCreateInstance failed: 0x%x\n", hr);
goto error;
}

// We now need to get the enrollment agent certificate
hCertStore = CertOpenStore(
CERT_STORE_PROV_SYSTEM, // The store provider type.
0, // The encoding type is not needed.
NULL, // Use the default HCRYPTPROV.
CERT_SYSTEM_STORE_CURRENT_USER,
// Set the store location in a
// registry location.
L"MY" // The store name as a Unicode string.
);
if(!hCertStore)
{
hr=HRESULT_FROM_WIN32(GetLastError());
wprintf( L"CertOpenStore failed: 0x%x\n", hr );
goto error;
}


// Look for a cert to renew with the required OID
// For a typical certificate renewal a certificate would be selected that is near expiry.
if((pEnrollmentCert=CertFindCertificateInStore(
hCertStore,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
0, // No dwFlags needed.
CERT_FIND_ENHKEY_USAGE,
&stCertUsage,
NULL)) == NULL)
{
hr=HRESULT_FROM_WIN32(GetLastError());
wprintf( L"Find Renewal Certifcate : CertFindCertificateInStore( ... ) failed: 0x%x\n", hr );
goto error;
}



// We get a ptr to the V2 Certificate Template Extension
PCERT_EXTENSION ext = CertFindExtension(
szOID_CERTIFICATE_TEMPLATE,
pEnrollmentCert->pCertInfo->cExtension,
pEnrollmentCert->pCertInfo->rgExtension );
if ( !ext )
{
// If there is no V2 Template Extension, look for the V1 template extension.
ext = CertFindExtension(
szOID_ENROLL_CERTTYPE_EXTENSION,
pEnrollmentCert->pCertInfo->cExtension,
pEnrollmentCert->pCertInfo->rgExtension );
if ( !ext )
{
hr=HRESULT_FROM_WIN32(GetLastError());
wprintf( L"CertFindExtension( ... ) failed: 0x%x\n", hr );
goto error;
}


// The V1 Template Extension is a string.
if ( !CryptDecodeObjectEx(
(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING),
X509_UNICODE_NAME_VALUE,
ext->Value.pbData,
ext->Value.cbData,
CRYPT_DECODE_ALLOC_FLAG,
NULL,
&TemplateExtName,
&TemplateExtNameSiz ))
{
hr=HRESULT_FROM_WIN32(GetLastError());
wprintf( L"Template Extension : CryptDecodeObjectEx( ... ) failed: 0x%x\n", hr );
goto error;
}

TemplateName = (LPWSTR) TemplateExtName->Value.pbData;
}
else
{
// The V2 Template extension has major/minor version numbers and an OID.
if ( !CryptDecodeObjectEx(
(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING),
X509_CERTIFICATE_TEMPLATE,
ext->Value.pbData,
ext->Value.cbData,
CRYPT_DECODE_ALLOC_FLAG,
NULL,
&TemplateExt,
&TemplateExtSiz ))
{
hr=HRESULT_FROM_WIN32(GetLastError());
wprintf( L"Template Extension : CryptDecodeObjectEx( ... ) failed: 0x%x\n", hr );
goto error;
}

// Convert the ASCII OID to Unicode
int tmplen = MultiByteToWideChar( CP_THREAD_ACP, 0, TemplateExt->pszObjId, -1, NULL, 0 );
if ( !tmplen )
{
hr=HRESULT_FROM_WIN32(GetLastError());
wprintf( L"MultiByteToWideChar( ... ) failed: 0x%x\n", hr );
goto error;
}

AllocatedTemplateName = (LPWSTR) LocalAlloc( LPTR, sizeof(WCHAR) * tmplen );
if ( !AllocatedTemplateName )
{
hr=HRESULT_FROM_WIN32(GetLastError());
wprintf( L"LocalAlloc( ... ) failed: 0x%x\n", hr );
goto error;
}

tmplen = MultiByteToWideChar( CP_THREAD_ACP, 0, TemplateExt->pszObjId, -1, AllocatedTemplateName, tmplen );
if ( !tmplen )
{
hr=HRESULT_FROM_WIN32(GetLastError());
wprintf( L"MultiByteToWideChar( ... ) failed: 0x%x\n", hr );
goto error;
}

TemplateName = AllocatedTemplateName;
}


// Add the certificate template name - this has to match to renew.
hr = CertEnroll->AddCertTypeToRequestWStr(TemplateName);
if (FAILED(hr))
{
wprintf(L"CertEnroll->AddCertTypeToRequestWStr(..) failed: 0x%x\n", hr);
goto error;
}


// Get the Key information for the certificate
if ( !CertGetCertificateContextProperty(
pEnrollmentCert,
CERT_KEY_PROV_INFO_PROP_ID,
NULL,
&ProvInfoSiz))
{
hr=HRESULT_FROM_WIN32(GetLastError());
wprintf( L"CertGetCertificateContextProperty() failed: 0x%x\n", hr );
goto error;
}


ProvInfo = (CRYPT_KEY_PROV_INFO*) LocalAlloc( LPTR, ProvInfoSiz );
if ( !ProvInfo )
{
hr=HRESULT_FROM_WIN32(GetLastError());
wprintf( L"LocalAlloc() failed: 0x%x\n", hr );
goto error;
}


if ( !CertGetCertificateContextProperty(
pEnrollmentCert,
CERT_KEY_PROV_INFO_PROP_ID,
ProvInfo,
&ProvInfoSiz))
{
hr=HRESULT_FROM_WIN32(GetLastError());
wprintf( L"CertGetCertificateContextProperty() failed: 0x%x\n", hr );
goto error;
}



// Now add the renewal certificate to the request.
hr=CertEnroll->put_RenewalCertificate( pEnrollmentCert );
if(FAILED(hr))
{
wprintf( L"CertEnroll->put_RenewalCertificate( ... ) failed: 0x%x\n", hr );
goto error;
}



// Renew with existing key
hr=CertEnroll->put_UseExistingKeySet( TRUE );
if (FAILED(hr))
{
hr=HRESULT_FROM_WIN32(GetLastError());
wprintf( L"put_UseExistingKeySet() failed: 0x%x\n", hr );
goto error;
}


// Set the CSP name from the existing key
hr = CertEnroll->put_ProviderNameWStr(ProvInfo->pwszProvName);
if (FAILED(hr))
{
wprintf( L"CertEnroll->put_ProviderNameWStr() failed: 0x%x\n", hr);
goto error;
}


// Set the container name for the existing key.
hr=CertEnroll->put_ContainerNameWStr(ProvInfo->pwszContainerName);
if (FAILED(hr))
{
hr=HRESULT_FROM_WIN32(GetLastError());
wprintf( L"put_ContainerNameWStr() failed: 0x%x\n", hr );
goto error;
}


// Ste the key spec for the renewal.
hr=CertEnroll->put_KeySpec( ProvInfo->dwKeySpec );
if(FAILED(hr))
{
wprintf(L"CertEnroll->put_KeySpec() failed: 0x%x\n", hr);
goto error;
}



// Set ProviderType if default is not OK
hr=CertEnroll->put_ProviderType( dwProviderType );
if(FAILED(hr))
{
wprintf(L"CertEnroll->put_ProviderType( %d ) failed: 0x%x\n", dwProviderType, hr);
goto error;
}



hr = CertEnroll->put_EnableSMIMECapabilities( TRUE );
if(FAILED(hr))
{
wprintf( L"CertEnroll->put_EnableSMIMECapabilities( FALSE ) failed: 0x%x\n", hr );
goto error;
}


// Create the request blob
hr=CertEnroll->createRequestWStr( dwCreateFlags, wszEntityDN, L"", &MyBlob );
if(FAILED(hr))
{
wprintf( L"CertEnroll->createRequestWStr( ... ) failed: 0x%x\n", hr );
goto error;
}


// Write the blob to a file
if ( !WriteRequestFile( szReqBinaryFileName, &MyBlob ))
{
hr=HRESULT_FROM_WIN32(GetLastError());
wprintf( L"WriteRequestFile() failed: 0x%x\n", hr );
goto error;
}


hr=CertEnroll->binaryBlobToString( CRYPT_STRING_BASE64REQUESTHEADER, &MyBlob, &OutputString );
if(FAILED(hr))
{
wprintf( L"CertEnroll->binaryBlobToString( ... ) failed: 0x%x\n", hr );
goto error;
}


MyB64Blob.cbData = WideCharToMultiByte( CP_THREAD_ACP, 0, OutputString, -1, NULL, 0, NULL, NULL );
MyB64Blob.pbData = (BYTE*) LocalAlloc( LPTR, MyB64Blob.cbData );
WideCharToMultiByte( CP_THREAD_ACP, 0, OutputString, -1, (LPSTR) MyB64Blob.pbData, MyB64Blob.cbData, NULL, NULL );


// Write the Base 64 to a file
if ( !WriteRequestFile( szReqB64FileName, &MyB64Blob ))
{
hr=HRESULT_FROM_WIN32(GetLastError());
wprintf( L"WriteRequestFile() failed: 0x%x\n", hr );
goto error;
}

hr = 0;

error:


if ( NULL != AllocatedTemplateName )
LocalFree( AllocatedTemplateName );

if ( NULL != TemplateExtName )
LocalFree( TemplateExtName );

if ( NULL != MyB64Blob.pbData )
LocalFree( MyB64Blob.pbData );

if ( NULL != pEnrollmentCert )
CertFreeCertificateContext( pEnrollmentCert );

if ( NULL != hCertStore )
CertCloseStore( hCertStore, 0 );

if ( NULL != CertEnroll )
CertEnroll->Release();

if ( NULL != MyBlob.pbData )
LocalFree( MyBlob.pbData );

if ( NULL != OutputString )
LocalFree( OutputString );

// Free COM resources.
CoUninitialize();


return hr;
}



BOOL WriteRequestFile( LPCTSTR Filename, CRYPT_DATA_BLOB* data )
{
DWORD numbytes = 0;

HANDLE fh = CreateFile(
Filename,
FILE_WRITE_DATA,
0,
NULL,
CREATE_ALWAYS,
0,
NULL );
if ( fh == INVALID_HANDLE_VALUE )
{
return FALSE;
}

WriteFile( fh, data->pbData, data->cbData, &numbytes, NULL );

CloseHandle( fh );

return TRUE;
}
 
P.s. i have tried using a PKCS#7 request too (dwCreateFlags = XECR_PKCS7) and still the same result.
 
Back
Top