Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Which version of bctls-fips is compatible with bc-fips 2.0.0? #1878

Open
jwojcie opened this issue Oct 23, 2024 · 5 comments
Open

Which version of bctls-fips is compatible with bc-fips 2.0.0? #1878

jwojcie opened this issue Oct 23, 2024 · 5 comments
Labels
question Further information is requested

Comments

@jwojcie
Copy link

jwojcie commented Oct 23, 2024

I'm trying to write some test SSL code, using bc-fips 2.0.0 and bctls-fips 2.0.19.
I'm a bit confused if that is a right combination because I get this exception when I try to use them together:
Exception in thread "main" java.lang.NoClassDefFoundError: org/bouncycastle/asn1/eac/EACObjectIdentifiers at org.bouncycastle.tls.TlsUtils.createCertSigAlgOIDs(TlsUtils.java:101) at org.bouncycastle.tls.TlsUtils.<clinit>(TlsUtils.java:63) at org.bouncycastle.jsse.provider.CipherSuiteInfo.forCipherSuite(CipherSuiteInfo.java:24) at org.bouncycastle.jsse.provider.ProvSSLContextSpi.addCipherSuite(ProvSSLContextSpi.java:77) at org.bouncycastle.jsse.provider.ProvSSLContextSpi.createSupportedCipherSuiteMap(ProvSSLContextSpi.java:178) at org.bouncycastle.jsse.provider.ProvSSLContextSpi.<clinit>(ProvSSLContextSpi.java:63) at org.bouncycastle.jsse.provider.BouncyCastleJsseProvider$3.createInstance(BouncyCastleJsseProvider.java:181) at org.bouncycastle.jsse.provider.BouncyCastleJsseProvider$BcJsseService.newInstance(BouncyCastleJsseProvider.java:407) at java.base/sun.security.jca.GetInstance.getInstance(GetInstance.java:236) at java.base/sun.security.jca.GetInstance.getInstance(GetInstance.java:164) at java.base/javax.net.ssl.SSLContext.getInstance(SSLContext.java:168)

Upon a closer examination I see in bctls-fips-2.0.19-sources.jar -> org.bouncycastle.tls.TlsUtils
it is importing from:
org.bouncycastle.asn1.eac.EACObjectIdentifiers;

Which blows up with bc-fips 2.0.0, becuase there, that class is moved to internal:
org.bouncycastle.internal.asn1.eac.EACObjectIdentifiers

so I can't instantiate the SSL context.

Does it mean those two libraries are not meant to be used together?

@jwojcie jwojcie changed the title Which version of bctls is compatible with bc-fips 2.0.0? Which version of bctls-fips is compatible with bc-fips 2.0.0? Oct 23, 2024
@dghgit
Copy link
Contributor

dghgit commented Oct 24, 2024

You also need to use bcutil with the 2.0.0 libraries.

@jwojcie
Copy link
Author

jwojcie commented Oct 24, 2024

Thank you, I see it now :)

I'm not sure if that is the right place to ask, if not then I'm sorry in advance.
The issue I'm trying to figure out/prepare test case is this exception:
Fr-Oct-18-2024,11:03 [measurement-coordinator-deployment-6f8ccbc4f5-rgrt9] {"@timestamp":"2024-10-18T11:03:34.306230201Z","@version":"1","message":"Certificate chain check failed","logger_name":"org.bouncycastle.jsse.provider.ProvX509KeyManager","thread_name":"grpc-default-executor-1","level":"TRACE","level_value":5000,"stack_trace":"java.security.cert.CertPathValidatorException: Signature algorithm 'SHA384WITHECDSA' not permitted with given parameters\n\tat org.bouncycastle.jsse.provider.ProvAlgorithmChecker.checkIssued(ProvAlgorithmChecker.java:263)\n\tat org.bouncycastle.jsse.provider.ProvAlgorithmChecker.checkChain(ProvAlgorithmChecker.java:206)\n\tat org.bouncycastle.jsse.provider.ProvX509KeyManager.isSuitableChain(ProvX509KeyManager.java:807)\n\tat org.bouncycastle.jsse.provider.ProvX509KeyManager.getKeyTypeQuality(ProvX509KeyManager.java:598)\n\tat org.bouncycastle.jsse.provider.ProvX509KeyManagerSimple.getPotentialMatch(ProvX509KeyManagerSimple.java:290)\n\tat org.bouncycastle.jsse.provider.ProvX509KeyManagerSimple.getBestMatch(ProvX509KeyManagerSimple.java:258)\n\tat org.bouncycastle.jsse.provider.ProvX509KeyManagerSimple.chooseAlias(ProvX509KeyManagerSimple.java:160)\n\tat org.bouncycastle.jsse.provider.ProvX509KeyManagerSimple.chooseEngineClientAlias(ProvX509KeyManagerSimple.java:97)\n\tat io.grpc.netty.shaded.io.netty.handler.ssl.OpenSslKeyMaterialManager.chooseClientAlias(OpenSslKeyMaterialManager.java:126)\n\tat

We switched to BC FIPS and what previously was perfectly fine certificate based on SHA384WITHECDSA with P-384 is now rejected with "Signature algorithm 'SHA384WITHECDSA' not permitted with given parameters". Trouble is that BCAlgorithmConstraints implementations of permits method have a lot of conditions with basically zero logging. So it is very hard to figure out what is wrong exactly with those parameters, which condition is failing. I can only speculate that the issue is SigAlgParams is null in that certificate. Although I've read somewhere it should be fine for SHA384WITHECDSA.

Can I get any hint on that? Is there any tool available in BC FIPS which would help to validate certificate for FIPS 140 constraints without the need of setting up entire SSL related machinery?

@peterdettman
Copy link
Collaborator

@jwojcie Did you resolve the issue with that SHA384WITHECDSA certificate? I'm curious how switching to BCFIPS could cause it to start being rejected. We could always use more logging, but we tend to chip away at it as we encounter interesting/common/tricky cases; so if you could provide details we could add logging for it.

If you are still stuck on this exception perhaps you could use an ASN.1 tool to dump out the certificate and see what the signature algorithm parameters actually contains.

@jwojcie jwojcie closed this as completed Nov 8, 2024
@jwojcie jwojcie reopened this Nov 8, 2024
@jwojcie
Copy link
Author

jwojcie commented Nov 8, 2024

@peterdettman - yes and no. We discovered that netty which is in the mix has PEM reader dependent on non compliant BC:
https://github.com/netty/netty/blob/925064ecf191936d7316732167805c6ecbacd469/handler/src/main/java/io/netty/handler/ssl/BouncyCastlePemReader.java#L80

So we are focusing on solving/bypassing that now. However I still have no clue how we can see issue with SHA384WITHECDSA in the logs when first we have clearly exception from reading the certificate and key in the first place. I will keep that open and keep you posted then if you are interested :) Definitely having some more logging in BC FIPS in TRACE mode would help a lot. Right now we can't tell which certificate in the chain fails and why exactly, which parameter of SHA384WITHECDSA is wrong, because clearly SHA384WITHECDSA is compliant and available in the approved mode, right?

In general the fact that the pieces were moved between FIPS and non FIPS BC, the fact that provider name changed - it brought multiple issues. It seems many open source libs have hardcoded non-compliant BC inside. For example in another service we have an issue with that:
kubernetes-client/java#3777
In the meantime they did some fix - not very good imho, but good enough for at least not blowing up. Feel free to comment there to help to make it better :) I think it should be just removed...

I suspect why BC and BC FIPS are not compatible but oh man... it is like a stone dropped into the lake of java source code in the industry :) We are doing that move to FIPS on multiple techstacks and frankly the only bigger issues we have are with Java and BC FIPS, and mostly because of that incompatibility.

Last but not least: can you provide a debug version of all FIPS libraries here?:
https://repo1.maven.org/maven2/org/bouncycastle/
in particular for bcpkix-fips-2.0.7

I'm struggling now with another "funny" library heavily dependent on direct imports from non-FIPS BC, which is working directly with BC classes, not via JCA. I'm trying to make it work with BC FIPS. I'm getting

org.bouncycastle.crypto.fips.FipsUnapprovedOperationError: RSA PKCS1.5 encryption disallowed
	at org.bouncycastle.crypto.fips.FipsRSA$KeyWrapOperatorFactory$KeyWrapper.<init>(Unknown Source)
	at org.bouncycastle.crypto.fips.FipsRSA$KeyWrapOperatorFactory$KeyWrapper.withSecureRandom(Unknown Source)
	at org.bouncycastle.crypto.fips.FipsRSA$KeyWrapOperatorFactory$KeyWrapper.withSecureRandom(Unknown Source)

from there and I'm trying to debug it to figure out from where this padding is coming from. I understand I should be using RSA-OAEP instead of PKCS#1 v1.5. But while there is debug jar for bc-fips, the one for bcpkix-fips seems to be missing. At least I think the one which is there doesn't have debug features and this is the reason I can't put breakpoint inside of it, even with the source code attached.

@jwojcie
Copy link
Author

jwojcie commented Nov 13, 2024

Just an update on the last issue - RSA PKCS1.5 encryption disallowed. I had to deal with this piece of code:

public byte[] encrypt(final byte[] data, @NonNull final X509Certificate encryptionCertificate)
         throws EncryptionException {
     final CMSEnvelopedDataGenerator cmsEnvelopedDataGenerator = new CMSEnvelopedDataGenerator();
     final JceKeyTransRecipientInfoGenerator jceKeyTransRecipientInfoGenerator;
     try {
 		jceKeyTransRecipientInfoGenerator =
 				new JceKeyTransRecipientInfoGenerator(encryptionCertificate);

turned out that org.bouncycastle.operator.jcajce.JceAsymmetricKeyWrapper is taking AlgorithmIdentifier directy from encryptionCertificate - which is just regular RSA: PKCSObjectIdentifiers.rsaEncryption which are used typically in the soft I deal with.

I thought, ok so I need to generate certificate with PKCSObjectIdentifiers.id_RSAES_OAEP inside which prove to be not an easy task - at least I think openssl doesn't provide such feature. So I did it programatically anyway - but stumbled upon some other issues indicating that is not a good idea. In the end I found out I can tell JceKeyTransRecipientInfoGenerator which algorithm to use, so I settled with below code:

    public byte[] encrypt(final byte[] data, @NonNull final X509Certificate encryptionCertificate)
            throws EncryptionException {
        final CMSEnvelopedDataGenerator cmsEnvelopedDataGenerator = new CMSEnvelopedDataGenerator();
        final JceKeyTransRecipientInfoGenerator jceKeyTransRecipientInfoGenerator;
        try {
            AlgorithmIdentifier algorithmIdentifier =
                    SubjectPublicKeyInfo.getInstance(encryptionCertificate.getPublicKey().getEncoded())
                            .getAlgorithm();

            if (algorithmIdentifier.getAlgorithm().equals(PKCSObjectIdentifiers.rsaEncryption)) {
                jceKeyTransRecipientInfoGenerator =
                        new JceKeyTransRecipientInfoGenerator(
                                encryptionCertificate, createRSAOAEPWithSHA256ForBCFIPS());
            } else {
                jceKeyTransRecipientInfoGenerator =
                        new JceKeyTransRecipientInfoGenerator(encryptionCertificate);
            }
[...]

    private AlgorithmIdentifier createRSAOAEPWithSHA256ForBCFIPS() {
        AlgorithmIdentifier hashAlgorithm = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha256);
        AlgorithmIdentifier mgf1Algorithm =
                new AlgorithmIdentifier(PKCSObjectIdentifiers.id_mgf1, hashAlgorithm);
        AlgorithmIdentifier pSourceAlgorithm =
                new AlgorithmIdentifier(
                        PKCSObjectIdentifiers.id_pSpecified, new DEROctetString(new byte[0]));

        RSAESOAEPparams oaepParams =
                new RSAESOAEPparams(hashAlgorithm, mgf1Algorithm, pSourceAlgorithm);

        return new AlgorithmIdentifier(PKCSObjectIdentifiers.id_RSAES_OAEP, oaepParams);
    }

I think that's fine, but if anybody thinks otherwise please prove me wrong.

@winfriedgerlach winfriedgerlach added the question Further information is requested label Dec 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

4 participants