diff --git a/jdk/src/java.base/share/classes/sun/security/jca/ProviderList.java b/jdk/src/java.base/share/classes/sun/security/jca/ProviderList.java index 9082670609e..971c4930b7e 100644 --- a/jdk/src/java.base/share/classes/sun/security/jca/ProviderList.java +++ b/jdk/src/java.base/share/classes/sun/security/jca/ProviderList.java @@ -650,12 +650,29 @@ public final class ProviderList { } } + /* Defined Groups for jdk.security.provider.preferred */ + private static final String SHA2Group[] = { "SHA-224", "SHA-256", + "SHA-384", "SHA-512", "SHA-512/224", "SHA-512/256" }; + private static final String HmacSHA2Group[] = { "HmacSHA224", + "HmacSHA256", "HmacSHA384", "HmacSHA512"}; + private static final String SHA2RSAGroup[] = { "SHA224withRSA", + "SHA256withRSA", "SHA384withRSA", "SHA512withRSA"}; + private static final String SHA2DSAGroup[] = { "SHA224withDSA", + "SHA256withDSA", "SHA384withDSA", "SHA512withDSA"}; + private static final String SHA2ECDSAGroup[] = { "SHA224withECDSA", + "SHA256withECDSA", "SHA384withECDSA", "SHA512withECDSA"}; + private static final String SHA3Group[] = { "SHA3-224", "SHA3-256", + "SHA3-384", "SHA3-512" }; + private static final String HmacSHA3Group[] = { "HmacSHA3-224", + "HmacSHA3-256", "HmacSHA3-384", "HmacSHA3-512"}; + // Individual preferred property entry from jdk.security.provider.preferred - private class PreferredEntry { - String type = null; - String algorithm; - String provider; - String alternateName = null; + private static class PreferredEntry { + private String type = null; + private String algorithm; + private String provider; + private String alternateNames[] = null; + private boolean group = false; PreferredEntry(String t, String p) { int i = t.indexOf('.'); @@ -667,47 +684,83 @@ public final class ProviderList { } provider = p; - if (algorithm.compareToIgnoreCase("SHA1") == 0) { - alternateName = "SHA-1"; + // Group definitions + if (type != null && type.compareToIgnoreCase("Group") == 0) { + // Currently intrinsic algorithm groups + if (algorithm.compareToIgnoreCase("SHA2") == 0) { + alternateNames = SHA2Group; + } else if (algorithm.compareToIgnoreCase("HmacSHA2") == 0) { + alternateNames = HmacSHA2Group; + } else if (algorithm.compareToIgnoreCase("SHA2RSA") == 0) { + alternateNames = SHA2RSAGroup; + } else if (algorithm.compareToIgnoreCase("SHA2DSA") == 0) { + alternateNames = SHA2DSAGroup; + } else if (algorithm.compareToIgnoreCase("SHA2ECDSA") == 0) { + alternateNames = SHA2ECDSAGroup; + } else if (algorithm.compareToIgnoreCase("SHA3") == 0) { + alternateNames = SHA3Group; + } else if (algorithm.compareToIgnoreCase("HmacSHA3") == 0) { + alternateNames = HmacSHA3Group; + } + if (alternateNames != null) { + group = true; + } + + // If the algorithm name given is SHA1 + } else if (algorithm.compareToIgnoreCase("SHA1") == 0) { + alternateNames = new String[] { "SHA-1" }; } else if (algorithm.compareToIgnoreCase("SHA-1") == 0) { - alternateName = "SHA1"; + alternateNames = new String[] { "SHA1" }; } } boolean match(String t, String a) { if (debug != null) { - debug.println("Config match: " + toString() + " == [" + t + - ", " + a + "]"); + debug.println("Config check: " + toString() + " == " + + print(t, a, null)); } // Compare service type if configured - if (type != null && type.compareToIgnoreCase(t) != 0) { + if (type != null && !group && type.compareToIgnoreCase(t) != 0) { return false; } // Compare the algorithm string. - if (a.compareToIgnoreCase(algorithm) == 0) { + if (!group && a.compareToIgnoreCase(algorithm) == 0) { if (debug != null) { - debug.println("Config entry found: " + toString()); + debug.println("Config entry matched: " + toString()); } return true; } - if (alternateName != null && - a.compareToIgnoreCase(alternateName) == 0) { - if (debug != null) { - debug.println("Config entry found (alternateName): " + - toString()); + if (alternateNames != null) { + for (String alt : alternateNames) { + if (debug != null) { + debug.println("AltName check: " + print(type, alt, + provider)); + } + if (a.compareToIgnoreCase(alt) == 0) { + if (debug != null) { + debug.println("AltName entry matched: " + + provider); + } + return true; + } } - return true; } // No match return false; } + // Print debugging output of PreferredEntry + private String print(String t, String a, String p) { + return "[" + ((t != null) ? t : "" ) + ", " + a + + ((p != null) ? " : " + p : "" ) + "] "; + } + public String toString() { - return "[" + type + ", " + algorithm + " : " + provider + "] "; + return print(type, algorithm, provider); } } diff --git a/jdk/src/java.base/share/conf/security/java.security b/jdk/src/java.base/share/conf/security/java.security index 72c381b9747..caf94448f25 100644 --- a/jdk/src/java.base/share/conf/security/java.security +++ b/jdk/src/java.base/share/conf/security/java.security @@ -105,15 +105,30 @@ security.provider.tbd=SunPKCS11 # The provider is the name of the provider. Any provider that does not # also appear in the registered list will be ignored. # +# There is a special serviceType for this property only to group a set of +# algorithms together. The type is "Group" and is followed by an algorithm +# keyword. Groups are to simplify and lessen the entries on the property +# line. Current groups are: +# Group.SHA2 = SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, SHA-512/256 +# Group.HmacSHA2 = HmacSHA224, HmacSHA256, HmacSHA384, HmacSHA512 +# Group.SHA2RSA = SHA224withRSA, SHA256withRSA, SHA384withRSA, SHA512withRSA +# Group.SHA2DSA = SHA224withDSA, SHA256withDSA, SHA384withDSA, SHA512withDSA +# Group.SHA2ECDSA = SHA224withECDSA, SHA256withECDSA, SHA384withECDSA, \ +# SHA512withECDSA +# Group.SHA3 = SHA3-224, SHA3-256, SHA3-384, SHA3-512 +# Group.HmacSHA3 = HmacSHA3-224, HmacSHA3-256, HmacSHA3-384, HmacSHA3-512 +# # Example: # jdk.security.provider.preferred=AES/GCM/NoPadding:SunJCE, \ -# MessageDigest.SHA-256:SUN +# MessageDigest.SHA-256:SUN, Group.HmacSHA2:SunJCE #ifdef solaris-sparc -jdk.security.provider.preferred=AES:SunJCE, SHA1:SUN, SHA-224:SUN, \ - SHA-256:SUN, SHA-384:SUN, SHA-512:SUN +jdk.security.provider.preferred=AES:SunJCE, SHA1:SUN, Group.SHA2:SUN, \ + HmacSHA1:SunJCE, Group.HmacSHA2:SunJCE #endif #ifdef solaris-x86 -jdk.security.provider.preferred=AES:SunJCE, RSA:SunRsaSign +jdk.security.provider.preferred=AES:SunJCE, SHA1:SUN, Group.SHA2:SUN, \ + HmacSHA1:SunJCE, Group.HmacSHA2:SunJCE, RSA:SunRsaSign, \ + SHA1withRSA:SunRsaSign, Group.SHA2RSA:SunRsaSign #endif @@ -613,14 +628,14 @@ krb5.kdc.bad.policy = tryLast # "CertConstraint" specifies additional constraints for # certificates that contain algorithms that are restricted: # -#   "jdkCA" prohibits the specified algorithm only if the algorithm is used -#     in a certificate chain that terminates at a marked trust anchor in the -#     lib/security/cacerts keystore.  All other chains are not affected. -#     If the jdkCA constraint is not set, then all chains using the -#     specified algorithm are restricted. jdkCA may only be used once in +# "jdkCA" prohibits the specified algorithm only if the algorithm is used +# in a certificate chain that terminates at a marked trust anchor in the +# lib/security/cacerts keystore.  All other chains are not affected. +# If the jdkCA constraint is not set, then all chains using the +# specified algorithm are restricted. jdkCA may only be used once in # a DisabledAlgorithm expression. -#     Example:  To apply this constraint to SHA-1 certificates, include -#     the following:  "SHA1 jdkCA" +# Example:  To apply this constraint to SHA-1 certificates, include +# the following:  "SHA1 jdkCA" # # When an algorithm must satisfy more than one constraint, it must be # delimited by an ampersand '&'. For example, to restrict certificates in a diff --git a/jdk/test/sun/security/jca/PreferredProviderTest.java b/jdk/test/sun/security/jca/PreferredProviderTest.java index 56aa4a0210e..72026222fee 100644 --- a/jdk/test/sun/security/jca/PreferredProviderTest.java +++ b/jdk/test/sun/security/jca/PreferredProviderTest.java @@ -25,15 +25,17 @@ import java.security.MessageDigest; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.Security; +import java.security.Signature; import java.security.Provider; import java.util.Arrays; import java.util.List; import javax.crypto.Cipher; +import javax.crypto.Mac; import javax.crypto.NoSuchPaddingException; /** * @test - * @bug 8076359 8133151 8145344 8150512 + * @bug 8076359 8133151 8145344 8150512 8155847 * @summary Test the value for new jdk.security.provider.preferred * security property */ @@ -61,8 +63,8 @@ public class PreferredProviderTest { //java.security file which will be verified. switch (type) { case "sparcv9": - preferredProp = "AES:SunJCE, SHA1:SUN, SHA-224:SUN," - + " SHA-256:SUN, SHA-384:SUN, SHA-512:SUN"; + preferredProp = "AES:SunJCE, SHA1:SUN, Group.SHA2:SUN, " + + "HmacSHA1:SunJCE, Group.HmacSHA2:SunJCE"; verifyPreferredProviderProperty(os, type, preferredProp); verifyDigestProvider(os, type, Arrays.asList( @@ -71,14 +73,51 @@ public class PreferredProviderTest { new DataTuple("SHA-224", "SUN"), new DataTuple("SHA-256", "SUN"), new DataTuple("SHA-384", "SUN"), - new DataTuple("SHA-512", "SUN"))); + new DataTuple("SHA-512", "SUN"), + new DataTuple("SHA-512/224", "SUN"), + new DataTuple("SHA-512/256", "SUN"))); + + verifyMacProvider(os, type, Arrays.asList( + new DataTuple("HmacSHA1", "SunJCE"), + new DataTuple("HmacSHA224", "SunJCE"), + new DataTuple("HmacSHA256", "SunJCE"), + new DataTuple("HmacSHA384", "SunJCE"), + new DataTuple("HmacSHA512", "SunJCE"))); break; case "amd64": - preferredProp = "AES:SunJCE, RSA:SunRsaSign"; + preferredProp = "AES:SunJCE, SHA1:SUN, Group.SHA2:SUN, " + + "HmacSHA1:SunJCE, Group.HmacSHA2:SunJCE, " + + "RSA:SunRsaSign, SHA1withRSA:SunRsaSign, " + + "Group.SHA2RSA:SunRsaSign"; + verifyPreferredProviderProperty(os, type, preferredProp); verifyKeyFactoryProvider(os, type, Arrays.asList( new DataTuple("RSA", "SunRsaSign"))); + + verifyDigestProvider(os, type, Arrays.asList( + new DataTuple("SHA1", "SUN"), + new DataTuple("SHA-1", "SUN"), + new DataTuple("SHA-224", "SUN"), + new DataTuple("SHA-256", "SUN"), + new DataTuple("SHA-384", "SUN"), + new DataTuple("SHA-512", "SUN"), + new DataTuple("SHA-512/224", "SUN"), + new DataTuple("SHA-512/256", "SUN"))); + + verifyMacProvider(os, type, Arrays.asList( + new DataTuple("HmacSHA1", "SunJCE"), + new DataTuple("HmacSHA224", "SunJCE"), + new DataTuple("HmacSHA256", "SunJCE"), + new DataTuple("HmacSHA384", "SunJCE"), + new DataTuple("HmacSHA512", "SunJCE"))); + + verifySignatureProvider(os, type, Arrays.asList( + new DataTuple("SHA1withRSA", "SunRsaSign"), + new DataTuple("SHA224withRSA", "SunRsaSign"), + new DataTuple("SHA256withRSA", "SunRsaSign"), + new DataTuple("SHA384withRSA", "SunRsaSign"), + new DataTuple("SHA512withRSA", "SunRsaSign"))); break; } verifyDigestProvider(os, type, Arrays.asList( @@ -99,6 +138,8 @@ public class PreferredProviderTest { String preferredProvider = Security.getProperty("jdk.security.provider.preferred"); if (!preferredProvider.equals(preferred)) { + System.out.println("Expected: " + preferred + "\nResult: " + + preferredProvider); throw new RuntimeException(String.format( "Test Failed: wrong jdk.security.provider.preferred value " + "on %s-%s", os, arch)); @@ -120,6 +161,19 @@ public class PreferredProviderTest { "Preferred MessageDigest algorithm verification successful."); } + private static void verifyMacProvider(String os, String arch, + List algoProviders) throws NoSuchAlgorithmException { + for (DataTuple dataTuple : algoProviders) { + System.out.printf( + "Verifying Mac for '%s'%n", dataTuple.algorithm); + Mac mac = Mac.getInstance(dataTuple.algorithm); + matchProvider(mac.getProvider(), dataTuple.provider, + dataTuple.algorithm, os, arch); + } + System.out.println( + "Preferred Mac algorithm verification successful."); + } + private static void verifyKeyFactoryProvider(String os, String arch, List algoProviders) throws NoSuchAlgorithmException { for (DataTuple dataTuple : algoProviders) { @@ -133,6 +187,19 @@ public class PreferredProviderTest { "Preferred KeyFactory algorithm verification successful."); } + private static void verifySignatureProvider(String os, String arch, + List algoProviders) throws NoSuchAlgorithmException { + for (DataTuple dataTuple : algoProviders) { + System.out.printf( + "Verifying Signature for '%s'%n", dataTuple.algorithm); + Signature si = Signature.getInstance(dataTuple.algorithm); + matchProvider(si.getProvider(), dataTuple.provider, + dataTuple.algorithm, os, arch); + } + System.out.println( + "Preferred Signature algorithm verification successful."); + } + private static void matchProvider(Provider provider, String expected, String algo, String os, String arch) { if (!provider.getName().equals(expected)) {