blob: 5951eef3f08b5f6fa3e5318f40d6de70ae8241a6 [file] [log] [blame]
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +00001/*
Sergio Giro17982542016-08-03 19:21:52 +01002 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +00003 * 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
26package javax.crypto;
27
28import java.util.*;
29
30import java.security.*;
31import java.security.Provider.Service;
32import java.security.spec.*;
33
34import sun.security.jca.*;
35import sun.security.jca.GetInstance.Instance;
36
37/**
38 * This class provides the functionality of a secret (symmetric) key generator.
39 *
40 * <p>Key generators are constructed using one of the <code>getInstance</code>
41 * class methods of this class.
42 *
43 * <p>KeyGenerator objects are reusable, i.e., after a key has been
44 * generated, the same KeyGenerator object can be re-used to generate further
45 * keys.
46 *
47 * <p>There are two ways to generate a key: in an algorithm-independent
48 * manner, and in an algorithm-specific manner.
49 * The only difference between the two is the initialization of the object:
50 *
51 * <ul>
52 * <li><b>Algorithm-Independent Initialization</b>
53 * <p>All key generators share the concepts of a <i>keysize</i> and a
54 * <i>source of randomness</i>.
55 * There is an
56 * {@link #init(int, java.security.SecureRandom) init}
57 * method in this KeyGenerator class that takes these two universally
58 * shared types of arguments. There is also one that takes just a
59 * <code>keysize</code> argument, and uses the SecureRandom implementation
60 * of the highest-priority installed provider as the source of randomness
61 * (or a system-provided source of randomness if none of the installed
62 * providers supply a SecureRandom implementation), and one that takes just a
63 * source of randomness.
64 *
65 * <p>Since no other parameters are specified when you call the above
66 * algorithm-independent <code>init</code> methods, it is up to the
67 * provider what to do about the algorithm-specific parameters (if any) to be
68 * associated with each of the keys.
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +000069 *
70 * <li><b>Algorithm-Specific Initialization</b>
71 * <p>For situations where a set of algorithm-specific parameters already
72 * exists, there are two
73 * {@link #init(java.security.spec.AlgorithmParameterSpec) init}
74 * methods that have an <code>AlgorithmParameterSpec</code>
75 * argument. One also has a <code>SecureRandom</code> argument, while the
76 * other uses the SecureRandom implementation
77 * of the highest-priority installed provider as the source of randomness
78 * (or a system-provided source of randomness if none of the installed
79 * providers supply a SecureRandom implementation).
80 * </ul>
81 *
82 * <p>In case the client does not explicitly initialize the KeyGenerator
83 * (via a call to an <code>init</code> method), each provider must
84 * supply (and document) a default initialization.
85 *
Przemyslaw Szczepaniak444325b2016-05-18 13:09:39 +010086 * <p> Android provides the following <code>KeyGenerator</code> algorithms:
87 * <table>
Adam Vartaniana52aa9f2017-03-20 11:32:38 +000088 * <thead>
89 * <tr>
90 * <th>Algorithm</th>
91 * <th>Supported API Levels</th>
92 * </tr>
93 * </thead>
94 * <tbody>
95 * <tr>
96 * <td>AES</td>
97 * <td>1+</td>
98 * </tr>
99 * <tr class="deprecated">
100 * <td>AESWRAP</td>
101 * <td>1-8</td>
102 * </tr>
103 * <tr>
104 * <td>ARC4</td>
105 * <td>14+</td>
106 * </tr>
107 * <tr>
108 * <td>BLOWFISH</td>
109 * <td>10+</td>
110 * </tr>
111 * <tr>
Adam Vartanian6b6741f2018-01-03 14:44:12 +0000112 * <td>ChaCha20</td>
113 * <td>28+</td>
114 * </tr>
115 * <tr>
Adam Vartaniana52aa9f2017-03-20 11:32:38 +0000116 * <td>DES</td>
117 * <td>1+</td>
118 * </tr>
119 * <tr>
120 * <td>DESede</td>
121 * <td>1+</td>
122 * </tr>
123 * <tr class="deprecated">
124 * <td>DESedeWRAP</td>
125 * <td>1-8</td>
126 * </tr>
127 * <tr>
128 * <td>HmacMD5</td>
129 * <td>1+</td>
130 * </tr>
131 * <tr>
132 * <td>HmacSHA1</td>
133 * <td>11+</td>
134 * </tr>
135 * <tr>
136 * <td>HmacSHA224</td>
137 * <td>1-8,22+</td>
138 * </tr>
139 * <tr>
140 * <td>HmacSHA256</td>
141 * <td>1+</td>
142 * </tr>
143 * <tr>
144 * <td>HmacSHA384</td>
145 * <td>1+</td>
146 * </tr>
147 * <tr>
148 * <td>HmacSHA512</td>
149 * <td>1+</td>
150 * </tr>
151 * <tr class="deprecated">
152 * <td>RC4</td>
153 * <td>10-13</td>
154 * </tr>
155 * </tbody>
Przemyslaw Szczepaniak444325b2016-05-18 13:09:39 +0100156 * </table>
157 *
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +0000158 * These algorithms are described in the <a href=
Tobias Thierer6bd07db2019-04-03 18:06:18 +0100159 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyGenerator">
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +0000160 * KeyGenerator section</a> of the
161 * Java Cryptography Architecture Standard Algorithm Name Documentation.
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +0000162 *
163 * @author Jan Luehe
164 *
165 * @see SecretKey
166 * @since 1.4
167 */
168
169public class KeyGenerator {
170
Tobias Thierer9eca2692017-04-12 18:16:06 +0100171 // Android-removed: this debugging mechanism is not used in Android.
172 /*
Sergio Giro17982542016-08-03 19:21:52 +0100173 private static final Debug pdebug =
174 Debug.getInstance("provider", "Provider");
175 private static final boolean skipDebug =
176 Debug.isOn("engine=") && !Debug.isOn("keygenerator");
177 */
178
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +0000179 // see java.security.KeyPairGenerator for failover notes
180
181 private final static int I_NONE = 1;
182 private final static int I_RANDOM = 2;
183 private final static int I_PARAMS = 3;
184 private final static int I_SIZE = 4;
185
186 // The provider
187 private Provider provider;
188
189 // The provider implementation (delegate)
190 private volatile KeyGeneratorSpi spi;
191
192 // The algorithm
193 private final String algorithm;
194
195 private final Object lock = new Object();
196
Sergio Giro17982542016-08-03 19:21:52 +0100197 private Iterator<Service> serviceIterator;
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +0000198
199 private int initType;
200 private int initKeySize;
201 private AlgorithmParameterSpec initParams;
202 private SecureRandom initRandom;
203
204 /**
205 * Creates a KeyGenerator object.
206 *
207 * @param keyGenSpi the delegate
208 * @param provider the provider
209 * @param algorithm the algorithm
210 */
211 protected KeyGenerator(KeyGeneratorSpi keyGenSpi, Provider provider,
212 String algorithm) {
213 this.spi = keyGenSpi;
214 this.provider = provider;
215 this.algorithm = algorithm;
Sergio Giro17982542016-08-03 19:21:52 +0100216
Tobias Thierer9eca2692017-04-12 18:16:06 +0100217 // Android-removed: this debugging mechanism is not used in Android.
218 /*
Sergio Giro17982542016-08-03 19:21:52 +0100219 if (!skipDebug && pdebug != null) {
220 pdebug.println("KeyGenerator." + algorithm + " algorithm from: " +
221 this.provider.getName());
222 }
223 */
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +0000224 }
225
226 private KeyGenerator(String algorithm) throws NoSuchAlgorithmException {
227 this.algorithm = algorithm;
Sergio Giro17982542016-08-03 19:21:52 +0100228 List<Service> list =
229 GetInstance.getServices("KeyGenerator", algorithm);
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +0000230 serviceIterator = list.iterator();
231 initType = I_NONE;
232 // fetch and instantiate initial spi
233 if (nextSpi(null, false) == null) {
234 throw new NoSuchAlgorithmException
235 (algorithm + " KeyGenerator not available");
236 }
Sergio Giro17982542016-08-03 19:21:52 +0100237
Tobias Thierer9eca2692017-04-12 18:16:06 +0100238 // Android-removed: this debugging mechanism is not used in Android.
239 /*
Sergio Giro17982542016-08-03 19:21:52 +0100240 if (!skipDebug && pdebug != null) {
241 pdebug.println("KeyGenerator." + algorithm + " algorithm from: " +
242 this.provider.getName());
243 }
244 */
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +0000245 }
246
247 /**
248 * Returns the algorithm name of this <code>KeyGenerator</code> object.
249 *
250 * <p>This is the same name that was specified in one of the
251 * <code>getInstance</code> calls that created this
252 * <code>KeyGenerator</code> object.
253 *
254 * @return the algorithm name of this <code>KeyGenerator</code> object.
255 */
256 public final String getAlgorithm() {
257 return this.algorithm;
258 }
259
260 /**
261 * Returns a <code>KeyGenerator</code> object that generates secret keys
262 * for the specified algorithm.
263 *
264 * <p> This method traverses the list of registered security Providers,
265 * starting with the most preferred Provider.
266 * A new KeyGenerator object encapsulating the
267 * KeyGeneratorSpi implementation from the first
268 * Provider that supports the specified algorithm is returned.
269 *
270 * <p> Note that the list of registered providers may be retrieved via
271 * the {@link Security#getProviders() Security.getProviders()} method.
272 *
273 * @param algorithm the standard name of the requested key algorithm.
274 * See the KeyGenerator section in the <a href=
Tobias Thierer6bd07db2019-04-03 18:06:18 +0100275 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyGenerator">
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +0000276 * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
277 * for information about standard algorithm names.
278 *
279 * @return the new <code>KeyGenerator</code> object.
280 *
281 * @exception NullPointerException if the specified algorithm is null.
282 *
283 * @exception NoSuchAlgorithmException if no Provider supports a
284 * KeyGeneratorSpi implementation for the
285 * specified algorithm.
286 *
287 * @see java.security.Provider
288 */
289 public static final KeyGenerator getInstance(String algorithm)
290 throws NoSuchAlgorithmException {
291 return new KeyGenerator(algorithm);
292 }
293
294 /**
295 * Returns a <code>KeyGenerator</code> object that generates secret keys
296 * for the specified algorithm.
297 *
298 * <p> A new KeyGenerator object encapsulating the
299 * KeyGeneratorSpi implementation from the specified provider
300 * is returned. The specified provider must be registered
301 * in the security provider list.
302 *
303 * <p> Note that the list of registered providers may be retrieved via
304 * the {@link Security#getProviders() Security.getProviders()} method.
305 *
306 * @param algorithm the standard name of the requested key algorithm.
307 * See the KeyGenerator section in the <a href=
Tobias Thierer6bd07db2019-04-03 18:06:18 +0100308 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyGenerator">
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +0000309 * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
310 * for information about standard algorithm names.
311 *
312 * @param provider the name of the provider.
313 *
314 * @return the new <code>KeyGenerator</code> object.
315 *
316 * @exception NullPointerException if the specified algorithm is null.
317 *
318 * @exception NoSuchAlgorithmException if a KeyGeneratorSpi
319 * implementation for the specified algorithm is not
320 * available from the specified provider.
321 *
322 * @exception NoSuchProviderException if the specified provider is not
323 * registered in the security provider list.
324 *
325 * @exception IllegalArgumentException if the <code>provider</code>
326 * is null or empty.
327 *
328 * @see java.security.Provider
329 */
330 public static final KeyGenerator getInstance(String algorithm,
331 String provider) throws NoSuchAlgorithmException,
332 NoSuchProviderException {
Adam Vartanian491d8882017-10-10 11:43:32 +0100333 // Android-added: Check for Bouncy Castle deprecation
334 Providers.checkBouncyCastleDeprecation(provider, "KeyGenerator", algorithm);
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +0000335 Instance instance = JceSecurity.getInstance("KeyGenerator",
336 KeyGeneratorSpi.class, algorithm, provider);
337 return new KeyGenerator((KeyGeneratorSpi)instance.impl,
338 instance.provider, algorithm);
339 }
340
341 /**
342 * Returns a <code>KeyGenerator</code> object that generates secret keys
343 * for the specified algorithm.
344 *
345 * <p> A new KeyGenerator object encapsulating the
346 * KeyGeneratorSpi implementation from the specified Provider
347 * object is returned. Note that the specified Provider object
348 * does not have to be registered in the provider list.
349 *
350 * @param algorithm the standard name of the requested key algorithm.
351 * See the KeyGenerator section in the <a href=
Tobias Thierer6bd07db2019-04-03 18:06:18 +0100352 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyGenerator">
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +0000353 * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
354 * for information about standard algorithm names.
355 *
356 * @param provider the provider.
357 *
358 * @return the new <code>KeyGenerator</code> object.
359 *
360 * @exception NullPointerException if the specified algorithm is null.
361 *
362 * @exception NoSuchAlgorithmException if a KeyGeneratorSpi
363 * implementation for the specified algorithm is not available
364 * from the specified Provider object.
365 *
366 * @exception IllegalArgumentException if the <code>provider</code>
367 * is null.
368 *
369 * @see java.security.Provider
370 */
371 public static final KeyGenerator getInstance(String algorithm,
372 Provider provider) throws NoSuchAlgorithmException {
Adam Vartanian491d8882017-10-10 11:43:32 +0100373 // Android-added: Check for Bouncy Castle deprecation
374 Providers.checkBouncyCastleDeprecation(provider, "KeyGenerator", algorithm);
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +0000375 Instance instance = JceSecurity.getInstance("KeyGenerator",
376 KeyGeneratorSpi.class, algorithm, provider);
377 return new KeyGenerator((KeyGeneratorSpi)instance.impl,
378 instance.provider, algorithm);
379 }
380
381 /**
382 * Returns the provider of this <code>KeyGenerator</code> object.
383 *
384 * @return the provider of this <code>KeyGenerator</code> object
385 */
386 public final Provider getProvider() {
387 synchronized (lock) {
388 disableFailover();
389 return provider;
390 }
391 }
392
393 /**
394 * Update the active spi of this class and return the next
395 * implementation for failover. If no more implemenations are
396 * available, this method returns null. However, the active spi of
397 * this class is never set to null.
398 */
399 private KeyGeneratorSpi nextSpi(KeyGeneratorSpi oldSpi,
400 boolean reinit) {
401 synchronized (lock) {
402 // somebody else did a failover concurrently
403 // try that spi now
404 if ((oldSpi != null) && (oldSpi != spi)) {
405 return spi;
406 }
407 if (serviceIterator == null) {
408 return null;
409 }
410 while (serviceIterator.hasNext()) {
Sergio Giro17982542016-08-03 19:21:52 +0100411 Service s = serviceIterator.next();
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +0000412 if (JceSecurity.canUseProvider(s.getProvider()) == false) {
413 continue;
414 }
415 try {
416 Object inst = s.newInstance(null);
417 // ignore non-spis
418 if (inst instanceof KeyGeneratorSpi == false) {
419 continue;
420 }
421 KeyGeneratorSpi spi = (KeyGeneratorSpi)inst;
422 if (reinit) {
423 if (initType == I_SIZE) {
424 spi.engineInit(initKeySize, initRandom);
425 } else if (initType == I_PARAMS) {
426 spi.engineInit(initParams, initRandom);
427 } else if (initType == I_RANDOM) {
428 spi.engineInit(initRandom);
429 } else if (initType != I_NONE) {
430 throw new AssertionError
431 ("KeyGenerator initType: " + initType);
432 }
433 }
434 provider = s.getProvider();
435 this.spi = spi;
436 return spi;
437 } catch (Exception e) {
438 // ignore
439 }
440 }
441 disableFailover();
442 return null;
443 }
444 }
445
446 void disableFailover() {
447 serviceIterator = null;
448 initType = 0;
449 initParams = null;
450 initRandom = null;
451 }
452
453 /**
454 * Initializes this key generator.
455 *
456 * @param random the source of randomness for this generator
457 */
458 public final void init(SecureRandom random) {
459 if (serviceIterator == null) {
460 spi.engineInit(random);
461 return;
462 }
463 RuntimeException failure = null;
464 KeyGeneratorSpi mySpi = spi;
465 do {
466 try {
467 mySpi.engineInit(random);
468 initType = I_RANDOM;
469 initKeySize = 0;
470 initParams = null;
471 initRandom = random;
472 return;
473 } catch (RuntimeException e) {
474 if (failure == null) {
475 failure = e;
476 }
477 mySpi = nextSpi(mySpi, false);
478 }
479 } while (mySpi != null);
480 throw failure;
481 }
482
483 /**
484 * Initializes this key generator with the specified parameter set.
485 *
486 * <p> If this key generator requires any random bytes, it will get them
487 * using the
Sergio Giro17982542016-08-03 19:21:52 +0100488 * {@link java.security.SecureRandom}
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +0000489 * implementation of the highest-priority installed
490 * provider as the source of randomness.
491 * (If none of the installed providers supply an implementation of
492 * SecureRandom, a system-provided source of randomness will be used.)
493 *
494 * @param params the key generation parameters
495 *
496 * @exception InvalidAlgorithmParameterException if the given parameters
497 * are inappropriate for this key generator
498 */
499 public final void init(AlgorithmParameterSpec params)
500 throws InvalidAlgorithmParameterException
501 {
502 init(params, JceSecurity.RANDOM);
503 }
504
505 /**
506 * Initializes this key generator with the specified parameter
507 * set and a user-provided source of randomness.
508 *
509 * @param params the key generation parameters
510 * @param random the source of randomness for this key generator
511 *
512 * @exception InvalidAlgorithmParameterException if <code>params</code> is
513 * inappropriate for this key generator
514 */
515 public final void init(AlgorithmParameterSpec params, SecureRandom random)
516 throws InvalidAlgorithmParameterException
517 {
518 if (serviceIterator == null) {
519 spi.engineInit(params, random);
520 return;
521 }
522 Exception failure = null;
523 KeyGeneratorSpi mySpi = spi;
524 do {
525 try {
526 mySpi.engineInit(params, random);
527 initType = I_PARAMS;
528 initKeySize = 0;
529 initParams = params;
530 initRandom = random;
531 return;
532 } catch (Exception e) {
533 if (failure == null) {
534 failure = e;
535 }
536 mySpi = nextSpi(mySpi, false);
537 }
538 } while (mySpi != null);
539 if (failure instanceof InvalidAlgorithmParameterException) {
540 throw (InvalidAlgorithmParameterException)failure;
541 }
542 if (failure instanceof RuntimeException) {
543 throw (RuntimeException)failure;
544 }
545 throw new InvalidAlgorithmParameterException("init() failed", failure);
546 }
547
548 /**
549 * Initializes this key generator for a certain keysize.
550 *
551 * <p> If this key generator requires any random bytes, it will get them
552 * using the
Sergio Giro17982542016-08-03 19:21:52 +0100553 * {@link java.security.SecureRandom}
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +0000554 * implementation of the highest-priority installed
555 * provider as the source of randomness.
556 * (If none of the installed providers supply an implementation of
557 * SecureRandom, a system-provided source of randomness will be used.)
558 *
559 * @param keysize the keysize. This is an algorithm-specific metric,
560 * specified in number of bits.
561 *
562 * @exception InvalidParameterException if the keysize is wrong or not
563 * supported.
564 */
565 public final void init(int keysize) {
566 init(keysize, JceSecurity.RANDOM);
567 }
568
569 /**
570 * Initializes this key generator for a certain keysize, using a
571 * user-provided source of randomness.
572 *
573 * @param keysize the keysize. This is an algorithm-specific metric,
574 * specified in number of bits.
575 * @param random the source of randomness for this key generator
576 *
577 * @exception InvalidParameterException if the keysize is wrong or not
578 * supported.
579 */
580 public final void init(int keysize, SecureRandom random) {
581 if (serviceIterator == null) {
582 spi.engineInit(keysize, random);
583 return;
584 }
585 RuntimeException failure = null;
586 KeyGeneratorSpi mySpi = spi;
587 do {
588 try {
589 mySpi.engineInit(keysize, random);
590 initType = I_SIZE;
591 initKeySize = keysize;
592 initParams = null;
593 initRandom = random;
594 return;
595 } catch (RuntimeException e) {
596 if (failure == null) {
597 failure = e;
598 }
599 mySpi = nextSpi(mySpi, false);
600 }
601 } while (mySpi != null);
602 throw failure;
603 }
604
605 /**
606 * Generates a secret key.
607 *
608 * @return the new key
609 */
610 public final SecretKey generateKey() {
611 if (serviceIterator == null) {
612 return spi.engineGenerateKey();
613 }
614 RuntimeException failure = null;
615 KeyGeneratorSpi mySpi = spi;
616 do {
617 try {
618 return mySpi.engineGenerateKey();
619 } catch (RuntimeException e) {
620 if (failure == null) {
621 failure = e;
622 }
623 mySpi = nextSpi(mySpi, true);
624 }
625 } while (mySpi != null);
626 throw failure;
627 }
628}