1/*
2 * Copyright (c) 2013, 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 6425477 8141039
27 * @summary Better support for generation of high entropy random numbers
28 * @run main StrongSecureRandom
29 */
30import java.security.*;
31import java.util.*;
32
33/**
34 * This test assumes that the standard Sun providers are installed.
35 */
36public class StrongSecureRandom {
37
38    private static final String os = System.getProperty("os.name", "unknown");
39
40    private static void testDefaultEgd() throws Exception {
41        // No SecurityManager installed.
42        String s = Security.getProperty("securerandom.source");
43
44        System.out.println("Testing:  default EGD: " + s);
45        if (!s.equals("file:/dev/random")) {
46            throw new Exception("Default is not 'file:/dev/random'");
47        }
48    }
49
50    private static void testNativePRNGImpls() throws Exception {
51        SecureRandom sr;
52        byte[] ba;
53
54        System.out.println("Testing new NativePRNGImpls");
55
56        if (os.startsWith("Windows")) {
57            System.out.println("Skip windows testing.");
58            return;
59        }
60
61        System.out.println("Testing regular");
62        sr = SecureRandom.getInstance("NativePRNG");
63        if (!sr.getAlgorithm().equals("NativePRNG")) {
64            throw new Exception("sr.getAlgorithm(): " + sr.getAlgorithm());
65        }
66        ba = sr.generateSeed(1);
67        sr.nextBytes(ba);
68        sr.setSeed(ba);
69
70        System.out.println("Testing NonBlocking");
71        sr = SecureRandom.getInstance("NativePRNGNonBlocking");
72        if (!sr.getAlgorithm().equals("NativePRNGNonBlocking")) {
73            throw new Exception("sr.getAlgorithm(): " + sr.getAlgorithm());
74        }
75        ba = sr.generateSeed(1);
76        sr.nextBytes(ba);
77        sr.setSeed(ba);
78
79        if (os.equals("Linux")) {
80            System.out.println("Skip Linux blocking test.");
81            return;
82        }
83
84        System.out.println("Testing Blocking");
85        sr = SecureRandom.getInstance("NativePRNGBlocking");
86        if (!sr.getAlgorithm().equals("NativePRNGBlocking")) {
87            throw new Exception("sr.getAlgorithm(): " + sr.getAlgorithm());
88        }
89        ba = sr.generateSeed(1);
90        sr.nextBytes(ba);
91        sr.setSeed(ba);
92    }
93
94    private static void testStrongInstance(boolean expected) throws Exception {
95
96        boolean result;
97
98        try {
99            SecureRandom.getInstanceStrong();
100            result = true;
101        } catch (NoSuchAlgorithmException e) {
102            result = false;
103        }
104
105        if (expected != result) {
106            throw new Exception("Received: " + result);
107        }
108    }
109
110    /*
111     * This test assumes that the standard providers are installed.
112     */
113    private static void testProperty(String property, boolean expected)
114            throws Exception {
115
116        System.out.println("Testing: '" + property + "' " + expected);
117        final String origStrongAlgoProp
118                = Security.getProperty("securerandom.strongAlgorithms");
119        try {
120            Security.setProperty("securerandom.strongAlgorithms", property);
121            testStrongInstance(expected);
122        } finally {
123            Security.setProperty(
124                    "securerandom.strongAlgorithms", origStrongAlgoProp);
125        }
126    }
127
128    private static void testProperties() throws Exception {
129        // Sets securerandom.strongAlgorithms, and then tests various combos.
130        testProperty("", false);
131
132        testProperty("SHA1PRNG", true);
133        testProperty(" SHA1PRNG", true);
134        testProperty("SHA1PRNG ", true);
135        testProperty(" SHA1PRNG ", true);
136
137        // Impls are case-insenstive, providers are sensitive.
138        testProperty("SHA1PRNG:SUN", true);
139        testProperty("Sha1PRNG:SUN", true);
140        testProperty("SHA1PRNG:Sun", false);
141
142        testProperty(" SHA1PRNG:SUN", true);
143        testProperty("SHA1PRNG:SUN ", true);
144        testProperty(" SHA1PRNG:SUN ", true);
145
146        testProperty(" SHA1PRNG:SUn", false);
147        testProperty("SHA1PRNG:SUn ", false);
148        testProperty(" SHA1PRNG:SUn ", false);
149
150        testProperty(",,,SHA1PRNG", true);
151        testProperty(",,, SHA1PRNG", true);
152        testProperty(" , , ,SHA1PRNG ", true);
153
154        testProperty(",,,, SHA1PRNG ,,,", true);
155        testProperty(",,,, SHA1PRNG:SUN ,,,", true);
156        testProperty(",,,, SHA1PRNG:SUn ,,,", false);
157
158        testProperty(",,,SHA1PRNG:Sun,, SHA1PRNG:SUN", true);
159        testProperty(",,,Sha1PRNG:Sun, SHA1PRNG:SUN", true);
160        testProperty(" SHA1PRNG:Sun, Sha1PRNG:Sun,,,,Sha1PRNG:SUN", true);
161
162        testProperty(",,,SHA1PRNG:Sun,, SHA1PRNG:SUn", false);
163        testProperty(",,,Sha1PRNG:Sun, SHA1PRNG:SUn", false);
164        testProperty(" SHA1PRNG:Sun, Sha1PRNG:Sun,,,,Sha1PRNG:SUn", false);
165
166        testProperty(
167                " @#%,%$#:!%^, NativePRNG:Sun, Sha1PRNG:Sun,,Sha1PRNG:SUN",
168                true);
169        testProperty(" @#%,%$#!%^, NativePRNG:Sun, Sha1PRNG:Sun,,Sha1PRNG:SUn",
170                false);
171    }
172
173    /*
174     * Linux tends to block, so ignore anything that reads /dev/random.
175     */
176    private static void handleLinuxRead(SecureRandom sr) throws Exception {
177        if (os.equals("Linux")) {
178            if (!sr.getAlgorithm().equalsIgnoreCase("NativePRNGBlocking")) {
179                sr.nextBytes(new byte[34]);
180            }
181        } else {
182            sr.nextBytes(new byte[34]);
183            sr.generateSeed(34);
184            sr.setSeed(new byte[34]);
185        }
186    }
187
188    /*
189     * This is duplicating stuff above, but just iterate over all impls
190     * just in case we missed something.
191     */
192    private static void testAllImpls() throws Exception {
193        System.out.print("Testing:  AllImpls:  ");
194
195        Iterator<String> i = Security.getAlgorithms("SecureRandom").iterator();
196
197        while (i.hasNext()) {
198            String s = i.next();
199            System.out.print("/" + s);
200            SecureRandom sr = SecureRandom.getInstance(s);
201
202            handleLinuxRead(sr);
203            handleLinuxRead(sr);
204        }
205        System.out.println("/");
206    }
207
208    public static void main(String args[]) throws Exception {
209        testDefaultEgd();
210
211        testNativePRNGImpls();
212        testAllImpls();
213
214        // test default.
215        testStrongInstance(true);
216        testProperties();
217    }
218}
219