RFR: 8315487: Security Providers Filter [v17]
Xue-Lei Andrew Fan
xuelei at openjdk.org
Tue Dec 17 22:15:39 UTC 2024
On Tue, 17 Dec 2024 17:57:02 GMT, Martin Balao <mbalao at openjdk.org> wrote:
>> In addition to the goals, scope, motivation, specification and requirement notes in [JDK-8315487](https://bugs.openjdk.org/browse/JDK-8315487), we would like to describe the most relevant decisions taken during the implementation of this enhancement. These notes are organized by feature, may encompass more than one file or code segment, and are aimed to provide a high-level view of this PR.
>>
>> ## ProvidersFilter
>>
>> ### Filter construction (parser)
>>
>> The providers filter is constructed from a string value, taken from either a system or a security property with name "jdk.security.providers.filter". This process occurs at sun.security.jca.ProvidersFilter class —simply referred as ProvidersFilter onward— static initialization. Thus, changes to the filter's overridable property are not effective afterwards and no assumptions should be made regarding when this class gets initialized.
>>
>> The filter's string value is processed with a custom parser of order 'n', being 'n' the number of characters. The parser, represented by the ProvidersFilter.Parser class, can be characterized as a Deterministic Finite Automaton (DFA). The ProvidersFilter.Parser::parse method is the starting point to get characters from the filter's string value and generate state transitions in the parser's internal state-machine. See ProvidersFilter.Parser::nextState for more details about the parser's states and both valid and invalid transitions. The ParsingState enum defines valid parser states and Transition the reasons to move between states. If a filter string cannot be parsed, a ProvidersFilter.ParserException exception is thrown, and turned into an unchecked IllegalArgumentException in the ProvidersFilter.Filter constructor.
>>
>> While we analyzed —and even tried, at early stages of the development— the use of regular expressions for filter parsing, we discarded the approach in order to get maximum performance, support a more advanced syntax and have flexibility for further extensions in the future.
>>
>> ### Filter (structure and behavior)
>>
>> A filter is represented by the ProvidersFilter.Filter class. It consists of an ordered list of rules, returned by the parser, that represents filter patterns from left to right (see the filter syntax for reference). At the end of this list, a match-all and deny rule is added for default behavior. When a service is evaluated against the filter, each filter rule is checked in the ProvidersFilter.Filter::apply method. The rule makes an all...
>
> Martin Balao has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains one additional commit since the last revision:
>
> Add a debug message to inform the Filter property value read.
>
> See more in https://mail.openjdk.org/pipermail/security-dev/2024-October/041800.html
>
> Co-authored-by: Martin Balao Alonso <mbalao at redhat.com>
> Co-authored-by: Francisco Ferrari Bihurriet <fferrari at redhat.com>
Sorry, I meant BCFIPS provider as linked in the URL I provided. Which may
not be able to use putService as it needs to support back to Java 1.5, IIRC.
Xuelei
On Tue, Dec 17, 2024 at 8:38 AM Martin Balao Alonso <
***@***.***> wrote:
> 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.
>
> FYI. I found a case
> <https://www.bouncycastle.org/download/bouncy-castle-java-fips/> that:
>
> 1. Override getService/getServices, has its own logic to use put
> properties.
> 2. Use extended Provider.Service, but not Provider.Service directly.
> 3. call put() and get() internally. But because of #1 and #2, the
> provider filter theory may not work, please verify.
> 4. overrides newInstance without calling its parent.
> 5. uses non-Java SE service types
>
> This is a popular provider (IIRC 17% marketing share per a report). I
> think you might have evaluated it and confirmed that the theory works.
> Otherwise, please make sure the compatibility issues is limited and the
> theory works for it. Thank you!
>
> BC has some sort of cache in BouncyCastleProvider::serviceMap but calls
> putService (BouncyCastleProvider.super.putService(service)) anyways.
>
> public static void main(String[] args) throws Throwable {
> System.setProperty("jdk.security.providers.filter",
> "!BC.Cipher.AES/CBC/PKCS5Padding; *");
> Provider bc = new BouncyCastleProvider();
> System.out.println("Name BC: " + bc);
> Cipher c1 = null;
> Cipher c2 = null;
> try {
> c1 = Cipher.getInstance("AES/CBC/PKCS5Padding", bc);
> } catch (NoSuchAlgorithmException e) {}
> try {
> c2 = Cipher.getInstance("AES/GCM/NoPadding", bc);
> } catch (NoSuchAlgorithmException e) {}
> System.out.println("Cipher AES/CBC/PKCS5Padding (BC): " + c1);
> System.out.println("Cipher AES/GCM/NoPadding (BC): " + c2);
> }
>
> Name BC: BC version 1.79
> Cipher AES/CBC/PKCS5Padding (BC): null
> Cipher AES/GCM/NoPadding (BC): Cipher.AES/GCM/NoPadding, mode: not initialized, algorithm from: BC
>
> —
> Reply to this email directly, view it on GitHub
> <https://github.com/openjdk/jdk/pull/15539#issuecomment-2548981071>, or
> unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AQSB3EDFX2XSXU7252LVXL32GBHRTAVCNFSM6AAAAAA4HWWOTGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDKNBYHE4DCMBXGE>
> .
> You are receiving this because you were mentioned.Message ID:
> ***@***.***>
>
-------------
PR Comment: https://git.openjdk.org/jdk/pull/15539#issuecomment-2549751897
More information about the core-libs-dev
mailing list