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

bc-fips 2.0.0 is not OSGi compatible #1769

Open
gabrielandrade2 opened this issue Aug 6, 2024 · 10 comments
Open

bc-fips 2.0.0 is not OSGi compatible #1769

gabrielandrade2 opened this issue Aug 6, 2024 · 10 comments

Comments

@gabrielandrade2
Copy link

The project I am currently working on is built on top of an Apache Karaf distribution; thus making use of the OSGi framework.

We have integrated the FIPS variant of BouncyCastle (version 1.0.2.4) into our system without any issues. However, during the migration process to the newly released 2.0.0 version, I am experiencing some missing requirement issues when trying to compile the Karaf distribution.

I noticed that the 2.0.0 version of bc-fips doesn't have an OSGi-compliant manifest. None of the mandatory OSGi fields are present and the lack of Export-Package explains the issue I am having.

[ERROR] Message: Unable to resolve root: missing requirement [root] osgi.identity; osgi.identity=my-framework; type=karaf.feature; version=22.0.0.SNAPSHOT; filter:="(&(osgi.identity=my-framework)(type=karaf.feature)(version>=22.0.0.SNAPSHOT))"
[caused by: Unable to resolve my-framework/22.0.0.SNAPSHOT: missing requirement [my-framework/22.0.0.SNAPSHOT] osgi.identity; osgi.identity=my-libraries; type=karaf.feature; version="[22.0.0.SNAPSHOT,22.0.0.SNAPSHOT]"
[caused by: Unable to resolve my-libraries/22.0.0.SNAPSHOT: missing requirement [my-libraries/22.0.0.SNAPSHOT] osgi.identity; osgi.identity=bcpkix; type=osgi.bundle; version="[2.0.7,2.0.7]"; resolution:=mandatory
[caused by: Unable to resolve bcpkix/2.0.7: missing requirement [bcpkix/2.0.7] osgi.wiring.package; filter:="(&(osgi.wiring.package=org.bouncycastle.asn1)(version>=2.0.0)(!(version>=2.1.0)))"]]]

I was able to modify the maven library to be OSGi-compliant by using the bnd.sh script in this repo paired with the 7.0 version of bnd as it provides support for multi-release jars. (I attached the resulting jar here).
With this jar, I was able to successfully compile and run my Karaf distribution

Interestingly, I noticed that other 2.0 bc libraries do provide OSGi-compliant manifests, such as bcpkix-fips or bcutil-fips.

Were the OSGi headers purposefully removed? Or is it a simple mistake on the 2.0.0 release of bc-fips?

@DavidHenri008
Copy link

Any news about this?

@dghgit
Copy link
Contributor

dghgit commented Sep 2, 2024

The problem was more that when the original submission went in there was no real tooling for dealing with multi-release jar.

The new jar looks better, but it's still missing the multi-release manifests, the only way I've found of getting these to add correctly (which is what was done with the additional jars) is via the gradle plugin, however everything was frozen until we got the certificate. I'll try and bump this up the list.

@Pharell
Copy link

Pharell commented Sep 3, 2024

An addition to the missing osgi compatibility:

We could deploy the modified bc-fips-2.0.0-osgi.jar in Karaf 4.4.4 but when initializing BouncyCastleFipsProvider the verification fails in FipsStatus with marker = "jar:bundle://a653bb1c-548b-4779-9c16-6e6897c2d394_336.0:0/!/" which is not supported:
org.bouncycastle.crypto.fips.FipsOperationError: Module checksum failed: unable to find at org.bouncycastle.crypto.fips.FipsStatus.checksumValidate(Unknown Source) ~[?:?] at org.bouncycastle.crypto.fips.FipsStatus.isReady(Unknown Source) ~[?:?] at org.bouncycastle.crypto.CryptoServicesRegistrar.getDefaultMode(Unknown Source) ~[?:?] at org.bouncycastle.crypto.CryptoServicesRegistrar.<clinit>(Unknown Source) ~[?:?] at org.bouncycastle.jcajce.provider.ProvSecureHash$MD5.configure(Unknown Source) ~[?:?] at org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider.<init>(Unknown Source) ~[?:?]

@gabrielandrade2
Copy link
Author

gabrielandrade2 commented Sep 4, 2024

@Pharell As far as I understand, you won't be able to pass the validation using the modified jar as it won't match the checksum of the validated FIPS release.

It was mainly created as a test to check whether the manifest was the only issue.

@Pharell
Copy link

Pharell commented Sep 4, 2024

@gabrielandrade2 I am aware that the bundle only resolves with the additional osgi-headers and that the checksum is changed when modifying the file content.

I just wanted to add that - when actually initializing the provider - the checksum is not loaded because the prefix of the marker ("jar:bundle") is not recognized as valid.

So no check is executed at all and the initialization fails.

@dghgit
Copy link
Contributor

dghgit commented Sep 11, 2024

Okay, try

https://downloads.bouncycastle.org/fips-java/osgi/bc-fips-2.0.0.jar

this has the OSGI properties in the primary manifest. We couldn't add the extra files as a code change is required to ignore them in the checksum calculation the checksum cannot be changed - we will in the next release though. It appears to activate the jar in karaf, not sure what other implications there might be though.

@gabrielandrade2
Copy link
Author

@dghgit
I tested the jar you provided and confirmed that I) can build my Karaf distribution with it.
As you said, it also appears as an active bundle in Karaf, however I still get the same error as @Pharell encountered.

As far as I know, such an error was fixed for version 1.0.2.5 of bc-fips, so maybe it was not ported to 2.0.0 (and 2.0.1)?

By the way, do you have an estimate for the next release date?

@dghgit
Copy link
Contributor

dghgit commented Sep 18, 2024

@gabrielandrade2 I've checked the jar, you shouldn't see that error, the checksum in the jar is correct. It sounds like there's something else going on, are you able to confirm what URI the jar thinks it's using for checksum calculation? Is it possible to provide a more complete stack trace? Thanks.

@Pharell
Copy link

Pharell commented Sep 19, 2024

The stacktrace above states that the checksum itself is not wrong but cannot even been found at all: "Module checksum failed: unable to find".

In the source code of bc-fips-2.0.0 this is thrown in FipsStatus.checksumValidate() because the resource name cannot be loaded:

      final String rscName = AccessController.doPrivileged(new PrivilegedAction<String>()
      {
          public String run()
          {
              return getResourceName();
          }
      });
      if (rscName == null)
      {
          moveToErrorStatus(new FipsOperationError("Module checksum failed: unable to find"));
      }

In FipsStatus.getResourceName() a marker file is tried to be loaded (LICENSE.class). The path to the marker is handled for different environments, but not for an OSGi-environment, where the marker String value starts with "jar:bundle://a653bb1c-548b-4779-9c16-6e6897c2d394_336.0:0/!/":


        final String marker = getMarker(LICENSE.class, markerName); // <--- "jar:bundle://..."

        if (marker != null)
        {
            if (marker.startsWith("jar:file:") && marker.contains("!/"))
            {
                try
                {
                    String jarFilename = URLDecoder.decode(marker.substring("jar:file:".length(), marker.lastIndexOf("!/")), "UTF-8");

                    result = jarFilename;
                }
                catch (IOException e)
                {
                    // we found our jar file, but couldn't open it
                    result = null;
                }
            }
            else if (marker.startsWith("file:") && marker.endsWith(".jar"))
            {
                try
                {
                    String jarFilename = URLDecoder.decode(marker.substring("file:".length()), "UTF-8");

                    result = jarFilename;
                }
                catch (IOException e)
                {
                    // we found our jar file, but couldn't open it
                    result = null;
                }
            }
            else if (marker.startsWith("jrt:"))
            {
                 return marker;
            }
            else if (marker.startsWith("file:"))
            {
                 return marker;    // this means we're running from classes (development)
            }
        }
        return result; // <--- is never set because no check matches

So the returned result for marker stays null which leads to the exception in FipsStatus.checksumValidate().

In v1.0.2.5 there is a matching check, but I assume the jar cannot not be loaded from the resulting name, so the result is set to null:

            if (marker.startsWith("jar:") && marker.contains("!/")) // <-- matches : "jar:bundle://a653bb1c-548b-4779-9c16-6e6897c2d394_336.0:0/!/"
            {
                try
                {
                    int secondColon = marker.indexOf(':', 4);
                    if (secondColon == -1)
                    {
                        return null;
                    }
                    String jarFilename = URLDecoder.decode(marker.substring(secondColon + 1, marker.lastIndexOf("!/")), "UTF-8"); // result is "//a653bb1c-548b-4779-9c16-6e6897c2d394_336.0:0"
                    result = jarFilename;
                }
                catch (IOException e) 
                {
                    // we found our jar file, but couldn't open it // <--- there is actually no code accessing the file, right?
                    result = null;
                }
            }

In the futher processing of the value of rscName "//a653bb1c-548b-4779-9c16-6e6897c2d394_336.0:0", the code in FipsStatus.checksumValidate() tries to load the jar file in the else-branch:

       ...
       else
        {
            JarFile jarFile = AccessController.doPrivileged(new PrivilegedAction<JarFile>()
            {
                public JarFile run()
                {
                    try
                    {
                        return new JarFile(rscName); // <-- I assume this to fail with rscName =  "//a653bb1c-548b-4779-9c16-6e6897c2d394_336.0:0"
                    }
                    catch (IOException e)
                    {
                        return null;
                    }
                }
            });
        

The value of jarFile is null because of the IOException so the following null-check before the checksum validation is not met and there is no checksum validation at all but also no exception is thrown.

So this works in OSGi but skips checksum validation at all which is probably not intended.

@dghgit
Copy link
Contributor

dghgit commented Sep 21, 2024

Okay, this may need a bit more thought... would you email me at [email protected] about this? I think I'll need to you to try a couple of things out for me, please mention "github #1769" in the subject line (spam filtering sometimes over enthusiastic...)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants