private key not available for client_cert_cb
Paul Nelson
nelson at openssl.org
Mon Dec 14 16:47:35 UTC 2020
How I did this:
1) You can make up your own EVP_PKEY that uses your own engine implementation and attach a data ptr to it
EVP_PKEY* returnPKey;
returnPKey = EVP_PKEY_new();
if( returnPKey )
{
ENGINE* engine = ENGINE_by_id(YOUR_ENGINE_ID);
RSA* sc_rsa = RSA_new_method(engine);
if( sc_rsa )
{
// attach a reference to a structure holding your smart card middleware info
RSA_set_ex_data(sc_rsa, ENGINE_smartcard_rsa_idx_middleware(),
(void*)middleware->handle);
EVP_PKEY* pk = X509_get_pubkey( returnCert );
if( pk )
{
sc_rsa->e = BN_new();
sc_rsa->n = BN_new();
BN_copy(sc_rsa->e, pk->pkey.rsa->e);
BN_copy(sc_rsa->n, pk->pkey.rsa->n);
EVP_PKEY_free(pk);
EVP_PKEY_set1_RSA(returnPKey, sc_rsa);
RSA_free(sc_rsa);
*outCert = make this X509 from your smart card certificate;
*outpkey = returnPKey;
}
else
LogError("smartcards_fetch_identity can't get pubkey\n");
}
Then for your engine you will need some methods to configure it as follows:
void ENGINE_load_smartcard_keychain(void);
/*
* ENGINE_tss_keychain_rsa_idx_middleware returns a ex_data index where engine user should store the
* pointer to the info needed to use the middleware
*/
int ENGINE_smartcard_rsa_idx_middleware(void);
Your ENGINE_load_smartcard_keychain method should set global values that get returned by ENGINE_smartcard_rsa_idx_middleware:
gMiddlewareRSAIndex = RSA_get_ex_new_index(0x1234, NULL, NULL, NULL, NULL);
Configure your engine filling in an RSA_METHOD structure with what you will need. You don’t really need all the methods in RSA_METHOD structure, and if you don’t need them add a stub that returns a 0. I did not need either of the mod_exp method or the public key encrypt and decrypt methods. I also did not need the verify or keygen methods. Your init and finish methods just need to return 1.
I set the RSA_METHOD flags to RSA_FLAG_FIPS_METHOD|RSA_METHOD_FLAG_NO_CHECK|RSA_FLAG_CACHE_PUBLIC
This leaves the cipher methods for private key encrypt/decrypt and sign. The private key methods will be where all the work is done. Write a function to perform the smartcard ‘crypt’ method and use it in private encrypt/decrypt and the signing methods. You will need to pay attention to padding and make sure you know how to pad for PKCS1 type 1. The RSA_SSLV23_PADDING is not required and you can just return an error if you get called with this.
I handle the PIN entry requirement by having the engine return a specific error if the PIN is needed, then handle the PIN entry in the application. Once the PIN is entered and available to the middleware, I retry the connection.
The trick is to get a pointer to your middleware implementation from the private key engine methods like this:
my_middleware_handle =
(my_middleware_handle)RSA_get_ex_data(rsa, gMiddlewareRSAIndex);
I found that writing the engine was more straightforward that attempting to use PKCS11.
> On Dec 14, 2020, at 1:08 AM, George <whippet0 at gmail.com> wrote:
>
> Hi,
>
> I'm new to OpenSSL and am trying to set up mutual authentication in a client. The client is setup with OpenSSL 1.0.2u. and the client's certificate + private key is stored on a Smart Card. When the client receives a certificate request from the server during the mutual authentication handshake, the OpenSSL client_cert_cb callback function is automatically invoked. The problem is that client_cert_cb requires a private key. Unfortunately, it is not possible to get a private key from a Smart Card. Is there a way to send a certificate to the server without needing the private key?
>
> I'm setting up the callback function with:
>
> void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, int (*client_cert_cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey));
>
>
> Here is a sample of what my code looks like when I set this up:
>
> SSL_CTX_set_client_cert_cb(context, openSSLClientAuthenticationCallBack);
>
> int openSSLClientAuthenticationCallBack(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
> {
> . . .
> }
>
>
> I can access the Smart Card using the PKCS#11 interface and I'm able to get the certificate and sign it, etc. However, I cannot get the actual private key from the Smart Card.
>
> Does anyone know how I can get around this problem?
>
>
> Thanks,
> George
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mta.openssl.org/pipermail/openssl-users/attachments/20201214/d7757876/attachment-0001.html>
More information about the openssl-users
mailing list