RFR: 8315487: Security Providers Filter [v13]

Xue-Lei Andrew Fan xuelei at openjdk.org
Fri Dec 13 05:16:38 UTC 2024


On Thu, 12 Dec 2024 22:54:59 GMT, Martin Balao <mbalao at openjdk.org> wrote:

>>> In rare situations, a third-party provider can override java.security.Provider.Service::newInstance and return an unvetted service implementation (SPI).
>> 
>> 
>> Well, there is a concern of mine. I don't agree the case is rare. What if you are making a wrong judgment about it popularity here? Did you have data to support your point. How could you get the case covered even for the rare case even if it is really rare?
> 
> While our perception of what is common and rare may be different, services overriding `newInstance` will be filtered anyways when used for Java SE service types (Cipher, Signature, Mac, etc). It's only the combination of a Provider that overrides getService/getServices + does not call putService/put + overrides newInstance without calling its parent + uses a non-Java SE service type that would be unfiltered.

OK, I have a better sense about what's the rare you are referring to.  If you are able to make it, it may means all popular providers should have been covered.  I did not find a provider yet that overrides getService/getServices + does not call putService/put + overrides newInstance without calling its parent + uses a non-Java SE service type.  It will simply imply that this solution works.

If the 3rd filter works, do you still need the 1st and 2nd filter?

And then the left question is: are you able to cover all crypto compliant case with the built-in filter and filter syntax.  If you have a chance to verify FIPS (I think you should have done it), please let me know if you are able to make a FIPS compliant filter with your proposal, which requires different algorithms, different strengths, different EOL times, different parameters.  Thanks!


>> With a new public API, for example ServicePermission.permit(Provider service). I don't think you need the 2nd filter for java.security.Provider.Service::newInstance any longer. All you need is to updates the following 2 or 3 methods, plus a few bug fixes out of the scope of this JEP: provider.putService() (optional, for performance improvement only) provider.getService() provider.getServices()
> > And document the public API and have third party provider follow the spec and use the API. Without a public API, there is not much we can do for unknown third party providers. Even with the public API, third party's provider may not follow it. But they now have a way to follow the spec, and application also have solutions for those that do not follow the new spec yet.
> 
> Our proposal makes filtering transparent to security providers (including 3rd-party ones) and does not require any cooperation: 3rd party security providers will be filtered whether they want/like it or not. If my understanding is correct, your proposal requires cooperation from 3rd-party providers so they invoke a public API and follow the filter's verdict. Even if they implement this API, older versions of the same provider will not be filter-aware. This would make the filter weaker, and compliance/enforcement provider-dependent. For example, you'll need to check the provider version and implementation to know if it is filter-aware.

You are right.  My proposal need third party provider takes actions.  But FIPS compliant is not something one can choose freely from, the provider must be examined and approved.  So I don't worry about it.

> 
> > Let's see the scenarios:
> > 
> > 1. Define a public service API: ServicePermission.permit(Provider service), and a method to get the service so that it can be set with a security property (see [UUID.fromString improvement to be more efficient when parsing 36-byte valid values #4](https://github.com/openjdk/jdk/pull/4)).
> > 2. Using the service specified in [UUID.fromString improvement to be more efficient when parsing 36-byte valid values #4](https://github.com/openjdk/jdk/pull/4), update  provider.getService() and provider.getServices(), and submit to JDK repository.
> > 3. Application implement the ServicePermission service, ThisIsMyFilterProvider (JDK could have a java.security property filter implementation in a new JEP, but it is not necessarily have any value in default JDK).
> > 4. Update java.security update, java.security.filter="ThisIsMyFilterProvider", default value is empty.
> > 5. Enjoy it.
> > 
> > > are we going to have different syntax depending on the 3rd-party filter implementor?
> > 
> > 
> > No, there is not syntax to maintain at all, unless you want to define a specific ServicePermission provider. You can do that with your proposal about the syntax for default JDK, and enforce it for your own proposal. You don't want to worry about those applications that don't use your proposal: java.security.filter=my-filter-Provider-with-my-loved-syntax
> 
> If my understanding is correct, your proposal opens the door for filter providers that may have, each of them, their own configuration to specify what is allowed and what is not. Statically determining what is filtered is not as easy as reading `java.security.filter` and interpreting a unique syntax: you need to analyze how 3rd-party filter providers are configured. This is what I mean by more complexity.

I see your point.  I worry about more if the built-in filter meets the requirements or not.  With a flexible API, you don't have to take the responsibility any longer.


> 
> > > The problems of filtering by algorithm parameters and by use (e.g. MD5 for UUID) are not easy to solve, will require further discussion and are orthogonal to a pluggable filter.
> > 
> > 
> > No, it is not easy for your proposal. But it is not that hard with a customizable ServicePermission.permit(Provider service) APIs. I think smart developers could have it addressed for specific environment, so that we don't need to worry about them for a general approach for all environment.
> 
> To filter by use, you need to know who the caller is (call stack, more specifically) and whether or not the use should be allowed. Java SE service types invoke the filter in getInstance but cache the filter decision in the Service instance for efficiency. To filter by use we would need to call the filter for every single getInstance call (it's not the service any more, but who is getting a reference to the service), and pass the call stack perhaps. Even if we do that, once an SPI instance is created, the filter loses track of further uses. This problem is orthogonal to who makes the decision (built-in? 3rd-party?), and it's not an easy one to solve.
>
> 
> I don't see how the problem of filtering with finer granularity would be addressed either. The problem is not the implementation —in fact, that would be the easy part for the built-in filter—, the problem is how concepts are less universal once you go down the algorithm level. In other words, it's not a single rule that applies to any security provider anymore but you need to write rules tailored to each provider —e.g. you need to know what algorithm parameters a provider use for X algorithm, how values are specified (bits? bytes?) and that will be reflected in the filtering rule—. This problem is orthogonal to who makes the filtering decision.
> 

I cannot speak for your experience, but I see it differently.  There might be guys smarter than me could get it addressed.  FIPS is not something new, the industry has been able to ship their FIPS-compliant products for many years, and MD5 has been successfully removed or by-passed in practice.

> > It looks like more simple, powerful and having actual requirements, is it?
> 
> I don't see it in the same way at the moment, but I'll let other engineers weigh-in and follow the discussion. @adinn ? @franferrax ?

Different options if the value of PR review.

Thank you!

-------------

PR Comment: https://git.openjdk.org/jdk/pull/15539#issuecomment-2540570793


More information about the core-libs-dev mailing list