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 import sun.security.provider.AbstractDrbg; 25 import sun.security.provider.EntropySource; 26 import java.security.DrbgParameters; 27 import java.security.SecureRandom; 28 import java.security.Security; 29 30 /** 31 * @test 32 * @bug 8051408 33 * @modules java.base/sun.security.provider 34 * @run main/othervm CommonSeeder 35 * @summary check entropy reading of DRBGs 36 */ 37 public class CommonSeeder { 38 39 static class MyES implements EntropySource { 40 int count = 100; 41 int lastCount = 100; 42 43 @Override 44 public byte[] getEntropy(int entropy, int minLength, 45 int maxLength, boolean pr) { 46 count--; 47 return new byte[minLength]; 48 } 49 50 /** 51 * Confirms genEntropy() has been called {@code less} times 52 * since last check. 53 */ 54 public void checkUsage(int less) throws Exception { 55 if (lastCount != count + less) { 56 throw new Exception(String.format( 57 "lastCount = %d, count = %d, less = %d", 58 lastCount, count, less)); 59 } 60 lastCount = count; 61 } 62 } 63 64 public static void main(String[] args) throws Exception { 65 66 byte[] result = new byte[10]; 67 MyES es = new MyES(); 68 69 // Set es as the default entropy source, overriding SeedGenerator. 70 setDefaultSeeder(es); 71 72 // Nothing happened yet 73 es.checkUsage(0); 74 75 SecureRandom sr; 76 sr = SecureRandom.getInstance("DRBG"); 77 78 // No entropy reading if only getInstance 79 es.checkUsage(0); 80 81 // Entropy is read at 1st nextBytes of the 1st DRBG 82 sr.nextInt(); 83 es.checkUsage(1); 84 85 for (String mech: new String[]{"Hash_DRBG", "HMAC_DRBG", "CTR_DRBG"}) { 86 System.out.println("Testing " + mech + "..."); 87 88 // DRBG with pr_false will never read entropy again no matter 89 // if nextBytes or reseed is called. 90 91 Security.setProperty("drbg", mech); 92 sr = SecureRandom.getInstance("DRBG"); 93 sr.nextInt(); 94 sr.reseed(); 95 es.checkUsage(0); 96 97 // DRBG with pr_true always read from default entropy, and 98 // its nextBytes always reseed itself 99 100 Security.setProperty("drbg", mech + ",pr_and_reseed"); 101 sr = SecureRandom.getInstance("DRBG"); 102 103 sr.nextInt(); 104 es.checkUsage(2); // one instantiate, one reseed 105 sr.nextInt(); 106 es.checkUsage(1); // one reseed in nextBytes 107 sr.reseed(); 108 es.checkUsage(1); // one reseed 109 sr.nextBytes(result, DrbgParameters.nextBytes(-1, false, null)); 110 es.checkUsage(0); // pr_false for this call 111 sr.nextBytes(result, DrbgParameters.nextBytes(-1, true, null)); 112 es.checkUsage(1); // pr_true for this call 113 sr.reseed(DrbgParameters.reseed(true, null)); 114 es.checkUsage(1); // reseed from es 115 sr.reseed(DrbgParameters.reseed(false, null)); 116 es.checkUsage(0); // reseed from AbstractDrbg.SeederHolder.seeder 117 } 118 } 119 120 static void setDefaultSeeder(EntropySource es) throws Exception { 121 AbstractDrbg.defaultES = es; 122 } 123 }