1 /*
   2  * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 import java.security.MessageDigest;
  25 import java.security.KeyFactory;
  26 import java.security.NoSuchAlgorithmException;
  27 import java.security.Security;
  28 import java.security.Signature;
  29 import java.security.Provider;
  30 import java.util.Arrays;
  31 import java.util.List;
  32 import javax.crypto.Cipher;
  33 import javax.crypto.Mac;
  34 import javax.crypto.NoSuchPaddingException;
  35 
  36 /**
  37  * @test
  38  * @bug 8076359 8133151 8145344 8150512 8155847
  39  * @summary Test the value for new jdk.security.provider.preferred
  40  *          security property
  41  * @run main/othervm PreferredProviderTest
  42  */
  43 public class PreferredProviderTest {
  44 
  45     public void RunTest(String type, String os)
  46             throws NoSuchAlgorithmException, NoSuchPaddingException {
  47 
  48         String actualProvider = null;
  49         boolean solaris = os.contains("sun");
  50         String preferredProp
  51                 = "AES/GCM/NoPadding:SunJCE, MessageDigest.SHA-256:SUN";
  52         System.out.printf("%nExecuting test for the platform '%s'%n", os);
  53         if (!solaris) {
  54             //For other platform it will try to set the preferred algorithm and
  55             //Provider and verify the usage of it.
  56             Security.setProperty(
  57                     "jdk.security.provider.preferred", preferredProp);
  58             verifyPreferredProviderProperty(os, type, preferredProp);
  59 
  60             verifyDigestProvider(os, type, Arrays.asList(
  61                     new DataTuple("SHA-256", "SUN")));
  62         } else {
  63             //Solaris has different providers that support the same algorithm
  64             //which makes for better testing.
  65             switch (type) {
  66                 case "sparcv9":
  67                     preferredProp = "AES:SunJCE, SHA1:SUN, Group.SHA2:SUN, " +
  68                             "HmacSHA1:SunJCE, Group.HmacSHA2:SunJCE";
  69                     Security.setProperty(
  70                             "jdk.security.provider.preferred", preferredProp);
  71                     verifyPreferredProviderProperty(os, type, preferredProp);
  72 
  73                     verifyDigestProvider(os, type, Arrays.asList(
  74                             new DataTuple("SHA1", "SUN"),
  75                             new DataTuple("SHA-1", "SUN"),
  76                             new DataTuple("SHA-224", "SUN"),
  77                             new DataTuple("SHA-256", "SUN"),
  78                             new DataTuple("SHA-384", "SUN"),
  79                             new DataTuple("SHA-512", "SUN"),
  80                             new DataTuple("SHA-512/224", "SUN"),
  81                             new DataTuple("SHA-512/256", "SUN")));
  82 
  83                     verifyMacProvider(os, type, Arrays.asList(
  84                             new DataTuple("HmacSHA1", "SunJCE"),
  85                             new DataTuple("HmacSHA224", "SunJCE"),
  86                             new DataTuple("HmacSHA256", "SunJCE"),
  87                             new DataTuple("HmacSHA384", "SunJCE"),
  88                             new DataTuple("HmacSHA512", "SunJCE")));
  89                     break;
  90                 case "amd64":
  91                     preferredProp = "AES:SunJCE, SHA1:SUN, Group.SHA2:SUN, " +
  92                             "HmacSHA1:SunJCE, Group.HmacSHA2:SunJCE, " +
  93                             "RSA:SunRsaSign, SHA1withRSA:SunRsaSign, " +
  94                             "Group.SHA2RSA:SunRsaSign";
  95                     Security.setProperty(
  96                             "jdk.security.provider.preferred", preferredProp);
  97                     verifyPreferredProviderProperty(os, type, preferredProp);
  98 
  99                     verifyKeyFactoryProvider(os, type, Arrays.asList(
 100                             new DataTuple("RSA", "SunRsaSign")));
 101 
 102                     verifyDigestProvider(os, type, Arrays.asList(
 103                             new DataTuple("SHA1", "SUN"),
 104                             new DataTuple("SHA-1", "SUN"),
 105                             new DataTuple("SHA-224", "SUN"),
 106                             new DataTuple("SHA-256", "SUN"),
 107                             new DataTuple("SHA-384", "SUN"),
 108                             new DataTuple("SHA-512", "SUN"),
 109                             new DataTuple("SHA-512/224", "SUN"),
 110                             new DataTuple("SHA-512/256", "SUN")));
 111 
 112                     verifyMacProvider(os, type, Arrays.asList(
 113                             new DataTuple("HmacSHA1", "SunJCE"),
 114                             new DataTuple("HmacSHA224", "SunJCE"),
 115                             new DataTuple("HmacSHA256", "SunJCE"),
 116                             new DataTuple("HmacSHA384", "SunJCE"),
 117                             new DataTuple("HmacSHA512", "SunJCE")));
 118 
 119                     verifySignatureProvider(os, type, Arrays.asList(
 120                             new DataTuple("SHA1withRSA", "SunRsaSign"),
 121                             new DataTuple("SHA224withRSA", "SunRsaSign"),
 122                             new DataTuple("SHA256withRSA", "SunRsaSign"),
 123                             new DataTuple("SHA384withRSA", "SunRsaSign"),
 124                             new DataTuple("SHA512withRSA", "SunRsaSign")));
 125                     break;
 126             }
 127             verifyDigestProvider(os, type, Arrays.asList(
 128                     new DataTuple("MD5", "OracleUcrypto")));
 129         }
 130 
 131         Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
 132         actualProvider = cipher.getProvider().getName();
 133         if (!actualProvider.equals("SunJCE")) {
 134             throw new RuntimeException(String.format("Test Failed:Got wrong "
 135                     + "provider from %s-%s platform, Expected Provider: SunJCE,"
 136                     + " Returned Provider: %s", os, type, actualProvider));
 137         }
 138     }
 139 
 140     private static void verifyPreferredProviderProperty(String os, String arch,
 141             String preferred) {
 142         String preferredProvider
 143                 = Security.getProperty("jdk.security.provider.preferred");
 144         if (!preferredProvider.equals(preferred)) {
 145             System.out.println("Expected: " + preferred + "\nResult: " +
 146                     preferredProvider);
 147             throw new RuntimeException(String.format(
 148                     "Test Failed: wrong jdk.security.provider.preferred value "
 149                     + "on %s-%s", os, arch));
 150         }
 151         System.out.println(
 152                 "Preferred provider security property verification complete.");
 153     }
 154 
 155     private static void verifyDigestProvider(String os, String arch,
 156             List<DataTuple> algoProviders) throws NoSuchAlgorithmException {
 157         for (DataTuple dataTuple : algoProviders) {
 158             System.out.printf(
 159                     "Verifying MessageDigest for '%s'%n", dataTuple.algorithm);
 160             MessageDigest md = MessageDigest.getInstance(dataTuple.algorithm);
 161             matchProvider(md.getProvider(), dataTuple.provider,
 162                     dataTuple.algorithm, os, arch);
 163         }
 164         System.out.println(
 165                 "Preferred MessageDigest algorithm verification successful.");
 166     }
 167 
 168     private static void verifyMacProvider(String os, String arch,
 169             List<DataTuple> algoProviders) throws NoSuchAlgorithmException {
 170         for (DataTuple dataTuple : algoProviders) {
 171             System.out.printf(
 172                     "Verifying Mac for '%s'%n", dataTuple.algorithm);
 173             Mac mac = Mac.getInstance(dataTuple.algorithm);
 174             matchProvider(mac.getProvider(), dataTuple.provider,
 175                     dataTuple.algorithm, os, arch);
 176         }
 177         System.out.println(
 178                 "Preferred Mac algorithm verification successful.");
 179     }
 180 
 181     private static void verifyKeyFactoryProvider(String os, String arch,
 182             List<DataTuple> algoProviders) throws NoSuchAlgorithmException {
 183         for (DataTuple dataTuple : algoProviders) {
 184             System.out.printf(
 185                     "Verifying KeyFactory for '%s'%n", dataTuple.algorithm);
 186             KeyFactory kf = KeyFactory.getInstance(dataTuple.algorithm);
 187             matchProvider(kf.getProvider(), dataTuple.provider,
 188                     dataTuple.algorithm, os, arch);
 189         }
 190         System.out.println(
 191                 "Preferred KeyFactory algorithm verification successful.");
 192     }
 193 
 194     private static void verifySignatureProvider(String os, String arch,
 195             List<DataTuple> algoProviders) throws NoSuchAlgorithmException {
 196         for (DataTuple dataTuple : algoProviders) {
 197             System.out.printf(
 198                     "Verifying Signature for '%s'%n", dataTuple.algorithm);
 199             Signature si = Signature.getInstance(dataTuple.algorithm);
 200             matchProvider(si.getProvider(), dataTuple.provider,
 201                     dataTuple.algorithm, os, arch);
 202         }
 203         System.out.println(
 204                 "Preferred Signature algorithm verification successful.");
 205     }
 206 
 207     private static void matchProvider(Provider provider, String expected,
 208             String algo, String os, String arch) {
 209         if (!provider.getName().equals(expected)) {
 210             throw new RuntimeException(String.format(
 211                     "Test Failed:Got wrong provider from %s-%s platform, "
 212                     + "for algorithm %s. Expected Provider: %s,"
 213                     + " Returned Provider: %s", os, arch, algo,
 214                     expected, provider.getName()));
 215         }
 216     }
 217 
 218     private static class DataTuple {
 219 
 220         private final String provider;
 221         private final String algorithm;
 222 
 223         private DataTuple(String algorithm, String provider) {
 224             this.algorithm = algorithm;
 225             this.provider = provider;
 226         }
 227     }
 228 
 229     public static void main(String[] args)
 230             throws NoSuchAlgorithmException, NoSuchPaddingException {
 231         String os = System.getProperty("os.name").toLowerCase();
 232         String arch = System.getProperty("os.arch").toLowerCase();
 233         PreferredProviderTest pp = new PreferredProviderTest();
 234         pp.RunTest(arch, os);
 235     }
 236 }