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