none
PFXImportCertStore doesnt import all linked certificates in the certification paths RRS feed

  • Question

  • Problem Statement :

    1. We have created a user certificate using the radius server page using steps specified in the user manual link below

    https://networklessons.com/uncategorized/peap-and-eap-tls-on-server-2008-and-cisco-wlc/#Installing-Active-Directory

    We have checked below options so that the private key and the cert chain(Root CA certificate) is also exported along with the user certificate in a single PFC File.

    - Select Yes, export the private key.

    - Select the checkbox of “Include all certificates in the certification path if possible” under “Personal Information Exchange – PKCS #12 (.PFX)”. click on Next to continue.

    2. We imported this PFX File to the windows CE 7 device(say Device1).The connection attempt to the WPA2 Enterprise network with TLS and validate server using this certificate is Passed.

    3. Now we exported the certificate from the Device1 to a PFX File(Exported.pfx) from the MY Store.

    4. I Imported this new Exported.pfx file to another Device2. Connection attempt to the WPA2 Enterprise network with TLS and validate server using this certificate failed on Device 2.However without Validate server option it works.

    Background : Further investigation shows that the root certificate was not installed under the root store of the Device 2 which is why connection attempt failed in step 4. It shows error message "The server certificate is issue by an unknown authority.

    Please help me resolve this issue ASAP.

    Sample code used for Certificates export and Import.

    //This function exports all the user certificates from the "MY" certificate store along with the provate keys

    //to a pfx file specified by the filepath.It overwrites the file if file with the same name already exists.


    HRESULT CertificateHandler::ExportCertificate(__in LPCTSTR filePath, __in LPCTSTR passwd)

    {

    HRESULT hr = S_OK;

    CRYPT_DATA_BLOB pfxBlob;

    HCERTSTORE hCertStore = NULL;

    DWORD numberOfBytesWritten = 0;

    HANDLE hCertFile = NULL;

    hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W, CRYPT_ASN_ENCODING,

                            0, CERT_SYSTEM_STORE_CURRENT_USER, L"MY");

    CBREx((hCertStore != NULL), GetLastError());

    CBREx(TRUE == PFXExportCertStoreEx(hCertStore, &pfxBlob, passwd, NULL, EXPORT_PRIVATE_KEYS | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY | REPORT_NO_PRIVATE_KEY ), GetLastError());

    if(pfxBlob.cbData > 0)

    {

    //create file


    hCertFile = ::CreateFile( filePath, GENERIC_WRITE,

    NULL , 0,CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0 );

    if( INVALID_HANDLE_VALUE == hCertFile )

    {

    hr = GetLastError();

    RETAILMSG(1, (_T("ExportCertificate ERROR: Filed to create the file.error code : %u\r\n"), hr));

    goto Error;

    }

    //write to file


    CBREx((0 !=  ::WriteFile( hCertFile, &pfxBlob.pbData[0], pfxBlob.cbData, &numberOfBytesWritten, NULL)), GetLastError());

    }

    Error:

    if (hCertStore)

    {

    CertCloseStore(hCertStore, 0);

    }

    //close the file handle


    if(hCertFile)

    {

    ::CloseHandle(hCertFile);

    }

    return hr;

    }

    HRESULT CertificateHandler::ImportCertificate(__in LPCTSTR filePath, __in LPCTSTR passwd)

    {

    HRESULT hr = S_OK;

    int rc = 0;

    DWORD byte_count = 0;

    DWORD byt_cnt = 0;

    unsigned char *blob_buf = NULL;

    CRYPT_DATA_BLOB pfxBlob;

    DWORD read_count = 0;

    HCERTSTORE hCertStore = NULL;

    HCERTSTORE hRootStore = NULL;//Static Analysis


    PBYTE pbCert=0;

    BSTR localToStore;

    HANDLE certfileHandle;

    HCERTSTORE myStore = 0;

    HCERTSTORE rootStore = 0;

    HCERTSTORE CAStore = 0;

    HCERTSTORE thisCertStore = 0;

    PCCERT_CONTEXT pctx = NULL;

    wchar_t filepathvar[MAX_PATH] = L"";

    //OPEN FILE


    certfileHandle = ::CreateFile( filePath, GENERIC_READ,

                        FILE_SHARE_READ | FILE_SHARE_WRITE, 0,OPEN_EXISTING,

                        FILE_ATTRIBUTE_NORMAL, 0 );

    if( INVALID_HANDLE_VALUE == certfileHandle )

    {

    hr = GetLastError();

    RETAILMSG(1, (_T("PFX_import ERROR: blob buffer was not read correctly!ErrorCode: %u\r\n"),hr));

    goto Error;

    }

    byte_count = ::GetFileSize( certfileHandle, NULL );

    if(INVALID_FILE_SIZE  == byte_count)

    {

    hr = GetLastError();

    RETAILMSG( TRUE, ( _T( "CertificateHandler::ImportCertificate() ErrorCode: %d \r\n" ),

                hr));

    goto Error;

    }

    blob_buf = (unsigned char *)malloc(byte_count);

    CPR(blob_buf);

    ::SetFilePointer( certfileHandle, 0, 0, FILE_BEGIN );

    if( !::ReadFile( certfileHandle, blob_buf, byte_count, &read_count, 0 ))

        {

    hr = GetLastError();

            RETAILMSG( TRUE, ( _T( "CertificateHandler::ImportCertificate():%d \r\n" ), hr));

    goto Error;

        }

    CloseHandle(certfileHandle);

    certfileHandle = NULL;

    pfxBlob.cbData = byte_count;

    pfxBlob.pbData = blob_buf;

    //ASSIGN Localtostore


    wcscpy(filepathvar,  filePath);

    wchar_t * wstr = wcstok(filepathvar,L".");

    while (wstr != NULL)

      {

    if((! (wcscmp(wstr, L"CER"))) || (! (wcscmp(wstr, L"cer"))) )// This logic needs to changed as .pfx can also be a ROOT certificate.


    {

    localToStore = L"CER";

    }

    else


    {

    localToStore = L"PFX";

    }

    wstr = wcstok (NULL,L".");

       

      }

    if((L"PFX") == localToStore)

    {

    wchar_t name[128] = _T("");

    CBREx((PFXIsPFXBlob(&pfxBlob) == TRUE), E_INVALIDPFX);

    CBREx((PFXVerifyPassword(&pfxBlob, passwd, 0) == TRUE), GetLastError()); //returns 86 on error


    hCertStore = PFXImportCertStore(&pfxBlob, passwd, CRYPT_EXPORTABLE | PKCS12_ALLOW_OVERWRITE_KEY | PKCS12_INCLUDE_EXTENDED_PROPERTIES);

    CBREx((NULL != hCertStore), GetLastError());

    //////////////////////////Added for SFM-5201 starts////////////////////


    myStore = CertOpenStore( CERT_STORE_PROV_SYSTEM,

    0,

    0,

    CERT_SYSTEM_STORE_CURRENT_USER,

    L"MY");

    CBREx((NULL != myStore), GetLastError());

    rootStore = CertOpenStore( CERT_STORE_PROV_SYSTEM,

    0,

    0,

    CERT_SYSTEM_STORE_LOCAL_MACHINE,

    L"Root");

    CBREx((NULL != rootStore), GetLastError());

    CAStore = CertOpenStore( CERT_STORE_PROV_SYSTEM,

    0,

    0,

    CERT_SYSTEM_STORE_LOCAL_MACHINE,

    L"CA");

    CBREx((NULL != CAStore), GetLastError());

    // We assume there are zero or more certificates. If a certificate has the


    // "CA:TRUE" basic contraint (X.509) it will be added to the CA store,


    // unless it is also self-signed, then it will be added to the Root store.


    // All other certificates are considered personal and are added to the MY store.


    while (0 != (pctx = CertEnumCertificatesInStore(hCertStore, pctx)))

    {

    if (CertIsCACert(pctx) == TRUE)

    {

    if (CACertIsSelfsigned(pctx) == TRUE)

    {

    thisCertStore = rootStore;

    }

    else


    {

    thisCertStore = CAStore;

    }

    }

    else

    {

    thisCertStore = myStore;

    }

    // This code is not working currectly.


    //https://security.stackexchange.com/questions/116503/why-the-private-key-is-not-present-for-the-certificate-retrieved-from-the-person


    //need to be fixed as per above reference.


    //Though the private key import is happening successfully the private key is not entering under enroll container name.


    PCCERT_CONTEXT pUsrAuthCertContext = CertCreateCertificateContext(X509_ASN_ENCODING,

    pctx->pbCertEncoded, pctx->cbCertEncoded );

    if(pUsrAuthCertContext)

    {

    void* pvData;

    DWORD cbData;

    //get the private key structure from the cert imported to tempstore


    if(CertGetCertificateContextProperty( pctx, CERT_KEY_PROV_INFO_PROP_ID, pvData, &cbData))

    {

    if(pvData)

    {

    CRYPT_KEY_PROV_INFO *keyInfo = (CRYPT_KEY_PROV_INFO *)pvData;

    //set the private key structure


    CertSetCertificateContextProperty(pUsrAuthCertContext,

    CERT_KEY_PROV_INFO_PROP_ID,

    cbData,

    keyInfo);

    //add the new cert context to cert store.


    CBREx((TRUE == CertAddCertificateContextToStore(thisCertStore,pUsrAuthCertContext,// pctx,


    CERT_STORE_ADD_REPLACE_EXISTING, 0)), GetLastError());

    }

    }

    else


    {

    CBREx((TRUE == CertAddCertificateContextToStore(thisCertStore, pctx,

    CERT_STORE_ADD_REPLACE_EXISTING, 0)), GetLastError());

    }

    if(pUsrAuthCertContext)

    {

    CertFreeCertificateContext(pUsrAuthCertContext);

    pUsrAuthCertContext = NULL;

    }

    }

    else


    {

    CBREx((TRUE == CertAddCertificateContextToStore(thisCertStore, pctx,

    CERT_STORE_ADD_REPLACE_EXISTING, 0)), GetLastError());

    }

    }

    }

    else if((L"CER") == localToStore)

    {

    hRootStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0,

                                NULL, CERT_SYSTEM_STORE_LOCAL_MACHINE, L"ROOT");

    CBREx((NULL != hRootStore), GetLastError());

    pbCert = ReadBase64Cert(blob_buf,byte_count, &byte_count);

    //not Base64 certificate.Take the original data read from the file.


    if(!pbCert)

    {

    pbCert = blob_buf;

    }

    BOOL bResult = CertAddEncodedCertificateToStore(

      hRootStore,

      X509_ASN_ENCODING,

      pbCert,

      byte_count,

      CERT_STORE_ADD_REPLACE_EXISTING,

      0

    );

    CBREx((TRUE == bResult), GetLastError());

    }

    Error:

    if (hCertStore)

    {

    CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);

    }

    if(blob_buf)

    {

    free(blob_buf);

    }

    if(certfileHandle)

    {

    CloseHandle(certfileHandle);

    }

    if (hRootStore)

    {

    CertCloseStore(hRootStore, CERT_CLOSE_STORE_FORCE_FLAG);

    }

    if (myStore)

    {

    CertCloseStore(myStore, 0);

    }

    if (rootStore)

    {

    CertCloseStore(rootStore, 0);

    }

    if (CAStore)

    {

    CertCloseStore(CAStore, 0);

    }

    if (pctx)

    {

    CertFreeCertificateContext(pctx);

    }

    return hr;

    }

     

    Monday, September 3, 2018 12:08 PM