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