Can OpenSSL on Windows use the system certificate store?
Solution 1
I have done it earlier. Hope this helps, if this is exactly what you are looking for.
- Load your certificate (in
PCCERT_CONTEXT
structure) from Windows Cert store using Crypto APIs. - Get encrypted content of it in binary format as it is. [
PCCERT_CONTEXT->pbCertEncoded
]. - Parse this binary buffer into X509 certificate Object using OpenSSL's
d2i_X509()
method. - Get handle to OpenSSL's trust store using
SSL_CTX_get_cert_store()
method. - Load above parsed X509 certificate into this trust store using
X509_STORE_add_cert()
method. - You are done!
Solution 2
For those of you still struggling with this as I have been, here is a sample code to get you started:
#include <stdio.h>
#include <windows.h>
#include <wincrypt.h>
#include <cryptuiapi.h>
#include <iostream>
#include <tchar.h>
#include "openssl\x509.h"
#pragma comment (lib, "crypt32.lib")
#pragma comment (lib, "cryptui.lib")
#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
int main(void)
{
HCERTSTORE hStore;
PCCERT_CONTEXT pContext = NULL;
X509 *x509;
X509_STORE *store = X509_STORE_new();
hStore = CertOpenSystemStore(NULL, L"ROOT");
if (!hStore)
return 1;
while (pContext = CertEnumCertificatesInStore(hStore, pContext))
{
//uncomment the line below if you want to see the certificates as pop ups
//CryptUIDlgViewContext(CERT_STORE_CERTIFICATE_CONTEXT, pContext, NULL, NULL, 0, NULL);
x509 = NULL;
x509 = d2i_X509(NULL, (const unsigned char **)&pContext->pbCertEncoded, pContext->cbCertEncoded);
if (x509)
{
int i = X509_STORE_add_cert(store, x509);
if (i == 1)
std::cout << "certificate added" << std::endl;
X509_free(x509);
}
}
CertFreeCertificateContext(pContext);
CertCloseStore(hStore, 0);
system("pause");
return 0;
}
Solution 3
No. Not out of the box.
No it is not possible out of the box. It would require additional programming. With OpenSSL you have two (out of the box) options:
- Use OpenSSL's own cert store (it is a hierarchy of directories created by perl script provided with OpenSSL)
- Use only a certificate chain file created by you (it is a text file with all PEM-encoded certificates in a chain of trust). Creating such a file is easy (just appending it)
Solution 4
Yes
It is possible to use OpenSSL
for operation-as-usual, and use CryptoAPI
only for the certificate verification process. I see several threads around here on this topic, and most are tiptoed around/through.
With CryptoAPI
you have to:
-
decode
PEM
toDER
withCryptStringToBinary()
, -
create a
CERT_CONTEXT
object withCertCreateCertificateContext()
-
and verify the certificate in this form by well known/documented procedure. (For example here at ETutorials.)
For last step to work, you also need to initialize
HCERTSTORE
for one ofMY
,ROOT
,CA
system stores, or iterate through them... depending on the behavior you want.
Comments
-
dicroce almost 2 years
Some working C++ code that I'm porting from Linux to Windows is failing on windows because
SSL_get_verify_result()
is returningX509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
.The code was using
SSL_CTX_set_default_verify_paths()
on Linux to tell SSL to just look in the standard default locations for the certificate store.Is it possible to get OpenSSL to use the system certificate store?
-
dicroce over 12 yearsMight it be possible to create a PEM file in memory from the windows pkcs files? Then load that? I found: marc.info/?l=openssl-users&m=119583966725315 which describes creating a PEM file from the pkcs packages... And stackoverflow.com/questions/5052563/… describes a mechanism of load a PEM file from a buffer... ?
-
sirgeorge over 12 yearsYes, that is certainly possible.
-
dicroce over 12 yearsYuck... For some reason, it doesn't like my file (made with the code from that page)... I would have thought someone before me would have done this?
-
dicroce over 11 yearsI'm curious if you can comment on the recent solution from @Tushar Sudake... Do you think still this is not possible with OpenSSL?
-
sirgeorge over 11 yearsYes, I think that might work. Besides, he wrote that he already did it and it worked. When I wrote that it is impossible I meant 'impossible directly' (e.g. OpenSSL using directly certificates from Windows).
-
Non-maskable Interrupt almost 8 yearsThanks for the info. I should add a few note on this: 1. enum windows's store with "ROOT" (not "CA"). 2. You need to add the cert before connect/handshake, and verify after connect/handshake, otherwise verification will fail.
-
herolover over 6 yearsYour usage of
d2i_X509
is invalid becaused2i_X509
increments*in
argument(you use the cast to avoid compiler error). You must use a temp variable to avoid memory issues, like this:const unsigned char *encoded_cert = win_cert_context->pbCertEncoded; d2i_X509(nullptr, &encoded_cert, ...
-
Tanz87 almost 5 years
pContext
will be NULL by the time it is passed toCertFreeCertificateContext()
(because thewhile
-loop does not break early), making that call unnecessary. -
RCECoder over 3 yearsProblem with this method is that it only verifies the intermediate certificate. It does not verify if your intermediate certificate is not directly trusted but rather their root is trusted. How can we verify that if the root is trusted but not the intermediate certificate?
-
Adam D. Ruppe about 2 yearsThis actually helped me a lot, with this patch here: github.com/adamdruppe/arsd/commit/… my thing seems to work pretty reliably to agree with the browsers on certificates.