1 /*
2  * Copyright (c) 1997, 2019, 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 import java.util.Objects;
32 
33 /**
34  * This class is used as an opaque representation of cryptographic parameters.
35  *
36  * <p>An {@code AlgorithmParameters} object for managing the parameters
37  * for a particular algorithm can be obtained by
38  * calling one of the {@code getInstance} factory methods
39  * (static methods that return instances of a given class).
40  *
41  * <p>Once an {@code AlgorithmParameters} object is obtained, it must be
42  * initialized via a call to {@code init}, using an appropriate parameter
43  * specification or parameter encoding.
44  *
45  * <p>A transparent parameter specification is obtained from an
46  * {@code AlgorithmParameters} object via a call to
47  * {@code getParameterSpec}, and a byte encoding of the parameters is
48  * obtained via a call to {@code getEncoded}.
49  *
50  * <p> Every implementation of the Java platform is required to support the
51  * following standard {@code AlgorithmParameters} algorithms:
52  * <ul>
53  * <li>{@code AES}</li>
54  * <li>{@code DESede}</li>
55  * <li>{@code DiffieHellman}</li>
56  * <li>{@code DSA}</li>
57  * </ul>
58  * These algorithms are described in the <a href=
59  * "{@docRoot}/../specs/security/standard-names.html#algorithmparameters-algorithms">
60  * AlgorithmParameters section</a> of the
61  * Java Security Standard Algorithm Names Specification.
62  * Consult the release documentation for your implementation to see if any
63  * other algorithms are supported.
64  *
65  * @author Jan Luehe
66  *
67  *
68  * @see java.security.spec.AlgorithmParameterSpec
69  * @see java.security.spec.DSAParameterSpec
70  * @see KeyPairGenerator
71  *
72  * @since 1.2
73  */
74 
75 public class AlgorithmParameters {
76 
77     // The provider
78     private Provider provider;
79 
80     // The provider implementation (delegate)
81     private AlgorithmParametersSpi paramSpi;
82 
83     // The algorithm
84     private String algorithm;
85 
86     // Has this object been initialized?
87     private boolean initialized = false;
88 
89     /**
90      * Creates an AlgorithmParameters object.
91      *
92      * @param paramSpi the delegate
93      * @param provider the provider
94      * @param algorithm the algorithm
95      */
AlgorithmParameters(AlgorithmParametersSpi paramSpi, Provider provider, String algorithm)96     protected AlgorithmParameters(AlgorithmParametersSpi paramSpi,
97                                   Provider provider, String algorithm)
98     {
99         this.paramSpi = paramSpi;
100         this.provider = provider;
101         this.algorithm = algorithm;
102     }
103 
104     /**
105      * Returns the name of the algorithm associated with this parameter object.
106      *
107      * @return the algorithm name.
108      */
getAlgorithm()109     public final String getAlgorithm() {
110         return this.algorithm;
111     }
112 
113     /**
114      * Returns a parameter object for the specified algorithm.
115      *
116      * <p> This method traverses the list of registered security Providers,
117      * starting with the most preferred Provider.
118      * A new AlgorithmParameters object encapsulating the
119      * AlgorithmParametersSpi implementation from the first
120      * Provider that supports the specified algorithm is returned.
121      *
122      * <p> Note that the list of registered providers may be retrieved via
123      * the {@link Security#getProviders() Security.getProviders()} method.
124      *
125      * <p> The returned parameter object must be initialized via a call to
126      * {@code init}, using an appropriate parameter specification or
127      * parameter encoding.
128      *
129      * @implNote
130      * The JDK Reference Implementation additionally uses the
131      * {@code jdk.security.provider.preferred}
132      * {@link Security#getProperty(String) Security} property to determine
133      * the preferred provider order for the specified algorithm. This
134      * may be different than the order of providers returned by
135      * {@link Security#getProviders() Security.getProviders()}.
136      *
137      * @param algorithm the name of the algorithm requested.
138      * See the AlgorithmParameters section in the <a href=
139      * "{@docRoot}/../specs/security/standard-names.html#algorithmparameters-algorithms">
140      * Java Security Standard Algorithm Names Specification</a>
141      * for information about standard algorithm names.
142      *
143      * @return the new parameter object
144      *
145      * @throws NoSuchAlgorithmException if no {@code Provider} supports an
146      *         {@code AlgorithmParametersSpi} implementation for the
147      *         specified algorithm
148      *
149      * @throws NullPointerException if {@code algorithm} is {@code null}
150      *
151      * @see Provider
152      */
getInstance(String algorithm)153     public static AlgorithmParameters getInstance(String algorithm)
154     throws NoSuchAlgorithmException {
155         Objects.requireNonNull(algorithm, "null algorithm name");
156         try {
157             Object[] objs = Security.getImpl(algorithm, "AlgorithmParameters",
158                                              (String)null);
159             return new AlgorithmParameters((AlgorithmParametersSpi)objs[0],
160                                            (Provider)objs[1],
161                                            algorithm);
162         } catch(NoSuchProviderException e) {
163             throw new NoSuchAlgorithmException(algorithm + " not found");
164         }
165     }
166 
167     /**
168      * Returns a parameter object for the specified algorithm.
169      *
170      * <p> A new AlgorithmParameters object encapsulating the
171      * AlgorithmParametersSpi implementation from the specified provider
172      * is returned.  The specified provider must be registered
173      * in the security provider list.
174      *
175      * <p> Note that the list of registered providers may be retrieved via
176      * the {@link Security#getProviders() Security.getProviders()} method.
177      *
178      * <p>The returned parameter object must be initialized via a call to
179      * {@code init}, using an appropriate parameter specification or
180      * parameter encoding.
181      *
182      * @param algorithm the name of the algorithm requested.
183      * See the AlgorithmParameters section in the <a href=
184      * "{@docRoot}/../specs/security/standard-names.html#algorithmparameters-algorithms">
185      * Java Security Standard Algorithm Names Specification</a>
186      * for information about standard algorithm names.
187      *
188      * @param provider the name of the provider.
189      *
190      * @return the new parameter object
191      *
192      * @throws IllegalArgumentException if the provider name is {@code null}
193      *         or empty
194      *
195      * @throws NoSuchAlgorithmException if an {@code AlgorithmParametersSpi}
196      *         implementation for the specified algorithm is not
197      *         available from the specified provider
198      *
199      * @throws NoSuchProviderException if the specified provider is not
200      *         registered in the security provider list
201      *
202      * @throws NullPointerException if {@code algorithm} is {@code null}
203      *
204      * @see Provider
205      */
getInstance(String algorithm, String provider)206     public static AlgorithmParameters getInstance(String algorithm,
207                                                   String provider)
208         throws NoSuchAlgorithmException, NoSuchProviderException
209     {
210         Objects.requireNonNull(algorithm, "null algorithm name");
211         if (provider == null || provider.isEmpty())
212             throw new IllegalArgumentException("missing provider");
213         Object[] objs = Security.getImpl(algorithm, "AlgorithmParameters",
214                                          provider);
215         return new AlgorithmParameters((AlgorithmParametersSpi)objs[0],
216                                        (Provider)objs[1],
217                                        algorithm);
218     }
219 
220     /**
221      * Returns a parameter object for the specified algorithm.
222      *
223      * <p> A new AlgorithmParameters object encapsulating the
224      * AlgorithmParametersSpi implementation from the specified Provider
225      * object is returned.  Note that the specified Provider object
226      * does not have to be registered in the provider list.
227      *
228      * <p>The returned parameter object must be initialized via a call to
229      * {@code init}, using an appropriate parameter specification or
230      * parameter encoding.
231      *
232      * @param algorithm the name of the algorithm requested.
233      * See the AlgorithmParameters section in the <a href=
234      * "{@docRoot}/../specs/security/standard-names.html#algorithmparameters-algorithms">
235      * Java Security Standard Algorithm Names Specification</a>
236      * for information about standard algorithm names.
237      *
238      * @param provider the name of the provider.
239      *
240      * @return the new parameter object
241      *
242      * @throws IllegalArgumentException if the provider is {@code null}
243      *
244      * @throws NoSuchAlgorithmException if an
245      *         {@code AlgorithmParameterGeneratorSpi}
246      *         implementation for the specified algorithm is not available
247      *         from the specified {@code Provider} object
248      *
249      * @throws NullPointerException if {@code algorithm} is {@code null}
250      *
251      * @see Provider
252      *
253      * @since 1.4
254      */
getInstance(String algorithm, Provider provider)255     public static AlgorithmParameters getInstance(String algorithm,
256                                                   Provider provider)
257         throws NoSuchAlgorithmException
258     {
259         Objects.requireNonNull(algorithm, "null algorithm name");
260         if (provider == null)
261             throw new IllegalArgumentException("missing provider");
262         Object[] objs = Security.getImpl(algorithm, "AlgorithmParameters",
263                                          provider);
264         return new AlgorithmParameters((AlgorithmParametersSpi)objs[0],
265                                        (Provider)objs[1],
266                                        algorithm);
267     }
268 
269     /**
270      * Returns the provider of this parameter object.
271      *
272      * @return the provider of this parameter object
273      */
getProvider()274     public final Provider getProvider() {
275         return this.provider;
276     }
277 
278     /**
279      * Initializes this parameter object using the parameters
280      * specified in {@code paramSpec}.
281      *
282      * @param paramSpec the parameter specification.
283      *
284      * @throws    InvalidParameterSpecException if the given parameter
285      * specification is inappropriate for the initialization of this parameter
286      * object, or if this parameter object has already been initialized.
287      */
init(AlgorithmParameterSpec paramSpec)288     public final void init(AlgorithmParameterSpec paramSpec)
289         throws InvalidParameterSpecException
290     {
291         if (this.initialized)
292             throw new InvalidParameterSpecException("already initialized");
293         paramSpi.engineInit(paramSpec);
294         this.initialized = true;
295     }
296 
297     /**
298      * Imports the specified parameters and decodes them according to the
299      * primary decoding format for parameters. The primary decoding
300      * format for parameters is ASN.1, if an ASN.1 specification for this type
301      * of parameters exists.
302      *
303      * @param params the encoded parameters.
304      *
305      * @throws    IOException on decoding errors, or if this parameter object
306      * has already been initialized.
307      */
init(byte[] params)308     public final void init(byte[] params) throws IOException {
309         if (this.initialized)
310             throw new IOException("already initialized");
311         paramSpi.engineInit(params);
312         this.initialized = true;
313     }
314 
315     /**
316      * Imports the parameters from {@code params} and decodes them
317      * according to the specified decoding scheme.
318      * If {@code format} is null, the
319      * primary decoding format for parameters is used. The primary decoding
320      * format is ASN.1, if an ASN.1 specification for these parameters
321      * exists.
322      *
323      * @param params the encoded parameters.
324      *
325      * @param format the name of the decoding scheme.
326      *
327      * @throws    IOException on decoding errors, or if this parameter object
328      * has already been initialized.
329      */
init(byte[] params, String format)330     public final void init(byte[] params, String format) throws IOException {
331         if (this.initialized)
332             throw new IOException("already initialized");
333         paramSpi.engineInit(params, format);
334         this.initialized = true;
335     }
336 
337     /**
338      * Returns a (transparent) specification of this parameter object.
339      * {@code paramSpec} identifies the specification class in which
340      * the parameters should be returned. It could, for example, be
341      * {@code DSAParameterSpec.class}, to indicate that the
342      * parameters should be returned in an instance of the
343      * {@code DSAParameterSpec} class.
344      *
345      * @param <T> the type of the parameter specification to be returrned
346      * @param paramSpec the specification class in which
347      * the parameters should be returned.
348      *
349      * @return the parameter specification.
350      *
351      * @throws    InvalidParameterSpecException if the requested parameter
352      * specification is inappropriate for this parameter object, or if this
353      * parameter object has not been initialized.
354      */
355     public final <T extends AlgorithmParameterSpec>
getParameterSpec(Class<T> paramSpec)356         T getParameterSpec(Class<T> paramSpec)
357         throws InvalidParameterSpecException
358     {
359         if (this.initialized == false) {
360             throw new InvalidParameterSpecException("not initialized");
361         }
362         return paramSpi.engineGetParameterSpec(paramSpec);
363     }
364 
365     /**
366      * Returns the parameters in their primary encoding format.
367      * The primary encoding format for parameters is ASN.1, if an ASN.1
368      * specification for this type of parameters exists.
369      *
370      * @return the parameters encoded using their primary encoding format.
371      *
372      * @throws    IOException on encoding errors, or if this parameter object
373      * has not been initialized.
374      */
getEncoded()375     public final byte[] getEncoded() throws IOException
376     {
377         if (this.initialized == false) {
378             throw new IOException("not initialized");
379         }
380         return paramSpi.engineGetEncoded();
381     }
382 
383     /**
384      * Returns the parameters encoded in the specified scheme.
385      * If {@code format} is null, the
386      * primary encoding format for parameters is used. The primary encoding
387      * format is ASN.1, if an ASN.1 specification for these parameters
388      * exists.
389      *
390      * @param format the name of the encoding format.
391      *
392      * @return the parameters encoded using the specified encoding scheme.
393      *
394      * @throws    IOException on encoding errors, or if this parameter object
395      * has not been initialized.
396      */
getEncoded(String format)397     public final byte[] getEncoded(String format) throws IOException
398     {
399         if (this.initialized == false) {
400             throw new IOException("not initialized");
401         }
402         return paramSpi.engineGetEncoded(format);
403     }
404 
405     /**
406      * Returns a formatted string describing the parameters.
407      *
408      * @return a formatted string describing the parameters, or null if this
409      * parameter object has not been initialized.
410      */
toString()411     public final String toString() {
412         if (this.initialized == false) {
413             return null;
414         }
415         return paramSpi.engineToString();
416     }
417 }
418