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