8202608: CommonSeeder test needs a white-box testing mechanism to replace the default entropy source
authorweijun
Tue, 26 Jun 2018 10:43:43 +0800
changeset 50777 11e7eb8cb583
parent 50776 cf0898a6441e
child 50778 bba1deda9216
8202608: CommonSeeder test needs a white-box testing mechanism to replace the default entropy source Reviewed-by: xuelei
src/java.base/share/classes/sun/security/provider/AbstractDrbg.java
test/jdk/sun/security/provider/SecureRandom/CommonSeeder.java
test/jdk/sun/security/provider/SecureRandom/java.base/sun/security/provider/SeedGenerator.java
--- a/src/java.base/share/classes/sun/security/provider/AbstractDrbg.java	Mon Jun 25 18:49:30 2018 -0700
+++ b/src/java.base/share/classes/sun/security/provider/AbstractDrbg.java	Tue Jun 26 10:43:43 2018 +0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -516,7 +516,7 @@
      * This object uses {@link SeedGenerator#generateSeed(byte[])} to
      * return a byte array containing {@code minLength} bytes. It is
      * assumed to support prediction resistance and always contains
-     * full-entropy. A trusted application can update this field.
+     * full-entropy.
      */
     private final static EntropySource defaultES =
             (minE, minLen, maxLen, pr) -> {
--- a/test/jdk/sun/security/provider/SecureRandom/CommonSeeder.java	Mon Jun 25 18:49:30 2018 -0700
+++ b/test/jdk/sun/security/provider/SecureRandom/CommonSeeder.java	Tue Jun 26 10:43:43 2018 +0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -21,70 +21,39 @@
  * questions.
  */
 
-import sun.security.provider.AbstractDrbg;
-import sun.security.provider.EntropySource;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
 import java.security.DrbgParameters;
 import java.security.SecureRandom;
 import java.security.Security;
 
+import sun.security.provider.SeedGenerator;
 /**
  * @test
- * @bug 8051408
- * @modules java.base/java.lang.reflect:open
- *          java.base/sun.security.provider:+open
+ * @bug 8051408 8202608
+ * @modules java.base/sun.security.provider
+ * @build java.base/sun.security.provider.SeedGenerator
  * @run main/othervm CommonSeeder
  * @summary check entropy reading of DRBGs
  */
 public class CommonSeeder {
 
-    static class MyES implements EntropySource {
-        int count = 100;
-        int lastCount = 100;
-
-        @Override
-        public byte[] getEntropy(int minEntropy, int minLength,
-                                 int maxLength, boolean pr) {
-            count--;
-            return new byte[minLength];
-        }
-
-        /**
-         * Confirms genEntropy() has been called {@code less} times
-         * since last check.
-         */
-        public void checkUsage(int less) throws Exception {
-            if (lastCount != count + less) {
-                throw new Exception(String.format(
-                        "lastCount = %d, count = %d, less = %d",
-                        lastCount, count, less));
-            }
-            lastCount = count;
-        }
-    }
-
     public static void main(String[] args) throws Exception {
 
         byte[] result = new byte[10];
-        MyES es = new MyES();
 
-        // Set es as the default entropy source, overriding SeedGenerator.
-        setDefaultSeeder(es);
+        // Use patched SeedGenerator in java.base/sun/security/provider/.
 
         // Nothing happened yet
-        es.checkUsage(0);
+        SeedGenerator.checkUsage(0);
 
         SecureRandom sr;
         sr = SecureRandom.getInstance("DRBG");
 
         // No entropy reading if only getInstance
-        es.checkUsage(0);
+        SeedGenerator.checkUsage(0);
 
         // Entropy is read at 1st nextBytes of the 1st DRBG
         sr.nextInt();
-        es.checkUsage(1);
+        SeedGenerator.checkUsage(1);
 
         for (String mech : new String[]{"Hash_DRBG", "HMAC_DRBG", "CTR_DRBG"}) {
             System.out.println("Testing " + mech + "...");
@@ -96,7 +65,7 @@
             sr = SecureRandom.getInstance("DRBG");
             sr.nextInt();
             sr.reseed();
-            es.checkUsage(0);
+            SeedGenerator.checkUsage(0);
 
             // DRBG with pr_true always read from default entropy, and
             // its nextBytes always reseed itself
@@ -106,28 +75,19 @@
             sr = SecureRandom.getInstance("DRBG");
 
             sr.nextInt();
-            es.checkUsage(2); // one instantiate, one reseed
+            SeedGenerator.checkUsage(2); // one instantiate, one reseed
             sr.nextInt();
-            es.checkUsage(1); // one reseed in nextBytes
+            SeedGenerator.checkUsage(1); // one reseed in nextBytes
             sr.reseed();
-            es.checkUsage(1); // one reseed
+            SeedGenerator.checkUsage(1); // one reseed
             sr.nextBytes(result, DrbgParameters.nextBytes(-1, false, null));
-            es.checkUsage(0); // pr_false for this call
+            SeedGenerator.checkUsage(0); // pr_false for this call
             sr.nextBytes(result, DrbgParameters.nextBytes(-1, true, null));
-            es.checkUsage(1); // pr_true for this call
+            SeedGenerator.checkUsage(1); // pr_true for this call
             sr.reseed(DrbgParameters.reseed(true, null));
-            es.checkUsage(1); // reseed from es
+            SeedGenerator.checkUsage(1); // reseed from es
             sr.reseed(DrbgParameters.reseed(false, null));
-            es.checkUsage(0); // reseed from AbstractDrbg.SeederHolder.seeder
+            SeedGenerator.checkUsage(0); // reseed from AbstractDrbg.SeederHolder.seeder
         }
     }
-
-    static void setDefaultSeeder(EntropySource es) throws Exception {
-        Field f = AbstractDrbg.class.getDeclaredField("defaultES");
-        f.setAccessible(true);  // no more private
-        Field f2 = Field.class.getDeclaredField("modifiers");
-        f2.setAccessible(true);
-        f2.setInt(f, f2.getInt(f) - Modifier.FINAL);    // no more final
-        f.set(null, es);
-    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/provider/SecureRandom/java.base/sun/security/provider/SeedGenerator.java	Tue Jun 26 10:43:43 2018 +0800
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// This is not the real sun.security.provider.SeedGenerator class. Used by
+// ../../../../CommonSeeder.java only.
+package sun.security.provider;
+
+public class SeedGenerator {
+
+    static int count = 100;
+    static int lastCount = 100;
+
+    public static void generateSeed(byte[] result) {
+        count--;
+    }
+
+    /**
+     * Confirms genEntropy() has been called {@code less} times
+     * since last check.
+     */
+    public static void checkUsage(int less) throws Exception {
+        if (lastCount != count + less) {
+            throw new Exception(String.format(
+                    "lastCount = %d, count = %d, less = %d",
+                    lastCount, count, less));
+        }
+        lastCount = count;
+    }
+
+    // Needed by AbstractDrbg.java
+    static byte[] getSystemEntropy() {
+        return new byte[20];
+    }
+}