Search code examples
c++windowscryptoapicertificate-store

How to get the public key from a certificate in windows system certstore


I have added a certificate to the system store with something like this:

PCCERT_CONTEXT pCertContext;
HCERTSTORE hCertStore;
CRYPT_KEY_PROV_INFO provInfo;

if (pCertContext = CertCreateCertificateContext(MY_ENCODING_TYPE, certDER, certSize)) {
    provInfo.pwszContainerName = idCert;
    provInfo.pwszProvName = provName;
    provInfo.dwProvType = provType;
    provInfo.dwFlags = 0;
    provInfo.cProvParam = 0;
    provInfo.rgProvParam = NULL;
    provInfo.dwKeySpec = AT_SIGNATURE;

    if (!CertSetCertificateContextProperty(pCertContext, CERT_KEY_PROV_INFO_PROP_ID, 0, &provInfo)) Error(TEXT("CertSetCertificateContextProperty"));

    if (!(hCertStore = CertOpenSystemStore(NULL, L"MY"))) Error(TEXT("CertOpenSystemStore"));
    if (!CertAddCertificateContextToStore(hCertStore, pCertContext, CERT_STORE_ADD_REPLACE_EXISTING, NULL)) Error(TEXT("CertAddCertificateContextToStore"));
    CertFreeCertificateContext(pCertContext);
} else Error(TEXT("CertCreateCertificateContext"));

Now I'm making a Cryptographyc Service Provider and need to get the public key from this certificate to implement the CPExportKey() function.

Is this possible? If it is, how can I do it?

Also, if someone could point me at a kind of guide, or howto, of CSP drivers implementation it would be great! I'm having a bad time searching documentation for these things.


Solution

  • So I found the solution below. With all non-essential for understanding code omitted.

    Iterate through the certificates in the store and through its properties to find my certificate, then use the CryptDecodeObjectEx() function to convert the key to the RSA_CSP_PUBLICKEYBLOB format.

    The key is kept at this location pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData and its size at pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData.

    HCERTSTORE hCertStore = NULL;
    PCCERT_CONTEXT pCertContext = NULL;
    PBYTE pbPKEY = NULL;
    DWORD iPKEYSize;
    
    hCertStore = CertOpenSystemStore(NULL, L"MY");
    
    while(pCertContext = CertEnumCertificatesInStore(
        hCertStore,
        pCertContext))
    {
        DWORD dwPropId = 0;
        while(dwPropId = CertEnumCertificateContextProperties(
            pCertContext, // The context whose properties are to be listed.
            dwPropId))    // Number of the last property found.  
        {
            // ...
            // here I compare the properties to see if it is the certificate that I want.
            // ...
            CryptDecodeObjectEx((PKCS_7_ASN_ENCODING | X509_ASN_ENCODING), 
                RSA_CSP_PUBLICKEYBLOB, 
                pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData, 
                pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData, 
                CRYPT_ENCODE_ALLOC_FLAG, 
                NULL, 
                &pbPKEY, 
                &iPKEYSize);
    
                // pbData and pcbDataLen are output parameters of the function
                *pcbDataLen = iPKEYSize;
                memcpy(pbData, pbPKEY, *pcbDataLen);
                LocalFree((HANDLE)pbPKEY);
            }
        }
    }