jdk/test/java/security/SecureRandom/GetInstanceTest.java
changeset 38423 5d6ff7d76bf4
child 38447 435b76ccc9e3
equal deleted inserted replaced
38422:638589997770 38423:5d6ff7d76bf4
       
     1 /*
       
     2  * Copyright (c) 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 /*
       
    25  * @test
       
    26  * @bug 8141039
       
    27  * @library /lib/testlibrary
       
    28  * @summary SecureRandom supports multiple getInstance method including
       
    29  *          getInstanceStrong() method. This test verifies a set of possible
       
    30  *          cases for getInstance with different SecureRandom mechanism
       
    31  *          supported in Java.
       
    32  * @run main GetInstanceTest
       
    33  */
       
    34 import java.security.NoSuchAlgorithmException;
       
    35 import java.security.NoSuchProviderException;
       
    36 import java.security.SecureRandom;
       
    37 import java.security.SecureRandomParameters;
       
    38 import java.security.DrbgParameters;
       
    39 
       
    40 import static java.security.DrbgParameters.Capability.*;
       
    41 
       
    42 import java.security.Security;
       
    43 import java.util.Arrays;
       
    44 
       
    45 import jdk.testlibrary.Asserts;
       
    46 
       
    47 public class GetInstanceTest {
       
    48 
       
    49     private static final boolean PASS = true;
       
    50     private static final String INVALID_ALGO = "INVALID";
       
    51     private static final String SUN_PROVIDER = "SUN";
       
    52     private static final String INVALID_PROVIDER = "INVALID";
       
    53     private static final String STRONG_ALG_SEC_PROP
       
    54             = "securerandom.strongAlgorithms";
       
    55     private static final String DRBG_CONFIG = "securerandom.drbg.config";
       
    56     private static final String DRBG_CONFIG_VALUE
       
    57             = Security.getProperty(DRBG_CONFIG);
       
    58 
       
    59     public static void main(String[] args) throws Exception {
       
    60 
       
    61         boolean success = true;
       
    62         // Only accepted failure is NoSuchAlgorithmException.
       
    63         // For any other failure the test case will fail here.
       
    64         SecureRandom sr = matchExc(() -> SecureRandom.getInstanceStrong(),
       
    65                 PASS, NoSuchAlgorithmException.class,
       
    66                 "PASS - Undefined security Property "
       
    67                 + "'securerandom.strongAlgorithms'");
       
    68         System.out.format("Current platform supports mechanism: '%s' through "
       
    69                 + "provider: '%s' for the method getInstanceStrong().",
       
    70                 sr.getAlgorithm(), sr.getProvider().getName());
       
    71 
       
    72         // DRBG name should appear with "securerandom.strongAlgorithms"
       
    73         // security property.
       
    74         String origDRBGConfig = Security.getProperty(STRONG_ALG_SEC_PROP);
       
    75         if (!origDRBGConfig.contains("DRBG")) {
       
    76             throw new RuntimeException("DRBG is not associated with default "
       
    77                     + "strong algorithm through security Property: "
       
    78                     + "'securerandom.strongAlgorithms'.");
       
    79         }
       
    80         Security.setProperty(STRONG_ALG_SEC_PROP, "DRBG:SUN");
       
    81         sr = matchExc(() -> SecureRandom.getInstanceStrong(),
       
    82                 PASS, NoSuchAlgorithmException.class,
       
    83                 "PASS - Undefined security Property "
       
    84                 + "'securerandom.strongAlgorithms'");
       
    85         checkAttributes(sr, "DRBG");
       
    86         Security.setProperty(STRONG_ALG_SEC_PROP, origDRBGConfig);
       
    87 
       
    88         for (String mech : new String[]{
       
    89             "SHA1PRNG", "Hash_DRBG", "HMAC_DRBG", "CTR_DRBG", INVALID_ALGO,}) {
       
    90             System.out.printf("%nTest SecureRandom mechanism: '%s'", mech);
       
    91             try {
       
    92                 if (isDRBG(mech)) {
       
    93                     Security.setProperty(DRBG_CONFIG, mech);
       
    94                 }
       
    95                 verifyInstance(mech);
       
    96             } catch (Exception e) {
       
    97                 e.printStackTrace(System.out);
       
    98                 success = false;
       
    99             } finally {
       
   100                 Security.setProperty(DRBG_CONFIG, DRBG_CONFIG_VALUE);
       
   101             }
       
   102         }
       
   103         if (!success) {
       
   104             throw new RuntimeException("At least one test failed.");
       
   105         }
       
   106     }
       
   107 
       
   108     private static void verifyInstance(String mech) throws Exception {
       
   109 
       
   110         String srAlgo = isDRBG(mech) ? "DRBG" : mech;
       
   111 
       
   112         // Test for getInstance(algorithm) method.
       
   113         // It should pass for all case other than invalid algorithm name.
       
   114         // If it fails then the expected exception type should be
       
   115         // NoSuchAlgorithmException. Any other Exception type occured will be
       
   116         // treated as failure.
       
   117         checkAttributes(
       
   118                 matchExc(() -> SecureRandom.getInstance(srAlgo), !(nsa(mech)),
       
   119                         NoSuchAlgorithmException.class,
       
   120                         String.format("PASS - It is expected to fail for"
       
   121                                 + " getInstance(algorithm) when algorithm: '%s'"
       
   122                                 + " is null or invalid.", mech)), mech);
       
   123         // Test for getInstance(algorithm, provider) method.
       
   124         checkAttributes(
       
   125                 matchExc(() -> SecureRandom.getInstance(srAlgo,
       
   126                                 Security.getProvider(SUN_PROVIDER)),
       
   127                         !(nsa(mech)),
       
   128                         NoSuchAlgorithmException.class,
       
   129                         String.format("PASS - It is expected to fail for"
       
   130                                 + " getInstance(algorithm, provider) when"
       
   131                                 + " algorithm:'%s' is null or invalid.", mech)),
       
   132                 mech);
       
   133         // Test for getInstance(algorithm, providerName) method.
       
   134         checkAttributes(
       
   135                 matchExc(() -> SecureRandom.getInstance(srAlgo, SUN_PROVIDER),
       
   136                         !(nsa(mech)), NoSuchAlgorithmException.class,
       
   137                         String.format("PASS - It is expected to fail for "
       
   138                                 + "getInstance(algorithm, providerName) when "
       
   139                                 + "algorithm: '%s' is null or invalid.", mech)),
       
   140                 mech);
       
   141         // Test for getInstance(algorithm, providerName) method.
       
   142         checkAttributes(
       
   143                 matchExc(() -> SecureRandom.getInstance(
       
   144                                 srAlgo, INVALID_PROVIDER),
       
   145                         !PASS, NoSuchProviderException.class,
       
   146                         String.format("PASS - It is expected to fail for "
       
   147                                 + "getInstance(algorithm, providerName) when "
       
   148                                 + "provider name: '%s' is invalid and "
       
   149                                 + "algorithm: '%s'", INVALID_PROVIDER, mech)),
       
   150                 mech);
       
   151 
       
   152         // Run the test for a set of SecureRandomParameters
       
   153         for (SecureRandomParameters param : Arrays.asList(null,
       
   154                 DrbgParameters.instantiation(-1, NONE, null))) {
       
   155 
       
   156             System.out.printf("%nRunning DRBG param getInstance() methods "
       
   157                     + "for algorithm: %s and DRBG param type: %s", mech,
       
   158                     (param != null) ? param.getClass().getName() : param);
       
   159 
       
   160             // Following Test are applicable for new DRBG methods only.
       
   161             // Test for getInstance(algorithm, params) method.
       
   162             // Tests are expected to pass for DRBG type with valid parameter
       
   163             // If it fails the expected exception type is derived from
       
   164             // getExcType(mech, param) method. If exception type is not
       
   165             // expected then the test will be considered as failure.
       
   166             checkAttributes(
       
   167                     matchExc(() -> SecureRandom.getInstance(srAlgo, param),
       
   168                             (isDRBG(mech)) && (isValidDRBGParam(param)),
       
   169                             getExcType(mech, param),
       
   170                             String.format("PASS - It is expected to fail "
       
   171                                     + "for getInstance(algorithm, params) "
       
   172                                     + "for algorithm: %s and parameter: %s",
       
   173                                     mech, param)),
       
   174                     mech);
       
   175             // Test for getInstance(algorithm, params, provider) method.
       
   176             checkAttributes(
       
   177                     matchExc(() -> SecureRandom.getInstance(srAlgo, param,
       
   178                                     Security.getProvider(SUN_PROVIDER)),
       
   179                             (isDRBG(mech)) && (isValidDRBGParam(param)),
       
   180                             getExcType(mech, param),
       
   181                             String.format("PASS - It is expected to fail "
       
   182                                     + "for getInstance(algorithm, params, "
       
   183                                     + "provider) for algorithm: %s and "
       
   184                                     + "parameter: %s", mech, param)),
       
   185                     mech);
       
   186             // Test for getInstance(algorithm, params, providerName) method.
       
   187             checkAttributes(
       
   188                     matchExc(() -> SecureRandom.getInstance(srAlgo, param,
       
   189                                     SUN_PROVIDER),
       
   190                             (isDRBG(mech)) && (isValidDRBGParam(param)),
       
   191                             getExcType(mech, param),
       
   192                             String.format("PASS - It is expected to fail "
       
   193                                     + "for getInstance(algorithm, params, "
       
   194                                     + "providerName) for algorithm: %s and "
       
   195                                     + "parameter: %s", mech, param)), mech);
       
   196             // getInstance(algorithm, params, providerName) when
       
   197             // providerName is invalid
       
   198             checkAttributes(
       
   199                     matchExc(() -> SecureRandom.getInstance(srAlgo, param,
       
   200                                     INVALID_PROVIDER),
       
   201                             !PASS, ((param == null)
       
   202                                     ? IllegalArgumentException.class
       
   203                                     : NoSuchProviderException.class),
       
   204                             String.format("PASS - It is expected to fail "
       
   205                                     + "for getInstance(algorithm, params, "
       
   206                                     + "providerName) when param is null or"
       
   207                                     + " provider: %s is invalid for "
       
   208                                     + "algorithm: '%s'", INVALID_PROVIDER,
       
   209                                     mech)), mech);
       
   210             // getInstance(algorithm, params, provider) when provider=null
       
   211             checkAttributes(
       
   212                     matchExc(() -> SecureRandom.getInstance(srAlgo, param,
       
   213                                     (String) null),
       
   214                             !PASS, IllegalArgumentException.class,
       
   215                             String.format("PASS - It is expected to fail "
       
   216                                     + "for getInstance(algorithm, params, "
       
   217                                     + "providerName) when provider name "
       
   218                                     + "is null")), mech);
       
   219             // getInstance(algorithm, params, providerName) when
       
   220             // providerName is empty.
       
   221             checkAttributes(
       
   222                     matchExc(() -> SecureRandom.getInstance(
       
   223                                     srAlgo, param, ""),
       
   224                             !PASS, IllegalArgumentException.class,
       
   225                             String.format("PASS - It is expected to fail "
       
   226                                     + "for getInstance(algorithm, params, "
       
   227                                     + "providerName) when provider name "
       
   228                                     + "is empty")), mech);
       
   229         }
       
   230     }
       
   231 
       
   232     private static boolean isValidDRBGParam(SecureRandomParameters param) {
       
   233         return (param instanceof DrbgParameters.Instantiation);
       
   234     }
       
   235 
       
   236     /**
       
   237      * If the mechanism should occur NoSuchAlgorithmException.
       
   238      */
       
   239     private static boolean nsa(String mech) {
       
   240         return mech.equals(INVALID_ALGO);
       
   241     }
       
   242 
       
   243     /**
       
   244      * Verify if the mechanism is DRBG type.
       
   245      * @param mech Mechanism name
       
   246      * @return True if the mechanism name is DRBG type else False.
       
   247      */
       
   248     private static boolean isDRBG(String mech) {
       
   249         return mech.contains("_DRBG");
       
   250     }
       
   251 
       
   252     /**
       
   253      * Type of exception expected for a SecureRandom instance when exception
       
   254      * occurred while calling getInstance method with a fixed set of parameter.
       
   255      * @param mech Mechanism used to create a SecureRandom instance
       
   256      * @param param Parameter to getInstance() method
       
   257      * @return Exception type expected
       
   258      */
       
   259     private static Class getExcType(String mech, SecureRandomParameters param) {
       
   260         return ((isDRBG(mech) && !isValidDRBGParam(param)) || param == null)
       
   261                 ? IllegalArgumentException.class
       
   262                 : NoSuchAlgorithmException.class;
       
   263     }
       
   264 
       
   265     private interface RunnableCode {
       
   266 
       
   267         SecureRandom run() throws Exception;
       
   268     }
       
   269 
       
   270     /**
       
   271      * Execute a given code block and verify, if the exception type is expected.
       
   272      * @param r Code block to run
       
   273      * @param ex Expected exception type
       
   274      * @param shouldPass If the code execution expected to pass without failure
       
   275      * @param msg Message to log in case of expected failure
       
   276      */
       
   277     private static SecureRandom matchExc(RunnableCode r, boolean shouldPass,
       
   278             Class ex, String msg) {
       
   279         SecureRandom sr = null;
       
   280         try {
       
   281             sr = r.run();
       
   282             if (!shouldPass) {
       
   283                 throw new RuntimeException("Excecution should fail here.");
       
   284             }
       
   285         } catch (Exception e) {
       
   286             System.out.printf("%nOccured exception: %s - Expected exception: %s"
       
   287                     + " : ", e.getClass(), ex.getCanonicalName());
       
   288             if (ex.isAssignableFrom(e.getClass())) {
       
   289                 System.out.printf("%n%s : Expected Exception: %s : ",
       
   290                         e.getClass(), msg);
       
   291             } else if (shouldPass) {
       
   292                 throw new RuntimeException(e);
       
   293             } else {
       
   294                 System.out.printf("%nIgnore the following exception: %s%n",
       
   295                         e.getMessage());
       
   296             }
       
   297         }
       
   298         return sr;
       
   299     }
       
   300 
       
   301     /**
       
   302      * Check specific attributes of a SecureRandom instance.
       
   303      */
       
   304     private static void checkAttributes(SecureRandom sr, String mech) {
       
   305         if (sr == null) {
       
   306             return;
       
   307         }
       
   308         Asserts.assertEquals(sr.getAlgorithm(), (isDRBG(mech) ? "DRBG" : mech));
       
   309         Asserts.assertEquals(sr.getProvider().getName(), SUN_PROVIDER);
       
   310     }
       
   311 
       
   312 }