RFD: Security Providers Filter (JEP)
Martin Balao
mbalao at redhat.com
Tue Nov 26 22:52:44 UTC 2024
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