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