Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Using certificate and private key from Windows cert store with OpenSSL

909 views
Skip to first unread message

Andrejs Å trumfs

unread,
Oct 28, 2011, 3:48:45 AM10/28/11
to

Hi!

I am trying to make a program, that uses some Web Services in Delphi XE. To connect to the Web Services, i have to use self signed (hope this is correct term) certificate, which is stored in Windows cert store. So, i open the cert store with CertOpenSystemStore, get cert with CertFindCertificateInStore and set it with SSL_CTX_use_certificate. No problem with this. Then i get the public key blob with CryptExportKey and make up a private key like this:

function PrivKeyBlob2RSA(const AKeyBlob: PByte; const ALength: Integer; const ASSLCtx: PSSL_CTX): IdSSLOpenSSLHeaders.PEVP_PKEY;
var
  modulus: PByte;
  bh: PBLOBHEADER;
  rp: PRSAPUBKEY;
  rsa_modlen: DWORD;
  rsa_modulus: PAnsiChar;
  rkey: PRSA;
begin
  bh := PBLOBHEADER(AKeyBlob);
  Assert(bh^.bType = PUBLICKEYBLOB);
  rp := PRSAPUBKEY(AKeyBlob + 8);
  Assert(rp.magic = $31415352);
  rsa_modulus := PAnsiChar(Integer(Pointer(rp))+12);
  rkey := RSA_new_method(ASSLCtx.client_cert_engine);
  rkey^.References := 1;
  rkey^.e := BN_new;
  rkey^.n := BN_new;
  BN_set_word(rkey^.e, rp^.pubexp);
  rsa_modlen := (rp^.bitlen div 8) + 1;
  modulus := AllocMem(rsa_modlen);
  CopyMemory(modulus, rsa_modulus, rsa_modlen);
  RevBuffer(modulus, rsa_modlen);
  BN_bin2bn(modulus, rsa_modlen, rkey^.n);
  Result := EVP_PKEY_new;
  EVP_PKEY_assign_RSA(Result, PAnsiChar(rkey));
end;

and set it up with SSL_CTX_use_PrivateKey and SSL_CTX_check_private_key. Also, no problem so far. But then, when data transfer begins, i get access violation in libeay32.dll - Access violation at address 09881C5F in module 'libeay32.dll'. Read of address 00000000. If i load the key from .pem file, everything is fine.

The libeay32.dll version is 1.0.0.5. Tried with version 0.9.something too - got the same error, just different address.

Below is the RSA structure i get in PrivKeyBlob2RSA:

pad    0
version  0
meth       $898030C
engine     nil
n      $A62D508
e      $A62D4D8
d      nil
p      nil
q      nil
dmp1       nil
dmq1       nil
iqmp       nil
ex_data (nil, -1163005939 {$BAADF00D})
references  1
flags      6
_method_mod_n   nil
_method_mod_p   nil
_method_mod_q   nil
bignum_data nil {#0}
blinding    nil
mt_blinding nil

I checked the n and e bignums, and they are CORRECT, and everything else looks ok. The error happens when calling function ssl_read. I can't see what i am doing wrong, please help :)

Thanks

 

Andrejs

Jakob Bohm

unread,
Oct 28, 2011, 9:06:32 AM10/28/11
to
Simple, really:

You have not set the "private" part of the private key (d, p, q, dmp1,
dmq1, iqmp).

You need to export the private key from CryptoAPI too, and convert that
blob,
not the public key blob.

Alternatively, I have heard rumors of a "CryptoAPI engine" plug in for
OpenSSL
which will let OpenSSL directly use the keys and certificates stored by
Windows.
______________________________________________________________________
OpenSSL Project http://www.openssl.org
User Support Mailing List openss...@openssl.org
Automated List Manager majo...@openssl.org

Andrejs Å trumfs

unread,
Oct 29, 2011, 2:21:58 AM10/29/11
to
Duh... I was sure these were the needed parts. Now, I tried to call CryptExportKey with PRIVATEKEYBLOB flag, and of course it returned error, because the certificate was imported to store without Mark as Exportable option. But there has to be way to use certificate and private key somehow with OpenSSL? I'm really beginner with this certificate thing, maybe I just don't understand something? :)

Jakob Bohm

unread,
Oct 31, 2011, 4:44:11 AM10/31/11
to
In that case look for the CryptoAPI engine for openssl, not sure of its
official name though.

Sergio NNX

unread,
Oct 31, 2011, 5:02:30 AM10/31/11
to
Ciao Andrejs.

I don't know much about the source code you posted previously but if you build OpenSSL with the 'enable-capieng' option you'll be able to access every single store and all the certs stored in Windows.

I hope it helps.

Sergio.


> Date: Mon, 31 Oct 2011 09:44:11 +0100
> From: jb-op...@wisemo.com
> To: openss...@openssl.org
> Subject: Re: Using certificate and private key from Windows cert store with OpenSSL

Jakob Bohm

unread,
Oct 31, 2011, 5:28:07 AM10/31/11
to
Thanks, that was the option I was just suggesting, but I could not
remember the name.

Thanks for finding the name for me, hope it helps the OP.

On 10/31/2011 10:02 AM, Sergio NNX wrote:
> Ciao Andrejs.
>
> I don't know much about the source code you posted previously but if you build OpenSSL with the 'enable-capieng' option you'll be able to access every single store and all the certs stored in Windows.
>
> I hope it helps.
>
> Sergio.
>
>
>> Date: Mon, 31 Oct 2011 09:44:11 +0100
>> From: jb-op...@wisemo.com
>> To: openss...@openssl.org
>> Subject: Re: Using certificate and private key from Windows cert store with OpenSSL
>>
>> In that case look for the CryptoAPI engine for openssl, not sure of its
>> official name though.
>>

Vladimir Belov

unread,
Oct 31, 2011, 1:40:44 PM10/31/11
to
Sergio, how to set this option building OpenSSL? I didn't find any
suggestions in documentation. And can you give a link to the documentation
on the site openssl.org where there are functions of API to work with
Windows CERT Stores?


From: Sergio NNX
Sent: Monday, October 31, 2011 1:02 PM
To: openss...@openssl.org
Subject: RE: Using certificate and private key from Windows cert store with
OpenSSL
Ciao Andrejs.

I don't know much about the source code you posted previously but if you
build OpenSSL with the 'enable-capieng' option you'll be able to access
every single store and all the certs stored in Windows.

I hope it helps.

Sergio.




Sergio NNX

unread,
Oct 31, 2011, 3:12:57 PM10/31/11
to
Ciao.

I use MinGW to build OpenSSL and it has always worked very well.

Steps: a)  perl Configure mingw shared enable-capieng --prefix=/mingw --openssldir=C:/OpenSSL

          b) make

After a while, you'll have openssl.exe and a couple of DLLs. At this stage, you'll be able to access Windows Certificate store.

If you're using Windows boxes, I can send you my copy of OpenSSL for you to test.


I hope it helps.

Sergio.


Vladimir Belov

unread,
Nov 1, 2011, 11:03:29 AM11/1/11
to

Thanks, I understood that 'enable-capieng' option is a standard option for
Configure (enable/no).

Is this option only for openssl.exe? How will openssl.exe use Windows CERT
store? Automatically or there is a command of openssl.exe for this.

I asked about OpenSSLAPI functions, that will let me to use Windows CERT
store directly in my own program. Like X509_verify_cert for OpenSSL CERT
Store.

Or I must manually extract Certificate during handshake, transform it(if
necessary) and give it to WinAPI functions to next verifications of
certificate with CryptoAPI?


-------------------------------------------------------------------------------
From: Sergio NNX
Sent: Monday, October 31, 2011 11:12 PM

Jakob Bohm

unread,
Nov 1, 2011, 12:04:42 PM11/1/11
to
This option is for the OpenSSL API, and I sure hope it would work
with all the supported Windows Compilers, so you can use it with
the compiler needed by the rest of your project.

Once compiled in, your code will need to use some "engine API"
at your program startup to request use of that engine plug-in, after
which you should be able to use the Windows Certificate store
and contents directly.

Vladimir Belov

unread,
Nov 1, 2011, 1:26:19 PM11/1/11
to

How to use some "engine API" in my program? What is the name of this "some
engine API" or engine plug-in?

Please, give a small example or where can I find documentation about this?
Is any documentation on the openssl.org?

----------------------------------------------------------
From: Jakob Bohm
Sent: Tuesday, November 01, 2011 8:04 PM

Jakob Bohm

unread,
Nov 1, 2011, 1:30:28 PM11/1/11
to
I actually don't know, but try looking in the source code for the
openssl.exe
utility and look at what it does with the "engine" command line option.

Dr. Stephen Henson

unread,
Nov 1, 2011, 2:45:20 PM11/1/11
to
On Tue, Nov 01, 2011, Vladimir Belov wrote:

>
> How to use some "engine API" in my program? What is the name of
> this "some engine API" or engine plug-in?
>
> Please, give a small example or where can I find documentation about
> this? Is any documentation on the openssl.org?
>

Note that the ENGINE API currently only accesses keys and not
certificates. The CryptoAPI ENGINE can be used to redirect operations to
private keys stored on Windows.

Steve.
--
Dr Stephen N. Henson. OpenSSL project core developer.
Commercial tech support now available see: http://www.openssl.org

Vladimir Belov

unread,
Nov 1, 2011, 3:13:02 PM11/1/11
to
Thanks for answer, Stephen. Does it mean that if I want to perform
Certificate Verification with Windows CryptoAPI I must manually extract
certificate from handshake procedure or get it through callback function,
change its format (to be compatible with WinAPI functions) and give it to
WinAPI functions for next verifications of certificate with Windows
CryptoAPI?

> From: Dr. Stephen Henson
> Sent: Tuesday, November 01, 2011 10:45 PM
> To: openss...@openssl.org
> Subject: Re: Using certificate and private key from Windows cert store
> with OpenSSL

Jakob Bohm

unread,
Nov 1, 2011, 3:21:56 PM11/1/11
to
Or you could use CryptoAPI functions to get the certificates
(not private keys) from CryptoAPI and load them into OpenSSL.

Note that while your original post used the historic CryptoAPI specific
structures for bare RSA keys, which differ a lot from their OpenSSL
counterparts, the CryptoAPI certificate functions (CertXxx) tend to
provide and accept raw DER encoded certificate blobs, which can
also be handled by OpenSSL.

Andrejs Å trumfs

unread,
Nov 2, 2011, 4:06:48 AM11/2/11
to
Hi!

I searched a bit around and came up with this. I used v1.0.0.5 OpenSSL Dlls, but if you compile 0.9 with engine enabled, it should work.

function UsePKeyFromCapi(const ASSLCtx: PSSL_CTX; const ACert: PCCERT_CONTEXT): Boolean;
var
CapiEngine: PENGINE;
EngStatus: Integer;
ProvLen, ContNameLen: Integer;
ProvInfo: ^CRYPT_KEY_PROV_INFO;
ContName: PAnsiChar;
LKey: PEVP_PKEY;
begin
f_ENGINE_load_builtin_engines;
CapiEngine := f_ENGINE_by_id('dynamic');
Result := True;
ContNameLen := 0;
ProvLen := 0;
ProvInfo := nil;
ContName := nil;
LKey := nil;
try
if CapiEngine <> nil then
begin
EngStatus := f_ENGINE_ctrl_cmd_string(CapiEngine, 'SO_PATH', '.\capi.dll', 0);
if EngStatus > 0 then
EngStatus := f_ENGINE_ctrl_cmd_string(CapiEngine, 'LOAD', nil, 0);
if EngStatus > 0 then
EngStatus := f_ENGINE_init(CapiEngine);
if EngStatus > 0 then
f_ENGINE_register_all_complete;
if (EngStatus > 0) and CertGetCertificateContextProperty(ACert, CERT_KEY_PROV_INFO_PROP_ID, nil, @ProvLen) then
begin
ProvInfo := AllocMem(ProvLen);
if CertGetCertificateContextProperty(ACert, CERT_KEY_PROV_INFO_PROP_ID, ProvInfo, @ProvLen) then
begin
ContNameLen := LocaleCharsFromUnicode(DefaultSystemCodePage, 0, ProvInfo^.pwszContainerName, -1, nil, 0, nil, nil);
ContName := AllocMem(ContNameLen);
LocaleCharsFromUnicode(DefaultSystemCodePage, 0, ProvInfo^.pwszContainerName, -1, ContName, ContNameLen, nil, nil)
end;
if f_ENGINE_ctrl_cmd_string(CapiEngine, 'lookup_method', '3', 0) <> 0 then
begin
LKey := f_ENGINE_load_private_key(CapiEngine, ContName, nil, nil);
if SSL_CTX_use_PrivateKey(ASSLCtx, LKey) > 0 then
if SSL_CTX_check_private_key(ASSLCtx) > 0 then
Result := True;
end;
end;
end;
finally
f_ENGINE_free(CapiEngine);
if Assigned(ProvInfo) then
FreeMem(ProvInfo);
if Assigned(ContName) then
FreeMem(ContName);
if Assigned(LKey) then
EVP_PKEY_free(LKey);
end;
end;

> -----Original Message-----
> From: owner-ope...@openssl.org [mailto:owner-openssl-
> us...@openssl.org] On Behalf Of Vladimir Belov
> Sent: Tuesday, November 01, 2011 7:26 PM
> To: openss...@openssl.org
> Subject: Re: Using certificate and private key from Windows cert store
> with OpenSSL
>
>
> How to use some "engine API" in my program? What is the name of this
> "some engine API" or engine plug-in?
>
> Please, give a small example or where can I find documentation about
> this?
> Is any documentation on the openssl.org?
>
> ----------------------------------------------------------
> From: Jakob Bohm
> Sent: Tuesday, November 01, 2011 8:04 PM
> To: openss...@openssl.org
> Subject: Re: Using certificate and private key from Windows cert store
> with OpenSSL
>
> This option is for the OpenSSL API, and I sure hope it would work with
> all the supported Windows Compilers, so you can use it with the
> compiler needed by the rest of your project.
>
> Once compiled in, your code will need to use some "engine API"
> at your program startup to request use of that engine plug-in, after
> which you should be able to use the Windows Certificate store and
> contents directly.
>
> On 11/1/2011 4:03 PM, Vladimir Belov wrote:
> >
> > Thanks, I understood that 'enable-capieng' option is a standard
> option
> > for Configure (enable/no).
> >
> > Is this option only for openssl.exe? How will openssl.exe use Windows
> > CERT store? Automatically or there is a command of openssl.exe for
> this.
> >
> > I asked about OpenSSLAPI functions, that will let me to use Windows
> > CERT store directly in my own program. Like X509_verify_cert for
> > OpenSSL CERT Store.
> >
> > Or I must manually extract Certificate during handshake, transform
> > it(if
> > necessary) and give it to WinAPI functions to next verifications of
> > certificate with CryptoAPI?
> >
> >
> > ---------------------------------------------------------------------
> -
> > ---------
> >
> > From: Sergio NNX
> > Sent: Monday, October 31, 2011 11:12 PM
> > To: openss...@openssl.org
> > Subject: RE: Using certificate and private key from Windows cert
> store
> > with OpenSSL Ciao.
> >
> > I use MinGW to build OpenSSL and it has always worked very well.
> >
> > Steps: a) perl Configure mingw shared enable-capieng --prefix=/mingw
> > --openssldir=C:/OpenSSL
> >
> > b) make
> >
> > After a while, you'll have openssl.exe and a couple of DLLs. At this
> > stage, you'll be able to access Windows Certificate store.
> >
> > If you're using Windows boxes, I can send you my copy of OpenSSL for
> > you to test.
> >
> > I hope it helps.
> >
> > Sergio.
> >
> >
> >
> >> From: ml.vlad...@gmail.com
> >> To: openss...@openssl.org
> >> Subject: Re: Using certificate and private key from Windows cert
> >> store with OpenSSL
> >> Date: Mon, 31 Oct 2011 21:40:44 +0400
> >>
> >> Sergio, how to set this option building OpenSSL? I didn't find any
> >> suggestions in documentation. And can you give a link to the
> >> documentation on the site openssl.org where there are functions of
> >> API to work with Windows CERT Stores?
> >>
> >>
> >> From: Sergio NNX
> >> Sent: Monday, October 31, 2011 1:02 PM
> >> To: openss...@openssl.org
> >> Subject: RE: Using certificate and private key from Windows cert
> >> store with OpenSSL Ciao Andrejs.
> >>
> >> I don't know much about the source code you posted previously but if
> >> you build OpenSSL with the 'enable-capieng' option you'll be able to
> >> access every single store and all the certs stored in Windows.
> >>
> >> I hope it helps.
> >>
> >> Sergio.
> >>
> >>
> >>
> >>
> >>
> _____________________________________________________________________
> >> _ OpenSSL Project http://www.openssl.org User Support Mailing List
> >> openss...@openssl.org Automated List Manager
> >> majo...@openssl.org
> >
> >
> ______________________________________________________________________
> > OpenSSL Project
> http://www.openssl.org
> > User Support Mailing List openssl-
> us...@openssl.org
0 new messages