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