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