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/* @test
25 * @bug 8051408 8157308 8130181
26 * @modules java.base/sun.security.provider
27 * @build java.base/sun.security.provider.S
28 * @run main SpecTest
29 * @summary check the AbstractDrbg API etc
30 */
31
32import java.security.*;
33import sun.security.provider.S;
34import static java.security.DrbgParameters.Capability.*;
35
36/**
37 * This test makes sure the AbstractDrbg API works as specified. It also
38 * checks the SecureRandom API.
39 *
40 * The implementations must be patched into java.base/sun.security.provider
41 * because AbstractDrbg is not a public interface.
42 */
43public class SpecTest {
44
45    public static void main(String args[]) throws Exception {
46
47        // getInstance from a provider.
48
49        Provider p = new All("A", "0", "");
50        byte[] bytes = new byte[100];
51
52        // A non-DRBG
53        iae(() -> SecureRandom.getInstance("S1", null, p));
54        nsae(() -> SecureRandom.getInstance("S1",
55                new SecureRandomParameters() {}, p));
56
57        SecureRandom s1 = SecureRandom.getInstance("S1", p);
58        if (s1.getParameters() != null) {
59            throw new Exception();
60        }
61
62        iae(() -> s1.nextBytes(bytes, null));
63        uoe(() -> s1.nextBytes(bytes, new SecureRandomParameters() {}));
64        uoe(() -> s1.reseed());
65        iae(() -> s1.reseed(null));
66        uoe(() -> s1.reseed(new SecureRandomParameters() {}));
67
68        // A weak DRBG
69        iae(() -> SecureRandom.getInstance("S2", null, p));
70        nsae(() -> SecureRandom.getInstance("S2",
71                new SecureRandomParameters() {}, p));
72        nsae(() -> SecureRandom.getInstance("S2",
73                DrbgParameters.instantiation(256, NONE, null), p));
74        nsae(() -> SecureRandom.getInstance("S2",
75                DrbgParameters.instantiation(-1, PR_AND_RESEED, null), p));
76        nsae(() -> SecureRandom.getInstance("S2",
77                DrbgParameters.instantiation(-1, RESEED_ONLY, null), p));
78
79        SecureRandom s2 = SecureRandom.getInstance("S2",
80                DrbgParameters.instantiation(-1, NONE, null), p);
81        equals(s2, "S2,SQUEEZE,128,none");
82        equals(s2.getParameters(), "128,none,null");
83
84        npe(() -> s2.nextBytes(null));
85        iae(() -> s2.nextBytes(bytes, null));
86        iae(() -> s2.nextBytes(bytes, new SecureRandomParameters() {}));
87        uoe(() -> s2.reseed());
88        iae(() -> s2.reseed(null));
89
90        iae(() -> s2.nextBytes(bytes,
91                DrbgParameters.nextBytes(-1, false, new byte[101])));
92        s2.nextBytes(new byte[101],
93                DrbgParameters.nextBytes(-1, false, new byte[100]));
94        s2.nextBytes(bytes,
95                DrbgParameters.nextBytes(-1, false, new byte[100]));
96
97        // A strong DRBG
98        iae(() -> SecureRandom.getInstance("S3", null, p));
99        nsae(() -> SecureRandom.getInstance("S3",
100                new SecureRandomParameters() {}, p));
101        SecureRandom.getInstance("S3",
102                DrbgParameters.instantiation(192, PR_AND_RESEED, null), p);
103
104        SecureRandom s3 = SecureRandom.getInstance("S3", p);
105        equals(s3, "S3,SQUEEZE,128,reseed_only");
106        equals(s3.getParameters(), "128,reseed_only,null");
107
108        iae(() -> s3.nextBytes(bytes,
109                DrbgParameters.nextBytes(192, false, null)));
110        iae(() -> s3.nextBytes(bytes,
111                DrbgParameters.nextBytes(112, true, null)));
112        iae(() -> s3.reseed(new SecureRandomParameters() {}));
113
114        SecureRandom s32 = SecureRandom.getInstance(
115                "S3", DrbgParameters.instantiation(192, PR_AND_RESEED, null), p);
116        equals(s32, "S3,SQUEEZE,192,pr_and_reseed");
117        equals(s32.getParameters(), "192,pr_and_reseed,null");
118
119        s32.nextBytes(bytes, DrbgParameters.nextBytes(192, false, null));
120        s32.nextBytes(bytes, DrbgParameters.nextBytes(112, true, null));
121        s32.reseed();
122        s32.reseed(DrbgParameters.reseed(true, new byte[100]));
123
124        // getInstance from competitive providers.
125
126        Provider l = new Legacy("L", "0", "");
127        Provider w = new Weak("W", "0", "");
128        Provider s = new Strong("S", "0", "");
129
130        Security.addProvider(l);
131        Security.addProvider(w);
132        Security.addProvider(s);
133
134        SecureRandom s4;
135
136        try {
137            s4 = SecureRandom.getInstance("S");
138            if (s4.getProvider() != l) {
139                throw new Exception();
140            }
141
142            nsae(() -> SecureRandom.getInstance(
143                    "S", DrbgParameters.instantiation(256, NONE, null)));
144
145            s4 = SecureRandom.getInstance(
146                    "S", DrbgParameters.instantiation(192, NONE, null));
147            if (s4.getProvider() != s) {
148                throw new Exception();
149            }
150
151            s4 = SecureRandom.getInstance(
152                    "S", DrbgParameters.instantiation(128, PR_AND_RESEED, null));
153            if (s4.getProvider() != s) {
154                throw new Exception();
155            }
156
157            s4 = SecureRandom.getInstance(
158                    "S", DrbgParameters.instantiation(128, RESEED_ONLY, null));
159            if (s4.getProvider() != s) {
160                throw new Exception();
161            }
162
163            s4 = SecureRandom.getInstance(
164                    "S", DrbgParameters.instantiation(128, NONE, null));
165            if (s4.getProvider() != w) {
166                throw new Exception();
167            }
168        } finally {
169            Security.removeProvider("L");
170            Security.removeProvider("W");
171            Security.removeProvider("S");
172        }
173    }
174
175    public static class All extends Provider {
176        protected All(String name, String version, String info) {
177            super(name, version, info);
178            put("SecureRandom.S1", S.S1.class.getName());
179            put("SecureRandom.S2", S.S2.class.getName());
180            put("SecureRandom.S3", S.S3.class.getName());
181        }
182    }
183
184    // Providing S with no params support
185    public static class Legacy extends Provider {
186        protected Legacy(String name, String version, String info) {
187            super(name, version, info);
188            put("SecureRandom.S", S.S1.class.getName());
189        }
190    }
191
192    public static class Weak extends Provider {
193        protected Weak(String name, String version, String info) {
194            super(name, version, info);
195            put("SecureRandom.S", S.S2.class.getName());
196        }
197    }
198
199    public static class Strong extends Provider {
200        protected Strong(String name, String version, String info) {
201            super(name, version, info);
202            put("SecureRandom.S", S.S3.class.getName());
203        }
204    }
205
206    static void nsae(RunnableWithException r) throws Exception {
207        checkException(r, NoSuchAlgorithmException.class);
208    }
209
210    static void iae(RunnableWithException r) throws Exception {
211        checkException(r, IllegalArgumentException.class);
212    }
213
214    static void uoe(RunnableWithException r) throws Exception {
215        checkException(r, UnsupportedOperationException.class);
216    }
217
218    static void npe(RunnableWithException r) throws Exception {
219        checkException(r, NullPointerException.class);
220    }
221
222    interface RunnableWithException {
223        void run() throws Exception;
224    }
225
226    static void checkException(RunnableWithException r, Class ex)
227            throws Exception {
228        try {
229            r.run();
230        } catch (Exception e) {
231            if (ex.isAssignableFrom(e.getClass())) {
232                return;
233            }
234            throw e;
235        }
236        throw new Exception("No exception thrown");
237    }
238
239    static void equals(Object o, String s) throws Exception {
240        if (!o.toString().equals(s)) {
241            throw new Exception(o.toString() + " is not " + s);
242        }
243    }
244}
245