Hi,
I have been trying to setup mutual authentication using a smart card but I can't seem to get the OpenSSL Engine to send a response back to the server containing client's certificate from the smart card.
I'm using the following to configure the certificate and private key:
ENGINE_ctrl_cmd(engine, "LOAD_CERT_CTRL", 0, &cert_info, NULL, 0);
SSL_CTX_use_certificate(sslContext, cert_info.cert);
EVP_PKEY* privateKey = ENGINE_load_private_key(engine, "2b2586c684d69b670c0a805edf514e720f2b757d8e2faa0b3a7ff23d1ccfc7ba", transfer_pin, &cb_data);
SSL_CTX_use_PrivateKey(sslContext, privateKey);
(I have been using the code in https://github.com/jjkeijser/ppp/blob/eap-tls/pppd/eap-tls.c as a guide.)
This seems be successful. However, when I start the mutual authentication with
SSL_connect(ssl)
, the mutual authentications handshake fails. I can see the server requesting the certificate from the client and the client sends back an ACK for this message. However, the client does not send the certificate to the server.
I was looking through the OpenSSL code openssl-1.0.2u\ssl\ssl_rsa.c and noticed something interesting. The comment indicates that the flag RSA_METHOD_FLAG_NO_CHECK should be set for smart cards:
static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey)
{
. . .
#ifndef OPENSSL_NO_RSA
/*
* Don't check the public/private key, this is mostly for smart
* cards.
*/
if ((pkey->type == EVP_PKEY_RSA) &&
(RSA_flags(pkey->pkey.rsa) & RSA_METHOD_FLAG_NO_CHECK)) ;
else
#endif
. . .
}
However, it is not actually set when I use a debugger to inspect the flag. Does it need to be set? If so, how is this done? I could not find anything related to this in
https://github.com/jjkeijser/ppp/blob/eap-tls/pppd/eap-tls.c
Thanks,
George
On 2021-01-05 11:51 a.m., Jan Just Keijser wrote:
I have been trying to setup mutual authentication using a smart card but I can't seem to get the OpenSSL Engine to send a response back to the server containing client's certificate from the smart card.
I'm using the following to configure the certificate and private key:
ENGINE_ctrl_cmd(engine, "LOAD_CERT_CTRL", 0, &cert_info, NULL, 0);
SSL_CTX_use_certificate(sslContext, cert_info.cert);
EVP_PKEY* privateKey = ENGINE_load_private_key(engine, "2b2586c684d69b670c0a805edf514e720f2b757d8e2faa0b3a7ff23d1ccfc7ba", transfer_pin, &cb_data);
SSL_CTX_use_PrivateKey(sslContext, privateKey);
(I have been using the code in https://github.com/jjkeijser/ppp/blob/eap-tls/pppd/eap-tls.c as a guide.)
This seems be successful. However, when I start the mutual authentication with
SSL_connect(ssl)
, the mutual authentications handshake fails. I can see the server requesting the certificate from the client and the client sends back an ACK for this message. However, the client does not send the certificate to the server.
I was looking through the OpenSSL code openssl-1.0.2u\ssl\ssl_rsa.c and noticed something interesting. The comment indicates that the flag RSA_METHOD_FLAG_NO_CHECK should be set for smart cards:
static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey)
{
. . .
#ifndef OPENSSL_NO_RSA
/*
* Don't check the public/private key, this is mostly for smart
* cards.
*/
if ((pkey->type == EVP_PKEY_RSA) &&
(RSA_flags(pkey->pkey.rsa) & RSA_METHOD_FLAG_NO_CHECK)) ;
else
#endif
. . .
}
However, it is not actually set when I use a debugger to inspect the flag. Does it need to be set? If so, how is this done? I could not find anything related to this in
https://github.com/jjkeijser/ppp/blob/eap-tls/pppd/eap-tls.c
Thanks,
George
On 2021-01-05 11:51 a.m., Jan Just Keijser wrote:
Hi,
On 05/01/21 07:39, George wrote:
Hi,
I was looking at the code in https://github.com/jjkeijser/ppp/blob/eap-tls/pppd/eap-tls.c and realized I forgot to call ENGINE_ctrl_cmd(...) to setup "LOAD_CERT_CTRL". However, when I do this, the callback function is no longer being called during the mutual authentication handshake. I'm wondering if I have the parameter "cert_info.s_slot_cert_id" incorrectly configured. Here is what my code looks like:
struct
{
const char* s_slot_cert_id;
X509* cert;
} cert_info;
cert_info.s_slot_cert_id = "a9bee4d72100c52f77c3fc288d2be01a34b5d44f91b3b7ea3d349b8a25752c45";
cert_info.cert = NULL;
ENGINE_ctrl_cmd(engine, "LOAD_CERT_CTRL", 0, &cert_info, NULL, 0);
SSL_CTX_use_certificate(sslContext, cert_info.cert);
I tried manually using LOAD_CERT_CTRL in the openssl shell but I cannot seem to get it to work and cannot find any examples of how to use it. Is the syntax for LOAD_CERT_CTRL correct? I am using "LOAD_CERT_CTRL:<certificate Object ID>".
OpenSSL> engine -vvvv -t dynamic -pre "SO_PATH:C:\\Users\\whipp\\junk4\\libp11-libp11-0.4.11\\src\\pkcs11.dll" -pre ID:pkcs11 -pre LIST_ADD:1 -pre LOAD -pre "MODULE_PATH:C:\Program Files (x86)\HID Global\ActivClient\\acpkcs211.dll" -pre PIN:123456 -pre FORCE_LOGIN -pre "LOAD_CERT_CTRL:a9bee4d72100c52f77c3fc288d2be01a34b5d44f91b3b7ea3d349b8a25752c45"
(dynamic) Dynamic engine loading support
[Success]: SO_PATH:C:\\Users\\whipp\\junk4\\libp11-libp11-0.4.11\\src\\pkcs11.dll
[Success]: ID:pkcs11
[Success]: LIST_ADD:1
[Success]: LOAD
[Success]: MODULE_PATH:C:\Program Files (x86)\HID Global\ActivClient\\acpkcs211.dll
[Success]: PIN:123456
[Success]: FORCE_LOGIN
[Failure]: LOAD_CERT_CTRL:a9bee4d72100c52f77c3fc288d2be01a34b5d44f91b3b7ea3d349b8a25752c45
4196:error:260AB086:engine routines:ENGINE_ctrl_cmd_string:cmd not executable:.\crypto\engine\eng_ctrl.c:316:
Loaded: (pkcs11) pkcs11 engine
[ available ]
SO_PATH: Specifies the path to the 'pkcs11' engine shared library
(input flags): STRING
MODULE_PATH: Specifies the path to the PKCS#11 module shared library
(input flags): STRING
PIN: Specifies the pin code
(input flags): STRING
VERBOSE: Print additional details
(input flags): NO_INPUT
QUIET: Remove additional details
(input flags): NO_INPUT
LOAD_CERT_CTRL: Get the certificate from card
(input flags): [Internal]
INIT_ARGS: Specifies additional initialization arguments to the PKCS#11 module
(input flags): STRING
SET_USER_INTERFACE: Set the global user interface (internal)
(input flags): [Internal]
SET_CALLBACK_DATA: Set the global user interface extra data (internal)
(input flags): [Internal]
FORCE_LOGIN: Force login to the PKCS#11 module
(input flags): NO_INPUT
OpenSSL>
I'm using the certificate object ID "a9bee4d72100c52f77c3fc288d2be01a34b5d44f91b3b7ea3d349b8a25752c45" for LOAD_CERT_CTRL. Is this right? (I also tried adding "0:" in front of it to indicate slot 0, but that did not work either.
this has little to do with OpenSSL at the moment and more with libp11 - perhaps someone more knowledgable on the libp11 mailing list can help you.
I'd try to use
-post LOAD_CERT_CTRL
instead of '-pre', as you want this done after the engine has been loaded.
The cert ID does look OK. Note that if you want to use the s_client command that you canNOT specify the certificate form '-certform engine' as the code does not grok that.
HTH,
JJK