openssl / openssl

TLS/SSL and crypto library
https://www.openssl.org
Apache License 2.0
25k stars 9.96k forks source link

add callback that called once client-side authentication is requested by server #17955

Open iradization opened 2 years ago

iradization commented 2 years ago

Hi,

Currently there's an option to set the signing certificate in advance, to be used to sign challenge. This is the method to do so:

void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx,
                                int (*client_cert_cb) (SSL *ssl, X509 **x509,
                                                       EVP_PKEY **pkey));

In the example above the signing certificate to be set (cert + pkey) in the callback function. They will be used to sign the challenge automatically once the server request client-side authentication.

I wish to create a callback in openssl that will get the challenge and will sign it using the specific implementation of this callback.

Such capability is required in macOS where the signing certificates are often saved in keychain and cannot be exported. The client may only get pkey reference and it sign the challenge inside the keychain. I think in windows they have a similar problem with the certificate store, where the private key cannot be exported.

I will be happy to contribute and implement it myself. Perhaps anybody can refer me to the code that perform the actual challenge signing ?

thanks

t8m commented 2 years ago

The proper way to do that is to have a provider that provides the EVP_PKEY from the OS key store. I understand that is a bigger work than implementing just a signing callback. However I do not think we are going to add such callback.

iradization commented 2 years ago

Hi @t8m,

you said provider that provides the EVP_PKEY from the OS key store, what do you mean by provider, what object should I look in the code ? how does the EVP_PKEY is used after it was being set ? is there a way to get callback once the EVP_PKEY is requested to sign anything (not just challenge)

I wish that my provider will provide a reference to the private key and not the real one, is it possible, since the private key cannot be exported from macOS key store.

If I could just set the EVP_PKEY with some key identifier (reference to the key in key store) , so perhaps there's also a callback that uses this key to sign the challenge inside the key store.

thanks !

t8m commented 2 years ago

See https://github.com/openssl/openssl/blob/master/doc/man7/provider.pod for what is meant by a provider.

Yes, the EVP_PKEYs do not need to contain the actual key data in the memory, the provider that owns the key is called for any operations with the key.

mattcaswell commented 2 years ago

what do you mean by provider, what object should I look in the code

You should probably read the main crypto man page which introduces and describes some fundamental OpenSSL concepts and describes the set of five providers that OpenSSL comes with out-of-the-box:

https://www.openssl.org/docs/man3.0/man7/crypto.html

is there a way to get callback once the EVP_PKEY is requested to sign anything (not just challenge)

I wish that my provider will provide a reference to the private key and not the real one, is it possible, since the private key cannot be exported from macOS key store.

You need to implement a provider that supplies the signature algorithm. This effectively diverts all signing operations into your code. You will also need to implement a key manager in order to represent the key (which in your case will just be a reference to the key in the underlying key store).

Some useful reading material:

https://www.openssl.org/docs/man3.0/man7/provider.html https://www.openssl.org/docs/man3.0/man7/provider-keymgmt.html https://www.openssl.org/docs/man3.0/man7/provider-signature.html

You can look at the legacy provider code for a fairly simple provider. Unfortunately this doesn't implement key management or signatures which you will need:

https://github.com/openssl/openssl/blob/master/providers/legacyprov.c

iradization commented 2 years ago

@mattcaswell , @t8m Thanks for your valuable inputs.

So except from the legacy provider I haven't found any reference for the signature or keymgmt providers.

Instead, I've found some other (older) example which is the CAPI engine that make use of windows key store (perhaps I can also modify it to work on macOS keychain) --> https://github.com/openssl/openssl/blob/master/engines/e_capi.c

So I wonder If I can still use this engine in openssl version 1.1.1 or 3.0 ?

if yes so when compiling the project, there's the compilation flag OPENSSL_NO_CAPIENG. if omitting this flag from the compilation, will openssl use client certificate from windows cert store when requested for client auth by server ?

is OPENSSL_NO_CAPIENG not defined by default when building openssl?

thanks !

tmshort commented 2 years ago

The proper way to do that is to have a provider that provides the EVP_PKEY from the OS key store. I understand that is a bigger work than implementing just a signing callback. However I do not think we are going to add such callback.

I'm thinking of all the OS-dependencies doing something like this. A callback would relieve OpenSSL of those dependencies (but place them on the application author).

t8m commented 2 years ago

You can use engines in both 1.1.1 and 3.0 versions. I am not sure it is a good idea to modify the engine to support OS/X store when engines are deprecated in 3.0 and will be eventually removed (in the next major release most probably).

nhorman commented 1 month ago

Marking as inactive, to be closed when 3.4 dev cycle ends, barring further input