RFD: Security Providers Filter (JEP)

Sean Mullan sean.mullan at oracle.com
Wed Nov 27 18:05:32 UTC 2024


Hi Martin,

 > We reviewed the full text and found no other changes to be made for now.
 > We are working in splitting the PR into two, so the refactoring for
 > class Provider and bug fixes can make their way first.

I think this is a good plan. Do you plan to decouple the refactoring 
from the JEP and propose it under a different issue? I think that would 
make the most sense as long as the refactoring has no direct 
dependencies on the JEP.

 > Any other comments about the JEP?

We have been very busy with JDK 24 deliverables. Let's sync up again on 
the JEP after RDP1.

--Sean

On 11/26/24 5:52 PM, Martin Balao wrote:
> Hello Sean,
> 
> We've made the following adjustments to the JEP [1]:
> 
> 1) Paragraphs starting with "When a security provider is installed..." 
> and "The filter applies to services..." replaced with paragraphs 
> starting with "The filter applies to services..." and "Each service is 
> evaluated by...". The purpose of this change was to better describe the 
> multi-layer filtering strategy. We fixed a minor error in the description.
> 
> 2) In Non-Goals, we clarified that characters are reserved in the syntax 
> (i.e. ":" and ",") with the purpose of extending the filter in the 
> future to provide more granularity in services selection: "(...) With 
> that said, extensions to this proposal may be explored in the future and 
> characters such as `:` and `,` will be reserved in the filter syntax for 
> this purpose.".
> 
> 3) Sub-section "Filtering at the ::getInstance API level only" added to 
> the Alternatives discussion.
> 
> 4) Sub-section "Leveraging on the existing 
> java.security.Provider::configure API to configure security providers" 
> added to the Alternatives discussion.
> 
> We reviewed the full text and found no other changes to be made for now. 
> We are working in splitting the PR into two, so the refactoring for 
> class Provider and bug fixes can make their way first.
> 
> Any other comments about the JEP?
> 
> Thanks,
> Martin.-
> 
> -- 
> [1] - https://bugs.openjdk.org/browse/JDK-8325511
> 
> 
> 
> On 10/18/24 14:55, Martin Balao wrote:
>> Hello Sean,
>>
>> On 9/19/24 12:00, Sean Mullan wrote:
>>> Hi Martin,
>>>
>>> Our team at Oracle has done another review of the proposed feature 
>>> and we have some questions that we would like to discuss below.
>>>
>>> This is a significant effort that would add some valuable features to 
>>> the Security Provider mechanism. However, this is also modifying an 
>>> important core function used by all JCA/JCE APIs to locate 
>>> implementations, so we want to make sure we spend the time to review 
>>> all aspects of the proposal thoroughly.
>>>
>>
>> Thanks for reviewing our proposal. We totally understand and are happy 
>> to have such a thorough review. It is in the best interest of the 
>> whole community and us to get this right.
>>
>>> - The current implementation introduces behavior changes in the 
>>> Provider API which we believe would need to be specified in the 
>>> specification. For example, if an application registers a service 
>>> that is restricted by   the filter using the Provider API, then that 
>>> service won't be returned by methods such as Provider.getServices(). 
>>> This is a behavior change in the API. I don't think it could be 
>>> specified as an implementation note, since it changes the specified 
>>> behavior of these methods.
>>>
>>> Adding specification changes will make any backport much more 
>>> difficult, if that was one of your goals.
>>
>> We agree that our proposal affects the behavior of 
>> Provider::getService(s) APIs and that a specification change is 
>> required. We are aware of this extra complexity but, in the interest 
>> of having the best solution possible for the long term, are willing to 
>> have the discussion. Our expectation is to have the Filter included in 
>> JDK 25 and have no plans for backports to earlier releases. With that 
>> said, if it takes longer to integrate the Filter into JDK main line, 
>> we will still be interested in a backport to JDK 25.
>>
>>>
>>> - Did you consider implementing the filtering mechanism at a higher 
>>> layer, in the getInstance methods? This could possibly avoid the 
>>> specification concerns above, as the behavior could potentially be 
>>> added as implementation notes in the getInstance methods, similar to 
>>> the implementation note for the jdk.security.provider.preferred 
>>> Security property.
>>
>> Yes, we considered that option. We just noticed that it is not in the 
>> Alternatives segment of the JEP. We will add it in the coming days. 
>> Being ::getInstance a public API and the Filter altering its behavior 
>> in terms of what is returned, we'd rather handle this alternative as a 
>> specification change as well. In any case, the main reason why we 
>> opted for filtering at the Service level is to handle any service type 
>> in a uniform and consistent way, including service types defined by 
>> 3rd-party applications/libraries/providers. Having taken 
>> the ::getInstance path, we would have had to either not support 3rd- 
>> party service types or create a new public API in the Filter to query 
>> whether a service is allowed or denied. This approach would have 
>> opened the door for flaws or inconsistencies in how 3rd-party 
>> implementations handle Filter decisions. Besides this, we thought that 
>> obtaining a service instance with Provider::getService(s) that cannot 
>> be obtained and used by ::getInstance could introduce some confusion. 
>> This would have had an impact not only programmatically but in - 
>> XshowSettings:security:providers.
>>
>>>
>>> - The syntax doesn't currently support key size constraints, or 
>>> algorithm constraints that are not specified in algorithm names, such 
>>> as the parameters used with the RSASSA-PSS algorithm. How would you 
>>> add support for these in the future?
>>>
>>
>> We reserved the colon (:) and comma (,) characters in the syntax for 
>> this purpose. As these characters must be escaped, we can extend the 
>> syntax in the future to allow further constraints (e.g. key size, 
>> algorithm constraints) in a backward-compatible way.
>>
>> We added the following reference in the JEP:
>>
>> "In addition, identifying services with a granularity finer than an 
>> algorithm name or alias (e.g. based on key size or other algorithm 
>> parameters) is not under the scope at this time. With that said, 
>> extensions to this proposal may be explored in the future and 
>> characters will be reserved in the filter syntax for this purpose."
>>
>> We also mentioned the full list of reserved characters:
>>
>> "The following characters, when part of one of the listed levels, must 
>> be escaped by prepending a '\' character: '!', '*', ' ' (white space), 
>> '.', ';', '\', ':' and ','."
>>
>> We did not connect the two references by matching the concept of finer 
>> granularity with the reserved characters for that purpose. We can add 
>> a loose connection. However, we prefer not to prescribe the exact 
>> syntax now as it is a non-goal and would require further analysis and 
>> to explore implementations.
>>
>> One thing to consider here is that the use of one of the reserved 
>> characters (e.g. ':') can open the door for an extension of the syntax 
>> with new reserved tokens and characters. For example: 
>> SunJCE.Cipher.AES : keySize > 128. In this case, '>' does not need to 
>> be reserved for the provider name, service type or algorithm. For the 
>> algorithm constraint, 'keySize' and '>' are assigned a specific meaning.
>>
>>> - Does the filtering work for providers that are not registered, and 
>>> just passed into the getInstance methods?
>>>
>>
>> Yes, it does. For most providers, filtering occurs when they invoke 
>> Provider::putService/put APIs. In very rare cases, a Provider may not 
>> invoke Provider::putService/put APIs and still return a Service 
>> overriding Provider::getService(s). In that situation, we filter when 
>> Service::newInstance is invoked. In theory, it is possible that a 
>> Service subclass overrides Service::newInstance. In such extreme 
>> circumstances, we filter at the ::getInstance level. The last case 
>> will not apply to 3rd-party service types, but should be extremely 
>> unlikely.
>>
>>> - Did you consider implementing this as a Provider.configure option? 
>>> There are pros/cons to doing that, but given that the configure 
>>> method is designed to configure providers, we think it should be
>>> considered and described in the Alternatives section.
>>>
>>
>> We did not consider Provider::configure. We will add it to the 
>> Alternatives section if you deem it important. I personally see more 
>> cons than pros but if someone has a different opinion and wants to 
>> advocate for it, we're happy to have a discussion.
>>
>>> -  Would early initialization of the filter inadvertently triggered 
>>> by a cryptographic operation (for example, when verifying a signed 
>>> JAR on the classpath) cause subsequent settings of the filter by an 
>>> application at runtime to be ignored? If so, this is something that 
>>> could easily go undetected, as the filter could be silently ignored 
>>> and thus restrictions not enforced as expected - it may be worth 
>>> considering throwing an exception if you can detect that the property 
>>> has already been set and processed. The logging and debugging 
>>> mechanisms are helpful but I view them as being more useful when 
>>> testing the filter or later debugging of issues.
>>
>> Our understanding is that in such an event the Filter would be 
>> initialized when the ClassLoader does JAR verification. If this is the 
>> case, programmatically defining a Filter in the signed JAR should not 
>> work. @Francisco will create a proof-of-concept to confirm this 
>> hypothesis in the coming days.
>>
>> We agree that throwing an exception in such a case would be ideal. 
>> However, this type of change —as we see it— involves a specification 
>> change in System::setProperty/Security::setProperty as that's the only 
>> interface to set a Filter value programmatically. We are open to 
>> having this discussion.
>>
>> Another alternative would be to reserve the property in 
>> System::setProperty/Security::setProperty and throw an exception 
>> irrespective of the Filter status. We think that setting the Filter 
>> programmatically should not be recommended for general use. However, 
>> this would prevent advanced users that know how things are initialized 
>> from benefiting.
>>
>>>
>>> - Does the additional searching for Cipher transformations cause 
>>> significant performance issues?
>>>
>>
>> We don't think so. When providers register the full "alg/mode/padding" 
>> as algorithm name, transformation queries against the filter are done 
>> at registration time (Provider::putService/put invocation) and cached 
>> in the Service instance. It's true that queries may be done at run 
>> time to explore different transformation combinations 
>> (e.g. ::getInstance of "alg/mode/padding" may explore services that 
>> registered "alg/mode", "alg//padding" and "alg" as algorithm name). 
>> However, these transformation queries are cached per Service instance 
>> after the Filter decision is made. In the worst case —extremely 
>> unlikely—, a provider may register 4 services relevant for the 
>> transformation (e.g. alg/mode/padding, alg/mode, alg//padding and alg) 
>> and the Filter blocks the transformation —if the Filter allows the 
>> transformation, the first service will be used and the others won't be 
>> queried because it is a lazy mechanism—. This case would require 3 
>> queries against the filter —the "alg/mode/padding" decision is read 
>> from the Service's cache— when they are not in the transformations 
>> cache. The reason why the transformation cache is per service and not 
>> per provider is because we include service aliases as part of the query.
>>
>> Regards,
>> Martin and Francisco.-
> 



More information about the security-dev mailing list