1 /*
   2  * Copyright (c) 2015, 2020, 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         String preferredProp
  50                 = "AES/GCM/NoPadding:SunJCE, MessageDigest.SHA-256:SUN";
  51         System.out.printf("%nExecuting test for the platform '%s'%n", os);
  52 
  53         // Try to set the preferred algorithm and Provider and verify
  54         // the usage of it.
  55         Security.setProperty(
  56                 "jdk.security.provider.preferred", preferredProp);
  57         verifyPreferredProviderProperty(os, type, preferredProp);
  58 
  59         verifyDigestProvider(os, type, Arrays.asList(
  60                 new DataTuple("SHA-256", "SUN")));
  61 
  62         Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
  63         actualProvider = cipher.getProvider().getName();
  64         if (!actualProvider.equals("SunJCE")) {
  65             throw new RuntimeException(String.format("Test Failed:Got wrong "
  66                     + "provider from %s-%s platform, Expected Provider: SunJCE,"
  67                     + " Returned Provider: %s", os, type, actualProvider));
  68         }
  69     }
  70 
  71     private static void verifyPreferredProviderProperty(String os, String arch,
  72             String preferred) {
  73         String preferredProvider
  74                 = Security.getProperty("jdk.security.provider.preferred");
  75         if (!preferredProvider.equals(preferred)) {
  76             System.out.println("Expected: " + preferred + "\nResult: " +
  77                     preferredProvider);
  78             throw new RuntimeException(String.format(
  79                     "Test Failed: wrong jdk.security.provider.preferred value "
  80                     + "on %s-%s", os, arch));
  81         }
  82         System.out.println(
  83                 "Preferred provider security property verification complete.");
  84     }
  85 
  86     private static void verifyDigestProvider(String os, String arch,
  87             List<DataTuple> algoProviders) throws NoSuchAlgorithmException {
  88         for (DataTuple dataTuple : algoProviders) {
  89             System.out.printf(
  90                     "Verifying MessageDigest for '%s'%n", dataTuple.algorithm);
  91             MessageDigest md = MessageDigest.getInstance(dataTuple.algorithm);
  92             matchProvider(md.getProvider(), dataTuple.provider,
  93                     dataTuple.algorithm, os, arch);
  94         }
  95         System.out.println(
  96                 "Preferred MessageDigest algorithm verification successful.");
  97     }
  98 
  99     private static void verifyMacProvider(String os, String arch,
 100             List<DataTuple> algoProviders) throws NoSuchAlgorithmException {
 101         for (DataTuple dataTuple : algoProviders) {
 102             System.out.printf(
 103                     "Verifying Mac for '%s'%n", dataTuple.algorithm);
 104             Mac mac = Mac.getInstance(dataTuple.algorithm);
 105             matchProvider(mac.getProvider(), dataTuple.provider,
 106                     dataTuple.algorithm, os, arch);
 107         }
 108         System.out.println(
 109                 "Preferred Mac algorithm verification successful.");
 110     }
 111 
 112     private static void verifyKeyFactoryProvider(String os, String arch,
 113             List<DataTuple> algoProviders) throws NoSuchAlgorithmException {
 114         for (DataTuple dataTuple : algoProviders) {
 115             System.out.printf(
 116                     "Verifying KeyFactory for '%s'%n", dataTuple.algorithm);
 117             KeyFactory kf = KeyFactory.getInstance(dataTuple.algorithm);
 118             matchProvider(kf.getProvider(), dataTuple.provider,
 119                     dataTuple.algorithm, os, arch);
 120         }
 121         System.out.println(
 122                 "Preferred KeyFactory algorithm verification successful.");
 123     }
 124 
 125     private static void verifySignatureProvider(String os, String arch,
 126             List<DataTuple> algoProviders) throws NoSuchAlgorithmException {
 127         for (DataTuple dataTuple : algoProviders) {
 128             System.out.printf(
 129                     "Verifying Signature for '%s'%n", dataTuple.algorithm);
 130             Signature si = Signature.getInstance(dataTuple.algorithm);
 131             matchProvider(si.getProvider(), dataTuple.provider,
 132                     dataTuple.algorithm, os, arch);
 133         }
 134         System.out.println(
 135                 "Preferred Signature algorithm verification successful.");
 136     }
 137 
 138     private static void matchProvider(Provider provider, String expected,
 139             String algo, String os, String arch) {
 140         if (!provider.getName().equals(expected)) {
 141             throw new RuntimeException(String.format(
 142                     "Test Failed:Got wrong provider from %s-%s platform, "
 143                     + "for algorithm %s. Expected Provider: %s,"
 144                     + " Returned Provider: %s", os, arch, algo,
 145                     expected, provider.getName()));
 146         }
 147     }
 148 
 149     private static class DataTuple {
 150 
 151         private final String provider;
 152         private final String algorithm;
 153 
 154         private DataTuple(String algorithm, String provider) {
 155             this.algorithm = algorithm;
 156             this.provider = provider;
 157         }
 158     }
 159 
 160     public static void main(String[] args)
 161             throws NoSuchAlgorithmException, NoSuchPaddingException {
 162         String os = System.getProperty("os.name").toLowerCase();
 163         String arch = System.getProperty("os.arch").toLowerCase();
 164         PreferredProviderTest pp = new PreferredProviderTest();
 165         pp.RunTest(arch, os);
 166     }
 167 }