1 /*
2  * Copyright (c) 1997, 2013, 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 java.io.*;
29 import java.security.spec.AlgorithmParameterSpec;
30 import java.security.spec.InvalidParameterSpecException;
31 
32 import sun.security.jca.Providers;
33 
34 /**
35  * This class is used as an opaque representation of cryptographic parameters.
36  *
37  * <p>An {@code AlgorithmParameters} object for managing the parameters
38  * for a particular algorithm can be obtained by
39  * calling one of the {@code getInstance} factory methods
40  * (static methods that return instances of a given class).
41  *
42  * <p>Once an {@code AlgorithmParameters} object is obtained, it must be
43  * initialized via a call to {@code init}, using an appropriate parameter
44  * specification or parameter encoding.
45  *
46  * <p>A transparent parameter specification is obtained from an
47  * {@code AlgorithmParameters} object via a call to
48  * {@code getParameterSpec}, and a byte encoding of the parameters is
49  * obtained via a call to {@code getEncoded}.
50  *
51  * <p> Android provides the following <code>AlgorithmParameters</code> algorithms:
52  * <table>
53  *   <thead>
54  *     <tr>
55  *       <th>Algorithm</th>
56  *       <th>Supported API Levels</th>
57  *     </tr>
58  *   </thead>
59  *   <tbody>
60  *     <tr>
61  *       <td>AES</td>
62  *       <td>1+</td>
63  *     </tr>
64  *     <tr>
65  *       <td>BLOWFISH</td>
66  *       <td>10+</td>
67  *     </tr>
68  *     <tr>
69  *       <td>ChaCha20</td>
70  *       <td>28+</td>
71  *     </tr>
72  *     <tr>
73  *       <td>DES</td>
74  *       <td>1+</td>
75  *     </tr>
76  *     <tr>
77  *       <td>DESede</td>
78  *       <td>1+</td>
79  *     </tr>
80  *     <tr>
81  *       <td>DH</td>
82  *       <td>1+</td>
83  *     </tr>
84  *     <tr>
85  *       <td>DSA</td>
86  *       <td>1+</td>
87  *     </tr>
88  *     <tr>
89  *       <td>EC</td>
90  *       <td>26+</td>
91  *     </tr>
92  *     <tr>
93  *       <td>GCM</td>
94  *       <td>22+</td>
95  *     </tr>
96  *     <tr class="deprecated">
97  *       <td>IES</td>
98  *       <td>1-8</td>
99  *     </tr>
100  *     <tr>
101  *       <td>OAEP</td>
102  *       <td>1+</td>
103  *     </tr>
104  *     <tr>
105  *       <td>PBEwithHmacSHA1AndAES_128</td>
106  *       <td>26+</td>
107  *     </tr>
108  *     <tr>
109  *       <td>PBEwithHmacSHA1AndAES_256</td>
110  *       <td>26+</td>
111  *     </tr>
112  *     <tr>
113  *       <td>PBEwithHmacSHA224AndAES_128</td>
114  *       <td>26+</td>
115  *     </tr>
116  *     <tr>
117  *       <td>PBEwithHmacSHA224AndAES_256</td>
118  *       <td>26+</td>
119  *     </tr>
120  *     <tr>
121  *       <td>PBEwithHmacSHA256AndAES_128</td>
122  *       <td>26+</td>
123  *     </tr>
124  *     <tr>
125  *       <td>PBEwithHmacSHA256AndAES_256</td>
126  *       <td>26+</td>
127  *     </tr>
128  *     <tr>
129  *       <td>PBEwithHmacSHA384AndAES_128</td>
130  *       <td>26+</td>
131  *     </tr>
132  *     <tr>
133  *       <td>PBEwithHmacSHA384AndAES_256</td>
134  *       <td>26+</td>
135  *     </tr>
136  *     <tr>
137  *       <td>PBEwithHmacSHA512AndAES_128</td>
138  *       <td>26+</td>
139  *     </tr>
140  *     <tr>
141  *       <td>PBEwithHmacSHA512AndAES_256</td>
142  *       <td>26+</td>
143  *     </tr>
144  *     <tr>
145  *       <td>PKCS12PBE</td>
146  *       <td>1+</td>
147  *     </tr>
148  *     <tr>
149  *       <td>PSS</td>
150  *       <td>1-8,24+</td>
151  *     </tr>
152  *   </tbody>
153  * </table>
154  *
155  * These algorithms are described in the <a href=
156  * "{@docRoot}/../technotes/guides/security/StandardNames.html#AlgorithmParameters">
157  * AlgorithmParameters section</a> of the
158  * Java Cryptography Architecture Standard Algorithm Name Documentation.
159  *
160  * @author Jan Luehe
161  *
162  *
163  * @see java.security.spec.AlgorithmParameterSpec
164  * @see java.security.spec.DSAParameterSpec
165  * @see KeyPairGenerator
166  *
167  * @since 1.2
168  */
169 
170 public class AlgorithmParameters {
171 
172     // The provider
173     private Provider provider;
174 
175     // The provider implementation (delegate)
176     private AlgorithmParametersSpi paramSpi;
177 
178     // The algorithm
179     private String algorithm;
180 
181     // Has this object been initialized?
182     private boolean initialized = false;
183 
184     /**
185      * Creates an AlgorithmParameters object.
186      *
187      * @param paramSpi the delegate
188      * @param provider the provider
189      * @param algorithm the algorithm
190      */
AlgorithmParameters(AlgorithmParametersSpi paramSpi, Provider provider, String algorithm)191     protected AlgorithmParameters(AlgorithmParametersSpi paramSpi,
192                                   Provider provider, String algorithm)
193     {
194         this.paramSpi = paramSpi;
195         this.provider = provider;
196         this.algorithm = algorithm;
197     }
198 
199     /**
200      * Returns the name of the algorithm associated with this parameter object.
201      *
202      * @return the algorithm name.
203      */
getAlgorithm()204     public final String getAlgorithm() {
205         return this.algorithm;
206     }
207 
208     /**
209      * Returns a parameter object for the specified algorithm.
210      *
211      * <p> This method traverses the list of registered security Providers,
212      * starting with the most preferred Provider.
213      * A new AlgorithmParameters object encapsulating the
214      * AlgorithmParametersSpi implementation from the first
215      * Provider that supports the specified algorithm is returned.
216      *
217      * <p> Note that the list of registered providers may be retrieved via
218      * the {@link Security#getProviders() Security.getProviders()} method.
219      *
220      * <p> The returned parameter object must be initialized via a call to
221      * {@code init}, using an appropriate parameter specification or
222      * parameter encoding.
223      *
224      * @param algorithm the name of the algorithm requested.
225      * See the AlgorithmParameters section in the <a href=
226      * "{@docRoot}/../technotes/guides/security/StandardNames.html#AlgorithmParameters">
227      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
228      * for information about standard algorithm names.
229      *
230      * @return the new parameter object.
231      *
232      * @exception NoSuchAlgorithmException if no Provider supports an
233      *          AlgorithmParametersSpi implementation for the
234      *          specified algorithm.
235      *
236      * @see Provider
237      */
getInstance(String algorithm)238     public static AlgorithmParameters getInstance(String algorithm)
239     throws NoSuchAlgorithmException {
240         try {
241             Object[] objs = Security.getImpl(algorithm, "AlgorithmParameters",
242                                              (String)null);
243             return new AlgorithmParameters((AlgorithmParametersSpi)objs[0],
244                                            (Provider)objs[1],
245                                            algorithm);
246         } catch(NoSuchProviderException e) {
247             throw new NoSuchAlgorithmException(algorithm + " not found");
248         }
249     }
250 
251     /**
252      * Returns a parameter object for the specified algorithm.
253      *
254      * <p> A new AlgorithmParameters object encapsulating the
255      * AlgorithmParametersSpi implementation from the specified provider
256      * is returned.  The specified provider must be registered
257      * in the security provider list.
258      *
259      * <p> Note that the list of registered providers may be retrieved via
260      * the {@link Security#getProviders() Security.getProviders()} method.
261      *
262      * <p>The returned parameter object must be initialized via a call to
263      * {@code init}, using an appropriate parameter specification or
264      * parameter encoding.
265      *
266      * @param algorithm the name of the algorithm requested.
267      * See the AlgorithmParameters section in the <a href=
268      * "{@docRoot}/../technotes/guides/security/StandardNames.html#AlgorithmParameters">
269      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
270      * for information about standard algorithm names.
271      *
272      * @param provider the name of the provider.
273      *
274      * @return the new parameter object.
275      *
276      * @exception NoSuchAlgorithmException if an AlgorithmParametersSpi
277      *          implementation for the specified algorithm is not
278      *          available from the specified provider.
279      *
280      * @exception NoSuchProviderException if the specified provider is not
281      *          registered in the security provider list.
282      *
283      * @exception IllegalArgumentException if the provider name is null
284      *          or empty.
285      *
286      * @see Provider
287      */
getInstance(String algorithm, String provider)288     public static AlgorithmParameters getInstance(String algorithm,
289                                                   String provider)
290         throws NoSuchAlgorithmException, NoSuchProviderException
291     {
292         if (provider == null || provider.length() == 0)
293             throw new IllegalArgumentException("missing provider");
294         // Android-added: Check for Bouncy Castle deprecation
295         Providers.checkBouncyCastleDeprecation(provider, "AlgorithmParameters", algorithm);
296         Object[] objs = Security.getImpl(algorithm, "AlgorithmParameters",
297                                          provider);
298         return new AlgorithmParameters((AlgorithmParametersSpi)objs[0],
299                                        (Provider)objs[1],
300                                        algorithm);
301     }
302 
303     /**
304      * Returns a parameter object for the specified algorithm.
305      *
306      * <p> A new AlgorithmParameters object encapsulating the
307      * AlgorithmParametersSpi implementation from the specified Provider
308      * object is returned.  Note that the specified Provider object
309      * does not have to be registered in the provider list.
310      *
311      * <p>The returned parameter object must be initialized via a call to
312      * {@code init}, using an appropriate parameter specification or
313      * parameter encoding.
314      *
315      * @param algorithm the name of the algorithm requested.
316      * See the AlgorithmParameters section in the <a href=
317      * "{@docRoot}/../technotes/guides/security/StandardNames.html#AlgorithmParameters">
318      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
319      * for information about standard algorithm names.
320      *
321      * @param provider the name of the provider.
322      *
323      * @return the new parameter object.
324      *
325      * @exception NoSuchAlgorithmException if an AlgorithmParameterGeneratorSpi
326      *          implementation for the specified algorithm is not available
327      *          from the specified Provider object.
328      *
329      * @exception IllegalArgumentException if the provider is null.
330      *
331      * @see Provider
332      *
333      * @since 1.4
334      */
getInstance(String algorithm, Provider provider)335     public static AlgorithmParameters getInstance(String algorithm,
336                                                   Provider provider)
337         throws NoSuchAlgorithmException
338     {
339         if (provider == null)
340             throw new IllegalArgumentException("missing provider");
341         // Android-added: Check for Bouncy Castle deprecation
342         Providers.checkBouncyCastleDeprecation(provider, "AlgorithmParameters", algorithm);
343         Object[] objs = Security.getImpl(algorithm, "AlgorithmParameters",
344                                          provider);
345         return new AlgorithmParameters((AlgorithmParametersSpi)objs[0],
346                                        (Provider)objs[1],
347                                        algorithm);
348     }
349 
350     /**
351      * Returns the provider of this parameter object.
352      *
353      * @return the provider of this parameter object
354      */
getProvider()355     public final Provider getProvider() {
356         return this.provider;
357     }
358 
359     /**
360      * Initializes this parameter object using the parameters
361      * specified in {@code paramSpec}.
362      *
363      * @param paramSpec the parameter specification.
364      *
365      * @exception InvalidParameterSpecException if the given parameter
366      * specification is inappropriate for the initialization of this parameter
367      * object, or if this parameter object has already been initialized.
368      */
init(AlgorithmParameterSpec paramSpec)369     public final void init(AlgorithmParameterSpec paramSpec)
370         throws InvalidParameterSpecException
371     {
372         if (this.initialized)
373             throw new InvalidParameterSpecException("already initialized");
374         paramSpi.engineInit(paramSpec);
375         this.initialized = true;
376     }
377 
378     /**
379      * Imports the specified parameters and decodes them according to the
380      * primary decoding format for parameters. The primary decoding
381      * format for parameters is ASN.1, if an ASN.1 specification for this type
382      * of parameters exists.
383      *
384      * @param params the encoded parameters.
385      *
386      * @exception IOException on decoding errors, or if this parameter object
387      * has already been initialized.
388      */
init(byte[] params)389     public final void init(byte[] params) throws IOException {
390         if (this.initialized)
391             throw new IOException("already initialized");
392         paramSpi.engineInit(params);
393         this.initialized = true;
394     }
395 
396     /**
397      * Imports the parameters from {@code params} and decodes them
398      * according to the specified decoding scheme.
399      * If {@code format} is null, the
400      * primary decoding format for parameters is used. The primary decoding
401      * format is ASN.1, if an ASN.1 specification for these parameters
402      * exists.
403      *
404      * @param params the encoded parameters.
405      *
406      * @param format the name of the decoding scheme.
407      *
408      * @exception IOException on decoding errors, or if this parameter object
409      * has already been initialized.
410      */
init(byte[] params, String format)411     public final void init(byte[] params, String format) throws IOException {
412         if (this.initialized)
413             throw new IOException("already initialized");
414         paramSpi.engineInit(params, format);
415         this.initialized = true;
416     }
417 
418     /**
419      * Returns a (transparent) specification of this parameter object.
420      * {@code paramSpec} identifies the specification class in which
421      * the parameters should be returned. It could, for example, be
422      * {@code DSAParameterSpec.class}, to indicate that the
423      * parameters should be returned in an instance of the
424      * {@code DSAParameterSpec} class.
425      *
426      * @param <T> the type of the parameter specification to be returrned
427      * @param paramSpec the specification class in which
428      * the parameters should be returned.
429      *
430      * @return the parameter specification.
431      *
432      * @exception InvalidParameterSpecException if the requested parameter
433      * specification is inappropriate for this parameter object, or if this
434      * parameter object has not been initialized.
435      */
436     public final <T extends AlgorithmParameterSpec>
getParameterSpec(Class<T> paramSpec)437         T getParameterSpec(Class<T> paramSpec)
438         throws InvalidParameterSpecException
439     {
440         if (this.initialized == false) {
441             throw new InvalidParameterSpecException("not initialized");
442         }
443         return paramSpi.engineGetParameterSpec(paramSpec);
444     }
445 
446     /**
447      * Returns the parameters in their primary encoding format.
448      * The primary encoding format for parameters is ASN.1, if an ASN.1
449      * specification for this type of parameters exists.
450      *
451      * @return the parameters encoded using their primary encoding format.
452      *
453      * @exception IOException on encoding errors, or if this parameter object
454      * has not been initialized.
455      */
getEncoded()456     public final byte[] getEncoded() throws IOException
457     {
458         if (this.initialized == false) {
459             throw new IOException("not initialized");
460         }
461         return paramSpi.engineGetEncoded();
462     }
463 
464     /**
465      * Returns the parameters encoded in the specified scheme.
466      * If {@code format} is null, the
467      * primary encoding format for parameters is used. The primary encoding
468      * format is ASN.1, if an ASN.1 specification for these parameters
469      * exists.
470      *
471      * @param format the name of the encoding format.
472      *
473      * @return the parameters encoded using the specified encoding scheme.
474      *
475      * @exception IOException on encoding errors, or if this parameter object
476      * has not been initialized.
477      */
getEncoded(String format)478     public final byte[] getEncoded(String format) throws IOException
479     {
480         if (this.initialized == false) {
481             throw new IOException("not initialized");
482         }
483         return paramSpi.engineGetEncoded(format);
484     }
485 
486     /**
487      * Returns a formatted string describing the parameters.
488      *
489      * @return a formatted string describing the parameters, or null if this
490      * parameter object has not been initialized.
491      */
toString()492     public final String toString() {
493         if (this.initialized == false) {
494             return null;
495         }
496         return paramSpi.engineToString();
497     }
498 }
499