Certificate Enrollment API Adventures

IX509PrivateKey::Export exports key data from COM object, MSDN:

strExportType [in]

A BSTR value that specifies how the private key is exported.

If the key was created by using a CNG KSP (Key Storage Provider), you can specify one of the values allowed by the pszBlobType parameter in the NCryptExportKey function.

If the key was created by using a CryptoAPI CSP (Cryptographic Service Provider), you can specify one of the following values from the Bcrypt.h header file included with Wincrypt.h.
BCRYPT_PUBLIC_KEY_BLOB – Exports only the public portion of the private key.
BCRYPT_
PRIVATE_KEY_BLOB – Exports the entire private key.

Well this is actually accurate, however trying to make it…

CComPtr<IX509PrivateKey> pPrivateKey;
// ...
CComBSTR sPublicKeyBlob, sPrivateKeyBlob;
ATLENSURE_SUCCEEDED(pPrivateKey->Export(BCRYPT_PUBLIC_KEY_BLOB, XCN_CRYPT_STRING_BASE64, &sPublicKeyBlob));
ATLENSURE_SUCCEEDED(pPrivateKey->Export(BCRYPT_PRIVATE_KEY_BLOB, XCN_CRYPT_STRING_BASE64, &sPrivateKeyBlob));

… the both calls result in E_POINTER (0x80004003). The first argument is not just LPCWSTR. It has to be BSTR and the API is checking the length of the value using SysStringLen. One has to wrap the argument to provide it as BSTR:

CComPtr<IX509PrivateKey> pPrivateKey;
// ...
CComBSTR sPublicKeyBlob, sPrivateKeyBlob;
ATLENSURE_SUCCEEDED(pPrivateKey->Export(CComBSTR(BCRYPT_PUBLIC_KEY_BLOB), XCN_CRYPT_STRING_BASE64, &sPublicKeyBlob));
ATLENSURE_SUCCEEDED(pPrivateKey->Export(CComBSTR(BCRYPT_PRIVATE_KEY_BLOB), XCN_CRYPT_STRING_BASE64, &sPrivateKeyBlob));

Another problem is related to IObjectId::InitializeFromAlgorithmName.

strAlgorithmName [in]

A BSTR variable that contains the name. You can specify a name, or an OID in dotted decimal format. The method verifies that the format is consistent with the ASN.1 X.208 standard. For more information about CNG algorithm names, see CNG Algorithm Identifiers.

MSDN offers choices to provide a string or OID. Unfortunately, OID does not work and fails on internal argument validation with E_INVALIDARG (0x80070057).

ATLENSURE_SUCCEEDED(pObjectId->InitializeFromAlgorithmName(XCN_CRYPT_HASH_ALG_OID_GROUP_ID, 
    XCN_CRYPT_OID_INFO_PUBKEY_ANY, AlgorithmFlagsNone, 
        CComBSTR(L"SHA256"))); //CComBSTR(szOID_RSA_SHA256RSA)));

Leave a Reply