<div dir="ltr"><div>Hi Sean,</div><div><br></div><div>Thanks for clarifying your idea. I understand your motivation and share your concerns. I can think of how this application-specific knowledge can turn into a library-specific one in real scenarios, which may open the door for undesired dependencies. I also agree with being wary about doing stack walks in a Security Manager style at time of use. We have to give it some thought. Just in case, we reserved the characters ":" and "," in our proposal for the Security Providers Filter [1] [2]. Extending the filter syntax in the future (in a backward compatible way) should not be a problem.</div><div><br></div><div>Martin.-</div><div><br></div><div>--</div><div>[1] - <a href="https://bugs.openjdk.org/browse/JDK-8315487">https://bugs.openjdk.org/browse/JDK-8315487</a></div><div>[2] - <a href="https://github.com/openjdk/jdk/pull/15539">https://github.com/openjdk/jdk/pull/15539</a></div><div><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Jul 13, 2023 at 1:01 PM Sean Mullan <<a href="mailto:sean.mullan@oracle.com">sean.mullan@oracle.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
<br>
On 7/13/23 12:27 PM, Martin Balao wrote:<br>
> On 7/13/23 12:06, Sean Mullan wrote:<br>
>> One other comment that I thought of - is that from a practical<br>
>> standpoint, I think it will be hard to unilaterally disable an algorithm<br>
>> at the JCE layer unless it is so broken that almost no code ever uses<br>
>> it, say MD2 or RC2. There may be cases where a weak algorithm is<br>
>> acceptable, for example using MD5 for a checksum. (For a real example,<br>
>> UUID.nameUUIDFromBytes uses MD5 to generate a UUID).<br>
>><br>
>> If you have a single case in your application where a weak algorithm is<br>
>> ok to use, you won't be able to disable it across the board.<br>
> <br>
> Yes, I agree with this observation. In fact, our original motivation was<br>
> not to disable an algorithm across the board but a specific<br>
> implementation of it —i.e. blocking the implementation from provider X,<br>
> because we want the one from provider Y or prefer the algorithm not to<br>
> be available. What we also have in mind is using this enhancement in<br>
> combination with security profiles that can enforce policies of allowed<br>
> algorithms, at the risk of requiring changes in an application to be<br>
> compliant.<br>
> <br>
>><br>
>> At the risk of complicating your syntax and implementation, it may be<br>
>> worth exploring adding the name of a class to the syntax for cases like<br>
>> this. But my comment is more about thinking about this a bit more first.<br>
>><br>
>> Or perhaps adding some extensibility into the format would be a good<br>
>> idea in case we want to add something like this down the line.<br>
>><br>
> <br>
> I have a couple of questions regarding this idea:<br>
> <br>
> 1) Isn't the class name an implementation detail? My concern is not much<br>
> on how to extend the syntax but on binding the filter value to internal<br>
> names.<br>
<br>
It is an application-specific detail. I would expect this to be applied <br>
by applications that are most familiar with their usage, and not as part <br>
of a global configuration.<br>
<br>
> 2) Why wouldn't a combination of Security Provider + Service Type +<br>
> Algorithm be enough to identify a specific implementation?<br>
<br>
Because that doesn't tell you who is calling the specific <br>
provider/service and whether that use case is acceptable or not. Also <br>
most code that calls JCE APIs doesn't specify a specific provider.<br>
<br>
Again, I think this needs more thought, and I am not suggesting this is <br>
the best course of action, but one thought is a syntax something like this:<br>
<br>
jdk.security.providers.filter=java.util.UUID.nameUUIDFromBytes:MessageDigest.MD5;!*.MessageDigest.MD5;*<br>
<br>
But, that would probably mean extending the implementation to do a stack <br>
walk to check if the specified class was one of the callers, which I am <br>
very wary about doing something like this. But the overall issue still <br>
remains for me. Maybe we should not be providing a way to unilaterally <br>
disable algorithms unless it can be used more effectively in practice. <br>
Otherwise I don't like the idea of telling a user they have to re-enable <br>
the algorithm even if they only have a single case where it is acceptable.<br>
<br>
--Sean<br>
<br>
> Thanks,<br>
> Martin.-<br>
> <br>
> <br>
>> --Sean<br>
>><br>
>><br>
>> On 7/13/23 11:44 AM, Martin Balao wrote:<br>
>>> Hi Sean,<br>
>>><br>
>>> Thanks for your feedback.<br>
>>><br>
>>> Just to give some visibility, we have implemented most of the<br>
>>> functionality and are now working on final adjustments, more tests<br>
>>> coverage, documentation and internal reviews. The implementation is<br>
>>> pretty much aligned to what we previously discussed, with the exception<br>
>>> of algorithm's alias that turned up to have more complexity than<br>
>>> anticipated —particularly in the legacy mode of registering Services—.<br>
>>><br>
>>> We will send a PR for public discussion in the coming weeks.<br>
>>><br>
>>> Martin.-<br>
>>><br>
>>><br>
>>> On 6/14/23 12:40, Sean Mullan wrote:<br>
>>>> This proposal looks pretty good, although I think I would like to see<br>
>>>> more examples and a prototype if you have it.<br>
>>>><br>
>>>> I think this would work well in conjunction with Sean Coffey's<br>
>>>> enhancement to add a security category to the java -XshowSettings option<br>
>>>> [1]. This would help debug issues with the syntax. The provider<br>
>>>> suboption could be enhanced (perhaps by default, perhaps with an<br>
>>>> additional suboption) to show the services that are disabled, ex, with<br>
>>>> the property set to<br>
>>>><br>
>>>> jdk.security.providers.filter=!*.MessageDigest.MD5;<br>
>>>> !*.MessageDigest.MD2; *:<br>
>>>><br>
>>>> it would show something like:<br>
>>>><br>
>>>>            Provider name: SUN<br>
>>>>            Provider information: ...<br>
>>>>            Provider services: (type : algorithm)<br>
>>>>                ...<br>
>>>>                MessageDigest : MD2 (disabled)<br>
>>>>                MessageDigest : MD5 (disabled)<br>
>>>>                ...<br>
>>>><br>
>>>> I would even add that as a debugging tip in the documenting of the<br>
>>>> syntax.<br>
>>>><br>
>>>> --Sean<br>
>>>><br>
>>>> [1] <a href="https://github.com/openjdk/jdk/pull/14394" rel="noreferrer" target="_blank">https://github.com/openjdk/jdk/pull/14394</a><br>
>>>><br>
>>>> On 5/24/23 5:03 PM, Martin Balao wrote:<br>
>>>>> Hi,<br>
>>>>><br>
>>>>> Thanks Anthony for your feedback.<br>
>>>>><br>
>>>>> We've been exploring the syntax and semantics for this new property<br>
>>>>> further, with the goal of making it more consistent and simple while<br>
>>>>> retaining expressiveness power. We understand the importance of clarity<br>
>>>>> to minimize the risk of security providers, service types or algorithms<br>
>>>>> being unexpectedly enabled.<br>
>>>>><br>
>>>>> In this new iteration of the proposal, we explore a filter that has<br>
>>>>> similarities to the serialization filter (jdk.serialFilter). We think<br>
>>>>> that it could be beneficial to leverage on a specification to which the<br>
>>>>> user is familiar already.<br>
>>>>><br>
>>>>><br>
>>>>> General structure<br>
>>>>> ====================<br>
>>>>><br>
>>>>> jdk.security.providers.filter=pattern-1; pattern-2; ...; pattern-n<br>
>>>>><br>
>>>>> The property jdk.security.providers.filter is an overrideable Security<br>
>>>>> property. Thus, a System property with the same name exists and, when<br>
>>>>> specified, overrides any value in its Security counterpart. When not<br>
>>>>> specified (value is null), filtering capabilities are completely<br>
>>>>> disabled: all installed security providers, service types and<br>
>>>>> algorithms<br>
>>>>> are allowed. If any of these properties are set during run time, the<br>
>>>>> filter could be initialized already and the new value may not take<br>
>>>>> effect.<br>
>>>>><br>
>>>>> When filtering capabilities are enabled, each service is checked<br>
>>>>> against<br>
>>>>> the filter before registration. Notice that this affects both the<br>
>>>>> initial list of security providers as well as those dynamically<br>
>>>>> installed during run time. Once a service is registered, instances<br>
>>>>> of it<br>
>>>>> can be obtained and used without any other checks that could affect<br>
>>>>> performance.<br>
>>>>><br>
>>>>> The registration of a service involves a combination of a security<br>
>>>>> provider, service type and algorithm. Each combination is evaluated<br>
>>>>> against the filter patterns, from left to right. When a pattern matches<br>
>>>>> —or, in other words, the rule concerns the service to be registered—, a<br>
>>>>> decision is made: the service will be allowed or denied. When a<br>
>>>>> decision<br>
>>>>> is made, remaining patterns are not checked for the service under<br>
>>>>> consideration. When all patterns are checked and a decision is not<br>
>>>>> made,<br>
>>>>> the default behavior is to deny the service registration.<br>
>>>>><br>
>>>>> Contrary to the serialization filter, white spaces between patterns do<br>
>>>>> not have any significance.<br>
>>>>><br>
>>>>><br>
>>>>> Pattern matching<br>
>>>>> =====================================================<br>
>>>>><br>
>>>>> pattern := ! security-provider.service-type.algorithm<br>
>>>>><br>
>>>>> pattern := security-provider.service-type.algorithm<br>
>>>>><br>
>>>>> A canonical pattern consists of 3 hierarchical levels separated by ".".<br>
>>>>>     From left to right in lexicographic order, these levels denote a<br>
>>>>> security provider, a service type and an algorithm. If a pattern starts<br>
>>>>> with "!", the decision made upon matching is to deny the service<br>
>>>>> registration. Otherwise, the service registration is allowed. White<br>
>>>>> spaces between "!" and the rest of the pattern do not have any<br>
>>>>> significance.<br>
>>>>><br>
>>>>> For a match to be successful, the security provider name, the service<br>
>>>>> type and the algorithm have to match the pattern exactly (case<br>
>>>>> insensitive). If the service type of a security provider interprets the<br>
>>>>> algorithm as a transformation composed of different parts, the full<br>
>>>>> transformation has to be specified in the pattern: the filter takes a<br>
>>>>> conservative approach and does not make any assumptions of what an<br>
>>>>> algorithm name means. For example, "AES" as the algorithm of a<br>
>>>>> canonical<br>
>>>>> filter pattern will not match an "AES/ECB/PKCS5Padding" transformation.<br>
>>>>><br>
>>>>> If an algorithm alias is specified in the filter pattern, a service<br>
>>>>> registering the alias will be matched.<br>
>>>>><br>
>>>>> For convenience, it's possible to specify patterns in non-canonical<br>
>>>>> forms:<br>
>>>>><br>
>>>>> 1) At any level, the security provider, the service type or the<br>
>>>>> algorithm name can contain wildcards ("*") to represent zero or more<br>
>>>>> repetitions of any character;<br>
>>>>><br>
>>>>> 2) The .algorithm part can be omitted to imply all algorithms under the<br>
>>>>> security provider and service type;<br>
>>>>><br>
>>>>> 3) The .service-type.algorithm part can be omitted to imply all service<br>
>>>>> types and algorithms under the security provider; and,<br>
>>>>><br>
>>>>> 4) The non-canonical form #1 can be combined with either #2 or #3.<br>
>>>>><br>
>>>>><br>
>>>>> Security provider, service type and algorithm names escaping<br>
>>>>> =================================================================<br>
>>>>><br>
>>>>> If the security provider, service type or algorithm name contains<br>
>>>>> any of<br>
>>>>> the characters "\", ".", ";" or "*", they have to be escaped by<br>
>>>>> prepending the character "\". If the character "\" is found not<br>
>>>>> escaping<br>
>>>>> a character, it's silently discarded.<br>
>>>>><br>
>>>>> White spaces are discarded at the beginning and end of names.<br>
>>>>><br>
>>>>> It's worth mentioning that the described escaping rules apply to the<br>
>>>>> jdk.security.providers.filter property value as read in<br>
>>>>> java.lang.System::getProperty or java.security.Security::getProperty.<br>
>>>>> Additional escaping might be needed depending on how the property is<br>
>>>>> passed. For example, Security properties require "\" characters to be<br>
>>>>> escaped. Thus, to match a provider name whose name is "\.", a filter<br>
>>>>> would require the "jdk.security.providers.filter=\\\\\\." entry in the<br>
>>>>> java.security file. See more about this in java.util.Properties::load<br>
>>>>> [1].<br>
>>>>><br>
>>>>><br>
>>>>> Examples (correct)<br>
>>>>> ====================<br>
>>>>><br>
>>>>> -- <br>
>>>>><br>
>>>>> Enable all security providers, service types and algorithms:<br>
>>>>><br>
>>>>> jdk.security.providers.filter=<br>
>>>>><br>
>>>>> or<br>
>>>>><br>
>>>>> jdk.security.providers.filter=*<br>
>>>>><br>
>>>>> or<br>
>>>>><br>
>>>>> jdk.security.providers.filter=*.*<br>
>>>>><br>
>>>>> or<br>
>>>>><br>
>>>>> jdk.security.providers.filter=*.*.*<br>
>>>>><br>
>>>>> -- <br>
>>>>><br>
>>>>> Enable everything except for the MD5 algorithm in MessageDigest<br>
>>>>> services<br>
>>>>> when implemented by the SUN security provider:<br>
>>>>><br>
>>>>> jdk.security.providers.filter=!SUN.MessageDigest.MD5; *<br>
>>>>><br>
>>>>> -- <br>
>>>>><br>
>>>>> Enable everything except for the MD5 algorithm in MessageDigest<br>
>>>>> services, irrespective of the security provider:<br>
>>>>><br>
>>>>> jdk.security.providers.filter=!*.MessageDigest.MD5; *<br>
>>>>><br>
>>>>> -- <br>
>>>>><br>
>>>>> Enable everything except for algorithms using MD5, irrespective of the<br>
>>>>> security provider and the service type:<br>
>>>>><br>
>>>>> jdk.security.providers.filter=!*.*.*MD5*; *<br>
>>>>><br>
>>>>> Notice that in this case there are wildcards at the beginning and<br>
>>>>> end of<br>
>>>>> the algorithm name. The reason is to match MD5 uses in algorithms such<br>
>>>>> as HmacMD5, MD5withRSA, PBEWithMD5AndDES, etc.<br>
>>>>><br>
>>>>> -- <br>
>>>>><br>
>>>>> Enable everything except for the RC4 algorithm in Cipher services when<br>
>>>>> implemented by the SunJCE security provider:<br>
>>>>><br>
>>>>> jdk.security.providers.filter=!SunJCE.Cipher.ARCFOUR; *<br>
>>>>><br>
>>>>> or<br>
>>>>><br>
>>>>> jdk.security.providers.filter=!SunJCE.Cipher.RC4; *<br>
>>>>><br>
>>>>> or<br>
>>>>><br>
>>>>> jdk.security.providers.filter=!SunJCE.Cipher.1\.2\.840\.113549\.3\.4; *<br>
>>>>><br>
>>>>> -- <br>
>>>>><br>
>>>>> Enable the SUN security provider only, with all its service types and<br>
>>>>> algorithms. Other security providers must be disabled.<br>
>>>>><br>
>>>>> jdk.security.providers.filter=SUN<br>
>>>>><br>
>>>>> -- <br>
>>>>><br>
>>>>> Enable the SUN security provider only, with all its service types and<br>
>>>>> algorithms except for MessageDigest. Other security providers must be<br>
>>>>> disabled.<br>
>>>>><br>
>>>>> jdk.security.providers.filter=!SUN.MessageDigest; SUN<br>
>>>>><br>
>>>>> -- <br>
>>>>><br>
>>>>><br>
>>>>> Examples (mistakes)<br>
>>>>> ====================<br>
>>>>><br>
>>>>> -- <br>
>>>>><br>
>>>>> Enable everything except for the MD5 algorithm, irrespective of the<br>
>>>>> security provider and the service type:<br>
>>>>><br>
>>>>> jdk.security.providers.filter=*; !*.*.MD5<br>
>>>>><br>
>>>>> This is wrong because the pattern "*" is matched first and a decision<br>
>>>>> allowing MD5 will be made immediately after. The pattern "!*.*.MD5"<br>
>>>>> will<br>
>>>>> never be checked.<br>
>>>>><br>
>>>>> -- <br>
>>>>><br>
>>>>> Enable all SUN service types except for MessageDigest. Disable other<br>
>>>>> security providers.<br>
>>>>><br>
>>>>> jdk.security.providers.filter=!SUN.MessageDigest<br>
>>>>><br>
>>>>> While non-SUN security providers are effectively disabled, this is<br>
>>>>> wrong<br>
>>>>> because SUN services other than MessageDigest will not match any<br>
>>>>> pattern<br>
>>>>> and, by default, the decision is to deny registration.<br>
>>>>><br>
>>>>> -- <br>
>>>>><br>
>>>>> Enable the SunPKCS11 security provider only.<br>
>>>>><br>
>>>>> jdk.security.providers.filter=SunPKCS11<br>
>>>>><br>
>>>>> This is wrong because the SunPKCS11 provider has to be identified by<br>
>>>>> its<br>
>>>>> name instead of its class. A possible name would have the form of<br>
>>>>> SunPKCS11-NAME. In a filter, this can be matched either by<br>
>>>>> "SunPKCS11-NAME" or "SunPKCS11-*".<br>
>>>>><br>
>>>>> -- <br>
>>>>><br>
>>>>><br>
>>>>> Look forward to your thoughts.<br>
>>>>><br>
>>>>> Thanks.-<br>
>>>>><br>
>>>>><br>
>>>>> -- <br>
>>>>> [1] -<br>
>>>>> <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Properties.html#load%28java.io.Reader%29" rel="noreferrer" target="_blank">https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Properties.html#load%28java.io.Reader%29</a><br>
>>>>><br>
>>>>> (†) - Thanks to Francisco Ferrari (@fferrari) for his contributions to<br>
>>>>> this proposal.<br>
>>>>><br>
>>>>><br>
>>>>><br>
>>>>><br>
>>>>> On 2/24/23 14:49, Anthony Scarpino wrote:<br>
>>>>>> Hi Martin,<br>
>>>>>><br>
>>>>>> Interesting proposal.  I think Alternative 1 is a better direction to<br>
>>>>>> explore from a code structure standpoint.  If I remember correctly,<br>
>>>>>> Preferred Provider is accessed when getting a service or instance<br>
>>>>>> of the<br>
>>>>>> algorithm.  That happens on a per-operation basis.  What you<br>
>>>>>> describe is<br>
>>>>>> something that would reshape contents of the ProviderList where<br>
>>>>>> algorithms or services would not be in the list at all.  That is<br>
>>>>>> were I<br>
>>>>>> think #2 gets too complex in trying to handle both in the same<br>
>>>>>> property.<br>
>>>>>>      #2 may end up putting all checks in a per-operation check,<br>
>>>>>> hindering<br>
>>>>>> performance every time as the list grows.<br>
>>>>>><br>
>>>>>> I agree this is mostly used in the FIPS situation or where someone<br>
>>>>>> wants<br>
>>>>>> to disable an algorithm completely, say MD5.  In those cases it's best<br>
>>>>>> to just prevent the algorithm from ever being available.<br>
>>>>>><br>
>>>>>> On the smaller details side that you list.  I think the name<br>
>>>>>> ".enabled"<br>
>>>>>> doesn't fit, particularly as the first thing in the example<br>
>>>>>> disables all<br>
>>>>>> Ciphers :).  I don't have any suggestions at this time.<br>
>>>>>><br>
>>>>>> As far as the syntax.  I think it maybe a bit difficult to parse in<br>
>>>>>> code<br>
>>>>>> and mental to disable all Ciphers, then enable just for SunJCE and<br>
>>>>>> SUN.<br>
>>>>>> The SUN '*" confused me until I realized you were enabling Ciphers.<br>
>>>>>> Seems too easy to get wrong.  I know you weren't making a formal spec,<br>
>>>>>> but we have to start somewhere.<br>
>>>>>><br>
>>>>>> thanks<br>
>>>>>><br>
>>>>>> Tony<br>
>>>>>><br>
>>>>>><br>
>>>>>> On 2/17/23 10:52 AM, Martin Balao wrote:<br>
>>>>>>> Hi,<br>
>>>>>>><br>
>>>>>>> We would like to discuss a limitation in the current configuration<br>
>>>>>>> capabilities for security providers and possible solutions that we<br>
>>>>>>> are<br>
>>>>>>> exploring (†).<br>
>>>>>>><br>
>>>>>>> As you know, current configuration capabilities in java.security<br>
>>>>>>> allow<br>
>>>>>>> users to install security providers, decide their priority in a list<br>
>>>>>>> (security.provider.<n> properties) and even circumvent this priority<br>
>>>>>>> for specific algorithms (jdk.security.provider.preferred property).<br>
>>>>>>> However, there is no granularity in terms of what service types and<br>
>>>>>>> algorithms are enabled once a security provider is installed: it's an<br>
>>>>>>> all or nothing scheme. It is worth noting that security providers can<br>
>>>>>>> bring with them a diverse range of service types. As an example, the<br>
>>>>>>> SUN security provider comes with the following service types:<br>
>>>>>>> SecureRandom, Signature, KeyPairGenerator,<br>
>>>>>>> AlgorithmParameterGenerator, AlgorithmParameters, KeyFactory,<br>
>>>>>>> MessageDigest, CertificateFactory, KeyStore, CertStore, Policy,<br>
>>>>>>> Configuration, CertPathBuilder and CertPathValidator [1].<br>
>>>>>>><br>
>>>>>>> In some cases, the user may need to enforce that all cryptographic<br>
>>>>>>> primitives come from a specific security provider. This could happen,<br>
>>>>>>> for example, when operating in a FIPS-compliant environment or under<br>
>>>>>>> strict security policies. To better illustrate, let's say that the<br>
>>>>>>> user requires that all cryptographic operations are performed in a<br>
>>>>>>> Hardware Security Module (HSM). On the OpenJDK side, this means that<br>
>>>>>>> the implementation for Cipher, Signature, Mac and other cryptographic<br>
>>>>>>> services must be the one in the SunPKCS11 security provider. Let's<br>
>>>>>>> also suppose that other non-cryptographic services such as those for<br>
>>>>>>> certificates validation and TLS are required, and their<br>
>>>>>>> implementation<br>
>>>>>>> is in the SUN and SunJSSE security providers respectively. Setting<br>
>>>>>>> SunPKCS11 at the highest priority of the list is not a strong<br>
>>>>>>> guarantee to ensure that all cryptographic operations come from it:<br>
>>>>>>> it's possible that an algorithm for Signature is not implemented in<br>
>>>>>>> SunPKCS11 or in its underlying token but in the SUN security<br>
>>>>>>> provider.<br>
>>>>>>> Disabling the SUN security provider wouldn't be an option in this<br>
>>>>>>> case<br>
>>>>>>> because we need its certificates validation service.<br>
>>>>>>><br>
>>>>>>> This problem goes beyond OpenJDK default security providers. Even if<br>
>>>>>>> we come up with a new layout for service types, algorithms and<br>
>>>>>>> providers —putting backward compatibility issues aside—, there is<br>
>>>>>>> always the possibility that a 3rd party security provider does not<br>
>>>>>>> follow any services grouping convention. It might also be the case<br>
>>>>>>> that we need to disable a specific algorithm only —i.e. for<br>
>>>>>>> cryptographic policy reasons— and TLS or JAR signing properties fall<br>
>>>>>>> short.<br>
>>>>>>><br>
>>>>>>> In our view, it would be beneficial to add more configuration<br>
>>>>>>> flexibility and control to the existing API in which any security<br>
>>>>>>> provider can be plugged in, in the form of deciding which service<br>
>>>>>>> types and algorithms are enabled for each installed provider.<br>
>>>>>>><br>
>>>>>>> There are 2 alternatives that we are exploring to tackle this<br>
>>>>>>> problem.<br>
>>>>>>><br>
>>>>>>> Alternative #1<br>
>>>>>>> ===========================<br>
>>>>>>><br>
>>>>>>> Introduce a new security property to decide which service types and<br>
>>>>>>> algorithms are enabled for each security provider. The default value<br>
>>>>>>> for this property would be empty, which keeps this feature disabled<br>
>>>>>>> and all services from installed security providers available.<br>
>>>>>>><br>
>>>>>>> As for the new property's syntax and semantics, we've been<br>
>>>>>>> considering<br>
>>>>>>> an allow-list along the lines of:<br>
>>>>>>><br>
>>>>>>> jdk.security.provider.enabled = security-provider-1 {<br>
>>>>>>> service-type-1 :<br>
>>>>>>> alg-1, ... ; ... } , ...<br>
>>>>>>><br>
>>>>>>> Note: we need a formal syntax specification, this is for illustration<br>
>>>>>>> only.<br>
>>>>>>><br>
>>>>>>> As part of the syntax we are considering the use of wildcards (*) to<br>
>>>>>>> match multiple security providers, service types and algorithms, and<br>
>>>>>>> minus signs (-) to remove service types. When a service type is<br>
>>>>>>> removed, the action applies to all algorithms and any attempt to<br>
>>>>>>> specify them explicitly would be an error. The minus sign cannot be<br>
>>>>>>> used at the algorithm level. We are also thinking that in case of a<br>
>>>>>>> partial or total contradiction between conditions, the right-most<br>
>>>>>>> value applies on top of the others. If a security provider, service<br>
>>>>>>> type or algorithm does not exist, we can simply write a debug warning<br>
>>>>>>> and ignore it. As for the name of the algorithms, we can also include<br>
>>>>>>> Ciphers transformations.<br>
>>>>>>><br>
>>>>>>> Example:<br>
>>>>>>><br>
>>>>>>> jdk.security.provider.enabled = * { -Cipher }, SunJCE { Cipher :<br>
>>>>>>> AES/GCM/NoPadding, DES ; Signature }, SUN { * ; -Signature }<br>
>>>>>>><br>
>>>>>>> This would be interpreted as:<br>
>>>>>>><br>
>>>>>>>      * Irrespective of the provider (*), Cipher services should be<br>
>>>>>>> removed (-). This rule would be superfluous in this case because the<br>
>>>>>>> property itself is an allow-list and there is nothing to the left<br>
>>>>>>> that<br>
>>>>>>> enables Cipher service types for any provider.<br>
>>>>>>>      * From the SunJCE security provider, Cipher services with<br>
>>>>>>> AES/GCM/NoPadding and DES transformations are allowed, and Signature<br>
>>>>>>> services with any algorithm are allowed. Notice that there is a<br>
>>>>>>> shortcut here: the algorithm list that follows the service name, "':<br>
>>>>>>> alg-1, ..." is optional. When omitted all the service's algorithms<br>
>>>>>>> are<br>
>>>>>>> enabled.<br>
>>>>>>>      * From the SUN security provider, every service type is allowed<br>
>>>>>>> except Signature (recall that a minus sign can only apply to a<br>
>>>>>>> service, removing all associated algorithms).<br>
>>>>>>><br>
>>>>>>> It's not the goal of this proposal to invalidate property values that<br>
>>>>>>> lead to inconsistent internal states, such as "the Cipher service of<br>
>>>>>>> SunJCE depends on AlgorithmParameters from SUN". This is because the<br>
>>>>>>> combinations for a check are virtually infinite: there can be 3rd<br>
>>>>>>> party security providers with their own semantics and<br>
>>>>>>> dependencies. In<br>
>>>>>>> the same way, we cannot determine at start time any application<br>
>>>>>>> dependencies. It's up to the user to analyze all types of<br>
>>>>>>> dependencies<br>
>>>>>>> before setting a value.<br>
>>>>>>><br>
>>>>>>><br>
>>>>>>> Alternative #2<br>
>>>>>>> ===========================<br>
>>>>>>><br>
>>>>>>> Introduce a boolean security property to turn the value of the<br>
>>>>>>> existing jdk.security.provider.preferred property into the only<br>
>>>>>>> combinations of algorithm, service and provider that are allowed:<br>
>>>>>>><br>
>>>>>>> jdk.security.provider.preferredOnly = true<br>
>>>>>>><br>
>>>>>>> The default value for the new property would be "false", keeping the<br>
>>>>>>> current "preferred" behavior in which all algorithms and services<br>
>>>>>>> from<br>
>>>>>>> installed security providers are available.<br>
>>>>>>><br>
>>>>>>> Contrary to Alternative #1, the user has to explicitly list the<br>
>>>>>>> algorithms and cannot rely on wildcards to express wide categories<br>
>>>>>>> such as "all Cipher algorithms from SunJCE" or "all algorithms from<br>
>>>>>>> SunJCE". The use of minus signs to remove service types or algorithms<br>
>>>>>>> wouldn't be available either.<br>
>>>>>>><br>
>>>>>>> In order to mitigate the burden on users we can consider extending<br>
>>>>>>> jdk.security.provider.preferred syntax as long as we keep<br>
>>>>>>> backward-compatibility and stay within the boundaries of a<br>
>>>>>>> "preferred"<br>
>>>>>>> semantics. For example, we can accept a value of<br>
>>>>>>> "jdk.security.provider.preferred=SunJCE" to mean that any service and<br>
>>>>>>> any algorithm from SunJCE is either preferred or allowed,<br>
>>>>>>> depending on<br>
>>>>>>> the value of jdk.security.provider.preferredOnly. This case would<br>
>>>>>>> be a<br>
>>>>>>> service type and algorithm wildcard. We can also define an<br>
>>>>>>> algorithms-only wildcard, such as Cipher.*:SunJCE.<br>
>>>>>>><br>
>>>>>>> Alternative #2 has the advantage of reusing most or all of the<br>
>>>>>>> existing syntax. However, it's worth noticing that it implies an<br>
>>>>>>> overloaded semantic that can turn confusing or inconvenient in some<br>
>>>>>>> cases. As an example, a user that relies on the prioritized security<br>
>>>>>>> providers list for most of the algorithms and has only a few<br>
>>>>>>> preferred<br>
>>>>>>> exceptions, would need to express preferences by extension upon<br>
>>>>>>> turning on this feature. Alternative #1 keeps preferences and<br>
>>>>>>> availability as two separate concepts, in a more clear way.<br>
>>>>>>><br>
>>>>>>><br>
>>>>>>> Thanks,<br>
>>>>>>> Martin.-<br>
>>>>>>><br>
>>>>>>> -- <br>
>>>>>>> [1] -<br>
>>>>>>> <a href="https://docs.oracle.com/en/java/javase/17/security/oracle-providers.html#GUID-3A80CC46-91E1-4E47-AC51-CB7B782CEA7D" rel="noreferrer" target="_blank">https://docs.oracle.com/en/java/javase/17/security/oracle-providers.html#GUID-3A80CC46-91E1-4E47-AC51-CB7B782CEA7D</a><br>
>>>>>>> (†) - Thanks to @fferrari for his contributions to this proposal.<br>
>>>>>>><br>
>>>>>><br>
>>>>><br>
>>>><br>
>>><br>
>><br>
> <br>
<br>
</blockquote></div></div>