caml-pkcs11 / caml-crush

Caml Crush: an OCaml PKCS#11 filtering proxy

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

enabling PFS on the proxy daemon

FrankHomeSend opened this issue · comments

I've compiled caml-crush against gnutls on CentOS 7.1, with ocaml-ssl 0.4.7 rebuild from the source RPM included in Fedora 23, ocamlnet-3.3.7 compiled from source and the other dependencies installed from the CentOS/EPEL repositories (except camlidl which was also built from the Fedora 23 source RPM).

The following configure command was used for caml-crush:
./configure --with-ssl --with-gnutls --with-ssl-clientfiles='env' --with-client-socket="tcp,SOME_IP_ADDRESS:SOME_PORT"

To test forcing a cipher suite that provides PFS, the following cipher suites are set in pkcs11proxyd.conf:
cipher_suite="DHE-DSS-AES128-SHA:!eNull:!aNull";

This results in pkcs11proxyd showing the following on startup:
CONFIGURATION: the 'DHE-DSS-AES128-SHA' SSL cipher suite is currently not supported by OCaml OpenSSL bindings => it is removed from the cipher suites that will be used!
CONFIGURATION: the cipher_suite list only contains negative expressions => we will append the OpenSSL HIGH suites!

Another thing that I found surprising is that ldd only shows linking against libssl for the pkcs11proxyd binary, while libp11client does show gnutls as linked library (both when compiling with --with-gnutls).

Is there a specific procedure to follow to enable support for PFS by the proxy daemon? I've based my tries on what is mentioned in https://github.com/ANSSI-FR/caml-crush/blob/master/ISSUES.md#PFS

Thanks!

Hi,

First, the --with-gnutls is only relevant for the client library. Hence this is perfectly normal that the pkcs11proxyd is not linked with GnuTLS. Ocamlnet 3.x.x releases can only link against OpenSSL through the ocaml-ssl bindings.

Second, as stated in the documentation, up until ocaml-ssl 0.4.7 PFS suites could not be enabled, hence we decided to blacklist them in the server code to avoid users thinking they could be enabled by setting them in the configuration as you did.

A more flexible approach has to be devised to detect the underlying support (either at configure or at runtime) in order to blacklist only when necessary.

In the meantime, you can modify src/pkcs11proxyd/server.ml and replace the current blacklist with the following one:

let unsupported_suites = ref ["ECDHE-RSA-RC4-SHA"; "ECDHE-ECDSA-RC4-SHA"; "ECDH-RSA-RC4-SHA"; "ECDH-ECDSA-RC4-SHA"; "DH-DSS-AES256-GCM-SHA384"; "DH-RSA-AES256-GCM-SHA384"; "DH-RSA-AES256-SHA256"; "DH-DSS-AES256-SHA256"; "DH-RSA-AES256-SHA"; "DH-DSS-AES256-SHA"; "DH-RSA-CAMELLIA256-SHA"; "DH-DSS-CAMELLIA256-SHA"; "ECDH-RSA-AES256-GCM-SHA384"; "ECDH-ECDSA-AES256-GCM-SHA384"; "ECDH-RSA-AES256-SHA384"; "ECDH-ECDSA-AES256-SHA384"; "ECDH-RSA-AES256-SHA"; "ECDH-ECDSA-AES256-SHA"; "DH-DSS-AES128-GCM-SHA256"; "DH-RSA-AES128-GCM-SHA256"; "DH-RSA-AES128-SHA256"; "DH-DSS-AES128-SHA256"; "DH-RSA-AES128-SHA"; "DH-DSS-AES128-SHA"; "DH-RSA-CAMELLIA128-SHA"; "DH-DSS-CAMELLIA128-SHA"; "ECDH-RSA-AES128-GCM-SHA256"; "ECDH-ECDSA-AES128-GCM-SHA256"; "ECDH-RSA-AES128-SHA256"; "ECDH-ECDSA-AES128-SHA256"; "ECDH-RSA-AES128-SHA"; "ECDH-ECDSA-AES128-SHA"]

This will enable all DHE/ECDHE suites (except RC4 ones) and maintain DH/ECDH ones in the blacklist.

As a side note, would you mind sharing your Caml Crush use case?

Now compiled with the newly provided blacklist, which removes the previously listed errors on startup of the caml-crush daemon process.

Unfortunately the following errors appear when trying to perform a TLS handshake (with the cipher list set to : cipher_suite="DHE-RSA-AES128-SHA:!eNull:!aNull" as tests are run with RSA key/certs)

openssl s_client -connect fqdn:port -cert location_of_server_cert -key location_of_server_key -CAfile location_of_CA_cert -cipher DHE-RSA-AES128-SHA -tls1_2

140500187010976:error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number:s3_pkt.c:339:

openssl s_client -connect fqdn:port -cert location_of_server_cert -key location_of_server_key -CAfile location_of_CA_cert -cipher DHE-RSA-AES128-SHA -tls1_1

140665539598240:error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number:s3_pkt.c:339:

openssl s_client -connect fqdn:port -cert location_of_server_cert -key location_of_server_key -CAfile location_of_CA_cert -cipher DHE-RSA-AES128-SHA -tls1

140458718316448:error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure:s3_pkt.c:1259:SSL alert number 40
140458718316448:error:1409E0E5:SSL routines:SSL3_WRITE_BYTES:ssl handshake failure:s3_pkt.c:598:

Is there a way to validate that my ocaml-ssl and ocamlnet truly have support for TLS1.1/TLS1.2 and for DHE ciphersuites enabled?

I'll post the use case in my next post in this thread

Our use case is as follows:

Goals:

  • Protect private keys in a PCI DSS environment by separating systems that use private keys from those that store them
  • Centralize storage and management of sensitive private keys
  • Ease transition when a future PCI DSS conformance requirement imposes usage of a HSM

Implementation:

  • Store private keys on a dedicated system in PKCS #11 software tokens (one of SoftHSM, openCryptoki or NSS DB w/libsoftokn3.so)
  • Provide filtering proxy capability to systems that access these private keys through the caml-crush PKCS #11 filtering proxy daemon running on said dedicated system.
  • On ‘private key client’ systems, access caml-crush client PKCS #11 library directly by applications, through p11-kit (when multiple apps access to the same keys concurrently from the same machine), or through adding the libp11client PKCS #11 module to an NSS DB instance to expose access through the NSS API.
  • Ideally the following will be implemented too:
    o SO login and any token management duties (token initialisation, generation of key pairs, User PIN changing, etc.) are to be disallowed through PKCS #11 calls that go through the PKCS #11 proxy ; only direct access to the software tokens, on the system running the caml-crush proxy daemon, would allow these tasks.
    o Rate limiting of User logins through the PKCS #11 proxy should make brute forcing the User PIN an unfeasible attack, when a token has a very limited maximum PIN length, such as 8 characters.

Thank you for sharing your use case, interesting project !

I modified the upstream code to enable PFS ciphersuites by default. Although this adds a hard requirement on ocaml-ssl 0.4.7, we feel that gaining PFS on supported platforms is worth this drawback.

I have tested this with in several configurations (DHE-, ECDHE-), it should fix your issue, let me know so I can close the bug.

PFS operational now - thanks!

I had to change the compilation platform to Fedora 22, as --with-rpcgen seems obligatory now (and CentOS 7.1 misses too many dependencies to get this to work easily).

On another note, the ocamlnet upstream release 3.7.7 still does not contain the 'fix-zombie-child-when-socket-fails.patch', which is a bit worrying to see; fortunately the version in Fedora 22 appears to have been patched.

Great, I'll close this bug then.

Well --with-rpcgen is always mandatory when working from a clean source directory.
As for CentOS, I guess if dependencies are missing, you must compile them manually.

Regarding the patch of ocamlnet, I guess it did not make it upstream since series 4.x was to be released. The TLS support was completely rewritten and Caml Crush is not yet compatible when linking against 4.x Ocamlnet.