These are examples of how we currently lock down the JVM, to limit
providers, policy files are generated using a tool, it may do as an
interim control measure, until something else is provided, it is of
course a deprecated feature, subject to future removal, but it may do
the job temporarily, without introducing code dependencies.
https://github.com/pfirmstone/JGDMS/blob/14608ea34eb7c109d41e296a62669522862f6a49/qa/harness/policy/defaultsecuretest.policy#LL194C27-L194C27
https://github.com/pfirmstone/JGDMS/blob/14608ea34eb7c109d41e296a62669522862f6a49/qa/harness/policy/defaultsecuretest.policy#L621
https://github.com/pfirmstone/JGDMS/blob/14608ea34eb7c109d41e296a62669522862f6a49/qa/harness/policy/defaultsecuretest.policy#L644
https://github.com/pfirmstone/JGDMS/blob/14608ea34eb7c109d41e296a62669522862f6a49/qa/harness/policy/defaultsecuretest.policy#L688
--
Regards,
Peter.
On 18/02/2023 4:52 am, Martin Balao wrote:
Hi,
We would like to discuss a limitation in the current configuration
capabilities for security providers and possible solutions that we are
exploring (†).
As you know, current configuration capabilities in java.security allow
users to install security providers, decide their priority in a list
(security.provider.<n> properties) and even circumvent this priority
for specific algorithms (jdk.security.provider.preferred property).
However, there is no granularity in terms of what service types and
algorithms are enabled once a security provider is installed: it's an
all or nothing scheme. It is worth noting that security providers can
bring with them a diverse range of service types. As an example, the
SUN security provider comes with the following service types:
SecureRandom, Signature, KeyPairGenerator,
AlgorithmParameterGenerator, AlgorithmParameters, KeyFactory,
MessageDigest, CertificateFactory, KeyStore, CertStore, Policy,
Configuration, CertPathBuilder and CertPathValidator [1].
In some cases, the user may need to enforce that all cryptographic
primitives come from a specific security provider. This could happen,
for example, when operating in a FIPS-compliant environment or under
strict security policies. To better illustrate, let's say that the
user requires that all cryptographic operations are performed in a
Hardware Security Module (HSM). On the OpenJDK side, this means that
the implementation for Cipher, Signature, Mac and other cryptographic
services must be the one in the SunPKCS11 security provider. Let's
also suppose that other non-cryptographic services such as those for
certificates validation and TLS are required, and their implementation
is in the SUN and SunJSSE security providers respectively. Setting
SunPKCS11 at the highest priority of the list is not a strong
guarantee to ensure that all cryptographic operations come from it:
it's possible that an algorithm for Signature is not implemented in
SunPKCS11 or in its underlying token but in the SUN security provider.
Disabling the SUN security provider wouldn't be an option in this case
because we need its certificates validation service.
This problem goes beyond OpenJDK default security providers. Even if
we come up with a new layout for service types, algorithms and
providers —putting backward compatibility issues aside—, there is
always the possibility that a 3rd party security provider does not
follow any services grouping convention. It might also be the case
that we need to disable a specific algorithm only —i.e. for
cryptographic policy reasons— and TLS or JAR signing properties fall
short.
In our view, it would be beneficial to add more configuration
flexibility and control to the existing API in which any security
provider can be plugged in, in the form of deciding which service
types and algorithms are enabled for each installed provider.
There are 2 alternatives that we are exploring to tackle this problem.
Alternative #1
===========================
Introduce a new security property to decide which service types and
algorithms are enabled for each security provider. The default value
for this property would be empty, which keeps this feature disabled
and all services from installed security providers available.
As for the new property's syntax and semantics, we've been considering
an allow-list along the lines of:
jdk.security.provider.enabled = security-provider-1 { service-type-1 :
alg-1, ... ; ... } , ...
Note: we need a formal syntax specification, this is for illustration
only.
As part of the syntax we are considering the use of wildcards (*) to
match multiple security providers, service types and algorithms, and
minus signs (-) to remove service types. When a service type is
removed, the action applies to all algorithms and any attempt to
specify them explicitly would be an error. The minus sign cannot be
used at the algorithm level. We are also thinking that in case of a
partial or total contradiction between conditions, the right-most
value applies on top of the others. If a security provider, service
type or algorithm does not exist, we can simply write a debug warning
and ignore it. As for the name of the algorithms, we can also include
Ciphers transformations.
Example:
jdk.security.provider.enabled = * { -Cipher }, SunJCE { Cipher :
AES/GCM/NoPadding, DES ; Signature }, SUN { * ; -Signature }
This would be interpreted as:
* Irrespective of the provider (*), Cipher services should be removed
(-). This rule would be superfluous in this case because the property
itself is an allow-list and there is nothing to the left that enables
Cipher service types for any provider.
* From the SunJCE security provider, Cipher services with
AES/GCM/NoPadding and DES transformations are allowed, and Signature
services with any algorithm are allowed. Notice that there is a
shortcut here: the algorithm list that follows the service name, "':
alg-1, ..." is optional. When omitted all the service's algorithms are
enabled.
* From the SUN security provider, every service type is allowed
except Signature (recall that a minus sign can only apply to a
service, removing all associated algorithms).
It's not the goal of this proposal to invalidate property values that
lead to inconsistent internal states, such as "the Cipher service of
SunJCE depends on AlgorithmParameters from SUN". This is because the
combinations for a check are virtually infinite: there can be 3rd
party security providers with their own semantics and dependencies. In
the same way, we cannot determine at start time any application
dependencies. It's up to the user to analyze all types of dependencies
before setting a value.
Alternative #2
===========================
Introduce a boolean security property to turn the value of the
existing jdk.security.provider.preferred property into the only
combinations of algorithm, service and provider that are allowed:
jdk.security.provider.preferredOnly = true
The default value for the new property would be "false", keeping the
current "preferred" behavior in which all algorithms and services from
installed security providers are available.
Contrary to Alternative #1, the user has to explicitly list the
algorithms and cannot rely on wildcards to express wide categories
such as "all Cipher algorithms from SunJCE" or "all algorithms from
SunJCE". The use of minus signs to remove service types or algorithms
wouldn't be available either.
In order to mitigate the burden on users we can consider extending
jdk.security.provider.preferred syntax as long as we keep
backward-compatibility and stay within the boundaries of a "preferred"
semantics. For example, we can accept a value of
"jdk.security.provider.preferred=SunJCE" to mean that any service and
any algorithm from SunJCE is either preferred or allowed, depending on
the value of jdk.security.provider.preferredOnly. This case would be a
service type and algorithm wildcard. We can also define an
algorithms-only wildcard, such as Cipher.*:SunJCE.
Alternative #2 has the advantage of reusing most or all of the
existing syntax. However, it's worth noticing that it implies an
overloaded semantic that can turn confusing or inconvenient in some
cases. As an example, a user that relies on the prioritized security
providers list for most of the algorithms and has only a few preferred
exceptions, would need to express preferences by extension upon
turning on this feature. Alternative #1 keeps preferences and
availability as two separate concepts, in a more clear way.
Thanks,
Martin.-
--
[1] -
https://docs.oracle.com/en/java/javase/17/security/oracle-providers.html#GUID-3A80CC46-91E1-4E47-AC51-CB7B782CEA7D
(†) - Thanks to @fferrari for his contributions to this proposal.