1/*
2 * Copyright (c) 1997, 2014, 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;
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.
69 *
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 *
86 * <p> Android provides the following <code>KeyGenerator</code> algorithms:
87 * <table>
88 *   <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>
112 *       <td>ChaCha20</td>
113 *       <td>28+</td>
114 *     </tr>
115 *     <tr>
116 *       <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>
156 * </table>
157 *
158 * These algorithms are described in the <a href=
159 * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#KeyGenerator">
160 * KeyGenerator section</a> of the
161 * Java Cryptography Architecture Standard Algorithm Name Documentation.
162 *
163 * @author Jan Luehe
164 *
165 * @see SecretKey
166 * @since 1.4
167 */
168
169public class KeyGenerator {
170
171    // Android-removed: this debugging mechanism is not used in Android.
172    /*
173    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
179    // 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
197    private Iterator<Service> serviceIterator;
198
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;
216
217        // Android-removed: this debugging mechanism is not used in Android.
218        /*
219        if (!skipDebug && pdebug != null) {
220            pdebug.println("KeyGenerator." + algorithm + " algorithm from: " +
221                this.provider.getName());
222        }
223        */
224    }
225
226    private KeyGenerator(String algorithm) throws NoSuchAlgorithmException {
227        this.algorithm = algorithm;
228        List<Service> list =
229                GetInstance.getServices("KeyGenerator", algorithm);
230        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        }
237
238        // Android-removed: this debugging mechanism is not used in Android.
239        /*
240        if (!skipDebug && pdebug != null) {
241            pdebug.println("KeyGenerator." + algorithm + " algorithm from: " +
242                this.provider.getName());
243        }
244        */
245    }
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=
275     * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#KeyGenerator">
276     * 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=
308     * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#KeyGenerator">
309     * 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 {
333        // Android-added: Check for Bouncy Castle deprecation
334        Providers.checkBouncyCastleDeprecation(provider, "KeyGenerator", algorithm);
335        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=
352     * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#KeyGenerator">
353     * 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 {
373        // Android-added: Check for Bouncy Castle deprecation
374        Providers.checkBouncyCastleDeprecation(provider, "KeyGenerator", algorithm);
375        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()) {
411                Service s = serviceIterator.next();
412                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
488     * {@link java.security.SecureRandom}
489     * 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
553     * {@link java.security.SecureRandom}
554     * 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}
629