1 /*
2 * Copyright (c) 1997, 2019, 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 javax.crypto;
27
28 import java.util.*;
29
30 import java.security.*;
31 import java.security.Provider.Service;
32 import java.security.spec.*;
33
34 import sun.security.jca.*;
35 import sun.security.jca.GetInstance.Instance;
36 import sun.security.util.Debug;
37
38 /**
39 * This class provides the functionality of a secret (symmetric) key generator.
40 *
41 * <p>Key generators are constructed using one of the {@code getInstance}
42 * class methods of this class.
43 *
44 * <p>KeyGenerator objects are reusable, i.e., after a key has been
45 * generated, the same KeyGenerator object can be re-used to generate further
46 * keys.
47 *
48 * <p>There are two ways to generate a key: in an algorithm-independent
49 * manner, and in an algorithm-specific manner.
50 * The only difference between the two is the initialization of the object:
51 *
52 * <ul>
53 * <li><b>Algorithm-Independent Initialization</b>
54 * <p>All key generators share the concepts of a <i>keysize</i> and a
55 * <i>source of randomness</i>.
56 * There is an
57 * {@link #init(int, java.security.SecureRandom) init}
58 * method in this KeyGenerator class that takes these two universally
59 * shared types of arguments. There is also one that takes just a
60 * {@code keysize} argument, and uses the SecureRandom implementation
61 * of the highest-priority installed provider as the source of randomness
62 * (or a system-provided source of randomness if none of the installed
63 * providers supply a SecureRandom implementation), and one that takes just a
64 * source of randomness.
65 *
66 * <p>Since no other parameters are specified when you call the above
67 * algorithm-independent {@code init} methods, it is up to the
68 * provider what to do about the algorithm-specific parameters (if any) to be
69 * associated with each of the keys.
70 *
71 * <li><b>Algorithm-Specific Initialization</b>
72 * <p>For situations where a set of algorithm-specific parameters already
73 * exists, there are two
74 * {@link #init(java.security.spec.AlgorithmParameterSpec) init}
75 * methods that have an {@code AlgorithmParameterSpec}
76 * argument. One also has a {@code SecureRandom} argument, while the
77 * other uses the SecureRandom implementation
78 * of the highest-priority installed provider as the source of randomness
79 * (or a system-provided source of randomness if none of the installed
80 * providers supply a SecureRandom implementation).
81 * </ul>
82 *
83 * <p>In case the client does not explicitly initialize the KeyGenerator
84 * (via a call to an {@code init} method), each provider must
85 * supply (and document) a default initialization.
86 * See the Keysize Restriction sections of the
87 * {@extLink security_guide_jdk_providers JDK Providers}
88 * document for information on the KeyGenerator defaults used by
89 * JDK providers.
90 * However, note that defaults may vary across different providers.
91 * Additionally, the default value for a provider may change in a future
92 * version. Therefore, it is recommended to explicitly initialize the
93 * KeyGenerator instead of relying on provider-specific defaults.
94 *
95 * <p> Every implementation of the Java platform is required to support the
96 * following standard {@code KeyGenerator} algorithms with the keysizes in
97 * parentheses:
98 * <ul>
99 * <li>{@code AES} (128)</li>
100 * <li>{@code DESede} (168)</li>
101 * <li>{@code HmacSHA1}</li>
102 * <li>{@code HmacSHA256}</li>
103 * </ul>
104 * These algorithms are described in the <a href=
105 * "{@docRoot}/../specs/security/standard-names.html#keygenerator-algorithms">
106 * KeyGenerator section</a> of the
107 * Java Security Standard Algorithm Names Specification.
108 * Consult the release documentation for your implementation to see if any
109 * other algorithms are supported.
110 *
111 * @author Jan Luehe
112 *
113 * @see SecretKey
114 * @since 1.4
115 */
116
117 public class KeyGenerator {
118
119 private static final Debug pdebug =
120 Debug.getInstance("provider", "Provider");
121 private static final boolean skipDebug =
122 Debug.isOn("engine=") && !Debug.isOn("keygenerator");
123
124 // see java.security.KeyPairGenerator for failover notes
125
126 private static final int I_NONE = 1;
127 private static final int I_RANDOM = 2;
128 private static final int I_PARAMS = 3;
129 private static final int I_SIZE = 4;
130
131 // The provider
132 private Provider provider;
133
134 // The provider implementation (delegate)
135 private volatile KeyGeneratorSpi spi;
136
137 // The algorithm
138 private final String algorithm;
139
140 private final Object lock = new Object();
141
142 private Iterator<Service> serviceIterator;
143
144 private int initType;
145 private int initKeySize;
146 private AlgorithmParameterSpec initParams;
147 private SecureRandom initRandom;
148
149 /**
150 * Creates a KeyGenerator object.
151 *
152 * @param keyGenSpi the delegate
153 * @param provider the provider
154 * @param algorithm the algorithm
155 */
156 protected KeyGenerator(KeyGeneratorSpi keyGenSpi, Provider provider,
157 String algorithm) {
158 this.spi = keyGenSpi;
159 this.provider = provider;
160 this.algorithm = algorithm;
161
162 if (!skipDebug && pdebug != null) {
163 pdebug.println("KeyGenerator." + algorithm + " algorithm from: " +
164 getProviderName());
165 }
166 }
167
168 private KeyGenerator(String algorithm) throws NoSuchAlgorithmException {
169 this.algorithm = algorithm;
170 List<Service> list =
171 GetInstance.getServices("KeyGenerator", algorithm);
172 serviceIterator = list.iterator();
173 initType = I_NONE;
174 // fetch and instantiate initial spi
175 if (nextSpi(null, false) == null) {
176 throw new NoSuchAlgorithmException
177 (algorithm + " KeyGenerator not available");
178 }
179
180 if (!skipDebug && pdebug != null) {
181 pdebug.println("KeyGenerator." + algorithm + " algorithm from: " +
182 getProviderName());
183 }
184 }
185
186 private String getProviderName() {
187 return (provider == null) ? "(no provider)" : provider.getName();
188 }
189
190 /**
191 * Returns the algorithm name of this {@code KeyGenerator} object.
192 *
193 * <p>This is the same name that was specified in one of the
194 * {@code getInstance} calls that created this
195 * {@code KeyGenerator} object.
196 *
197 * @return the algorithm name of this {@code KeyGenerator} object.
198 */
199 public final String getAlgorithm() {
200 return this.algorithm;
201 }
202
203 /**
204 * Returns a {@code KeyGenerator} object that generates secret keys
205 * for the specified algorithm.
206 *
207 * <p> This method traverses the list of registered security Providers,
208 * starting with the most preferred Provider.
209 * A new KeyGenerator object encapsulating the
210 * KeyGeneratorSpi implementation from the first
211 * Provider that supports the specified algorithm is returned.
212 *
213 * <p> Note that the list of registered providers may be retrieved via
214 * the {@link Security#getProviders() Security.getProviders()} method.
215 *
216 * @implNote
217 * The JDK Reference Implementation additionally uses the
218 * {@code jdk.security.provider.preferred}
219 * {@link Security#getProperty(String) Security} property to determine
220 * the preferred provider order for the specified algorithm. This
221 * may be different than the order of providers returned by
222 * {@link Security#getProviders() Security.getProviders()}.
223 *
224 * @param algorithm the standard name of the requested key algorithm.
225 * See the KeyGenerator section in the <a href=
226 * "{@docRoot}/../specs/security/standard-names.html#keygenerator-algorithms">
227 * Java Security Standard Algorithm Names Specification</a>
228 * for information about standard algorithm names.
229 *
230 * @return the new {@code KeyGenerator} object
231 *
232 * @throws NoSuchAlgorithmException if no {@code Provider} supports a
233 * {@code KeyGeneratorSpi} implementation for the
234 * specified algorithm
235 *
236 * @throws NullPointerException if {@code algorithm} is {@code null}
237 *
238 * @see java.security.Provider
239 */
240 public static final KeyGenerator getInstance(String algorithm)
241 throws NoSuchAlgorithmException {
242 Objects.requireNonNull(algorithm, "null algorithm name");
243 return new KeyGenerator(algorithm);
244 }
245
246 /**
247 * Returns a {@code KeyGenerator} object that generates secret keys
248 * for the specified algorithm.
249 *
250 * <p> A new KeyGenerator object encapsulating the
251 * KeyGeneratorSpi implementation from the specified provider
252 * is returned. The specified provider must be registered
253 * in the security provider list.
254 *
255 * <p> Note that the list of registered providers may be retrieved via
256 * the {@link Security#getProviders() Security.getProviders()} method.
257 *
258 * @param algorithm the standard name of the requested key algorithm.
259 * See the KeyGenerator section in the <a href=
260 * "{@docRoot}/../specs/security/standard-names.html#keygenerator-algorithms">
261 * Java Security Standard Algorithm Names Specification</a>
262 * for information about standard algorithm names.
263 *
264 * @param provider the name of the provider.
265 *
266 * @return the new {@code KeyGenerator} object
267 *
268 * @throws IllegalArgumentException if the {@code provider}
269 * is {@code null} or empty
270 *
271 * @throws NoSuchAlgorithmException if a {@code KeyGeneratorSpi}
272 * implementation for the specified algorithm is not
273 * available from the specified provider
274 *
275 * @throws NoSuchProviderException if the specified provider is not
276 * registered in the security provider list
277 *
278 * @throws NullPointerException if {@code algorithm} is {@code null}
279 *
280 * @see java.security.Provider
281 */
282 public static final KeyGenerator getInstance(String algorithm,
283 String provider) throws NoSuchAlgorithmException,
284 NoSuchProviderException {
285 Objects.requireNonNull(algorithm, "null algorithm name");
286 Instance instance = JceSecurity.getInstance("KeyGenerator",
287 KeyGeneratorSpi.class, algorithm, provider);
288 return new KeyGenerator((KeyGeneratorSpi)instance.impl,
289 instance.provider, algorithm);
290 }
291
292 /**
293 * Returns a {@code KeyGenerator} object that generates secret keys
294 * for the specified algorithm.
295 *
296 * <p> A new KeyGenerator object encapsulating the
297 * KeyGeneratorSpi implementation from the specified Provider
298 * object is returned. Note that the specified Provider object
299 * does not have to be registered in the provider list.
300 *
301 * @param algorithm the standard name of the requested key algorithm.
302 * See the KeyGenerator section in the <a href=
303 * "{@docRoot}/../specs/security/standard-names.html#keygenerator-algorithms">
304 * Java Security Standard Algorithm Names Specification</a>
305 * for information about standard algorithm names.
306 *
307 * @param provider the provider.
308 *
309 * @return the new {@code KeyGenerator} object
310 *
311 * @throws IllegalArgumentException if the {@code provider}
312 * is {@code null}
313 *
314 * @throws NoSuchAlgorithmException if a {@code KeyGeneratorSpi}
315 * implementation for the specified algorithm is not available
316 * from the specified {@code Provider} object
317 *
318 * @throws NullPointerException if {@code algorithm} is {@code null}
319 *
320 * @see java.security.Provider
321 */
322 public static final KeyGenerator getInstance(String algorithm,
323 Provider provider) throws NoSuchAlgorithmException {
324 Objects.requireNonNull(algorithm, "null algorithm name");
325 Instance instance = JceSecurity.getInstance("KeyGenerator",
326 KeyGeneratorSpi.class, algorithm, provider);
327 return new KeyGenerator((KeyGeneratorSpi)instance.impl,
328 instance.provider, algorithm);
329 }
330
331 /**
332 * Returns the provider of this {@code KeyGenerator} object.
333 *
334 * @return the provider of this {@code KeyGenerator} object
335 */
336 public final Provider getProvider() {
337 synchronized (lock) {
338 disableFailover();
339 return provider;
340 }
341 }
342
343 /**
344 * Update the active spi of this class and return the next
345 * implementation for failover. If no more implementations are
346 * available, this method returns null. However, the active spi of
347 * this class is never set to null.
348 */
349 private KeyGeneratorSpi nextSpi(KeyGeneratorSpi oldSpi,
350 boolean reinit) {
351 synchronized (lock) {
352 // somebody else did a failover concurrently
353 // try that spi now
354 if ((oldSpi != null) && (oldSpi != spi)) {
355 return spi;
356 }
357 if (serviceIterator == null) {
358 return null;
359 }
360 while (serviceIterator.hasNext()) {
361 Service s = serviceIterator.next();
362 if (JceSecurity.canUseProvider(s.getProvider()) == false) {
363 continue;
364 }
365 try {
366 Object inst = s.newInstance(null);
367 // ignore non-spis
368 if (inst instanceof KeyGeneratorSpi == false) {
369 continue;
370 }
371 KeyGeneratorSpi spi = (KeyGeneratorSpi)inst;
372 if (reinit) {
373 if (initType == I_SIZE) {
374 spi.engineInit(initKeySize, initRandom);
375 } else if (initType == I_PARAMS) {
376 spi.engineInit(initParams, initRandom);
377 } else if (initType == I_RANDOM) {
378 spi.engineInit(initRandom);
379 } else if (initType != I_NONE) {
380 throw new AssertionError
381 ("KeyGenerator initType: " + initType);
382 }
383 }
384 provider = s.getProvider();
385 this.spi = spi;
386 return spi;
387 } catch (Exception e) {
388 // ignore
389 }
390 }
391 disableFailover();
392 return null;
393 }
394 }
395
396 void disableFailover() {
397 serviceIterator = null;
398 initType = 0;
399 initParams = null;
400 initRandom = null;
401 }
402
403 /**
404 * Initializes this key generator.
405 *
406 * @param random the source of randomness for this generator
407 */
408 public final void init(SecureRandom random) {
409 if (serviceIterator == null) {
410 spi.engineInit(random);
411 return;
412 }
413 RuntimeException failure = null;
414 KeyGeneratorSpi mySpi = spi;
415 do {
416 try {
417 mySpi.engineInit(random);
418 initType = I_RANDOM;
419 initKeySize = 0;
420 initParams = null;
421 initRandom = random;
422 return;
423 } catch (RuntimeException e) {
424 if (failure == null) {
425 failure = e;
426 }
427 mySpi = nextSpi(mySpi, false);
428 }
429 } while (mySpi != null);
430 throw failure;
431 }
432
433 /**
434 * Initializes this key generator with the specified parameter set.
435 *
436 * <p> If this key generator requires any random bytes, it will get them
437 * using the
438 * {@link java.security.SecureRandom}
439 * implementation of the highest-priority installed
440 * provider as the source of randomness.
441 * (If none of the installed providers supply an implementation of
442 * SecureRandom, a system-provided source of randomness will be used.)
443 *
444 * @param params the key generation parameters
445 *
446 * @exception InvalidAlgorithmParameterException if the given parameters
447 * are inappropriate for this key generator
448 */
449 public final void init(AlgorithmParameterSpec params)
450 throws InvalidAlgorithmParameterException
451 {
452 init(params, JceSecurity.RANDOM);
453 }
454
455 /**
456 * Initializes this key generator with the specified parameter
457 * set and a user-provided source of randomness.
458 *
459 * @param params the key generation parameters
460 * @param random the source of randomness for this key generator
461 *
462 * @exception InvalidAlgorithmParameterException if {@code params} is
463 * inappropriate for this key generator
464 */
465 public final void init(AlgorithmParameterSpec params, SecureRandom random)
466 throws InvalidAlgorithmParameterException
467 {
468 if (serviceIterator == null) {
469 spi.engineInit(params, random);
470 return;
471 }
472 Exception failure = null;
473 KeyGeneratorSpi mySpi = spi;
474 do {
475 try {
476 mySpi.engineInit(params, random);
477 initType = I_PARAMS;
478 initKeySize = 0;
479 initParams = params;
480 initRandom = random;
481 return;
482 } catch (Exception e) {
483 if (failure == null) {
484 failure = e;
485 }
486 mySpi = nextSpi(mySpi, false);
487 }
488 } while (mySpi != null);
489 if (failure instanceof InvalidAlgorithmParameterException) {
490 throw (InvalidAlgorithmParameterException)failure;
491 }
492 if (failure instanceof RuntimeException) {
493 throw (RuntimeException)failure;
494 }
495 throw new InvalidAlgorithmParameterException("init() failed", failure);
496 }
497
498 /**
499 * Initializes this key generator for a certain keysize.
500 *
501 * <p> If this key generator requires any random bytes, it will get them
502 * using the
503 * {@link java.security.SecureRandom}
504 * implementation of the highest-priority installed
505 * provider as the source of randomness.
506 * (If none of the installed providers supply an implementation of
507 * SecureRandom, a system-provided source of randomness will be used.)
508 *
509 * @param keysize the keysize. This is an algorithm-specific metric,
510 * specified in number of bits.
511 *
512 * @exception InvalidParameterException if the keysize is wrong or not
513 * supported.
514 */
515 public final void init(int keysize) {
516 init(keysize, JceSecurity.RANDOM);
517 }
518
519 /**
520 * Initializes this key generator for a certain keysize, using a
521 * user-provided source of randomness.
522 *
523 * @param keysize the keysize. This is an algorithm-specific metric,
524 * specified in number of bits.
525 * @param random the source of randomness for this key generator
526 *
527 * @exception InvalidParameterException if the keysize is wrong or not
528 * supported.
529 */
530 public final void init(int keysize, SecureRandom random) {
531 if (serviceIterator == null) {
532 spi.engineInit(keysize, random);
533 return;
534 }
535 RuntimeException failure = null;
536 KeyGeneratorSpi mySpi = spi;
537 do {
538 try {
539 mySpi.engineInit(keysize, random);
540 initType = I_SIZE;
541 initKeySize = keysize;
542 initParams = null;
543 initRandom = random;
544 return;
545 } catch (RuntimeException e) {
546 if (failure == null) {
547 failure = e;
548 }
549 mySpi = nextSpi(mySpi, false);
550 }
551 } while (mySpi != null);
552 throw failure;
553 }
554
555 /**
556 * Generates a secret key.
557 *
558 * @return the new key
559 */
560 public final SecretKey generateKey() {
561 if (serviceIterator == null) {
562 return spi.engineGenerateKey();
563 }
564 RuntimeException failure = null;
565 KeyGeneratorSpi mySpi = spi;
566 do {
567 try {
568 return mySpi.engineGenerateKey();
569 } catch (RuntimeException e) {
570 if (failure == null) {
571 failure = e;
572 }
573 mySpi = nextSpi(mySpi, true);
574 }
575 } while (mySpi != null);
576 throw failure;
577 }
578 }
--- EOF ---