Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/java/security/DrbgParameters.java
41152 views
1
/*
2
* Copyright (c) 2016, 2018, 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. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package java.security;
27
28
import java.util.Locale;
29
import java.util.Objects;
30
31
/**
32
* This class specifies the parameters used by a DRBG (Deterministic
33
* Random Bit Generator).
34
* <p>
35
* According to
36
* <a href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf">
37
* NIST Special Publication 800-90A Revision 1, Recommendation for Random
38
* Number Generation Using Deterministic Random Bit Generators</a> (800-90Ar1),
39
* <blockquote>
40
* A DRBG is based on a DRBG mechanism as specified in this Recommendation
41
* and includes a source of randomness. A DRBG mechanism uses an algorithm
42
* (i.e., a DRBG algorithm) that produces a sequence of bits from an initial
43
* value that is determined by a seed that is determined from the output of
44
* the randomness source."
45
* </blockquote>
46
* <p>
47
* The 800-90Ar1 specification allows for a variety of DRBG implementation
48
* choices, such as:
49
* <ul>
50
* <li> an entropy source,
51
* <li> a DRBG mechanism (for example, Hash_DRBG),
52
* <li> a DRBG algorithm (for example, SHA-256 for Hash_DRBG and AES-256
53
* for CTR_DRBG. Please note that it is not the algorithm used in
54
* {@link SecureRandom#getInstance}, which we will call a
55
* <em>SecureRandom algorithm</em> below),
56
* <li> optional features, including prediction resistance
57
* and reseeding supports,
58
* <li> highest security strength.
59
* </ul>
60
* <p>
61
* These choices are set in each implementation and are not directly
62
* managed by the {@code SecureRandom} API. Check your DRBG provider's
63
* documentation to find an appropriate implementation for the situation.
64
* <p>
65
* On the other hand, the 800-90Ar1 specification does have some configurable
66
* options, such as:
67
* <ul>
68
* <li> required security strength,
69
* <li> if prediction resistance is required,
70
* <li> personalization string and additional input.
71
* </ul>
72
* <p>
73
* A DRBG instance can be instantiated with parameters from an
74
* {@link DrbgParameters.Instantiation} object and other information
75
* (for example, the nonce, which is not managed by this API). This maps
76
* to the {@code Instantiate_function} defined in NIST SP 800-90Ar1.
77
* <p>
78
* A DRBG instance can be reseeded with parameters from a
79
* {@link DrbgParameters.Reseed} object. This maps to the
80
* {@code Reseed_function} defined in NIST SP 800-90Ar1. Calling
81
* {@link SecureRandom#reseed()} is equivalent to calling
82
* {@link SecureRandom#reseed(SecureRandomParameters)} with the effective
83
* instantiated prediction resistance flag (as returned by
84
* {@link SecureRandom#getParameters()}) with no additional input.
85
* <p>
86
* A DRBG instance generates data with additional parameters from a
87
* {@link DrbgParameters.NextBytes} object. This maps to the
88
* {@code Generate_function} defined in NIST SP 800-90Ar1. Calling
89
* {@link SecureRandom#nextBytes(byte[])} is equivalent to calling
90
* {@link SecureRandom#nextBytes(byte[], SecureRandomParameters)}
91
* with the effective instantiated strength and prediction resistance flag
92
* (as returned by {@link SecureRandom#getParameters()}) with no
93
* additional input.
94
* <p>
95
* A DRBG should be implemented as a subclass of {@link SecureRandomSpi}.
96
* It is recommended that the implementation contain the 1-arg
97
* {@linkplain SecureRandomSpi#SecureRandomSpi(SecureRandomParameters) constructor}
98
* that takes a {@code DrbgParameters.Instantiation} argument. If implemented
99
* this way, this implementation can be chosen by any
100
* {@code SecureRandom.getInstance()} method. If it is chosen by a
101
* {@code SecureRandom.getInstance()} with a {@link SecureRandomParameters}
102
* parameter, the parameter is passed into this constructor. If it is chosen
103
* by a {@code SecureRandom.getInstance()} without a
104
* {@code SecureRandomParameters} parameter, the constructor is called with
105
* a {@code null} argument and the implementation should choose its own
106
* parameters. Its {@link SecureRandom#getParameters()} must always return a
107
* non-null effective {@code DrbgParameters.Instantiation} object that reflects
108
* how the DRBG is actually instantiated. A caller can use this information
109
* to determine whether a {@code SecureRandom} object is a DRBG and what
110
* features it supports. Please note that the returned value does not
111
* necessarily equal to the {@code DrbgParameters.Instantiation} object passed
112
* into the {@code SecureRandom.getInstance()} call. For example,
113
* the requested capability can be {@link DrbgParameters.Capability#NONE}
114
* but the effective value can be {@link DrbgParameters.Capability#RESEED_ONLY}
115
* if the implementation supports reseeding. The implementation must implement
116
* the {@link SecureRandomSpi#engineNextBytes(byte[], SecureRandomParameters)}
117
* method which takes a {@code DrbgParameters.NextBytes} parameter. Unless
118
* the result of {@link SecureRandom#getParameters()} has its
119
* {@linkplain DrbgParameters.Instantiation#getCapability() capability} being
120
* {@link Capability#NONE NONE}, it must implement
121
* {@link SecureRandomSpi#engineReseed(SecureRandomParameters)} which takes
122
* a {@code DrbgParameters.Reseed} parameter.
123
* <p>
124
* On the other hand, if a DRBG implementation does not contain a constructor
125
* that has an {@code DrbgParameters.Instantiation} argument (not recommended),
126
* it can only be chosen by a {@code SecureRandom.getInstance()} without
127
* a {@code SecureRandomParameters} parameter, but will not be chosen if
128
* a {@code getInstance} method with a {@code SecureRandomParameters} parameter
129
* is called. If implemented this way, its {@link SecureRandom#getParameters()}
130
* must return {@code null}, and it does not need to implement either
131
* {@link SecureRandomSpi#engineNextBytes(byte[], SecureRandomParameters)}
132
* or {@link SecureRandomSpi#engineReseed(SecureRandomParameters)}.
133
* <p>
134
* A DRBG might reseed itself automatically if the seed period is bigger
135
* than the maximum seed life defined by the DRBG mechanism.
136
* <p>
137
* A DRBG implementation should support serialization and deserialization
138
* by retaining the configuration and effective parameters, but the internal
139
* state must not be serialized and the deserialized object must be
140
* reinstantiated.
141
* <p>
142
* Examples:
143
* <blockquote><pre>
144
* SecureRandom drbg;
145
* byte[] buffer = new byte[32];
146
*
147
* // Any DRBG is OK
148
* drbg = SecureRandom.getInstance("DRBG");
149
* drbg.nextBytes(buffer);
150
*
151
* SecureRandomParameters params = drbg.getParameters();
152
* if (params instanceof DrbgParameters.Instantiation) {
153
* DrbgParameters.Instantiation ins = (DrbgParameters.Instantiation) params;
154
* if (ins.getCapability().supportsReseeding()) {
155
* drbg.reseed();
156
* }
157
* }
158
*
159
* // The following call requests a weak DRBG instance. It is only
160
* // guaranteed to support 112 bits of security strength.
161
* drbg = SecureRandom.getInstance("DRBG",
162
* DrbgParameters.instantiation(112, NONE, null));
163
*
164
* // Both the next two calls will likely fail, because drbg could be
165
* // instantiated with a smaller strength with no prediction resistance
166
* // support.
167
* drbg.nextBytes(buffer,
168
* DrbgParameters.nextBytes(256, false, "more".getBytes()));
169
* drbg.nextBytes(buffer,
170
* DrbgParameters.nextBytes(112, true, "more".getBytes()));
171
*
172
* // The following call requests a strong DRBG instance, with a
173
* // personalization string. If it successfully returns an instance,
174
* // that instance is guaranteed to support 256 bits of security strength
175
* // with prediction resistance available.
176
* drbg = SecureRandom.getInstance("DRBG", DrbgParameters.instantiation(
177
* 256, PR_AND_RESEED, "hello".getBytes()));
178
*
179
* // Prediction resistance is not requested in this single call,
180
* // but an additional input is used.
181
* drbg.nextBytes(buffer,
182
* DrbgParameters.nextBytes(-1, false, "more".getBytes()));
183
*
184
* // Same for this call.
185
* drbg.reseed(DrbgParameters.reseed(false, "extra".getBytes()));</pre>
186
* </blockquote>
187
*
188
* @implSpec
189
* By convention, a provider should name its primary DRBG implementation
190
* with the <a href=
191
* "{@docRoot}/../specs/security/standard-names.html#securerandom-number-generation-algorithms">
192
* standard {@code SecureRandom} algorithm name</a> "DRBG".
193
*
194
* @implNote
195
* The following notes apply to the "DRBG" implementation in the SUN provider
196
* of the JDK reference implementation.
197
* <p>
198
* This implementation supports the Hash_DRBG and HMAC_DRBG mechanisms with
199
* DRBG algorithm SHA-224, SHA-512/224, SHA-256, SHA-512/256, SHA-384 and
200
* SHA-512, and CTR_DRBG (both using derivation function and not using
201
* derivation function) with DRBG algorithm AES-128, AES-192 and AES-256.
202
* <p>
203
* The mechanism name and DRBG algorithm name are determined by the
204
* {@linkplain Security#getProperty(String) security property}
205
* {@code securerandom.drbg.config}. The default choice is Hash_DRBG
206
* with SHA-256.
207
* <p>
208
* For each combination, the security strength can be requested from 112
209
* up to the highest strength it supports. Both reseeding and prediction
210
* resistance are supported.
211
* <p>
212
* Personalization string is supported through the
213
* {@link DrbgParameters.Instantiation} class and additional input is supported
214
* through the {@link DrbgParameters.NextBytes} and
215
* {@link DrbgParameters.Reseed} classes.
216
* <p>
217
* If a DRBG is not instantiated with a {@link DrbgParameters.Instantiation}
218
* object explicitly, this implementation instantiates it with a default
219
* requested strength of 128 bits, no prediction resistance request, and
220
* no personalization string. These default instantiation parameters can also
221
* be customized with the {@code securerandom.drbg.config} security property.
222
* <p>
223
* This implementation reads fresh entropy from the system default entropy
224
* source determined by the security property {@code securerandom.source}.
225
* <p>
226
* Calling {@link SecureRandom#generateSeed(int)} will directly read
227
* from this system default entropy source.
228
*
229
* @since 9
230
*/
231
public class DrbgParameters {
232
233
private DrbgParameters() {
234
// This class should not be instantiated
235
}
236
237
/**
238
* The reseedable and prediction resistance capabilities of a DRBG.
239
* <p>
240
* When this object is passed to a {@code SecureRandom.getInstance()} call,
241
* it is the requested minimum capability. When it's returned from
242
* {@code SecureRandom.getParameters()}, it is the effective capability.
243
* <p>
244
* Please note that while the {@code Instantiate_function} defined in
245
* NIST SP 800-90Ar1 only includes a {@code prediction_resistance_flag}
246
* parameter, the {@code Capability} type includes an extra value
247
* {@link #RESEED_ONLY} because reseeding is an optional function.
248
* If {@code NONE} is used in an {@code Instantiation} object in calling the
249
* {@code SecureRandom.getInstance} method, the returned DRBG instance
250
* is not guaranteed to support reseeding. If {@code RESEED_ONLY} or
251
* {@code PR_AND_RESEED} is used, the instance must support reseeding.
252
* <p>
253
* The table below lists possible effective values if a certain
254
* capability is requested, i.e.
255
* <blockquote><pre>
256
* Capability requested = ...;
257
* SecureRandom s = SecureRandom.getInstance("DRBG",
258
* DrbgParameters(-1, requested, null));
259
* Capability effective = ((DrbgParametes.Initiate) s.getParameters())
260
* .getCapability();</pre>
261
* </blockquote>
262
* <table class="striped">
263
* <caption style="display:none">requested and effective capabilities</caption>
264
* <thead>
265
* <tr>
266
* <th scope="col">Requested Value</th>
267
* <th scope="col">Possible Effective Values</th>
268
* </tr>
269
* </thead>
270
* <tbody style="text-align:left">
271
* <tr><th scope="row">NONE</th><td>NONE, RESEED_ONLY, PR_AND_RESEED</td></tr>
272
* <tr><th scope="row">RESEED_ONLY</th><td>RESEED_ONLY, PR_AND_RESEED</td></tr>
273
* <tr><th scope="row">PR_AND_RESEED</th><td>PR_AND_RESEED</td></tr>
274
* </tbody>
275
* </table>
276
* <p>
277
* A DRBG implementation supporting prediction resistance must also
278
* support reseeding.
279
*
280
* @since 9
281
*/
282
public enum Capability {
283
284
/**
285
* Both prediction resistance and reseed.
286
*/
287
PR_AND_RESEED,
288
289
/**
290
* Reseed but no prediction resistance.
291
*/
292
RESEED_ONLY,
293
294
/**
295
* Neither prediction resistance nor reseed.
296
*/
297
NONE;
298
299
@Override
300
public String toString() {
301
return name().toLowerCase(Locale.ROOT);
302
}
303
304
/**
305
* Returns whether this capability supports reseeding.
306
*
307
* @return {@code true} for {@link #PR_AND_RESEED} and
308
* {@link #RESEED_ONLY}, and {@code false} for {@link #NONE}
309
*/
310
public boolean supportsReseeding() {
311
return this != NONE;
312
}
313
314
/**
315
* Returns whether this capability supports prediction resistance.
316
*
317
* @return {@code true} for {@link #PR_AND_RESEED}, and {@code false}
318
* for {@link #RESEED_ONLY} and {@link #NONE}
319
*/
320
public boolean supportsPredictionResistance() {
321
return this == PR_AND_RESEED;
322
}
323
}
324
325
/**
326
* DRBG parameters for instantiation.
327
* <p>
328
* When used in
329
* {@link SecureRandom#getInstance(String, SecureRandomParameters)}
330
* or one of the other similar {@code getInstance} calls that take a
331
* {@code SecureRandomParameters} parameter, it means the
332
* requested instantiate parameters the newly created {@code SecureRandom}
333
* object must minimally support. When used as the return value of the
334
* {@link SecureRandom#getParameters()} method, it means the effective
335
* instantiate parameters of the {@code SecureRandom} object.
336
*
337
* @since 9
338
*/
339
public static final class Instantiation
340
implements SecureRandomParameters {
341
342
private final int strength;
343
private final Capability capability;
344
private final byte[] personalizationString;
345
346
/**
347
* Returns the security strength in bits.
348
*
349
* @return If used in {@code getInstance}, returns the minimum strength
350
* requested, or -1 if there is no specific request on the strength.
351
* If used in {@code getParameters}, returns the effective strength.
352
* The effective strength must be greater than or equal to the minimum
353
* strength requested.
354
*/
355
public int getStrength() {
356
return strength;
357
}
358
359
/**
360
* Returns the capability.
361
*
362
* @return If used in {@code getInstance}, returns the minimum
363
* capability requested. If used in {@code getParameters}, returns
364
* information on the effective prediction resistance flag and
365
* whether it supports reseeding.
366
*/
367
public Capability getCapability() {
368
return capability;
369
}
370
371
/**
372
* Returns the personalization string as a byte array.
373
*
374
* @return If used in {@code getInstance}, returns the requested
375
* personalization string as a newly allocated array, or {@code null}
376
* if no personalization string is requested. The same string should
377
* be returned in {@code getParameters} as a new copy, or {@code null}
378
* if no personalization string is requested in {@code getInstance}.
379
*/
380
public byte[] getPersonalizationString() {
381
return (personalizationString == null) ?
382
null : personalizationString.clone();
383
}
384
385
private Instantiation(int strength, Capability capability,
386
byte[] personalizationString) {
387
if (strength < -1) {
388
throw new IllegalArgumentException(
389
"Illegal security strength: " + strength);
390
}
391
this.strength = strength;
392
this.capability = capability;
393
this.personalizationString = (personalizationString == null) ?
394
null : personalizationString.clone();
395
}
396
397
/**
398
* Returns a Human-readable string representation of this
399
* {@code Instantiation}.
400
*
401
* @return the string representation
402
*/
403
@Override
404
public String toString() {
405
// I don't care what personalizationString looks like
406
return strength + "," + capability + "," + personalizationString;
407
}
408
}
409
410
/**
411
* DRBG parameters for random bits generation. It is used in
412
* {@link SecureRandom#nextBytes(byte[], SecureRandomParameters)}.
413
*
414
* @since 9
415
*/
416
public static final class NextBytes
417
implements SecureRandomParameters {
418
private final int strength;
419
private final boolean predictionResistance;
420
private final byte[] additionalInput;
421
422
/**
423
* Returns the security strength requested in bits.
424
*
425
* @return the strength requested, or -1 if the effective strength
426
* should be used.
427
*/
428
public int getStrength() {
429
return strength;
430
}
431
432
/**
433
* Returns whether prediction resistance is requested.
434
*
435
* @return whether prediction resistance is requested
436
*/
437
public boolean getPredictionResistance() {
438
return predictionResistance;
439
}
440
441
/**
442
* Returns the requested additional input.
443
*
444
* @return the requested additional input, {@code null} if not
445
* requested. A new byte array is returned each time this method
446
* is called.
447
*/
448
public byte[] getAdditionalInput() {
449
return additionalInput == null? null: additionalInput.clone();
450
}
451
452
private NextBytes(int strength, boolean predictionResistance,
453
byte[] additionalInput) {
454
if (strength < -1) {
455
throw new IllegalArgumentException(
456
"Illegal security strength: " + strength);
457
}
458
this.strength = strength;
459
this.predictionResistance = predictionResistance;
460
this.additionalInput = (additionalInput == null) ?
461
null : additionalInput.clone();
462
}
463
}
464
465
/**
466
* DRBG parameters for reseed. It is used in
467
* {@link SecureRandom#reseed(SecureRandomParameters)}.
468
*
469
* @since 9
470
*/
471
public static final class Reseed implements SecureRandomParameters {
472
473
private final byte[] additionalInput;
474
private final boolean predictionResistance;
475
476
/**
477
* Returns whether prediction resistance is requested.
478
*
479
* @return whether prediction resistance is requested
480
*/
481
public boolean getPredictionResistance() {
482
return predictionResistance;
483
}
484
485
/**
486
* Returns the requested additional input.
487
*
488
* @return the requested additional input, or {@code null} if
489
* not requested. A new byte array is returned each time this method
490
* is called.
491
*/
492
public byte[] getAdditionalInput() {
493
return additionalInput == null ? null : additionalInput.clone();
494
}
495
496
private Reseed(boolean predictionResistance, byte[] additionalInput) {
497
this.predictionResistance = predictionResistance;
498
this.additionalInput = (additionalInput == null) ?
499
null : additionalInput.clone();
500
}
501
}
502
503
/**
504
* Generates a {@link DrbgParameters.Instantiation} object.
505
*
506
* @param strength security strength in bits, -1 for default strength
507
* if used in {@code getInstance}.
508
* @param capability capability
509
* @param personalizationString personalization string as a byte array,
510
* can be {@code null}. The content of this
511
* byte array will be copied.
512
* @return a new {@code Instantiation} object
513
* @throws NullPointerException if {@code capability} is {@code null}
514
* @throws IllegalArgumentException if {@code strength} is less than -1
515
*/
516
public static Instantiation instantiation(int strength,
517
Capability capability,
518
byte[] personalizationString) {
519
return new Instantiation(strength, Objects.requireNonNull(capability),
520
personalizationString);
521
}
522
523
/**
524
* Generates a {@link NextBytes} object.
525
*
526
* @param strength requested security strength in bits. If set to -1, the
527
* effective strength will be used.
528
* @param predictionResistance prediction resistance requested
529
* @param additionalInput additional input, can be {@code null}.
530
* The content of this byte array will be copied.
531
* @throws IllegalArgumentException if {@code strength} is less than -1
532
* @return a new {@code NextBytes} object
533
*/
534
public static NextBytes nextBytes(int strength,
535
boolean predictionResistance,
536
byte[] additionalInput) {
537
return new NextBytes(strength, predictionResistance, additionalInput);
538
}
539
540
/**
541
* Generates a {@link Reseed} object.
542
*
543
* @param predictionResistance prediction resistance requested
544
* @param additionalInput additional input, can be {@code null}.
545
* The content of this byte array will be copied.
546
* @return a new {@code Reseed} object
547
*/
548
public static Reseed reseed(
549
boolean predictionResistance, byte[] additionalInput) {
550
return new Reseed(predictionResistance, additionalInput);
551
}
552
}
553
554