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