1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. Oracle designates this 9 * particular file as subject to the "Classpath" exception as provided 10 * by Oracle in the LICENSE file that accompanied this code. 11 * 12 * This code is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 * version 2 for more details (a copy is included in the LICENSE file that 16 * accompanied this code). 17 * 18 * You should have received a copy of the GNU General Public License version 19 * 2 along with this work; if not, write to the Free Software Foundation, 20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21 * 22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 23 * or visit www.oracle.com if you need additional information or have any 24 * questions. 25 */ 26 27 package sun.security.jca; 28 29 import dalvik.system.VMRuntime; 30 import java.security.NoSuchAlgorithmException; 31 import java.security.Provider; 32 import java.util.Arrays; 33 import java.util.HashSet; 34 import java.util.Locale; 35 import java.util.Set; 36 37 /** 38 * Collection of methods to get and set provider list. Also includes 39 * special code for the provider list during JAR verification. 40 * 41 * @author Andreas Sterbenz 42 * @since 1.5 43 */ 44 public class Providers { 45 46 private static final ThreadLocal<ProviderList> threadLists = 47 new InheritableThreadLocal<>(); 48 49 // number of threads currently using thread-local provider lists 50 // tracked to allow an optimization if == 0 51 private static volatile int threadListsUsed; 52 53 // current system-wide provider list 54 // Note volatile immutable object, so no synchronization needed. 55 private static volatile ProviderList providerList; 56 57 // Android-added: Keep reference to system-created Bouncy Castle provider 58 // See comments near deprecation methods at the bottom of this file. 59 private static volatile Provider SYSTEM_BOUNCY_CASTLE_PROVIDER; 60 61 static { 62 // set providerList to empty list first in case initialization somehow 63 // triggers a getInstance() call (although that should not happen) 64 providerList = ProviderList.EMPTY; 65 providerList = ProviderList.fromSecurityProperties(); 66 67 // BEGIN Android-added: Initialize all providers and assert that this succeeds. 68 // removeInvalid is specified to try initializing all configured providers 69 // and removing those that aren't instantiable. This has the side effect 70 // of eagerly initializing all providers. 71 final int numConfiguredProviders = providerList.size(); 72 providerList = providerList.removeInvalid(); 73 if (numConfiguredProviders != providerList.size()) { 74 throw new AssertionError("Unable to configure default providers"); 75 } 76 // END Android-added: Initialize all providers and assert that this succeeds. 77 // Android-added: Set BC provider instance 78 SYSTEM_BOUNCY_CASTLE_PROVIDER = providerList.getProvider("BC"); 79 } 80 81 private Providers() { 82 // empty 83 } 84 85 // we need special handling to resolve circularities when loading 86 // signed JAR files during startup. The code below is part of that. 87 88 // Basically, before we load data from a signed JAR file, we parse 89 // the PKCS#7 file and verify the signature. We need a 90 // CertificateFactory, Signatures, etc. to do that. We have to make 91 // sure that we do not try to load the implementation from the JAR 92 // file we are just verifying. 93 // 94 // To avoid that, we use different provider settings during JAR 95 // verification. However, we do not want those provider settings to 96 // interfere with other parts of the system. Therefore, we make them local 97 // to the Thread executing the JAR verification code. 98 // 99 // The code here is used by sun.security.util.SignatureFileVerifier. 100 // See there for details. 101 102 private static final String BACKUP_PROVIDER_CLASSNAME = 103 "sun.security.provider.VerificationProvider"; 104 105 // Hardcoded classnames of providers to use for JAR verification. 106 // MUST NOT be on the bootclasspath and not in signed JAR files. 107 private static final String[] jarVerificationProviders = { 108 // BEGIN Android-changed: Use Conscrypt and BC, not the sun.security providers. 109 /* 110 "sun.security.provider.Sun", 111 "sun.security.rsa.SunRsaSign", 112 // Note: SunEC *is* in a signed JAR file, but it's not signed 113 // by EC itself. So it's still safe to be listed here. 114 "sun.security.ec.SunEC", 115 */ 116 "com.android.org.conscrypt.OpenSSLProvider", 117 "com.android.org.bouncycastle.jce.provider.BouncyCastleProvider", 118 "com.android.org.conscrypt.JSSEProvider", 119 // END Android-changed: Use Conscrypt and BC, not the sun.security providers. 120 BACKUP_PROVIDER_CLASSNAME, 121 }; 122 123 // Return to Sun provider or its backup. 124 // This method should only be called by 125 // sun.security.util.ManifestEntryVerifier and java.security.SecureRandom. 126 public static Provider getSunProvider() { 127 try { 128 Class<?> clazz = Class.forName(jarVerificationProviders[0]); 129 return (Provider)clazz.newInstance(); 130 } catch (Exception e) { 131 try { 132 Class<?> clazz = Class.forName(BACKUP_PROVIDER_CLASSNAME); 133 return (Provider)clazz.newInstance(); 134 } catch (Exception ee) { 135 throw new RuntimeException("Sun provider not found", e); 136 } 137 } 138 } 139 140 /** 141 * Start JAR verification. This sets a special provider list for 142 * the current thread. You MUST save the return value from this 143 * method and you MUST call stopJarVerification() with that object 144 * once you are done. 145 */ 146 public static Object startJarVerification() { 147 ProviderList currentList = getProviderList(); 148 ProviderList jarList = currentList.getJarList(jarVerificationProviders); 149 // return the old thread-local provider list, usually null 150 return beginThreadProviderList(jarList); 151 } 152 153 /** 154 * Stop JAR verification. Call once you have completed JAR verification. 155 */ 156 public static void stopJarVerification(Object obj) { 157 // restore old thread-local provider list 158 endThreadProviderList((ProviderList)obj); 159 } 160 161 /** 162 * Return the current ProviderList. If the thread-local list is set, 163 * it is returned. Otherwise, the system wide list is returned. 164 */ 165 public static ProviderList getProviderList() { 166 ProviderList list = getThreadProviderList(); 167 if (list == null) { 168 list = getSystemProviderList(); 169 } 170 return list; 171 } 172 173 /** 174 * Set the current ProviderList. Affects the thread-local list if set, 175 * otherwise the system wide list. 176 */ 177 public static void setProviderList(ProviderList newList) { 178 if (getThreadProviderList() == null) { 179 setSystemProviderList(newList); 180 } else { 181 changeThreadProviderList(newList); 182 } 183 } 184 185 /** 186 * Get the full provider list with invalid providers (those that 187 * could not be loaded) removed. This is the list we need to 188 * present to applications. 189 */ 190 public static ProviderList getFullProviderList() { 191 ProviderList list; 192 synchronized (Providers.class) { 193 list = getThreadProviderList(); 194 if (list != null) { 195 ProviderList newList = list.removeInvalid(); 196 if (newList != list) { 197 changeThreadProviderList(newList); 198 list = newList; 199 } 200 return list; 201 } 202 } 203 list = getSystemProviderList(); 204 ProviderList newList = list.removeInvalid(); 205 if (newList != list) { 206 setSystemProviderList(newList); 207 list = newList; 208 } 209 return list; 210 } 211 212 private static ProviderList getSystemProviderList() { 213 return providerList; 214 } 215 216 private static void setSystemProviderList(ProviderList list) { 217 providerList = list; 218 } 219 220 public static ProviderList getThreadProviderList() { 221 // avoid accessing the threadlocal if none are currently in use 222 // (first use of ThreadLocal.get() for a Thread allocates a Map) 223 if (threadListsUsed == 0) { 224 return null; 225 } 226 return threadLists.get(); 227 } 228 229 // Change the thread local provider list. Use only if the current thread 230 // is already using a thread local list and you want to change it in place. 231 // In other cases, use the begin/endThreadProviderList() methods. 232 private static void changeThreadProviderList(ProviderList list) { 233 threadLists.set(list); 234 } 235 236 /** 237 * Methods to manipulate the thread local provider list. It is for use by 238 * JAR verification (see above) and the SunJSSE FIPS mode only. 239 * 240 * It should be used as follows: 241 * 242 * ProviderList list = ...; 243 * ProviderList oldList = Providers.beginThreadProviderList(list); 244 * try { 245 * // code that needs thread local provider list 246 * } finally { 247 * Providers.endThreadProviderList(oldList); 248 * } 249 * 250 */ 251 252 public static synchronized ProviderList beginThreadProviderList(ProviderList list) { 253 if (ProviderList.debug != null) { 254 ProviderList.debug.println("ThreadLocal providers: " + list); 255 } 256 ProviderList oldList = threadLists.get(); 257 threadListsUsed++; 258 threadLists.set(list); 259 return oldList; 260 } 261 262 public static synchronized void endThreadProviderList(ProviderList list) { 263 if (list == null) { 264 if (ProviderList.debug != null) { 265 ProviderList.debug.println("Disabling ThreadLocal providers"); 266 } 267 threadLists.remove(); 268 } else { 269 if (ProviderList.debug != null) { 270 ProviderList.debug.println 271 ("Restoring previous ThreadLocal providers: " + list); 272 } 273 threadLists.set(list); 274 } 275 threadListsUsed--; 276 } 277 278 // BEGIN Android-added: Check for requests of deprecated Bouncy Castle algorithms. 279 // Beginning in Android P, Bouncy Castle versions of algorithms available through 280 // Conscrypt are deprecated. We will no longer supply them to applications 281 // with a target API level of P or later, and will print a warning for applications 282 // with a target API level before P. 283 // 284 // We only care about the system-provided Bouncy Castle provider; applications are allowed to 285 // install their own copy of Bouncy Castle if they want to continue using those implementations. 286 287 /** 288 * Maximum target API level for which we will provide the deprecated Bouncy Castle algorithms. 289 * 290 * Only exists for testing and shouldn't be changed. 291 * 292 * @hide 293 */ 294 public static final int DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION = 27; 295 296 private static int maximumAllowableApiLevelForBcDeprecation = 297 DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION; 298 299 /** 300 * Sets the target API level for BC deprecation, only for use in tests. 301 * 302 * @hide 303 */ 304 public static void setMaximumAllowableApiLevelForBcDeprecation(int targetApiLevel) { 305 maximumAllowableApiLevelForBcDeprecation = targetApiLevel; 306 } 307 308 /** 309 * Returns the target API level for BC deprecation, only for use in tests. 310 * 311 * @hide 312 */ 313 public static int getMaximumAllowableApiLevelForBcDeprecation() { 314 return maximumAllowableApiLevelForBcDeprecation; 315 } 316 317 /** 318 * Checks if the installed provider with the given name is the system-installed Bouncy 319 * Castle provider. If so, throws {@code NoSuchAlgorithmException} if the algorithm 320 * being requested is deprecated and the application targets a late-enough API level. 321 * 322 * @hide 323 */ 324 public static synchronized void checkBouncyCastleDeprecation(String provider, 325 String service, String algorithm) throws NoSuchAlgorithmException { 326 // Applications may install their own BC provider, only the algorithms from the system 327 // provider are deprecated. 328 if ("BC".equals(provider) 329 && providerList.getProvider(provider) == SYSTEM_BOUNCY_CASTLE_PROVIDER) { 330 checkBouncyCastleDeprecation(service, algorithm); 331 } 332 } 333 334 /** 335 * Checks if the given provider is the system-installed Bouncy Castle provider. If so, 336 * throws {@code NoSuchAlgorithmException} if the algorithm being requested is deprecated 337 * and the application targets a late-enough API level. 338 * 339 * @hide 340 */ 341 public static synchronized void checkBouncyCastleDeprecation(Provider provider, 342 String service, String algorithm) throws NoSuchAlgorithmException { 343 // Applications may install their own BC provider, only the algorithms from the system 344 // provider are deprecated. 345 if (provider == SYSTEM_BOUNCY_CASTLE_PROVIDER) { 346 checkBouncyCastleDeprecation(service, algorithm); 347 } 348 } 349 350 // The set of algorithms that are deprecated. This list is created using 351 // libcore/tools/crypto/src/java/libcore/java/security/ProviderOverlap.java, with 352 // additional Ciphers added manually (see comment below). 353 private static final Set<String> DEPRECATED_ALGORITHMS = new HashSet<String>(); 354 static { 355 DEPRECATED_ALGORITHMS.addAll(Arrays.asList( 356 "ALGORITHMPARAMETERS.1.2.840.113549.3.7", 357 "ALGORITHMPARAMETERS.2.16.840.1.101.3.4.1.2", 358 "ALGORITHMPARAMETERS.2.16.840.1.101.3.4.1.22", 359 "ALGORITHMPARAMETERS.2.16.840.1.101.3.4.1.26", 360 "ALGORITHMPARAMETERS.2.16.840.1.101.3.4.1.42", 361 "ALGORITHMPARAMETERS.2.16.840.1.101.3.4.1.46", 362 "ALGORITHMPARAMETERS.2.16.840.1.101.3.4.1.6", 363 "ALGORITHMPARAMETERS.AES", 364 "ALGORITHMPARAMETERS.DESEDE", 365 "ALGORITHMPARAMETERS.EC", 366 "ALGORITHMPARAMETERS.GCM", 367 "ALGORITHMPARAMETERS.OAEP", 368 "ALGORITHMPARAMETERS.TDEA", 369 "CERTIFICATEFACTORY.X.509", 370 "CERTIFICATEFACTORY.X509", 371 // List of Ciphers produced by ProviderOverlap: 372 "CIPHER.1.2.840.113549.3.4", 373 "CIPHER.2.16.840.1.101.3.4.1.26", 374 "CIPHER.2.16.840.1.101.3.4.1.46", 375 "CIPHER.2.16.840.1.101.3.4.1.6", 376 "CIPHER.AES/GCM/NOPADDING", 377 "CIPHER.ARC4", 378 "CIPHER.ARCFOUR", 379 "CIPHER.OID.1.2.840.113549.3.4", 380 "CIPHER.RC4", 381 // End of Ciphers produced by ProviderOverlap 382 // Additional ciphers transformations that will resolve to the same things as 383 // the automatically-produced overlap due to the Cipher transformation rules. 384 // These have been added manually. 385 "CIPHER.ARC4/ECB/NOPADDING", 386 "CIPHER.ARC4/NONE/NOPADDING", 387 "CIPHER.ARCFOUR/ECB/NOPADDING", 388 "CIPHER.ARCFOUR/NONE/NOPADDING", 389 "CIPHER.RC4/ECB/NOPADDING", 390 "CIPHER.RC4/NONE/NOPADDING", 391 // End of additional Ciphers 392 "KEYAGREEMENT.ECDH", 393 "KEYFACTORY.1.2.840.10045.2.1", 394 "KEYFACTORY.1.2.840.113549.1.1.1", 395 "KEYFACTORY.1.2.840.113549.1.1.7", 396 "KEYFACTORY.1.3.133.16.840.63.0.2", 397 "KEYFACTORY.2.5.8.1.1", 398 "KEYFACTORY.EC", 399 "KEYFACTORY.RSA", 400 "KEYGENERATOR.1.2.840.113549.2.10", 401 "KEYGENERATOR.1.2.840.113549.2.11", 402 "KEYGENERATOR.1.2.840.113549.2.7", 403 "KEYGENERATOR.1.2.840.113549.2.8", 404 "KEYGENERATOR.1.2.840.113549.2.9", 405 "KEYGENERATOR.1.3.6.1.5.5.8.1.1", 406 "KEYGENERATOR.1.3.6.1.5.5.8.1.2", 407 "KEYGENERATOR.2.16.840.1.101.3.4.2.1", 408 "KEYGENERATOR.AES", 409 "KEYGENERATOR.DESEDE", 410 "KEYGENERATOR.HMAC-MD5", 411 "KEYGENERATOR.HMAC-SHA1", 412 "KEYGENERATOR.HMAC-SHA224", 413 "KEYGENERATOR.HMAC-SHA256", 414 "KEYGENERATOR.HMAC-SHA384", 415 "KEYGENERATOR.HMAC-SHA512", 416 "KEYGENERATOR.HMAC/MD5", 417 "KEYGENERATOR.HMAC/SHA1", 418 "KEYGENERATOR.HMAC/SHA224", 419 "KEYGENERATOR.HMAC/SHA256", 420 "KEYGENERATOR.HMAC/SHA384", 421 "KEYGENERATOR.HMAC/SHA512", 422 "KEYGENERATOR.HMACMD5", 423 "KEYGENERATOR.HMACSHA1", 424 "KEYGENERATOR.HMACSHA224", 425 "KEYGENERATOR.HMACSHA256", 426 "KEYGENERATOR.HMACSHA384", 427 "KEYGENERATOR.HMACSHA512", 428 "KEYGENERATOR.TDEA", 429 "KEYPAIRGENERATOR.1.2.840.10045.2.1", 430 "KEYPAIRGENERATOR.1.2.840.113549.1.1.1", 431 "KEYPAIRGENERATOR.1.2.840.113549.1.1.7", 432 "KEYPAIRGENERATOR.1.3.133.16.840.63.0.2", 433 "KEYPAIRGENERATOR.2.5.8.1.1", 434 "KEYPAIRGENERATOR.EC", 435 "KEYPAIRGENERATOR.RSA", 436 "MAC.1.2.840.113549.2.10", 437 "MAC.1.2.840.113549.2.11", 438 "MAC.1.2.840.113549.2.7", 439 "MAC.1.2.840.113549.2.8", 440 "MAC.1.2.840.113549.2.9", 441 "MAC.1.3.6.1.5.5.8.1.1", 442 "MAC.1.3.6.1.5.5.8.1.2", 443 "MAC.2.16.840.1.101.3.4.2.1", 444 "MAC.HMAC-MD5", 445 "MAC.HMAC-SHA1", 446 "MAC.HMAC-SHA224", 447 "MAC.HMAC-SHA256", 448 "MAC.HMAC-SHA384", 449 "MAC.HMAC-SHA512", 450 "MAC.HMAC/MD5", 451 "MAC.HMAC/SHA1", 452 "MAC.HMAC/SHA224", 453 "MAC.HMAC/SHA256", 454 "MAC.HMAC/SHA384", 455 "MAC.HMAC/SHA512", 456 "MAC.HMACMD5", 457 "MAC.HMACSHA1", 458 "MAC.HMACSHA224", 459 "MAC.HMACSHA256", 460 "MAC.HMACSHA384", 461 "MAC.HMACSHA512", 462 "MAC.PBEWITHHMACSHA224", 463 "MAC.PBEWITHHMACSHA256", 464 "MAC.PBEWITHHMACSHA384", 465 "MAC.PBEWITHHMACSHA512", 466 "MESSAGEDIGEST.1.2.840.113549.2.5", 467 "MESSAGEDIGEST.1.3.14.3.2.26", 468 "MESSAGEDIGEST.2.16.840.1.101.3.4.2.1", 469 "MESSAGEDIGEST.2.16.840.1.101.3.4.2.2", 470 "MESSAGEDIGEST.2.16.840.1.101.3.4.2.3", 471 "MESSAGEDIGEST.2.16.840.1.101.3.4.2.4", 472 "MESSAGEDIGEST.MD5", 473 "MESSAGEDIGEST.SHA", 474 "MESSAGEDIGEST.SHA-1", 475 "MESSAGEDIGEST.SHA-224", 476 "MESSAGEDIGEST.SHA-256", 477 "MESSAGEDIGEST.SHA-384", 478 "MESSAGEDIGEST.SHA-512", 479 "MESSAGEDIGEST.SHA1", 480 "MESSAGEDIGEST.SHA224", 481 "MESSAGEDIGEST.SHA256", 482 "MESSAGEDIGEST.SHA384", 483 "MESSAGEDIGEST.SHA512", 484 "SECRETKEYFACTORY.DESEDE", 485 "SECRETKEYFACTORY.TDEA", 486 "SIGNATURE.1.2.840.10045.4.1", 487 "SIGNATURE.1.2.840.10045.4.3.1", 488 "SIGNATURE.1.2.840.10045.4.3.2", 489 "SIGNATURE.1.2.840.10045.4.3.3", 490 "SIGNATURE.1.2.840.10045.4.3.4", 491 "SIGNATURE.1.2.840.113549.1.1.11", 492 "SIGNATURE.1.2.840.113549.1.1.12", 493 "SIGNATURE.1.2.840.113549.1.1.13", 494 "SIGNATURE.1.2.840.113549.1.1.14", 495 "SIGNATURE.1.2.840.113549.1.1.4", 496 "SIGNATURE.1.2.840.113549.1.1.5", 497 "SIGNATURE.1.3.14.3.2.29", 498 "SIGNATURE.ECDSA", 499 "SIGNATURE.ECDSAWITHSHA1", 500 "SIGNATURE.MD5/RSA", 501 "SIGNATURE.MD5WITHRSA", 502 "SIGNATURE.MD5WITHRSAENCRYPTION", 503 "SIGNATURE.NONEWITHECDSA", 504 "SIGNATURE.OID.1.2.840.10045.4.3.1", 505 "SIGNATURE.OID.1.2.840.10045.4.3.2", 506 "SIGNATURE.OID.1.2.840.10045.4.3.3", 507 "SIGNATURE.OID.1.2.840.10045.4.3.4", 508 "SIGNATURE.OID.1.2.840.113549.1.1.11", 509 "SIGNATURE.OID.1.2.840.113549.1.1.12", 510 "SIGNATURE.OID.1.2.840.113549.1.1.13", 511 "SIGNATURE.OID.1.2.840.113549.1.1.14", 512 "SIGNATURE.OID.1.2.840.113549.1.1.4", 513 "SIGNATURE.OID.1.2.840.113549.1.1.5", 514 "SIGNATURE.OID.1.3.14.3.2.29", 515 "SIGNATURE.SHA1/RSA", 516 "SIGNATURE.SHA1WITHECDSA", 517 "SIGNATURE.SHA1WITHRSA", 518 "SIGNATURE.SHA1WITHRSAENCRYPTION", 519 "SIGNATURE.SHA224/ECDSA", 520 "SIGNATURE.SHA224/RSA", 521 "SIGNATURE.SHA224WITHECDSA", 522 "SIGNATURE.SHA224WITHRSA", 523 "SIGNATURE.SHA224WITHRSAENCRYPTION", 524 "SIGNATURE.SHA256/ECDSA", 525 "SIGNATURE.SHA256/RSA", 526 "SIGNATURE.SHA256WITHECDSA", 527 "SIGNATURE.SHA256WITHRSA", 528 "SIGNATURE.SHA256WITHRSAENCRYPTION", 529 "SIGNATURE.SHA384/ECDSA", 530 "SIGNATURE.SHA384/RSA", 531 "SIGNATURE.SHA384WITHECDSA", 532 "SIGNATURE.SHA384WITHRSA", 533 "SIGNATURE.SHA384WITHRSAENCRYPTION", 534 "SIGNATURE.SHA512/ECDSA", 535 "SIGNATURE.SHA512/RSA", 536 "SIGNATURE.SHA512WITHECDSA", 537 "SIGNATURE.SHA512WITHRSA", 538 "SIGNATURE.SHA512WITHRSAENCRYPTION" 539 )); 540 } 541 542 /** 543 * Throws an exception or logs a warning if the supplied service and algorithm identify 544 * a deprecated algorithm from Bouncy Castle, depending on the application's target API level. 545 * Only called if we have already determined that the request is for the system Bouncy Castle 546 * provider. 547 */ 548 private static void checkBouncyCastleDeprecation(String service, String algorithm) 549 throws NoSuchAlgorithmException { 550 String key = service + "." + algorithm; 551 if (DEPRECATED_ALGORITHMS.contains(key.toUpperCase(Locale.US))) { 552 if (VMRuntime.getRuntime().getTargetSdkVersion() 553 <= maximumAllowableApiLevelForBcDeprecation) { 554 // This application is allowed to access these functions, only print a warning 555 System.logE(" ******** DEPRECATED FUNCTIONALITY ********"); 556 System.logE(" * The implementation of the " + key + " algorithm from"); 557 System.logE(" * the BC provider is deprecated in this version of Android."); 558 System.logE(" * It will be removed in a future version of Android and your"); 559 System.logE(" * application will no longer be able to request it. Please see"); 560 System.logE(" * https://android-developers.googleblog.com/2018/03/cryptography-changes-in-android-p.html"); 561 System.logE(" * for more details."); 562 } else { 563 throw new NoSuchAlgorithmException("The BC provider no longer provides an" 564 + " implementation for " + key + ". Please see" 565 + " https://android-developers.googleblog.com/2018/03/cryptography-changes-in-android-p.html" 566 + " for more details."); 567 } 568 } 569 } 570 571 } 572