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