1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package test.java.security.Provider; 18 19 import com.android.org.bouncycastle.jce.provider.BouncyCastleProvider; 20 21 import dalvik.system.VMRuntime; 22 23 import java.lang.reflect.Method; 24 import java.security.AlgorithmParameters; 25 import java.security.GeneralSecurityException; 26 import java.security.KeyFactory; 27 import java.security.KeyPairGenerator; 28 import java.security.MessageDigest; 29 import java.security.NoSuchAlgorithmException; 30 import java.security.Provider; 31 import java.security.Security; 32 import java.security.Signature; 33 import java.security.cert.CertificateException; 34 import java.security.cert.CertificateFactory; 35 import java.util.ArrayList; 36 import java.util.Arrays; 37 import java.util.List; 38 import java.util.HashSet; 39 import java.util.Locale; 40 import java.util.Set; 41 import javax.crypto.Cipher; 42 import javax.crypto.KeyAgreement; 43 import javax.crypto.KeyGenerator; 44 import javax.crypto.Mac; 45 import javax.crypto.SecretKeyFactory; 46 47 import sun.security.jca.Providers; 48 49 import static org.junit.Assert.assertEquals; 50 import static org.junit.Assert.assertNotNull; 51 import static org.junit.Assert.fail; 52 import org.testng.annotations.Test; 53 54 /** 55 * Tests that the deprecation of algorithms from the BC provider works as expected. Requests 56 * from an application targeting an API level before the deprecation should receive them, 57 * but those targeting an API level after the deprecation should cause an exception. Tests 58 * a representative sample of services and algorithms and various ways of naming them. 59 */ 60 public class ProvidersTest { 61 62 /** 63 * An object that can be called to call an appropriate getInstance method. Since 64 * each type of object has its own class that the method should be called on, 65 * it's either this or reflection, and this seems more straightforward. 66 */ 67 private interface Algorithm { getInstance()68 Object getInstance() throws GeneralSecurityException; 69 } 70 71 // getInstance calls that result in requests to BC 72 private static final List<Algorithm> BC_ALGORITHMS = new ArrayList<>(); 73 // getInstance calls that result in requests to Conscrypt 74 private static final List<Algorithm> CONSCRYPT_ALGORITHMS = new ArrayList<>(); 75 static { 76 // All the same algorithms as for BC, but with no provider, which should produce 77 // the Conscrypt implementation CONSCRYPT_ALGORITHMS.add(new Algorithm() { @Override public Object getInstance() throws GeneralSecurityException { return Signature.getInstance("sha224withrsa"); } })78 CONSCRYPT_ALGORITHMS.add(new Algorithm() { 79 @Override 80 public Object getInstance() throws GeneralSecurityException { 81 return Signature.getInstance("sha224withrsa"); 82 } 83 }); CONSCRYPT_ALGORITHMS.add(new Algorithm() { @Override public Object getInstance() throws GeneralSecurityException { return KeyFactory.getInstance("EC"); } })84 CONSCRYPT_ALGORITHMS.add(new Algorithm() { 85 @Override 86 public Object getInstance() throws GeneralSecurityException { 87 return KeyFactory.getInstance("EC"); 88 } 89 }); CONSCRYPT_ALGORITHMS.add(new Algorithm() { @Override public Object getInstance() throws GeneralSecurityException { return Signature.getInstance("MD5withRSAEncryption"); } })90 CONSCRYPT_ALGORITHMS.add(new Algorithm() { 91 @Override 92 public Object getInstance() throws GeneralSecurityException { 93 return Signature.getInstance("MD5withRSAEncryption"); 94 } 95 }); CONSCRYPT_ALGORITHMS.add(new Algorithm() { @Override public Object getInstance() throws GeneralSecurityException { return KeyGenerator.getInstance("HMAC-MD5"); } })96 CONSCRYPT_ALGORITHMS.add(new Algorithm() { 97 @Override 98 public Object getInstance() throws GeneralSecurityException { 99 return KeyGenerator.getInstance("HMAC-MD5"); 100 } 101 }); CONSCRYPT_ALGORITHMS.add(new Algorithm() { @Override public Object getInstance() throws GeneralSecurityException { return Mac.getInstance("Hmac/sha256"); } })102 CONSCRYPT_ALGORITHMS.add(new Algorithm() { 103 @Override 104 public Object getInstance() throws GeneralSecurityException { 105 return Mac.getInstance("Hmac/sha256"); 106 } 107 }); CONSCRYPT_ALGORITHMS.add(new Algorithm() { @Override public Object getInstance() throws GeneralSecurityException { return Signature.getInstance("SHA384/rsA"); } })108 CONSCRYPT_ALGORITHMS.add(new Algorithm() { 109 @Override 110 public Object getInstance() throws GeneralSecurityException { 111 return Signature.getInstance("SHA384/rsA"); 112 } 113 }); CONSCRYPT_ALGORITHMS.add(new Algorithm() { @Override public Object getInstance() throws GeneralSecurityException { return MessageDigest.getInstance("2.16.840.1.101.3.4.2.1"); } })114 CONSCRYPT_ALGORITHMS.add(new Algorithm() { 115 @Override 116 public Object getInstance() throws GeneralSecurityException { 117 // OID for SHA-256 118 return MessageDigest.getInstance("2.16.840.1.101.3.4.2.1"); 119 } 120 }); CONSCRYPT_ALGORITHMS.add(new Algorithm() { @Override public Object getInstance() throws GeneralSecurityException { return AlgorithmParameters.getInstance("2.16.840.1.101.3.4.1.2"); } })121 CONSCRYPT_ALGORITHMS.add(new Algorithm() { 122 @Override 123 public Object getInstance() throws GeneralSecurityException { 124 // OID for AES-128 125 return AlgorithmParameters.getInstance("2.16.840.1.101.3.4.1.2"); 126 } 127 }); 128 } 129 130 private static final Set<String> REMOVED_BC_ALGORITHMS = new HashSet<String>(); 131 static { 132 REMOVED_BC_ALGORITHMS.addAll(Arrays.asList( 133 "ALGORITHMPARAMETERS.1.2.840.113549.3.7", 134 "ALGORITHMPARAMETERS.2.16.840.1.101.3.4.1.2", 135 "ALGORITHMPARAMETERS.2.16.840.1.101.3.4.1.22", 136 "ALGORITHMPARAMETERS.2.16.840.1.101.3.4.1.26", 137 "ALGORITHMPARAMETERS.2.16.840.1.101.3.4.1.42", 138 "ALGORITHMPARAMETERS.2.16.840.1.101.3.4.1.46", 139 "ALGORITHMPARAMETERS.2.16.840.1.101.3.4.1.6", 140 "ALGORITHMPARAMETERS.AES", 141 "ALGORITHMPARAMETERS.DESEDE", 142 "ALGORITHMPARAMETERS.EC", 143 "ALGORITHMPARAMETERS.GCM", 144 "ALGORITHMPARAMETERS.OAEP", 145 "ALGORITHMPARAMETERS.TDEA", 146 "CERTIFICATEFACTORY.X.509", 147 "CERTIFICATEFACTORY.X509", 148 // List of Ciphers produced by ProviderOverlap: 149 "CIPHER.1.2.840.113549.3.4", 150 "CIPHER.2.16.840.1.101.3.4.1.26", 151 "CIPHER.2.16.840.1.101.3.4.1.46", 152 "CIPHER.2.16.840.1.101.3.4.1.6", 153 "CIPHER.AES/GCM/NOPADDING", 154 "CIPHER.ARC4", 155 "CIPHER.ARCFOUR", 156 "CIPHER.OID.1.2.840.113549.3.4", 157 "CIPHER.RC4", 158 // End of Ciphers produced by ProviderOverlap 159 // Additional ciphers transformations that will resolve to the same things as 160 // the automatically-produced overlap due to the Cipher transformation rules. 161 // These have been added manually. 162 "CIPHER.ARC4/ECB/NOPADDING", 163 "CIPHER.ARC4/NONE/NOPADDING", 164 "CIPHER.ARCFOUR/ECB/NOPADDING", 165 "CIPHER.ARCFOUR/NONE/NOPADDING", 166 "CIPHER.RC4/ECB/NOPADDING", 167 "CIPHER.RC4/NONE/NOPADDING", 168 // End of additional Ciphers 169 "KEYAGREEMENT.ECDH", 170 "KEYFACTORY.1.2.840.10045.2.1", 171 "KEYFACTORY.1.2.840.113549.1.1.1", 172 "KEYFACTORY.1.2.840.113549.1.1.7", 173 "KEYFACTORY.1.3.133.16.840.63.0.2", 174 "KEYFACTORY.2.5.8.1.1", 175 "KEYFACTORY.EC", 176 "KEYGENERATOR.1.2.840.113549.2.10", 177 "KEYGENERATOR.1.2.840.113549.2.11", 178 "KEYGENERATOR.1.2.840.113549.2.7", 179 "KEYGENERATOR.1.2.840.113549.2.8", 180 "KEYGENERATOR.1.2.840.113549.2.9", 181 "KEYGENERATOR.1.3.6.1.5.5.8.1.1", 182 "KEYGENERATOR.1.3.6.1.5.5.8.1.2", 183 "KEYGENERATOR.2.16.840.1.101.3.4.2.1", 184 "KEYGENERATOR.AES", 185 "KEYGENERATOR.DESEDE", 186 "KEYGENERATOR.HMAC-MD5", 187 "KEYGENERATOR.HMAC-SHA1", 188 "KEYGENERATOR.HMAC-SHA224", 189 "KEYGENERATOR.HMAC-SHA256", 190 "KEYGENERATOR.HMAC-SHA384", 191 "KEYGENERATOR.HMAC-SHA512", 192 "KEYGENERATOR.HMAC/MD5", 193 "KEYGENERATOR.HMAC/SHA1", 194 "KEYGENERATOR.HMAC/SHA224", 195 "KEYGENERATOR.HMAC/SHA256", 196 "KEYGENERATOR.HMAC/SHA384", 197 "KEYGENERATOR.HMAC/SHA512", 198 "KEYGENERATOR.HMACMD5", 199 "KEYGENERATOR.HMACSHA1", 200 "KEYGENERATOR.HMACSHA224", 201 "KEYGENERATOR.HMACSHA256", 202 "KEYGENERATOR.HMACSHA384", 203 "KEYGENERATOR.HMACSHA512", 204 "KEYGENERATOR.TDEA", 205 "KEYPAIRGENERATOR.1.2.840.10045.2.1", 206 "KEYPAIRGENERATOR.1.2.840.113549.1.1.1", 207 "KEYPAIRGENERATOR.1.2.840.113549.1.1.7", 208 "KEYPAIRGENERATOR.1.3.133.16.840.63.0.2", 209 "KEYPAIRGENERATOR.2.5.8.1.1", 210 "KEYPAIRGENERATOR.EC", 211 "KEYPAIRGENERATOR.RSA", 212 "MAC.1.2.840.113549.2.10", 213 "MAC.1.2.840.113549.2.11", 214 "MAC.1.2.840.113549.2.7", 215 "MAC.1.2.840.113549.2.8", 216 "MAC.1.2.840.113549.2.9", 217 "MAC.1.3.6.1.5.5.8.1.1", 218 "MAC.1.3.6.1.5.5.8.1.2", 219 "MAC.2.16.840.1.101.3.4.2.1", 220 "MAC.HMAC-MD5", 221 "MAC.HMAC-SHA1", 222 "MAC.HMAC-SHA224", 223 "MAC.HMAC-SHA256", 224 "MAC.HMAC-SHA384", 225 "MAC.HMAC-SHA512", 226 "MAC.HMAC/MD5", 227 "MAC.HMAC/SHA1", 228 "MAC.HMAC/SHA224", 229 "MAC.HMAC/SHA256", 230 "MAC.HMAC/SHA384", 231 "MAC.HMAC/SHA512", 232 "MAC.HMACMD5", 233 "MAC.HMACSHA1", 234 "MAC.HMACSHA224", 235 "MAC.HMACSHA256", 236 "MAC.HMACSHA384", 237 "MAC.HMACSHA512", 238 "MAC.PBEWITHHMACSHA224", 239 "MAC.PBEWITHHMACSHA256", 240 "MAC.PBEWITHHMACSHA384", 241 "MAC.PBEWITHHMACSHA512", 242 "MESSAGEDIGEST.1.2.840.113549.2.5", 243 "MESSAGEDIGEST.1.3.14.3.2.26", 244 "MESSAGEDIGEST.2.16.840.1.101.3.4.2.1", 245 "MESSAGEDIGEST.2.16.840.1.101.3.4.2.2", 246 "MESSAGEDIGEST.2.16.840.1.101.3.4.2.3", 247 "MESSAGEDIGEST.2.16.840.1.101.3.4.2.4", 248 "MESSAGEDIGEST.MD5", 249 "MESSAGEDIGEST.SHA", 250 "MESSAGEDIGEST.SHA-1", 251 "MESSAGEDIGEST.SHA-224", 252 "MESSAGEDIGEST.SHA-256", 253 "MESSAGEDIGEST.SHA-384", 254 "MESSAGEDIGEST.SHA-512", 255 "MESSAGEDIGEST.SHA1", 256 "MESSAGEDIGEST.SHA224", 257 "MESSAGEDIGEST.SHA256", 258 "MESSAGEDIGEST.SHA384", 259 "MESSAGEDIGEST.SHA512", 260 "SECRETKEYFACTORY.DESEDE", 261 "SECRETKEYFACTORY.TDEA", 262 "SIGNATURE.1.2.840.10045.4.1", 263 "SIGNATURE.1.2.840.10045.4.3.1", 264 "SIGNATURE.1.2.840.10045.4.3.2", 265 "SIGNATURE.1.2.840.10045.4.3.3", 266 "SIGNATURE.1.2.840.10045.4.3.4", 267 "SIGNATURE.1.2.840.113549.1.1.11", 268 "SIGNATURE.1.2.840.113549.1.1.12", 269 "SIGNATURE.1.2.840.113549.1.1.13", 270 "SIGNATURE.1.2.840.113549.1.1.14", 271 "SIGNATURE.1.2.840.113549.1.1.4", 272 "SIGNATURE.1.2.840.113549.1.1.5", 273 "SIGNATURE.1.3.14.3.2.29", 274 "SIGNATURE.ECDSA", 275 "SIGNATURE.ECDSAWITHSHA1", 276 "SIGNATURE.MD5/RSA", 277 "SIGNATURE.MD5WITHRSA", 278 "SIGNATURE.MD5WITHRSAENCRYPTION", 279 "SIGNATURE.NONEWITHECDSA", 280 "SIGNATURE.OID.1.2.840.10045.4.3.1", 281 "SIGNATURE.OID.1.2.840.10045.4.3.2", 282 "SIGNATURE.OID.1.2.840.10045.4.3.3", 283 "SIGNATURE.OID.1.2.840.10045.4.3.4", 284 "SIGNATURE.OID.1.2.840.113549.1.1.11", 285 "SIGNATURE.OID.1.2.840.113549.1.1.12", 286 "SIGNATURE.OID.1.2.840.113549.1.1.13", 287 "SIGNATURE.OID.1.2.840.113549.1.1.14", 288 "SIGNATURE.OID.1.2.840.113549.1.1.4", 289 "SIGNATURE.OID.1.2.840.113549.1.1.5", 290 "SIGNATURE.OID.1.3.14.3.2.29", 291 "SIGNATURE.SHA1/RSA", 292 "SIGNATURE.SHA1WITHECDSA", 293 "SIGNATURE.SHA1WITHRSA", 294 "SIGNATURE.SHA1WITHRSAENCRYPTION", 295 "SIGNATURE.SHA224/ECDSA", 296 "SIGNATURE.SHA224/RSA", 297 "SIGNATURE.SHA224WITHECDSA", 298 "SIGNATURE.SHA224WITHRSA", 299 "SIGNATURE.SHA224WITHRSAENCRYPTION", 300 "SIGNATURE.SHA256/ECDSA", 301 "SIGNATURE.SHA256/RSA", 302 "SIGNATURE.SHA256WITHECDSA", 303 "SIGNATURE.SHA256WITHRSA", 304 "SIGNATURE.SHA256WITHRSAENCRYPTION", 305 "SIGNATURE.SHA384/ECDSA", 306 "SIGNATURE.SHA384/RSA", 307 "SIGNATURE.SHA384WITHECDSA", 308 "SIGNATURE.SHA384WITHRSA", 309 "SIGNATURE.SHA384WITHRSAENCRYPTION", 310 "SIGNATURE.SHA512/ECDSA", 311 "SIGNATURE.SHA512/RSA", 312 "SIGNATURE.SHA512WITHECDSA", 313 "SIGNATURE.SHA512WITHRSA", 314 "SIGNATURE.SHA512WITHRSAENCRYPTION" 315 )); 316 } 317 getProvider(Object object)318 private static Provider getProvider(Object object) throws Exception { 319 // Every JCA object has a getProvider() method 320 Method m = object.getClass().getMethod("getProvider"); 321 return (Provider) m.invoke(object); 322 } 323 324 @Test testBeforeLimit()325 public void testBeforeLimit() throws Exception { 326 // When we're before the limit of the target API, all calls should succeed 327 try { 328 Providers.setMaximumAllowableApiLevelForBcDeprecation( 329 VMRuntime.getRuntime().getTargetSdkVersion() + 1); 330 for (Algorithm a : BC_ALGORITHMS) { 331 Object result = a.getInstance(); 332 assertEquals("BC", getProvider(result).getName()); 333 } 334 for (Algorithm a : CONSCRYPT_ALGORITHMS) { 335 Object result = a.getInstance(); 336 assertEquals("AndroidOpenSSL", getProvider(result).getName()); 337 } 338 } finally { 339 Providers.setMaximumAllowableApiLevelForBcDeprecation( 340 Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION); 341 } 342 } 343 344 @Test testAtLimit()345 public void testAtLimit() throws Exception { 346 // When we're at the limit of the target API, all calls should still succeed 347 try { 348 Providers.setMaximumAllowableApiLevelForBcDeprecation( 349 VMRuntime.getRuntime().getTargetSdkVersion()); 350 for (Algorithm a : BC_ALGORITHMS) { 351 Object result = a.getInstance(); 352 assertEquals("BC", getProvider(result).getName()); 353 } 354 for (Algorithm a : CONSCRYPT_ALGORITHMS) { 355 Object result = a.getInstance(); 356 assertEquals("AndroidOpenSSL", getProvider(result).getName()); 357 } 358 } finally { 359 Providers.setMaximumAllowableApiLevelForBcDeprecation( 360 Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION); 361 } 362 } 363 364 @Test testPastLimit()365 public void testPastLimit() throws Exception { 366 // When we're beyond the limit of the target API, the Conscrypt calls should succeed 367 // but the BC calls should throw NoSuchAlgorithmException 368 try { 369 Providers.setMaximumAllowableApiLevelForBcDeprecation( 370 VMRuntime.getRuntime().getTargetSdkVersion() - 1); 371 for (Algorithm a : BC_ALGORITHMS) { 372 try { 373 a.getInstance(); 374 fail("getInstance should have thrown"); 375 } catch (NoSuchAlgorithmException expected) { 376 } 377 } 378 for (Algorithm a : CONSCRYPT_ALGORITHMS) { 379 Object result = a.getInstance(); 380 assertEquals("AndroidOpenSSL", getProvider(result).getName()); 381 } 382 } finally { 383 Providers.setMaximumAllowableApiLevelForBcDeprecation( 384 Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION); 385 } 386 } 387 388 @Test testCustomProvider()389 public void testCustomProvider() throws Exception { 390 // When we install our own separate instance of Bouncy Castle, the system should 391 // respect that and allow us to use its implementation. 392 Provider originalBouncyCastle = null; 393 int originalBouncyCastleIndex = -1; 394 for (int i = 0; i < Security.getProviders().length; i++) { 395 if (Security.getProviders()[i].getName().equals("BC")) { 396 originalBouncyCastle = Security.getProviders()[i]; 397 originalBouncyCastleIndex = i; 398 break; 399 } 400 } 401 assertNotNull(originalBouncyCastle); 402 Provider newBouncyCastle = new BouncyCastleProvider(); 403 assertEquals("BC", newBouncyCastle.getName()); 404 try { 405 // Remove the existing BC provider and replace it with a different one 406 Security.removeProvider("BC"); 407 Security.insertProviderAt(newBouncyCastle, originalBouncyCastleIndex); 408 // Set the target API limit such that the BC algorithms are disallowed 409 Providers.setMaximumAllowableApiLevelForBcDeprecation( 410 VMRuntime.getRuntime().getTargetSdkVersion() - 1); 411 for (Algorithm a : BC_ALGORITHMS) { 412 Object result = a.getInstance(); 413 assertEquals("BC", getProvider(result).getName()); 414 } 415 for (Algorithm a : CONSCRYPT_ALGORITHMS) { 416 Object result = a.getInstance(); 417 assertEquals("AndroidOpenSSL", getProvider(result).getName()); 418 } 419 } finally { 420 Providers.setMaximumAllowableApiLevelForBcDeprecation( 421 Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION); 422 Security.removeProvider("BC"); 423 Security.insertProviderAt(originalBouncyCastle, originalBouncyCastleIndex); 424 } 425 } 426 427 @Test testRemovedBCAlgorithms()428 public void testRemovedBCAlgorithms() throws Exception { 429 for (String fullAlgorithm : REMOVED_BC_ALGORITHMS) { 430 String[] parts = fullAlgorithm.split("\\.", 2); 431 assertEquals("Algortihm names are expected to be of format Type.Name", 432 2, parts.length); 433 434 Provider bcProvider = Security.getProvider("BC"); 435 String type = parts[0]; 436 String algorithm = parts[1]; 437 try { 438 switch (parts[0]) { 439 case "ALGORITHMPARAMETERS": 440 AlgorithmParameters.getInstance(algorithm, bcProvider); 441 case "CERTIFICATEFACTORY": 442 CertificateFactory.getInstance(algorithm, bcProvider); 443 case "CIPHER": 444 Cipher.getInstance(algorithm, bcProvider); 445 case "KEYAGREEMENT": 446 KeyAgreement.getInstance(algorithm, bcProvider); 447 case "KEYFACTORY": 448 KeyFactory.getInstance(algorithm, bcProvider); 449 case "KEYGENERATOR": 450 KeyGenerator.getInstance(algorithm, bcProvider); 451 case "KEYPAIRGENERATOR": 452 KeyPairGenerator.getInstance(algorithm, bcProvider); 453 case "MAC": 454 Mac.getInstance(algorithm, bcProvider); 455 case "MESSAGEDIGEST": 456 MessageDigest.getInstance(algorithm, bcProvider); 457 case "SECRETKEYFACTORY": 458 SecretKeyFactory.getInstance(algorithm, bcProvider); 459 case "SIGNATURE": 460 Signature.getInstance(algorithm, bcProvider); 461 default: 462 fail("unhandled algorithm type " + parts[0]); 463 } 464 fail("getInstance should have thrown for type: " + parts[0] + ", name: " + algorithm); 465 } catch(CertificateException | NoSuchAlgorithmException expected) { 466 } 467 } 468 } 469 }