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 
26 package java.security;
27 
28 import dalvik.annotation.compat.VersionCodes;
29 import dalvik.system.VMRuntime;
30 
31 import java.security.spec.AlgorithmParameterSpec;
32 import java.util.Objects;
33 
34 /**
35  * The {@code AlgorithmParameterGenerator} class is used to generate a
36  * set of
37  * parameters to be used with a certain algorithm. Parameter generators
38  * are constructed using the {@code getInstance} factory methods
39  * (static methods that return instances of a given class).
40  *
41  * <P>The object that will generate the parameters can be initialized
42  * in two different ways: in an algorithm-independent manner, or in an
43  * algorithm-specific manner:
44  *
45  * <ul>
46  * <li>The algorithm-independent approach uses the fact that all parameter
47  * generators share the concept of a "size" and a
48  * source of randomness. The measure of size is universally shared
49  * by all algorithm parameters, though it is interpreted differently
50  * for different algorithms. For example, in the case of parameters for
51  * the <i>DSA</i> algorithm, "size" corresponds to the size
52  * of the prime modulus (in bits).
53  * When using this approach, algorithm-specific parameter generation
54  * values - if any - default to some standard values, unless they can be
55  * derived from the specified size.
56  *
57  * <li>The other approach initializes a parameter generator object
58  * using algorithm-specific semantics, which are represented by a set of
59  * algorithm-specific parameter generation values. To generate
60  * Diffie-Hellman system parameters, for example, the parameter generation
61  * values usually
62  * consist of the size of the prime modulus and the size of the
63  * random exponent, both specified in number of bits.
64  * </ul>
65  *
66  * <P>In case the client does not explicitly initialize the
67  * AlgorithmParameterGenerator (via a call to an {@code init} method),
68  * each provider must supply (and document) a default initialization.
69  * However, note that defaults may vary across different providers.
70  * Additionally, the default value for a provider may change in a future
71  * version. Therefore, it is recommended to explicitly initialize the
72  * AlgorithmParameterGenerator instead of relying on provider-specific defaults.
73  *
74  * <p> Android provides the following <code>AlgorithmParameterGenerator</code> algorithms:
75  * <table>
76  *   <thead>
77  *     <tr>
78  *       <th>Algorithm</th>
79  *       <th>Supported API Levels</th>
80  *     </tr>
81  *   </thead>
82  *   <tbody>
83  *     <tr class="deprecated">
84  *       <td>AES</td>
85  *       <td>1-8</td>
86  *     </tr>
87  *     <tr class="deprecated">
88  *       <td>DES</td>
89  *       <td>1-8</td>
90  *     </tr>
91  *     <tr class="deprecated">
92  *       <td>DESede</td>
93  *       <td>1-8</td>
94  *     </tr>
95  *     <tr>
96  *       <td>DH</td>
97  *       <td>1+</td>
98  *     </tr>
99  *     <tr>
100  *       <td>DSA</td>
101  *       <td>1+</td>
102  *     </tr>
103  *   </tbody>
104  * </table>
105  *
106  * @author Jan Luehe
107  *
108  *
109  * @see AlgorithmParameters
110  * @see java.security.spec.AlgorithmParameterSpec
111  *
112  * @since 1.2
113  */
114 
115 public class AlgorithmParameterGenerator {
116 
117     // The provider
118     private Provider provider;
119 
120     // The provider implementation (delegate)
121     private AlgorithmParameterGeneratorSpi paramGenSpi;
122 
123     // The algorithm
124     private String algorithm;
125 
126     /**
127      * Creates an AlgorithmParameterGenerator object.
128      *
129      * @param paramGenSpi the delegate
130      * @param provider the provider
131      * @param algorithm the algorithm
132      */
AlgorithmParameterGenerator(AlgorithmParameterGeneratorSpi paramGenSpi, Provider provider, String algorithm)133     protected AlgorithmParameterGenerator
134     (AlgorithmParameterGeneratorSpi paramGenSpi, Provider provider,
135      String algorithm) {
136         this.paramGenSpi = paramGenSpi;
137         this.provider = provider;
138         this.algorithm = algorithm;
139     }
140 
141     /**
142      * Returns the standard name of the algorithm this parameter
143      * generator is associated with.
144      *
145      * @return the string name of the algorithm.
146      */
getAlgorithm()147     public final String getAlgorithm() {
148         return this.algorithm;
149     }
150 
151     // Android-changed: javadoc to throw on Android 14 or above.
152     /**
153      * Returns an AlgorithmParameterGenerator object for generating
154      * a set of parameters to be used with the specified algorithm.
155      *
156      * <p> This method traverses the list of registered security Providers,
157      * starting with the most preferred Provider.
158      * A new AlgorithmParameterGenerator object encapsulating the
159      * AlgorithmParameterGeneratorSpi implementation from the first
160      * Provider that supports the specified algorithm is returned.
161      *
162      * <p> Note that the list of registered providers may be retrieved via
163      * the {@link Security#getProviders() Security.getProviders()} method.
164      *
165      * @param algorithm the name of the algorithm this
166      * parameter generator is associated with.cc
167      *
168      * @return the new {@code AlgorithmParameterGenerator} object
169      *
170      * @throws NoSuchAlgorithmException if no {@code Provider} supports an
171      *         {@code AlgorithmParameterGeneratorSpi} implementation for the
172      *         specified algorithm
173      *
174      * @throws NullPointerException if {@code algorithm} is {@code null} on Android 14 or above
175      *
176      * @see Provider
177      */
getInstance(String algorithm)178     public static AlgorithmParameterGenerator getInstance(String algorithm)
179         throws NoSuchAlgorithmException {
180             // Android-changed: To be compat with the older Android, don't throw NPE on Android 13-.
181             // Objects.requireNonNull(algorithm, "null algorithm name");
182             if (VMRuntime.getSdkVersion() >= VersionCodes.UPSIDE_DOWN_CAKE) {
183                 Objects.requireNonNull(algorithm, "null algorithm name");
184             }
185             try {
186                 Object[] objs = Security.getImpl(algorithm,
187                                                  "AlgorithmParameterGenerator",
188                                                  (String)null);
189                 return new AlgorithmParameterGenerator
190                     ((AlgorithmParameterGeneratorSpi)objs[0],
191                      (Provider)objs[1],
192                      algorithm);
193             } catch(NoSuchProviderException e) {
194                 throw new NoSuchAlgorithmException(algorithm + " not found");
195             }
196     }
197 
198     // Android-changed: javadoc to throw on Android 14 or above.
199     /**
200      * Returns an AlgorithmParameterGenerator object for generating
201      * a set of parameters to be used with the specified algorithm.
202      *
203      * <p> A new AlgorithmParameterGenerator object encapsulating the
204      * AlgorithmParameterGeneratorSpi implementation from the specified provider
205      * is returned.  The specified provider must be registered
206      * in the security provider list.
207      *
208      * <p> Note that the list of registered providers may be retrieved via
209      * the {@link Security#getProviders() Security.getProviders()} method.
210      *
211      * @param algorithm the name of the algorithm this
212      * parameter generator is associated with.
213      *
214      * @param provider the string name of the Provider.
215      *
216      * @return the new {@code AlgorithmParameterGenerator} object
217      *
218      * @throws IllegalArgumentException if the provider name is {@code null}
219      *         or empty
220      *
221      * @throws NoSuchAlgorithmException if an
222      *         {@code AlgorithmParameterGeneratorSpi}
223      *         implementation for the specified algorithm is not
224      *         available from the specified provider
225      *
226      * @throws NoSuchProviderException if the specified provider is not
227      *         registered in the security provider list
228      *
229      * @throws NullPointerException if {@code algorithm} is {@code null} on Android 14 or above
230      *
231      * @see Provider
232      */
getInstance(String algorithm, String provider)233     public static AlgorithmParameterGenerator getInstance(String algorithm,
234                                                           String provider)
235         throws NoSuchAlgorithmException, NoSuchProviderException
236     {
237         // Android-changed: To be compat with the older Android, don't throw NPE on Android 13-.
238         // Objects.requireNonNull(algorithm, "null algorithm name");
239         if (VMRuntime.getSdkVersion() >= VersionCodes.UPSIDE_DOWN_CAKE) {
240             Objects.requireNonNull(algorithm, "null algorithm name");
241         }
242         if (provider == null || provider.isEmpty())
243             throw new IllegalArgumentException("missing provider");
244         Object[] objs = Security.getImpl(algorithm,
245                                          "AlgorithmParameterGenerator",
246                                          provider);
247         return new AlgorithmParameterGenerator
248             ((AlgorithmParameterGeneratorSpi)objs[0], (Provider)objs[1],
249              algorithm);
250     }
251 
252     // Android-changed: javadoc to throw on Android 14 or above.
253     /**
254      * Returns an AlgorithmParameterGenerator object for generating
255      * a set of parameters to be used with the specified algorithm.
256      *
257      * <p> A new AlgorithmParameterGenerator object encapsulating the
258      * AlgorithmParameterGeneratorSpi implementation from the specified Provider
259      * object is returned.  Note that the specified Provider object
260      * does not have to be registered in the provider list.
261      *
262      * @param algorithm the string name of the algorithm this
263      * parameter generator is associated with.
264      *
265      * @param provider the {@code Provider} object.
266      *
267      * @return the new {@code AlgorithmParameterGenerator} object
268      *
269      * @throws IllegalArgumentException if the specified provider is
270      *         {@code null}
271      *
272      * @throws NoSuchAlgorithmException if an
273      *         {@code AlgorithmParameterGeneratorSpi}
274      *         implementation for the specified algorithm is not available
275      *         from the specified {@code Provider} object
276      *
277      * @throws NullPointerException if {@code algorithm} is {@code null} on Android 14 or above
278      *
279      * @see Provider
280      *
281      * @since 1.4
282      */
getInstance(String algorithm, Provider provider)283     public static AlgorithmParameterGenerator getInstance(String algorithm,
284                                                           Provider provider)
285         throws NoSuchAlgorithmException
286     {
287         // Android-changed: To be compat with the older Android, don't throw NPE on Android 13-.
288         // Objects.requireNonNull(algorithm, "null algorithm name");
289         if (VMRuntime.getSdkVersion() >= VersionCodes.UPSIDE_DOWN_CAKE) {
290             Objects.requireNonNull(algorithm, "null algorithm name");
291         }
292         if (provider == null)
293             throw new IllegalArgumentException("missing provider");
294         Object[] objs = Security.getImpl(algorithm,
295                                          "AlgorithmParameterGenerator",
296                                          provider);
297         return new AlgorithmParameterGenerator
298             ((AlgorithmParameterGeneratorSpi)objs[0], (Provider)objs[1],
299              algorithm);
300     }
301 
302     /**
303      * Returns the provider of this algorithm parameter generator object.
304      *
305      * @return the provider of this algorithm parameter generator object
306      */
getProvider()307     public final Provider getProvider() {
308         return this.provider;
309     }
310 
311     /**
312      * Initializes this parameter generator for a certain size.
313      * To create the parameters, the {@code SecureRandom}
314      * implementation of the highest-priority installed provider is used as
315      * the source of randomness.
316      * (If none of the installed providers supply an implementation of
317      * {@code SecureRandom}, a system-provided source of randomness is
318      * used.)
319      *
320      * @param size the size (number of bits).
321      */
init(int size)322     public final void init(int size) {
323         paramGenSpi.engineInit(size, new SecureRandom());
324     }
325 
326     /**
327      * Initializes this parameter generator for a certain size and source
328      * of randomness.
329      *
330      * @param size the size (number of bits).
331      * @param random the source of randomness.
332      */
init(int size, SecureRandom random)333     public final void init(int size, SecureRandom random) {
334         paramGenSpi.engineInit(size, random);
335     }
336 
337     /**
338      * Initializes this parameter generator with a set of algorithm-specific
339      * parameter generation values.
340      * To generate the parameters, the {@code SecureRandom}
341      * implementation of the highest-priority installed provider is used as
342      * the source of randomness.
343      * (If none of the installed providers supply an implementation of
344      * {@code SecureRandom}, a system-provided source of randomness is
345      * used.)
346      *
347      * @param genParamSpec the set of algorithm-specific parameter generation values.
348      *
349      * @exception InvalidAlgorithmParameterException if the given parameter
350      * generation values are inappropriate for this parameter generator.
351      */
init(AlgorithmParameterSpec genParamSpec)352     public final void init(AlgorithmParameterSpec genParamSpec)
353         throws InvalidAlgorithmParameterException {
354             paramGenSpi.engineInit(genParamSpec, new SecureRandom());
355     }
356 
357     /**
358      * Initializes this parameter generator with a set of algorithm-specific
359      * parameter generation values.
360      *
361      * @param genParamSpec the set of algorithm-specific parameter generation values.
362      * @param random the source of randomness.
363      *
364      * @exception InvalidAlgorithmParameterException if the given parameter
365      * generation values are inappropriate for this parameter generator.
366      */
init(AlgorithmParameterSpec genParamSpec, SecureRandom random)367     public final void init(AlgorithmParameterSpec genParamSpec,
368                            SecureRandom random)
369         throws InvalidAlgorithmParameterException {
370             paramGenSpi.engineInit(genParamSpec, random);
371     }
372 
373     /**
374      * Generates the parameters.
375      *
376      * @return the new AlgorithmParameters object.
377      */
generateParameters()378     public final AlgorithmParameters generateParameters() {
379         return paramGenSpi.engineGenerateParameters();
380     }
381 }
382