sslbouncycastlejcefipsjsse

BouncyCastle JSSE and BCTLS No Credentials for Cipher


Using BouncyCastle FIPS JSSE and TLS providers for my server application.

<dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bcpkix-fips</artifactId>
        <version>1.0.3</version>
    </dependency>
    <dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bc-fips</artifactId>
        <version>1.0.2</version>
    </dependency>
    <dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bctls-fips</artifactId>
        <version>1.0.10</version>
    </dependency>

Configured FIPS and JSSE providers in the application as below.

Security.insertProviderAt(new BouncyCastleFipsProvider(), 1);
Security.insertProviderAt(new BouncyCastleJsseProvider("fips:BCFIPS"), 2);
Security.setProperty("keystore.type", "BCFKS");

The SSL certificate configuration is as below:

Server Cert - Public Key: RSA 2048 bit, Sign Algorithm: SHA256WithRSA
Issuing CA - Public Key: RSA 2048 bit, Sign Algorithm: SHA256WithRSA
Root CA - Public Key: RSA 2048 bit, Sign Algorithm: SHA1WithRSA

Using Zulu OpenJDK JRE 11. Below are additional system properties related to TLS

-Djdk.tls.disabledAlgorithms="MD5, RC4, TLSv1, SSLv2Hello, SSLv3, DSA, DESede, DES, 3DES, DES40_CBC, RC4_40, MD5withRSA, DH, 3DES_EDE_CBC, DHE, DH keySize < 1024, EC keySize < 224" -Djdk.tls.ephemeralDHKeySize=2048 -Djdk.tls.rejectClientInitiatedRenegotiation=true -Djava.security.egd=file:/dev/./urandom -Dorg.bouncycastle.rsa.allow_multi_use=true

Supported protocol is TLSv1.2.

Expectation:

I expected the server to support TLS_ECDHE_RSA type of ciphers. When using the same application with Sun JSSE with same configuration (minus BC libraries above), those ciphers are enabled.

Actual:

Issue is that in the SSL scan shows only TLS_RSA type of ciphers listed below:

TLS_RSA_WITH_AES_256_GCM_SHA384
TLS_RSA_WITH_AES_128_GCM_SHA256
TLS_RSA_WITH_AES_256_CBC_SHA256
TLS_RSA_WITH_AES_128_CBC_SHA256
TLS_RSA_WITH_AES_256_CBC_SHA
TLS_RSA_WITH_AES_128_CBC_SHA

In the bouncycastle debug logs I see below entries

[o.b.j.p.ProvTlsServer] - Server found no credentials for cipher suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
[o.b.j.p.ProvTlsServer] - Server found no credentials for cipher suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
[o.b.j.p.ProvTlsServer] - Server found no credentials for cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
[o.b.j.p.ProvTlsServer] - Server found no credentials for cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
[o.b.j.p.ProvTlsServer] - Server found no credentials for cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
[o.b.j.p.ProvTlsServer] - Server found no credentials for cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA

What does that mean? I did not find any useful information from Google search. Could somebody please help how to resolve this.

Thanks in advance.

Probable similar question: DHE ciphers not exposed by BouncyCastle provider


Update-1

This is the update after setting the ssl.KeyManagerFactory.algorithm and ssl.TrustManagerFactory.algorithm to PKIX as suggested in the answer below.

Thanks for suggesting that configuration. Now TLS_ECDHE_RSA* ciphers are showing up in the SSL scan.

However there is a concern. The list of supported ciphers also includes TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (refer the screenshot) which is not supported in FIPS mode as per this document (Appendix-B): https://downloads.bouncycastle.org/fips-java/BC-FJA-(D)TLSUserGuide-1.0.10.pdf.

I have the set the system property -Dorg.bouncycastle.fips.approved_only=true, but did not find any difference.

I'm not sure if this is expected. Any thoughts on this?

supported-cipher-suites

Additional Observations: Once I configured PKIX algorithm as suggested above, I soon started receiving the error org.bouncycastle.crypto.IllegalKeyException: Attempt to sign/verify with RSA modulus already used for encrypt/decrypt. after SSL scan. This error prevented all subsequent TLS connections with my application. I tried below two approaches for this.

  1. Setting -Dorg.bouncycastle.jsse.fips.allowRSAKeyExchange=false as explained at this forum. However, this disabled all TLS_RSA ciphers.

  2. Configured the system property -Dorg.bouncycastle.rsa.allow_multi_use=true. With this I'm able to use both TLS_RSA and TLS_ECDHE_RSA ciphers together.


Solution

  • Those log entries ("Server found no credentials..." mean that the server is configured to support the mentioned algorithm, but could not find a suitable credential (key-plus-certificate) via the X509KeyManager the SSLContext was initialized with.

    BCJSSE (especially FIPS) doesn't interoperate with KeyManagerFactory or TrustManagerFactory from other providers, so please check that you have the default algorithms configured to PKIX (in java.security) to use the BCJSSE ones:

    ssl.KeyManagerFactory.algorithm=PKIX
    ssl.TrustManagerFactory.algorithm=PKIX
    

    Else: either the KeyManagerFactory didn't initialize correctly (problem with they KeyStore), or the chooseServer... method call failed to find any credential suitable for RSA signing, or they have expired, or have incompatible KeyUsage or ExtendedKeyUsage, or some other detail. We do have in some cases somewhat more restrictive conditions than SunJSSE. If you can lower the logging level to FINEST, you should see more entries relating to the failed lookup (may need to upgrade to 1.0.11 of bctls-fips for this).

    We provide a source jar for bctls-fips, so if you are able to look at the X509KeyManager calls in a debugger you could track down the specific reason no acceptable credentials are found. Otherwise we would need to see more details of the certificate(s). It may be better in that case to raise an issue at our GitHub.


    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: I believe this is permitted, so this is an error in the documentation.


    If you are in approved mode you cannot use a single RSA key for both signing/verification and encryption/decryption. TLS_RSA_* cipher suites will use the key for decryption at the server, and TLS_ECDHE_RSA_* cipher suites will use the key for signing. In order to enable both you would need to have separate RSA credentials for each case, one with KeyUsage 'digitalSignature' and one with KeyUsage 'keyEncipherment' (so the KeyManager knows which to use in each case). org.bouncycastle.rsa.allow_multi_use can let it work for debugging purposes, but it's not FIPS compliant to allow multi-use in approved mode. org.bouncycastle.jsse.fips.allowRSAKeyExchange can be used to disable TLS_RSA_*, and this is recommended since these are obsolete cipher suites anyway.