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.util.*; 32 import java.security.Provider.Service; 33 import java.security.spec.KeySpec; 34 import java.security.spec.InvalidKeySpecException; 35 import java.security.spec.RSAPrivateKeySpec; 36 37 import sun.security.util.Debug; 38 import sun.security.jca.*; 39 import sun.security.jca.GetInstance.Instance; 40 41 /** 42 * Key factories are used to convert <I>keys</I> (opaque 43 * cryptographic keys of type {@code Key}) into <I>key specifications</I> 44 * (transparent representations of the underlying key material), and vice 45 * versa. 46 * 47 * <P> Key factories are bi-directional. That is, they allow you to build an 48 * opaque key object from a given key specification (key material), or to 49 * retrieve the underlying key material of a key object in a suitable format. 50 * 51 * <P> Multiple compatible key specifications may exist for the same key. 52 * For example, a DSA public key may be specified using 53 * {@code DSAPublicKeySpec} or 54 * {@code X509EncodedKeySpec}. A key factory can be used to translate 55 * between compatible key specifications. 56 * 57 * <P> The following is an example of how to use a key factory in order to 58 * instantiate a DSA public key from its encoding. 59 * Assume Alice has received a digital signature from Bob. 60 * Bob also sent her his public key (in encoded format) to verify 61 * his signature. Alice then performs the following actions: 62 * 63 * <pre> 64 * X509EncodedKeySpec bobPubKeySpec = new X509EncodedKeySpec(bobEncodedPubKey); 65 * KeyFactory keyFactory = KeyFactory.getInstance("DSA"); 66 * PublicKey bobPubKey = keyFactory.generatePublic(bobPubKeySpec); 67 * Signature sig = Signature.getInstance("DSA"); 68 * sig.initVerify(bobPubKey); 69 * sig.update(data); 70 * sig.verify(signature); 71 * </pre> 72 * 73 * <p> Android provides the following <code>KeyFactory</code> algorithms: 74 * <table> 75 * <thead> 76 * <tr> 77 * <th>Algorithm</th> 78 * <th>Supported API Levels</th> 79 * </tr> 80 * </thead> 81 * <tbody> 82 * <tr> 83 * <td>DH</td> 84 * <td>1+</td> 85 * </tr> 86 * <tr> 87 * <td>DSA</td> 88 * <td>1+</td> 89 * </tr> 90 * <tr> 91 * <td>EC</td> 92 * <td>11+</td> 93 * </tr> 94 * <tr> 95 * <td>RSA</td> 96 * <td>1+</td> 97 * </tr> 98 * <tr class="deprecated"> 99 * <td>X.509</td> 100 * <td>1-8</td> 101 * </tr> 102 * <tr> 103 * <td>XDH</td> 104 * <td>33+</td> 105 * </tr> 106 * </tbody> 107 * </table> 108 * 109 * @author Jan Luehe 110 * 111 * @see Key 112 * @see PublicKey 113 * @see PrivateKey 114 * @see java.security.spec.KeySpec 115 * @see java.security.spec.DSAPublicKeySpec 116 * @see java.security.spec.X509EncodedKeySpec 117 * 118 * @since 1.2 119 */ 120 121 public class KeyFactory { 122 123 private static final Debug debug = 124 Debug.getInstance("jca", "KeyFactory"); 125 126 // The algorithm associated with this key factory 127 private final String algorithm; 128 129 // The provider 130 private Provider provider; 131 132 // The provider implementation (delegate) 133 private volatile KeyFactorySpi spi; 134 135 // lock for mutex during provider selection 136 private final Object lock = new Object(); 137 138 // remaining services to try in provider selection 139 // null once provider is selected 140 private Iterator<Service> serviceIterator; 141 142 /** 143 * Creates a KeyFactory object. 144 * 145 * @param keyFacSpi the delegate 146 * @param provider the provider 147 * @param algorithm the name of the algorithm 148 * to associate with this {@code KeyFactory} 149 */ KeyFactory(KeyFactorySpi keyFacSpi, Provider provider, String algorithm)150 protected KeyFactory(KeyFactorySpi keyFacSpi, Provider provider, 151 String algorithm) { 152 this.spi = keyFacSpi; 153 this.provider = provider; 154 this.algorithm = algorithm; 155 } 156 KeyFactory(String algorithm)157 private KeyFactory(String algorithm) throws NoSuchAlgorithmException { 158 this.algorithm = algorithm; 159 List<Service> list = GetInstance.getServices("KeyFactory", algorithm); 160 serviceIterator = list.iterator(); 161 // fetch and instantiate initial spi 162 if (nextSpi(null) == null) { 163 throw new NoSuchAlgorithmException 164 (algorithm + " KeyFactory not available"); 165 } 166 } 167 168 /** 169 * Returns a KeyFactory object that converts 170 * public/private keys of the specified algorithm. 171 * 172 * <p> This method traverses the list of registered security Providers, 173 * starting with the most preferred Provider. 174 * A new KeyFactory object encapsulating the 175 * KeyFactorySpi implementation from the first 176 * Provider that supports the specified algorithm is returned. 177 * 178 * <p> Note that the list of registered providers may be retrieved via 179 * the {@link Security#getProviders() Security.getProviders()} method. 180 * 181 * @param algorithm the name of the requested key algorithm. 182 * 183 * @return the new {@code KeyFactory} object 184 * 185 * @throws NoSuchAlgorithmException if no {@code Provider} supports a 186 * {@code KeyFactorySpi} implementation for the 187 * specified algorithm 188 * 189 * @throws NullPointerException if {@code algorithm} is {@code null} on Android 14 or above 190 * 191 * @see Provider 192 */ getInstance(String algorithm)193 public static KeyFactory getInstance(String algorithm) 194 throws NoSuchAlgorithmException { 195 // Android-changed: To be compat with the older Android, don't throw NPE on Android 13-. 196 // Objects.requireNonNull(algorithm, "null algorithm name"); 197 if (VMRuntime.getSdkVersion() >= VersionCodes.UPSIDE_DOWN_CAKE) { 198 Objects.requireNonNull(algorithm, "null algorithm name"); 199 } 200 return new KeyFactory(algorithm); 201 } 202 203 /** 204 * Returns a KeyFactory object that converts 205 * public/private keys of the specified algorithm. 206 * 207 * <p> A new KeyFactory object encapsulating the 208 * KeyFactorySpi implementation from the specified provider 209 * is returned. The specified provider must be registered 210 * in the security provider list. 211 * 212 * <p> Note that the list of registered providers may be retrieved via 213 * the {@link Security#getProviders() Security.getProviders()} method. 214 * 215 * @param algorithm the name of the requested key algorithm. 216 * 217 * @param provider the name of the provider. 218 * 219 * @return the new {@code KeyFactory} object 220 * 221 * @throws IllegalArgumentException if the provider name is {@code null} 222 * or empty 223 * 224 * @throws NoSuchAlgorithmException if a {@code KeyFactorySpi} 225 * implementation for the specified algorithm is not 226 * available from the specified provider 227 * 228 * @throws NoSuchProviderException if the specified provider is not 229 * registered in the security provider list 230 * 231 * @throws NullPointerException if {@code algorithm} is {@code null} on Android 14 or above 232 * 233 * @see Provider 234 */ getInstance(String algorithm, String provider)235 public static KeyFactory getInstance(String algorithm, String provider) 236 throws NoSuchAlgorithmException, NoSuchProviderException { 237 // Android-changed: To be compat with the older Android, don't throw NPE on Android 13-. 238 // Objects.requireNonNull(algorithm, "null algorithm name"); 239 if (VMRuntime.getSdkVersion() >= VersionCodes.UPSIDE_DOWN_CAKE) { 240 Objects.requireNonNull(algorithm, "null algorithm name"); 241 } 242 // Android-added: Check for Bouncy Castle deprecation 243 Providers.checkBouncyCastleDeprecation(provider, "KeyFactory", algorithm); 244 Instance instance = GetInstance.getInstance("KeyFactory", 245 KeyFactorySpi.class, algorithm, provider); 246 return new KeyFactory((KeyFactorySpi)instance.impl, 247 instance.provider, algorithm); 248 } 249 250 /** 251 * Returns a KeyFactory object that converts 252 * public/private keys of the specified algorithm. 253 * 254 * <p> A new KeyFactory object encapsulating the 255 * KeyFactorySpi implementation from the specified Provider 256 * object is returned. Note that the specified Provider object 257 * does not have to be registered in the provider list. 258 * 259 * @param algorithm the name of the requested key algorithm. 260 * 261 * @param provider the provider. 262 * 263 * @return the new {@code KeyFactory} object 264 * 265 * @throws IllegalArgumentException if the specified provider is 266 * {@code null} 267 * 268 * @throws NoSuchAlgorithmException if a {@code KeyFactorySpi} 269 * implementation for the specified algorithm is not available 270 * from the specified {@code Provider} object 271 * 272 * @throws NullPointerException if {@code algorithm} is {@code null} on Android 14 or above 273 * 274 * @see Provider 275 * 276 * @since 1.4 277 */ getInstance(String algorithm, Provider provider)278 public static KeyFactory getInstance(String algorithm, Provider provider) 279 throws NoSuchAlgorithmException { 280 // Android-changed: To be compat with the older Android, don't throw NPE on Android 13-. 281 // Objects.requireNonNull(algorithm, "null algorithm name"); 282 if (VMRuntime.getSdkVersion() >= VersionCodes.UPSIDE_DOWN_CAKE) { 283 Objects.requireNonNull(algorithm, "null algorithm name"); 284 } 285 // Android-added: Check for Bouncy Castle deprecation 286 Providers.checkBouncyCastleDeprecation(provider, "KeyFactory", algorithm); 287 Instance instance = GetInstance.getInstance("KeyFactory", 288 KeyFactorySpi.class, algorithm, provider); 289 return new KeyFactory((KeyFactorySpi)instance.impl, 290 instance.provider, algorithm); 291 } 292 293 /** 294 * Returns the provider of this key factory object. 295 * 296 * @return the provider of this key factory object 297 */ getProvider()298 public final Provider getProvider() { 299 synchronized (lock) { 300 // disable further failover after this call 301 serviceIterator = null; 302 return provider; 303 } 304 } 305 306 /** 307 * Gets the name of the algorithm 308 * associated with this {@code KeyFactory}. 309 * 310 * @return the name of the algorithm associated with this 311 * {@code KeyFactory} 312 */ getAlgorithm()313 public final String getAlgorithm() { 314 return this.algorithm; 315 } 316 317 /** 318 * Update the active KeyFactorySpi of this class and return the next 319 * implementation for failover. If no more implemenations are 320 * available, this method returns null. However, the active spi of 321 * this class is never set to null. 322 */ nextSpi(KeyFactorySpi oldSpi)323 private KeyFactorySpi nextSpi(KeyFactorySpi oldSpi) { 324 synchronized (lock) { 325 // somebody else did a failover concurrently 326 // try that spi now 327 if ((oldSpi != null) && (oldSpi != spi)) { 328 return spi; 329 } 330 if (serviceIterator == null) { 331 return null; 332 } 333 while (serviceIterator.hasNext()) { 334 Service s = serviceIterator.next(); 335 try { 336 Object obj = s.newInstance(null); 337 if (obj instanceof KeyFactorySpi == false) { 338 continue; 339 } 340 KeyFactorySpi spi = (KeyFactorySpi)obj; 341 provider = s.getProvider(); 342 this.spi = spi; 343 return spi; 344 } catch (NoSuchAlgorithmException e) { 345 // ignore 346 } 347 } 348 serviceIterator = null; 349 return null; 350 } 351 } 352 353 /** 354 * Generates a public key object from the provided key specification 355 * (key material). 356 * 357 * @param keySpec the specification (key material) of the public key. 358 * 359 * @return the public key. 360 * 361 * @exception InvalidKeySpecException if the given key specification 362 * is inappropriate for this key factory to produce a public key. 363 */ generatePublic(KeySpec keySpec)364 public final PublicKey generatePublic(KeySpec keySpec) 365 throws InvalidKeySpecException { 366 if (serviceIterator == null) { 367 return spi.engineGeneratePublic(keySpec); 368 } 369 Exception failure = null; 370 KeyFactorySpi mySpi = spi; 371 do { 372 try { 373 return mySpi.engineGeneratePublic(keySpec); 374 } catch (Exception e) { 375 if (failure == null) { 376 failure = e; 377 } 378 mySpi = nextSpi(mySpi); 379 } 380 } while (mySpi != null); 381 if (failure instanceof RuntimeException) { 382 throw (RuntimeException)failure; 383 } 384 if (failure instanceof InvalidKeySpecException) { 385 throw (InvalidKeySpecException)failure; 386 } 387 throw new InvalidKeySpecException 388 ("Could not generate public key", failure); 389 } 390 391 /** 392 * Generates a private key object from the provided key specification 393 * (key material). 394 * 395 * @param keySpec the specification (key material) of the private key. 396 * 397 * @return the private key. 398 * 399 * @exception InvalidKeySpecException if the given key specification 400 * is inappropriate for this key factory to produce a private key. 401 */ generatePrivate(KeySpec keySpec)402 public final PrivateKey generatePrivate(KeySpec keySpec) 403 throws InvalidKeySpecException { 404 if (serviceIterator == null) { 405 return spi.engineGeneratePrivate(keySpec); 406 } 407 Exception failure = null; 408 KeyFactorySpi mySpi = spi; 409 do { 410 try { 411 return mySpi.engineGeneratePrivate(keySpec); 412 } catch (Exception e) { 413 if (failure == null) { 414 failure = e; 415 } 416 mySpi = nextSpi(mySpi); 417 } 418 } while (mySpi != null); 419 if (failure instanceof RuntimeException) { 420 throw (RuntimeException)failure; 421 } 422 if (failure instanceof InvalidKeySpecException) { 423 throw (InvalidKeySpecException)failure; 424 } 425 throw new InvalidKeySpecException 426 ("Could not generate private key", failure); 427 } 428 429 /** 430 * Returns a specification (key material) of the given key object. 431 * {@code keySpec} identifies the specification class in which 432 * the key material should be returned. It could, for example, be 433 * {@code DSAPublicKeySpec.class}, to indicate that the 434 * key material should be returned in an instance of the 435 * {@code DSAPublicKeySpec} class. 436 * 437 * @param <T> the type of the key specification to be returned 438 * 439 * @param key the key. 440 * 441 * @param keySpec the specification class in which 442 * the key material should be returned. 443 * 444 * @return the underlying key specification (key material) in an instance 445 * of the requested specification class. 446 * 447 * @exception InvalidKeySpecException if the requested key specification is 448 * inappropriate for the given key, or the given key cannot be processed 449 * (e.g., the given key has an unrecognized algorithm or format). 450 */ getKeySpec(Key key, Class<T> keySpec)451 public final <T extends KeySpec> T getKeySpec(Key key, Class<T> keySpec) 452 throws InvalidKeySpecException { 453 if (serviceIterator == null) { 454 return spi.engineGetKeySpec(key, keySpec); 455 } 456 Exception failure = null; 457 KeyFactorySpi mySpi = spi; 458 do { 459 try { 460 return mySpi.engineGetKeySpec(key, keySpec); 461 } catch (Exception e) { 462 if (failure == null) { 463 failure = e; 464 } 465 mySpi = nextSpi(mySpi); 466 } 467 } while (mySpi != null); 468 if (failure instanceof RuntimeException) { 469 throw (RuntimeException)failure; 470 } 471 if (failure instanceof InvalidKeySpecException) { 472 throw (InvalidKeySpecException)failure; 473 } 474 throw new InvalidKeySpecException 475 ("Could not get key spec", failure); 476 } 477 478 /** 479 * Translates a key object, whose provider may be unknown or potentially 480 * untrusted, into a corresponding key object of this key factory. 481 * 482 * @param key the key whose provider is unknown or untrusted. 483 * 484 * @return the translated key. 485 * 486 * @exception InvalidKeyException if the given key cannot be processed 487 * by this key factory. 488 */ translateKey(Key key)489 public final Key translateKey(Key key) throws InvalidKeyException { 490 if (serviceIterator == null) { 491 return spi.engineTranslateKey(key); 492 } 493 Exception failure = null; 494 KeyFactorySpi mySpi = spi; 495 do { 496 try { 497 return mySpi.engineTranslateKey(key); 498 } catch (Exception e) { 499 if (failure == null) { 500 failure = e; 501 } 502 mySpi = nextSpi(mySpi); 503 } 504 } while (mySpi != null); 505 if (failure instanceof RuntimeException) { 506 throw (RuntimeException)failure; 507 } 508 if (failure instanceof InvalidKeyException) { 509 throw (InvalidKeyException)failure; 510 } 511 throw new InvalidKeyException 512 ("Could not translate key", failure); 513 } 514 515 } 516