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