1 /* 2 * Copyright (c) 1997, 2014, 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 javax.crypto; 27 28 import java.util.*; 29 30 import java.security.*; 31 import java.security.Provider.Service; 32 import java.security.spec.*; 33 34 import sun.security.jca.*; 35 import sun.security.jca.GetInstance.Instance; 36 37 /** 38 * This class provides the functionality of a secret (symmetric) key generator. 39 * 40 * <p>Key generators are constructed using one of the <code>getInstance</code> 41 * class methods of this class. 42 * 43 * <p>KeyGenerator objects are reusable, i.e., after a key has been 44 * generated, the same KeyGenerator object can be re-used to generate further 45 * keys. 46 * 47 * <p>There are two ways to generate a key: in an algorithm-independent 48 * manner, and in an algorithm-specific manner. 49 * The only difference between the two is the initialization of the object: 50 * 51 * <ul> 52 * <li><b>Algorithm-Independent Initialization</b> 53 * <p>All key generators share the concepts of a <i>keysize</i> and a 54 * <i>source of randomness</i>. 55 * There is an 56 * {@link #init(int, java.security.SecureRandom) init} 57 * method in this KeyGenerator class that takes these two universally 58 * shared types of arguments. There is also one that takes just a 59 * <code>keysize</code> argument, and uses the SecureRandom implementation 60 * of the highest-priority installed provider as the source of randomness 61 * (or a system-provided source of randomness if none of the installed 62 * providers supply a SecureRandom implementation), and one that takes just a 63 * source of randomness. 64 * 65 * <p>Since no other parameters are specified when you call the above 66 * algorithm-independent <code>init</code> methods, it is up to the 67 * provider what to do about the algorithm-specific parameters (if any) to be 68 * associated with each of the keys. 69 * 70 * <li><b>Algorithm-Specific Initialization</b> 71 * <p>For situations where a set of algorithm-specific parameters already 72 * exists, there are two 73 * {@link #init(java.security.spec.AlgorithmParameterSpec) init} 74 * methods that have an <code>AlgorithmParameterSpec</code> 75 * argument. One also has a <code>SecureRandom</code> argument, while the 76 * other uses the SecureRandom implementation 77 * of the highest-priority installed provider as the source of randomness 78 * (or a system-provided source of randomness if none of the installed 79 * providers supply a SecureRandom implementation). 80 * </ul> 81 * 82 * <p>In case the client does not explicitly initialize the KeyGenerator 83 * (via a call to an <code>init</code> method), each provider must 84 * supply (and document) a default initialization. 85 * 86 * <p> Android provides the following <code>KeyGenerator</code> algorithms: 87 * <table> 88 * <thead> 89 * <tr> 90 * <th>Algorithm</th> 91 * <th>Supported API Levels</th> 92 * </tr> 93 * </thead> 94 * <tbody> 95 * <tr> 96 * <td>AES</td> 97 * <td>1+</td> 98 * </tr> 99 * <tr class="deprecated"> 100 * <td>AESWRAP</td> 101 * <td>1-8</td> 102 * </tr> 103 * <tr> 104 * <td>ARC4</td> 105 * <td>14+</td> 106 * </tr> 107 * <tr> 108 * <td>BLOWFISH</td> 109 * <td>10+</td> 110 * </tr> 111 * <tr> 112 * <td>ChaCha20</td> 113 * <td>28+</td> 114 * </tr> 115 * <tr> 116 * <td>DES</td> 117 * <td>1+</td> 118 * </tr> 119 * <tr> 120 * <td>DESede</td> 121 * <td>1+</td> 122 * </tr> 123 * <tr class="deprecated"> 124 * <td>DESedeWRAP</td> 125 * <td>1-8</td> 126 * </tr> 127 * <tr> 128 * <td>HmacMD5</td> 129 * <td>1+</td> 130 * </tr> 131 * <tr> 132 * <td>HmacSHA1</td> 133 * <td>11+</td> 134 * </tr> 135 * <tr> 136 * <td>HmacSHA224</td> 137 * <td>1-8,22+</td> 138 * </tr> 139 * <tr> 140 * <td>HmacSHA256</td> 141 * <td>1+</td> 142 * </tr> 143 * <tr> 144 * <td>HmacSHA384</td> 145 * <td>1+</td> 146 * </tr> 147 * <tr> 148 * <td>HmacSHA512</td> 149 * <td>1+</td> 150 * </tr> 151 * <tr class="deprecated"> 152 * <td>RC4</td> 153 * <td>10-13</td> 154 * </tr> 155 * </tbody> 156 * </table> 157 * 158 * These algorithms are described in the <a href= 159 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyGenerator"> 160 * KeyGenerator section</a> of the 161 * Java Cryptography Architecture Standard Algorithm Name Documentation. 162 * 163 * @author Jan Luehe 164 * 165 * @see SecretKey 166 * @since 1.4 167 */ 168 169 public class KeyGenerator { 170 171 // Android-removed: this debugging mechanism is not used in Android. 172 /* 173 private static final Debug pdebug = 174 Debug.getInstance("provider", "Provider"); 175 private static final boolean skipDebug = 176 Debug.isOn("engine=") && !Debug.isOn("keygenerator"); 177 */ 178 179 // see java.security.KeyPairGenerator for failover notes 180 181 private final static int I_NONE = 1; 182 private final static int I_RANDOM = 2; 183 private final static int I_PARAMS = 3; 184 private final static int I_SIZE = 4; 185 186 // The provider 187 private Provider provider; 188 189 // The provider implementation (delegate) 190 private volatile KeyGeneratorSpi spi; 191 192 // The algorithm 193 private final String algorithm; 194 195 private final Object lock = new Object(); 196 197 private Iterator<Service> serviceIterator; 198 199 private int initType; 200 private int initKeySize; 201 private AlgorithmParameterSpec initParams; 202 private SecureRandom initRandom; 203 204 /** 205 * Creates a KeyGenerator object. 206 * 207 * @param keyGenSpi the delegate 208 * @param provider the provider 209 * @param algorithm the algorithm 210 */ KeyGenerator(KeyGeneratorSpi keyGenSpi, Provider provider, String algorithm)211 protected KeyGenerator(KeyGeneratorSpi keyGenSpi, Provider provider, 212 String algorithm) { 213 this.spi = keyGenSpi; 214 this.provider = provider; 215 this.algorithm = algorithm; 216 217 // Android-removed: this debugging mechanism is not used in Android. 218 /* 219 if (!skipDebug && pdebug != null) { 220 pdebug.println("KeyGenerator." + algorithm + " algorithm from: " + 221 this.provider.getName()); 222 } 223 */ 224 } 225 KeyGenerator(String algorithm)226 private KeyGenerator(String algorithm) throws NoSuchAlgorithmException { 227 this.algorithm = algorithm; 228 List<Service> list = 229 GetInstance.getServices("KeyGenerator", algorithm); 230 serviceIterator = list.iterator(); 231 initType = I_NONE; 232 // fetch and instantiate initial spi 233 if (nextSpi(null, false) == null) { 234 throw new NoSuchAlgorithmException 235 (algorithm + " KeyGenerator not available"); 236 } 237 238 // Android-removed: this debugging mechanism is not used in Android. 239 /* 240 if (!skipDebug && pdebug != null) { 241 pdebug.println("KeyGenerator." + algorithm + " algorithm from: " + 242 this.provider.getName()); 243 } 244 */ 245 } 246 247 /** 248 * Returns the algorithm name of this <code>KeyGenerator</code> object. 249 * 250 * <p>This is the same name that was specified in one of the 251 * <code>getInstance</code> calls that created this 252 * <code>KeyGenerator</code> object. 253 * 254 * @return the algorithm name of this <code>KeyGenerator</code> object. 255 */ getAlgorithm()256 public final String getAlgorithm() { 257 return this.algorithm; 258 } 259 260 /** 261 * Returns a <code>KeyGenerator</code> object that generates secret keys 262 * for the specified algorithm. 263 * 264 * <p> This method traverses the list of registered security Providers, 265 * starting with the most preferred Provider. 266 * A new KeyGenerator object encapsulating the 267 * KeyGeneratorSpi implementation from the first 268 * Provider that supports the specified algorithm is returned. 269 * 270 * <p> Note that the list of registered providers may be retrieved via 271 * the {@link Security#getProviders() Security.getProviders()} method. 272 * 273 * @param algorithm the standard name of the requested key algorithm. 274 * See the KeyGenerator section in the <a href= 275 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyGenerator"> 276 * Java Cryptography Architecture Standard Algorithm Name Documentation</a> 277 * for information about standard algorithm names. 278 * 279 * @return the new <code>KeyGenerator</code> object. 280 * 281 * @exception NullPointerException if the specified algorithm is null. 282 * 283 * @exception NoSuchAlgorithmException if no Provider supports a 284 * KeyGeneratorSpi implementation for the 285 * specified algorithm. 286 * 287 * @see java.security.Provider 288 */ getInstance(String algorithm)289 public static final KeyGenerator getInstance(String algorithm) 290 throws NoSuchAlgorithmException { 291 return new KeyGenerator(algorithm); 292 } 293 294 /** 295 * Returns a <code>KeyGenerator</code> object that generates secret keys 296 * for the specified algorithm. 297 * 298 * <p> A new KeyGenerator object encapsulating the 299 * KeyGeneratorSpi implementation from the specified provider 300 * is returned. The specified provider must be registered 301 * in the security provider list. 302 * 303 * <p> Note that the list of registered providers may be retrieved via 304 * the {@link Security#getProviders() Security.getProviders()} method. 305 * 306 * @param algorithm the standard name of the requested key algorithm. 307 * See the KeyGenerator section in the <a href= 308 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyGenerator"> 309 * Java Cryptography Architecture Standard Algorithm Name Documentation</a> 310 * for information about standard algorithm names. 311 * 312 * @param provider the name of the provider. 313 * 314 * @return the new <code>KeyGenerator</code> object. 315 * 316 * @exception NullPointerException if the specified algorithm is null. 317 * 318 * @exception NoSuchAlgorithmException if a KeyGeneratorSpi 319 * implementation for the specified algorithm is not 320 * available from the specified provider. 321 * 322 * @exception NoSuchProviderException if the specified provider is not 323 * registered in the security provider list. 324 * 325 * @exception IllegalArgumentException if the <code>provider</code> 326 * is null or empty. 327 * 328 * @see java.security.Provider 329 */ getInstance(String algorithm, String provider)330 public static final KeyGenerator getInstance(String algorithm, 331 String provider) throws NoSuchAlgorithmException, 332 NoSuchProviderException { 333 // Android-added: Check for Bouncy Castle deprecation 334 Providers.checkBouncyCastleDeprecation(provider, "KeyGenerator", algorithm); 335 Instance instance = JceSecurity.getInstance("KeyGenerator", 336 KeyGeneratorSpi.class, algorithm, provider); 337 return new KeyGenerator((KeyGeneratorSpi)instance.impl, 338 instance.provider, algorithm); 339 } 340 341 /** 342 * Returns a <code>KeyGenerator</code> object that generates secret keys 343 * for the specified algorithm. 344 * 345 * <p> A new KeyGenerator object encapsulating the 346 * KeyGeneratorSpi implementation from the specified Provider 347 * object is returned. Note that the specified Provider object 348 * does not have to be registered in the provider list. 349 * 350 * @param algorithm the standard name of the requested key algorithm. 351 * See the KeyGenerator section in the <a href= 352 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyGenerator"> 353 * Java Cryptography Architecture Standard Algorithm Name Documentation</a> 354 * for information about standard algorithm names. 355 * 356 * @param provider the provider. 357 * 358 * @return the new <code>KeyGenerator</code> object. 359 * 360 * @exception NullPointerException if the specified algorithm is null. 361 * 362 * @exception NoSuchAlgorithmException if a KeyGeneratorSpi 363 * implementation for the specified algorithm is not available 364 * from the specified Provider object. 365 * 366 * @exception IllegalArgumentException if the <code>provider</code> 367 * is null. 368 * 369 * @see java.security.Provider 370 */ getInstance(String algorithm, Provider provider)371 public static final KeyGenerator getInstance(String algorithm, 372 Provider provider) throws NoSuchAlgorithmException { 373 // Android-added: Check for Bouncy Castle deprecation 374 Providers.checkBouncyCastleDeprecation(provider, "KeyGenerator", algorithm); 375 Instance instance = JceSecurity.getInstance("KeyGenerator", 376 KeyGeneratorSpi.class, algorithm, provider); 377 return new KeyGenerator((KeyGeneratorSpi)instance.impl, 378 instance.provider, algorithm); 379 } 380 381 /** 382 * Returns the provider of this <code>KeyGenerator</code> object. 383 * 384 * @return the provider of this <code>KeyGenerator</code> object 385 */ getProvider()386 public final Provider getProvider() { 387 synchronized (lock) { 388 disableFailover(); 389 return provider; 390 } 391 } 392 393 /** 394 * Update the active spi of this class and return the next 395 * implementation for failover. If no more implemenations are 396 * available, this method returns null. However, the active spi of 397 * this class is never set to null. 398 */ nextSpi(KeyGeneratorSpi oldSpi, boolean reinit)399 private KeyGeneratorSpi nextSpi(KeyGeneratorSpi oldSpi, 400 boolean reinit) { 401 synchronized (lock) { 402 // somebody else did a failover concurrently 403 // try that spi now 404 if ((oldSpi != null) && (oldSpi != spi)) { 405 return spi; 406 } 407 if (serviceIterator == null) { 408 return null; 409 } 410 while (serviceIterator.hasNext()) { 411 Service s = serviceIterator.next(); 412 if (JceSecurity.canUseProvider(s.getProvider()) == false) { 413 continue; 414 } 415 try { 416 Object inst = s.newInstance(null); 417 // ignore non-spis 418 if (inst instanceof KeyGeneratorSpi == false) { 419 continue; 420 } 421 KeyGeneratorSpi spi = (KeyGeneratorSpi)inst; 422 if (reinit) { 423 if (initType == I_SIZE) { 424 spi.engineInit(initKeySize, initRandom); 425 } else if (initType == I_PARAMS) { 426 spi.engineInit(initParams, initRandom); 427 } else if (initType == I_RANDOM) { 428 spi.engineInit(initRandom); 429 } else if (initType != I_NONE) { 430 throw new AssertionError 431 ("KeyGenerator initType: " + initType); 432 } 433 } 434 provider = s.getProvider(); 435 this.spi = spi; 436 return spi; 437 } catch (Exception e) { 438 // ignore 439 } 440 } 441 disableFailover(); 442 return null; 443 } 444 } 445 disableFailover()446 void disableFailover() { 447 serviceIterator = null; 448 initType = 0; 449 initParams = null; 450 initRandom = null; 451 } 452 453 /** 454 * Initializes this key generator. 455 * 456 * @param random the source of randomness for this generator 457 */ init(SecureRandom random)458 public final void init(SecureRandom random) { 459 if (serviceIterator == null) { 460 spi.engineInit(random); 461 return; 462 } 463 RuntimeException failure = null; 464 KeyGeneratorSpi mySpi = spi; 465 do { 466 try { 467 mySpi.engineInit(random); 468 initType = I_RANDOM; 469 initKeySize = 0; 470 initParams = null; 471 initRandom = random; 472 return; 473 } catch (RuntimeException e) { 474 if (failure == null) { 475 failure = e; 476 } 477 mySpi = nextSpi(mySpi, false); 478 } 479 } while (mySpi != null); 480 throw failure; 481 } 482 483 /** 484 * Initializes this key generator with the specified parameter set. 485 * 486 * <p> If this key generator requires any random bytes, it will get them 487 * using the 488 * {@link java.security.SecureRandom} 489 * implementation of the highest-priority installed 490 * provider as the source of randomness. 491 * (If none of the installed providers supply an implementation of 492 * SecureRandom, a system-provided source of randomness will be used.) 493 * 494 * @param params the key generation parameters 495 * 496 * @exception InvalidAlgorithmParameterException if the given parameters 497 * are inappropriate for this key generator 498 */ init(AlgorithmParameterSpec params)499 public final void init(AlgorithmParameterSpec params) 500 throws InvalidAlgorithmParameterException 501 { 502 init(params, JceSecurity.RANDOM); 503 } 504 505 /** 506 * Initializes this key generator with the specified parameter 507 * set and a user-provided source of randomness. 508 * 509 * @param params the key generation parameters 510 * @param random the source of randomness for this key generator 511 * 512 * @exception InvalidAlgorithmParameterException if <code>params</code> is 513 * inappropriate for this key generator 514 */ init(AlgorithmParameterSpec params, SecureRandom random)515 public final void init(AlgorithmParameterSpec params, SecureRandom random) 516 throws InvalidAlgorithmParameterException 517 { 518 if (serviceIterator == null) { 519 spi.engineInit(params, random); 520 return; 521 } 522 Exception failure = null; 523 KeyGeneratorSpi mySpi = spi; 524 do { 525 try { 526 mySpi.engineInit(params, random); 527 initType = I_PARAMS; 528 initKeySize = 0; 529 initParams = params; 530 initRandom = random; 531 return; 532 } catch (Exception e) { 533 if (failure == null) { 534 failure = e; 535 } 536 mySpi = nextSpi(mySpi, false); 537 } 538 } while (mySpi != null); 539 if (failure instanceof InvalidAlgorithmParameterException) { 540 throw (InvalidAlgorithmParameterException)failure; 541 } 542 if (failure instanceof RuntimeException) { 543 throw (RuntimeException)failure; 544 } 545 throw new InvalidAlgorithmParameterException("init() failed", failure); 546 } 547 548 /** 549 * Initializes this key generator for a certain keysize. 550 * 551 * <p> If this key generator requires any random bytes, it will get them 552 * using the 553 * {@link java.security.SecureRandom} 554 * implementation of the highest-priority installed 555 * provider as the source of randomness. 556 * (If none of the installed providers supply an implementation of 557 * SecureRandom, a system-provided source of randomness will be used.) 558 * 559 * @param keysize the keysize. This is an algorithm-specific metric, 560 * specified in number of bits. 561 * 562 * @exception InvalidParameterException if the keysize is wrong or not 563 * supported. 564 */ init(int keysize)565 public final void init(int keysize) { 566 init(keysize, JceSecurity.RANDOM); 567 } 568 569 /** 570 * Initializes this key generator for a certain keysize, using a 571 * user-provided source of randomness. 572 * 573 * @param keysize the keysize. This is an algorithm-specific metric, 574 * specified in number of bits. 575 * @param random the source of randomness for this key generator 576 * 577 * @exception InvalidParameterException if the keysize is wrong or not 578 * supported. 579 */ init(int keysize, SecureRandom random)580 public final void init(int keysize, SecureRandom random) { 581 if (serviceIterator == null) { 582 spi.engineInit(keysize, random); 583 return; 584 } 585 RuntimeException failure = null; 586 KeyGeneratorSpi mySpi = spi; 587 do { 588 try { 589 mySpi.engineInit(keysize, random); 590 initType = I_SIZE; 591 initKeySize = keysize; 592 initParams = null; 593 initRandom = random; 594 return; 595 } catch (RuntimeException e) { 596 if (failure == null) { 597 failure = e; 598 } 599 mySpi = nextSpi(mySpi, false); 600 } 601 } while (mySpi != null); 602 throw failure; 603 } 604 605 /** 606 * Generates a secret key. 607 * 608 * @return the new key 609 */ generateKey()610 public final SecretKey generateKey() { 611 if (serviceIterator == null) { 612 return spi.engineGenerateKey(); 613 } 614 RuntimeException failure = null; 615 KeyGeneratorSpi mySpi = spi; 616 do { 617 try { 618 return mySpi.engineGenerateKey(); 619 } catch (RuntimeException e) { 620 if (failure == null) { 621 failure = e; 622 } 623 mySpi = nextSpi(mySpi, true); 624 } 625 } while (mySpi != null); 626 throw failure; 627 } 628 } 629