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 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 DES}</li>
55  * <li>{@code DESede}</li>
56  * <li>{@code DiffieHellman}</li>
57  * <li>{@code DSA}</li>
58  * </ul>
59  * These algorithms are described in the <a href=
60  * "{@docRoot}/../specs/security/standard-names.html#algorithmparameters-algorithms">
61  * AlgorithmParameters section</a> of the
62  * Java Security Standard Algorithm Names Specification.
63  * Consult the release documentation for your implementation to see if any
64  * other algorithms are supported.
65  *
66  * @author Jan Luehe
67  *
68  *
69  * @see java.security.spec.AlgorithmParameterSpec
70  * @see java.security.spec.DSAParameterSpec
71  * @see KeyPairGenerator
72  *
73  * @since 1.2
74  */

75
76 public class AlgorithmParameters {
77
78     // The provider
79     private Provider provider;
80
81     // The provider implementation (delegate)
82     private AlgorithmParametersSpi paramSpi;
83
84     // The algorithm
85     private String algorithm;
86
87     // Has this object been initialized?
88     private boolean initialized = false;
89
90     /**
91      * Creates an AlgorithmParameters object.
92      *
93      * @param paramSpi the delegate
94      * @param provider the provider
95      * @param algorithm the algorithm
96      */

97     protected AlgorithmParameters(AlgorithmParametersSpi paramSpi,
98                                   Provider provider, String algorithm)
99     {
100         this.paramSpi = paramSpi;
101         this.provider = provider;
102         this.algorithm = algorithm;
103     }
104
105     /**
106      * Returns the name of the algorithm associated with this parameter object.
107      *
108      * @return the algorithm name.
109      */

110     public final String getAlgorithm() {
111         return this.algorithm;
112     }
113
114     /**
115      * Returns a parameter object for the specified algorithm.
116      *
117      * <p> This method traverses the list of registered security Providers,
118      * starting with the most preferred Provider.
119      * A new AlgorithmParameters object encapsulating the
120      * AlgorithmParametersSpi implementation from the first
121      * Provider that supports the specified algorithm is returned.
122      *
123      * <p> Note that the list of registered providers may be retrieved via
124      * the {@link Security#getProviders() Security.getProviders()} method.
125      *
126      * <p> The returned parameter object must be initialized via a call to
127      * {@code init}, using an appropriate parameter specification or
128      * parameter encoding.
129      *
130      * @implNote
131      * The JDK Reference Implementation additionally uses the
132      * {@code jdk.security.provider.preferred}
133      * {@link Security#getProperty(String) Security} property to determine
134      * the preferred provider order for the specified algorithm. This
135      * may be different than the order of providers returned by
136      * {@link Security#getProviders() Security.getProviders()}.
137      *
138      * @param algorithm the name of the algorithm requested.
139      * See the AlgorithmParameters section in the <a href=
140      * "{@docRoot}/../specs/security/standard-names.html#algorithmparameters-algorithms">
141      * Java Security Standard Algorithm Names Specification</a>
142      * for information about standard algorithm names.
143      *
144      * @return the new parameter object
145      *
146      * @throws NoSuchAlgorithmException if no {@code Provider} supports an
147      *         {@code AlgorithmParametersSpi} implementation for the
148      *         specified algorithm
149      *
150      * @throws NullPointerException if {@code algorithm} is {@code null}
151      *
152      * @see Provider
153      */

154     public static AlgorithmParameters getInstance(String algorithm)
155     throws NoSuchAlgorithmException {
156         Objects.requireNonNull(algorithm, "null algorithm name");
157         try {
158             Object[] objs = Security.getImpl(algorithm, "AlgorithmParameters",
159                                              (String)null);
160             return new AlgorithmParameters((AlgorithmParametersSpi)objs[0],
161                                            (Provider)objs[1],
162                                            algorithm);
163         } catch(NoSuchProviderException e) {
164             throw new NoSuchAlgorithmException(algorithm + " not found");
165         }
166     }
167
168     /**
169      * Returns a parameter object for the specified algorithm.
170      *
171      * <p> A new AlgorithmParameters object encapsulating the
172      * AlgorithmParametersSpi implementation from the specified provider
173      * is returned.  The specified provider must be registered
174      * in the security provider list.
175      *
176      * <p> Note that the list of registered providers may be retrieved via
177      * the {@link Security#getProviders() Security.getProviders()} method.
178      *
179      * <p>The returned parameter object must be initialized via a call to
180      * {@code init}, using an appropriate parameter specification or
181      * parameter encoding.
182      *
183      * @param algorithm the name of the algorithm requested.
184      * See the AlgorithmParameters section in the <a href=
185      * "{@docRoot}/../specs/security/standard-names.html#algorithmparameters-algorithms">
186      * Java Security Standard Algorithm Names Specification</a>
187      * for information about standard algorithm names.
188      *
189      * @param provider the name of the provider.
190      *
191      * @return the new parameter object
192      *
193      * @throws IllegalArgumentException if the provider name is {@code null}
194      *         or empty
195      *
196      * @throws NoSuchAlgorithmException if an {@code AlgorithmParametersSpi}
197      *         implementation for the specified algorithm is not
198      *         available from the specified provider
199      *
200      * @throws NoSuchProviderException if the specified provider is not
201      *         registered in the security provider list
202      *
203      * @throws NullPointerException if {@code algorithm} is {@code null}
204      *
205      * @see Provider
206      */

207     public static AlgorithmParameters getInstance(String algorithm,
208                                                   String provider)
209         throws NoSuchAlgorithmException, NoSuchProviderException
210     {
211         Objects.requireNonNull(algorithm, "null algorithm name");
212         if (provider == null || provider.isEmpty())
213             throw new IllegalArgumentException("missing provider");
214         Object[] objs = Security.getImpl(algorithm, "AlgorithmParameters",
215                                          provider);
216         return new AlgorithmParameters((AlgorithmParametersSpi)objs[0],
217                                        (Provider)objs[1],
218                                        algorithm);
219     }
220
221     /**
222      * Returns a parameter object for the specified algorithm.
223      *
224      * <p> A new AlgorithmParameters object encapsulating the
225      * AlgorithmParametersSpi implementation from the specified Provider
226      * object is returned.  Note that the specified Provider object
227      * does not have to be registered in the provider list.
228      *
229      * <p>The returned parameter object must be initialized via a call to
230      * {@code init}, using an appropriate parameter specification or
231      * parameter encoding.
232      *
233      * @param algorithm the name of the algorithm requested.
234      * See the AlgorithmParameters section in the <a href=
235      * "{@docRoot}/../specs/security/standard-names.html#algorithmparameters-algorithms">
236      * Java Security Standard Algorithm Names Specification</a>
237      * for information about standard algorithm names.
238      *
239      * @param provider the name of the provider.
240      *
241      * @return the new parameter object
242      *
243      * @throws IllegalArgumentException if the provider is {@code null}
244      *
245      * @throws NoSuchAlgorithmException if an
246      *         {@code AlgorithmParameterGeneratorSpi}
247      *         implementation for the specified algorithm is not available
248      *         from the specified {@code Provider} object
249      *
250      * @throws NullPointerException if {@code algorithm} is {@code null}
251      *
252      * @see Provider
253      *
254      * @since 1.4
255      */

256     public static AlgorithmParameters getInstance(String algorithm,
257                                                   Provider provider)
258         throws NoSuchAlgorithmException
259     {
260         Objects.requireNonNull(algorithm, "null algorithm name");
261         if (provider == null)
262             throw new IllegalArgumentException("missing provider");
263         Object[] objs = Security.getImpl(algorithm, "AlgorithmParameters",
264                                          provider);
265         return new AlgorithmParameters((AlgorithmParametersSpi)objs[0],
266                                        (Provider)objs[1],
267                                        algorithm);
268     }
269
270     /**
271      * Returns the provider of this parameter object.
272      *
273      * @return the provider of this parameter object
274      */

275     public final Provider getProvider() {
276         return this.provider;
277     }
278
279     /**
280      * Initializes this parameter object using the parameters
281      * specified in {@code paramSpec}.
282      *
283      * @param paramSpec the parameter specification.
284      *
285      * @exception InvalidParameterSpecException if the given parameter
286      * specification is inappropriate for the initialization of this parameter
287      * object, or if this parameter object has already been initialized.
288      */

289     public final void init(AlgorithmParameterSpec paramSpec)
290         throws InvalidParameterSpecException
291     {
292         if (this.initialized)
293             throw new InvalidParameterSpecException("already initialized");
294         paramSpi.engineInit(paramSpec);
295         this.initialized = true;
296     }
297
298     /**
299      * Imports the specified parameters and decodes them according to the
300      * primary decoding format for parameters. The primary decoding
301      * format for parameters is ASN.1, if an ASN.1 specification for this type
302      * of parameters exists.
303      *
304      * @param params the encoded parameters.
305      *
306      * @exception IOException on decoding errors, or if this parameter object
307      * has already been initialized.
308      */

309     public final void init(byte[] params) throws IOException {
310         if (this.initialized)
311             throw new IOException("already initialized");
312         paramSpi.engineInit(params);
313         this.initialized = true;
314     }
315
316     /**
317      * Imports the parameters from {@code params} and decodes them
318      * according to the specified decoding scheme.
319      * If {@code format} is null, the
320      * primary decoding format for parameters is used. The primary decoding
321      * format is ASN.1, if an ASN.1 specification for these parameters
322      * exists.
323      *
324      * @param params the encoded parameters.
325      *
326      * @param format the name of the decoding scheme.
327      *
328      * @exception IOException on decoding errors, or if this parameter object
329      * has already been initialized.
330      */

331     public final void init(byte[] params, String format) throws IOException {
332         if (this.initialized)
333             throw new IOException("already initialized");
334         paramSpi.engineInit(params, format);
335         this.initialized = true;
336     }
337
338     /**
339      * Returns a (transparent) specification of this parameter object.
340      * {@code paramSpec} identifies the specification class in which
341      * the parameters should be returned. It could, for example, be
342      * {@code DSAParameterSpec.class}, to indicate that the
343      * parameters should be returned in an instance of the
344      * {@code DSAParameterSpec} class.
345      *
346      * @param <T> the type of the parameter specification to be returrned
347      * @param paramSpec the specification class in which
348      * the parameters should be returned.
349      *
350      * @return the parameter specification.
351      *
352      * @exception InvalidParameterSpecException if the requested parameter
353      * specification is inappropriate for this parameter object, or if this
354      * parameter object has not been initialized.
355      */

356     public final <T extends AlgorithmParameterSpec>
357         T getParameterSpec(Class<T> paramSpec)
358         throws InvalidParameterSpecException
359     {
360         if (this.initialized == false) {
361             throw new InvalidParameterSpecException("not initialized");
362         }
363         return paramSpi.engineGetParameterSpec(paramSpec);
364     }
365
366     /**
367      * Returns the parameters in their primary encoding format.
368      * The primary encoding format for parameters is ASN.1, if an ASN.1
369      * specification for this type of parameters exists.
370      *
371      * @return the parameters encoded using their primary encoding format.
372      *
373      * @exception IOException on encoding errors, or if this parameter object
374      * has not been initialized.
375      */

376     public final byte[] getEncoded() throws IOException
377     {
378         if (this.initialized == false) {
379             throw new IOException("not initialized");
380         }
381         return paramSpi.engineGetEncoded();
382     }
383
384     /**
385      * Returns the parameters encoded in the specified scheme.
386      * If {@code format} is null, the
387      * primary encoding format for parameters is used. The primary encoding
388      * format is ASN.1, if an ASN.1 specification for these parameters
389      * exists.
390      *
391      * @param format the name of the encoding format.
392      *
393      * @return the parameters encoded using the specified encoding scheme.
394      *
395      * @exception IOException on encoding errors, or if this parameter object
396      * has not been initialized.
397      */

398     public final byte[] getEncoded(String format) throws IOException
399     {
400         if (this.initialized == false) {
401             throw new IOException("not initialized");
402         }
403         return paramSpi.engineGetEncoded(format);
404     }
405
406     /**
407      * Returns a formatted string describing the parameters.
408      *
409      * @return a formatted string describing the parameters, or null if this
410      * parameter object has not been initialized.
411      */

412     public final String toString() {
413         if (this.initialized == false) {
414             return null;
415         }
416         return paramSpi.engineToString();
417     }
418 }
419