1 /* 2 * Copyright 2013 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 android.keystore.cts; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertNotNull; 22 import static org.junit.Assert.assertTrue; 23 import static org.junit.Assert.fail; 24 25 import android.content.Context; 26 import android.keystore.cts.util.TestUtils; 27 import android.security.KeyPairGeneratorSpec; 28 import android.security.keystore.KeyGenParameterSpec; 29 import android.security.keystore.KeyInfo; 30 import android.security.keystore.KeyProperties; 31 import android.test.MoreAsserts; 32 import android.text.TextUtils; 33 import android.util.Log; 34 35 import androidx.test.InstrumentationRegistry; 36 import androidx.test.runner.AndroidJUnit4; 37 38 import com.android.internal.util.HexDump; 39 40 import libcore.java.security.TestKeyStore; 41 import libcore.javax.net.ssl.TestKeyManager; 42 import libcore.javax.net.ssl.TestSSLContext; 43 44 import org.junit.Before; 45 import org.junit.Test; 46 import org.junit.runner.RunWith; 47 48 import java.math.BigInteger; 49 import java.net.InetAddress; 50 import java.net.Socket; 51 import java.nio.charset.StandardCharsets; 52 import java.security.InvalidAlgorithmParameterException; 53 import java.security.KeyPair; 54 import java.security.KeyPairGenerator; 55 import java.security.KeyStore; 56 import java.security.NoSuchAlgorithmException; 57 import java.security.NoSuchProviderException; 58 import java.security.Principal; 59 import java.security.PrivateKey; 60 import java.security.Provider; 61 import java.security.Provider.Service; 62 import java.security.PublicKey; 63 import java.security.SecureRandom; 64 import java.security.Security; 65 import java.security.Signature; 66 import java.security.cert.Certificate; 67 import java.security.cert.X509Certificate; 68 import java.security.interfaces.ECKey; 69 import java.security.interfaces.ECPublicKey; 70 import java.security.interfaces.RSAPublicKey; 71 import java.security.spec.AlgorithmParameterSpec; 72 import java.security.spec.ECGenParameterSpec; 73 import java.security.spec.ECParameterSpec; 74 import java.security.spec.RSAKeyGenParameterSpec; 75 import java.text.DecimalFormatSymbols; 76 import java.text.SimpleDateFormat; 77 import java.util.ArrayList; 78 import java.util.Arrays; 79 import java.util.Date; 80 import java.util.HashSet; 81 import java.util.List; 82 import java.util.Locale; 83 import java.util.Map; 84 import java.util.Set; 85 import java.util.TreeMap; 86 import java.util.concurrent.Callable; 87 import java.util.concurrent.ExecutorService; 88 import java.util.concurrent.Executors; 89 import java.util.concurrent.Future; 90 91 import javax.crypto.KeyAgreement; 92 import javax.net.ssl.KeyManager; 93 import javax.net.ssl.SSLContext; 94 import javax.net.ssl.SSLEngine; 95 import javax.net.ssl.SSLServerSocket; 96 import javax.net.ssl.SSLSocket; 97 import javax.net.ssl.X509ExtendedKeyManager; 98 import javax.security.auth.x500.X500Principal; 99 100 @RunWith(AndroidJUnit4.class) 101 public class KeyPairGeneratorTest { 102 103 private static final String TAG = "KeyPairGeneratorTest"; 104 105 private KeyStore mKeyStore; 106 107 private CountingSecureRandom mRng; 108 109 private static final String TEST_ALIAS_1 = "test1"; 110 111 private static final String TEST_ALIAS_2 = "test2"; 112 113 private static final String TEST_ALIAS_3 = "test3"; 114 115 private static final X500Principal TEST_DN_1 = new X500Principal("CN=test1"); 116 117 private static final X500Principal TEST_DN_2 = new X500Principal("CN=test2"); 118 119 private static final BigInteger TEST_SERIAL_1 = BigInteger.ONE; 120 121 private static final BigInteger TEST_SERIAL_2 = BigInteger.valueOf(2L); 122 123 private static final long NOW_MILLIS = System.currentTimeMillis(); 124 125 /* We have to round this off because X509v3 doesn't store milliseconds. */ 126 private static final Date NOW = new Date(NOW_MILLIS - (NOW_MILLIS % 1000L)); 127 128 @SuppressWarnings("deprecation") 129 private static final Date NOW_PLUS_10_YEARS = new Date(NOW.getYear() + 10, 0, 1); 130 131 private static final long DAY_IN_MILLIS = 1000 * 60 * 60 * 24; 132 133 private static final X500Principal DEFAULT_CERT_SUBJECT = new X500Principal("CN=fake"); 134 private static final BigInteger DEFAULT_CERT_SERIAL_NUMBER = new BigInteger("1"); 135 private static final Date DEFAULT_CERT_NOT_BEFORE = new Date(0L); // Jan 1 1970 136 private static final Date DEFAULT_CERT_NOT_AFTER = new Date(2461449600000L); // Jan 1 2048 137 138 private static final String EXPECTED_PROVIDER_NAME = TestUtils.EXPECTED_PROVIDER_NAME; 139 140 private static final String[] EXPECTED_ALGORITHMS = { 141 "EC", 142 "RSA", 143 }; 144 145 private static final Map<String, Integer> DEFAULT_KEY_SIZES = 146 new TreeMap<>(String.CASE_INSENSITIVE_ORDER); 147 static { 148 DEFAULT_KEY_SIZES.put("EC", 256); 149 DEFAULT_KEY_SIZES.put("RSA", 2048); 150 } 151 getContext()152 private Context getContext() { 153 return InstrumentationRegistry.getInstrumentation().getTargetContext(); 154 } 155 156 @Before setUp()157 public void setUp() throws Exception { 158 mRng = new CountingSecureRandom(); 159 mKeyStore = KeyStore.getInstance("AndroidKeyStore"); 160 mKeyStore.load(null, null); 161 } 162 163 @Test testAlgorithmList()164 public void testAlgorithmList() { 165 // Assert that Android Keystore Provider exposes exactly the expected KeyPairGenerator 166 // algorithms. We don't care whether the algorithms are exposed via aliases, as long as 167 // canonical names of algorithms are accepted. If the Provider exposes extraneous 168 // algorithms, it'll be caught because it'll have to expose at least one Service for such an 169 // algorithm, and this Service's algorithm will not be in the expected set. 170 171 Provider provider = Security.getProvider(EXPECTED_PROVIDER_NAME); 172 Set<Service> services = provider.getServices(); 173 Set<String> actualAlgsLowerCase = new HashSet<String>(); 174 Set<String> expectedAlgsLowerCase = new HashSet<String>( 175 Arrays.asList(TestUtils.toLowerCase(EXPECTED_ALGORITHMS))); 176 177 // XDH is also a supported algorithm, but not available for other tests as the keys 178 // generated with it have more limited set of uses. 179 expectedAlgsLowerCase.add("xdh"); 180 181 for (Service service : services) { 182 if ("KeyPairGenerator".equalsIgnoreCase(service.getType())) { 183 String algLowerCase = service.getAlgorithm().toLowerCase(Locale.US); 184 actualAlgsLowerCase.add(algLowerCase); 185 } 186 } 187 188 TestUtils.assertContentsInAnyOrder(actualAlgsLowerCase, 189 expectedAlgsLowerCase.toArray(new String[0])); 190 } 191 192 @Test testInitialize_LegacySpec()193 public void testInitialize_LegacySpec() throws Exception { 194 @SuppressWarnings("deprecation") 195 KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(getContext()) 196 .setAlias(TEST_ALIAS_1) 197 .setSubject(TEST_DN_1) 198 .setSerialNumber(TEST_SERIAL_1) 199 .setStartDate(NOW) 200 .setEndDate(NOW_PLUS_10_YEARS) 201 .build(); 202 getRsaGenerator().initialize(spec); 203 getRsaGenerator().initialize(spec, new SecureRandom()); 204 205 getEcGenerator().initialize(spec); 206 getEcGenerator().initialize(spec, new SecureRandom()); 207 } 208 209 @Test testInitialize_ModernSpec()210 public void testInitialize_ModernSpec() throws Exception { 211 KeyGenParameterSpec spec = new KeyGenParameterSpec.Builder( 212 TEST_ALIAS_1, 213 KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY) 214 .build(); 215 getRsaGenerator().initialize(spec); 216 getRsaGenerator().initialize(spec, new SecureRandom()); 217 218 getEcGenerator().initialize(spec); 219 getEcGenerator().initialize(spec, new SecureRandom()); 220 } 221 222 @Test testInitialize_KeySizeOnly()223 public void testInitialize_KeySizeOnly() throws Exception { 224 try { 225 getRsaGenerator().initialize(1024); 226 fail("KeyPairGenerator should not support setting the key size"); 227 } catch (IllegalArgumentException success) { 228 } 229 230 try { 231 getEcGenerator().initialize(256); 232 fail("KeyPairGenerator should not support setting the key size"); 233 } catch (IllegalArgumentException success) { 234 } 235 } 236 237 @Test testInitialize_KeySizeAndSecureRandomOnly()238 public void testInitialize_KeySizeAndSecureRandomOnly() 239 throws Exception { 240 try { 241 getRsaGenerator().initialize(1024, new SecureRandom()); 242 fail("KeyPairGenerator should not support setting the key size"); 243 } catch (IllegalArgumentException success) { 244 } 245 246 try { 247 getEcGenerator().initialize(1024, new SecureRandom()); 248 fail("KeyPairGenerator should not support setting the key size"); 249 } catch (IllegalArgumentException success) { 250 } 251 } 252 253 @Test testDefaultKeySize()254 public void testDefaultKeySize() throws Exception { 255 for (String algorithm : EXPECTED_ALGORITHMS) { 256 try { 257 int expectedSizeBits = DEFAULT_KEY_SIZES.get(algorithm); 258 KeyPairGenerator generator = getGenerator(algorithm); 259 generator.initialize(getWorkingSpec().build()); 260 KeyPair keyPair = generator.generateKeyPair(); 261 assertEquals(expectedSizeBits, 262 TestUtils.getKeyInfo(keyPair.getPrivate()).getKeySize()); 263 } catch (Throwable e) { 264 throw new RuntimeException("Failed for " + algorithm, e); 265 } 266 } 267 } 268 269 @Test testInitWithUnknownBlockModeFails()270 public void testInitWithUnknownBlockModeFails() { 271 for (String algorithm : EXPECTED_ALGORITHMS) { 272 try { 273 KeyPairGenerator generator = getGenerator(algorithm); 274 try { 275 generator.initialize(getWorkingSpec().setBlockModes("weird").build()); 276 fail(); 277 } catch (InvalidAlgorithmParameterException expected) {} 278 } catch (Throwable e) { 279 throw new RuntimeException("Failed for " + algorithm, e); 280 } 281 } 282 } 283 284 @Test testInitWithUnknownEncryptionPaddingFails()285 public void testInitWithUnknownEncryptionPaddingFails() { 286 for (String algorithm : EXPECTED_ALGORITHMS) { 287 try { 288 KeyPairGenerator generator = getGenerator(algorithm); 289 try { 290 generator.initialize(getWorkingSpec().setEncryptionPaddings("weird").build()); 291 fail(); 292 } catch (InvalidAlgorithmParameterException expected) {} 293 } catch (Throwable e) { 294 throw new RuntimeException("Failed for " + algorithm, e); 295 } 296 } 297 } 298 299 @Test testInitWithUnknownSignaturePaddingFails()300 public void testInitWithUnknownSignaturePaddingFails() { 301 for (String algorithm : EXPECTED_ALGORITHMS) { 302 try { 303 KeyPairGenerator generator = getGenerator(algorithm); 304 try { 305 generator.initialize(getWorkingSpec().setSignaturePaddings("weird").build()); 306 fail(); 307 } catch (InvalidAlgorithmParameterException expected) {} 308 } catch (Throwable e) { 309 throw new RuntimeException("Failed for " + algorithm, e); 310 } 311 } 312 } 313 314 @Test testInitWithUnknownDigestFails()315 public void testInitWithUnknownDigestFails() { 316 for (String algorithm : EXPECTED_ALGORITHMS) { 317 try { 318 KeyPairGenerator generator = getGenerator(algorithm); 319 try { 320 generator.initialize(getWorkingSpec().setDigests("weird").build()); 321 fail(); 322 } catch (InvalidAlgorithmParameterException expected) {} 323 } catch (Throwable e) { 324 throw new RuntimeException("Failed for " + algorithm, e); 325 } 326 } 327 } 328 329 @Test testInitRandomizedEncryptionRequiredButViolatedFails()330 public void testInitRandomizedEncryptionRequiredButViolatedFails() throws Exception { 331 for (String algorithm : EXPECTED_ALGORITHMS) { 332 try { 333 KeyPairGenerator generator = getGenerator(algorithm); 334 try { 335 generator.initialize(getWorkingSpec( 336 KeyProperties.PURPOSE_ENCRYPT) 337 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) 338 .build()); 339 fail(); 340 } catch (InvalidAlgorithmParameterException expected) {} 341 } catch (Throwable e) { 342 throw new RuntimeException("Failed for " + algorithm, e); 343 } 344 } 345 } 346 347 @Test testGenerateHonorsRequestedAuthorizations()348 public void testGenerateHonorsRequestedAuthorizations() throws Exception { 349 testGenerateHonorsRequestedAuthorizationsHelper(false /* useStrongbox */); 350 if (TestUtils.hasStrongBox(getContext())) { 351 testGenerateHonorsRequestedAuthorizationsHelper(true /* useStrongbox */); 352 } 353 } 354 testGenerateHonorsRequestedAuthorizationsHelper(boolean useStrongbox)355 private void testGenerateHonorsRequestedAuthorizationsHelper(boolean useStrongbox) { 356 Date keyValidityStart = new Date(System.currentTimeMillis() - TestUtils.DAY_IN_MILLIS); 357 Date keyValidityForOriginationEnd = 358 new Date(System.currentTimeMillis() + TestUtils.DAY_IN_MILLIS); 359 Date keyValidityForConsumptionEnd = 360 new Date(System.currentTimeMillis() + 3 * TestUtils.DAY_IN_MILLIS); 361 for (String algorithm : EXPECTED_ALGORITHMS) { 362 try { 363 String[] blockModes = 364 new String[] {KeyProperties.BLOCK_MODE_GCM, KeyProperties.BLOCK_MODE_CBC}; 365 String[] encryptionPaddings = 366 new String[] {KeyProperties.ENCRYPTION_PADDING_RSA_OAEP, 367 KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1}; 368 String[] digests = 369 new String[] {KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA1}; 370 int purposes = KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_ENCRYPT; 371 KeyPairGenerator generator = getGenerator(algorithm); 372 generator.initialize(getWorkingSpec(purposes) 373 .setBlockModes(blockModes) 374 .setEncryptionPaddings(encryptionPaddings) 375 .setDigests(digests) 376 .setKeyValidityStart(keyValidityStart) 377 .setKeyValidityForOriginationEnd(keyValidityForOriginationEnd) 378 .setKeyValidityForConsumptionEnd(keyValidityForConsumptionEnd) 379 .setIsStrongBoxBacked(useStrongbox) 380 .build()); 381 KeyPair keyPair = generator.generateKeyPair(); 382 assertEquals(algorithm, keyPair.getPrivate().getAlgorithm()); 383 384 KeyInfo keyInfo = TestUtils.getKeyInfo(keyPair.getPrivate()); 385 assertEquals(purposes, keyInfo.getPurposes()); 386 TestUtils.assertContentsInAnyOrder( 387 Arrays.asList(keyInfo.getBlockModes()), blockModes); 388 389 List<String> actualEncryptionPaddings = 390 new ArrayList<String>(Arrays.asList(keyInfo.getEncryptionPaddings())); 391 // Keystore may have added ENCRYPTION_PADDING_NONE to allow software OAEP 392 actualEncryptionPaddings.remove(KeyProperties.ENCRYPTION_PADDING_NONE); 393 TestUtils.assertContentsInAnyOrder( 394 actualEncryptionPaddings, encryptionPaddings); 395 396 List<String> actualDigests = 397 new ArrayList<String>(Arrays.asList(keyInfo.getDigests())); 398 // Keystore may have added DIGEST_NONE, to allow software digesting. 399 actualDigests.remove(KeyProperties.DIGEST_NONE); 400 TestUtils.assertContentsInAnyOrder(actualDigests, digests); 401 402 MoreAsserts.assertEmpty(Arrays.asList(keyInfo.getSignaturePaddings())); 403 assertEquals(keyValidityStart, keyInfo.getKeyValidityStart()); 404 assertEquals(keyValidityForOriginationEnd, 405 keyInfo.getKeyValidityForOriginationEnd()); 406 assertEquals(keyValidityForConsumptionEnd, 407 keyInfo.getKeyValidityForConsumptionEnd()); 408 assertFalse(keyInfo.isUserAuthenticationRequired()); 409 assertFalse(keyInfo.isUserAuthenticationRequirementEnforcedBySecureHardware()); 410 } catch (Throwable e) { 411 String specific = useStrongbox ? "Strongbox:" : ""; 412 throw new RuntimeException(specific + "Failed for " + algorithm, e); 413 } 414 } 415 } 416 417 @SuppressWarnings("deprecation") 418 @Test testGenerate_EC_LegacySpec()419 public void testGenerate_EC_LegacySpec() throws Exception { 420 // There are three legacy ways to generate an EC key pair using Android Keystore 421 // KeyPairGenerator: 422 // 1. Use an RSA KeyPairGenerator and specify EC as key type, 423 // 2. Use an EC KeyPairGenerator and specify EC as key type, 424 // 3. Use an EC KeyPairGenerator and leave the key type unspecified. 425 // 426 // We test all three. 427 428 // 1. Use an RSA KeyPairGenerator and specify EC as key type. 429 KeyPairGenerator generator = getRsaGenerator(); 430 generator.initialize(new KeyPairGeneratorSpec.Builder(getContext()) 431 .setAlias(TEST_ALIAS_1) 432 .setKeyType("EC") 433 .setSubject(TEST_DN_1) 434 .setSerialNumber(TEST_SERIAL_1) 435 .setStartDate(NOW) 436 .setEndDate(NOW_PLUS_10_YEARS) 437 .build()); 438 KeyPair keyPair = generator.generateKeyPair(); 439 assertGeneratedKeyPairAndSelfSignedCertificate( 440 keyPair, 441 TEST_ALIAS_1, 442 "EC", 443 256, 444 TEST_DN_1, 445 TEST_SERIAL_1, NOW, 446 NOW_PLUS_10_YEARS); 447 assertSelfSignedCertificateSignatureVerifies(TEST_ALIAS_1); 448 assertKeyPairAndCertificateUsableForTLSPeerAuthentication(TEST_ALIAS_1); 449 TestUtils.assertECParameterSpecEqualsIgnoreSeedIfNotPresent( 450 ECCurves.NIST_P_256_SPEC, ((ECPublicKey) keyPair.getPublic()).getParams()); 451 KeyInfo keyInfo = TestUtils.getKeyInfo(keyPair.getPrivate()); 452 assertEquals(256, keyInfo.getKeySize()); 453 assertEquals(TEST_ALIAS_1, keyInfo.getKeystoreAlias()); 454 assertOneOf(keyInfo.getOrigin(), 455 KeyProperties.ORIGIN_GENERATED, KeyProperties.ORIGIN_UNKNOWN); 456 assertEquals( 457 KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY, 458 keyInfo.getPurposes()); 459 assertFalse(keyInfo.isUserAuthenticationRequired()); 460 assertEquals(null, keyInfo.getKeyValidityStart()); 461 assertEquals(null, keyInfo.getKeyValidityForOriginationEnd()); 462 assertEquals(null, keyInfo.getKeyValidityForConsumptionEnd()); 463 MoreAsserts.assertEmpty(Arrays.asList(keyInfo.getBlockModes())); 464 MoreAsserts.assertContentsInAnyOrder(Arrays.asList(keyInfo.getDigests()), 465 KeyProperties.DIGEST_NONE, 466 KeyProperties.DIGEST_SHA1, 467 KeyProperties.DIGEST_SHA224, 468 KeyProperties.DIGEST_SHA256, 469 KeyProperties.DIGEST_SHA384, 470 KeyProperties.DIGEST_SHA512); 471 MoreAsserts.assertEmpty(Arrays.asList(keyInfo.getSignaturePaddings())); 472 MoreAsserts.assertEmpty(Arrays.asList(keyInfo.getEncryptionPaddings())); 473 474 // 2. Use an EC KeyPairGenerator and specify EC as key type. 475 generator = getEcGenerator(); 476 generator.initialize(new KeyPairGeneratorSpec.Builder(getContext()) 477 .setAlias(TEST_ALIAS_2) 478 .setKeyType("EC") 479 .setSubject(TEST_DN_1) 480 .setSerialNumber(TEST_SERIAL_1) 481 .setStartDate(NOW) 482 .setEndDate(NOW_PLUS_10_YEARS) 483 .build()); 484 keyPair = generator.generateKeyPair(); 485 assertGeneratedKeyPairAndSelfSignedCertificate( 486 keyPair, 487 TEST_ALIAS_2, 488 "EC", 489 256, 490 TEST_DN_1, 491 TEST_SERIAL_1, 492 NOW, 493 NOW_PLUS_10_YEARS); 494 assertSelfSignedCertificateSignatureVerifies(TEST_ALIAS_2); 495 assertKeyPairAndCertificateUsableForTLSPeerAuthentication(TEST_ALIAS_2); 496 TestUtils.assertECParameterSpecEqualsIgnoreSeedIfNotPresent( 497 ECCurves.NIST_P_256_SPEC, ((ECPublicKey) keyPair.getPublic()).getParams()); 498 keyInfo = TestUtils.getKeyInfo(keyPair.getPrivate()); 499 assertEquals(256, keyInfo.getKeySize()); 500 assertEquals(TEST_ALIAS_2, keyInfo.getKeystoreAlias()); 501 assertOneOf(keyInfo.getOrigin(), 502 KeyProperties.ORIGIN_GENERATED, KeyProperties.ORIGIN_UNKNOWN); 503 assertEquals( 504 KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY, 505 keyInfo.getPurposes()); 506 assertFalse(keyInfo.isUserAuthenticationRequired()); 507 assertEquals(null, keyInfo.getKeyValidityStart()); 508 assertEquals(null, keyInfo.getKeyValidityForOriginationEnd()); 509 assertEquals(null, keyInfo.getKeyValidityForConsumptionEnd()); 510 MoreAsserts.assertEmpty(Arrays.asList(keyInfo.getBlockModes())); 511 MoreAsserts.assertContentsInAnyOrder(Arrays.asList(keyInfo.getDigests()), 512 KeyProperties.DIGEST_NONE, 513 KeyProperties.DIGEST_SHA1, 514 KeyProperties.DIGEST_SHA224, 515 KeyProperties.DIGEST_SHA256, 516 KeyProperties.DIGEST_SHA384, 517 KeyProperties.DIGEST_SHA512); 518 MoreAsserts.assertEmpty(Arrays.asList(keyInfo.getSignaturePaddings())); 519 MoreAsserts.assertEmpty(Arrays.asList(keyInfo.getEncryptionPaddings())); 520 521 // 3. Use an EC KeyPairGenerator and leave the key type unspecified. 522 generator = getEcGenerator(); 523 generator.initialize(new KeyPairGeneratorSpec.Builder(getContext()) 524 .setAlias(TEST_ALIAS_3) 525 .setSubject(TEST_DN_1) 526 .setSerialNumber(TEST_SERIAL_1) 527 .setStartDate(NOW) 528 .setEndDate(NOW_PLUS_10_YEARS) 529 .build()); 530 keyPair = generator.generateKeyPair(); 531 assertGeneratedKeyPairAndSelfSignedCertificate( 532 keyPair, 533 TEST_ALIAS_3, 534 "EC", 535 256, 536 TEST_DN_1, 537 TEST_SERIAL_1, 538 NOW, 539 NOW_PLUS_10_YEARS); 540 assertSelfSignedCertificateSignatureVerifies(TEST_ALIAS_3); 541 assertKeyPairAndCertificateUsableForTLSPeerAuthentication(TEST_ALIAS_3); 542 TestUtils.assertECParameterSpecEqualsIgnoreSeedIfNotPresent( 543 ECCurves.NIST_P_256_SPEC, ((ECPublicKey) keyPair.getPublic()).getParams()); 544 keyInfo = TestUtils.getKeyInfo(keyPair.getPrivate()); 545 assertEquals(256, keyInfo.getKeySize()); 546 assertEquals(TEST_ALIAS_3, keyInfo.getKeystoreAlias()); 547 assertOneOf(keyInfo.getOrigin(), 548 KeyProperties.ORIGIN_GENERATED, KeyProperties.ORIGIN_UNKNOWN); 549 assertEquals( 550 KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY, 551 keyInfo.getPurposes()); 552 assertFalse(keyInfo.isUserAuthenticationRequired()); 553 assertEquals(null, keyInfo.getKeyValidityStart()); 554 assertEquals(null, keyInfo.getKeyValidityForOriginationEnd()); 555 assertEquals(null, keyInfo.getKeyValidityForConsumptionEnd()); 556 MoreAsserts.assertEmpty(Arrays.asList(keyInfo.getBlockModes())); 557 MoreAsserts.assertContentsInAnyOrder(Arrays.asList(keyInfo.getDigests()), 558 KeyProperties.DIGEST_NONE, 559 KeyProperties.DIGEST_SHA1, 560 KeyProperties.DIGEST_SHA224, 561 KeyProperties.DIGEST_SHA256, 562 KeyProperties.DIGEST_SHA384, 563 KeyProperties.DIGEST_SHA512); 564 MoreAsserts.assertEmpty(Arrays.asList(keyInfo.getSignaturePaddings())); 565 MoreAsserts.assertEmpty(Arrays.asList(keyInfo.getEncryptionPaddings())); 566 } 567 568 @Test testGenerate_RSA_LegacySpec()569 public void testGenerate_RSA_LegacySpec() throws Exception { 570 KeyPairGenerator generator = getRsaGenerator(); 571 generator.initialize(new KeyPairGeneratorSpec.Builder(getContext()) 572 .setAlias(TEST_ALIAS_1) 573 .setSubject(TEST_DN_1) 574 .setSerialNumber(TEST_SERIAL_1) 575 .setStartDate(NOW) 576 .setEndDate(NOW_PLUS_10_YEARS) 577 .build()); 578 KeyPair keyPair = generator.generateKeyPair(); 579 assertGeneratedKeyPairAndSelfSignedCertificate( 580 keyPair, 581 TEST_ALIAS_1, 582 "RSA", 583 2048, 584 TEST_DN_1, 585 TEST_SERIAL_1, 586 NOW, 587 NOW_PLUS_10_YEARS); 588 assertSelfSignedCertificateSignatureVerifies(TEST_ALIAS_1); 589 assertKeyPairAndCertificateUsableForTLSPeerAuthentication(TEST_ALIAS_1); 590 assertEquals(RSAKeyGenParameterSpec.F4, 591 ((RSAPublicKey) keyPair.getPublic()).getPublicExponent()); 592 KeyInfo keyInfo = TestUtils.getKeyInfo(keyPair.getPrivate()); 593 assertEquals(2048, keyInfo.getKeySize()); 594 assertEquals(TEST_ALIAS_1, keyInfo.getKeystoreAlias()); 595 assertOneOf(keyInfo.getOrigin(), 596 KeyProperties.ORIGIN_GENERATED, KeyProperties.ORIGIN_UNKNOWN); 597 assertEquals( 598 KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY 599 | KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT, 600 keyInfo.getPurposes()); 601 assertFalse(keyInfo.isUserAuthenticationRequired()); 602 assertEquals(null, keyInfo.getKeyValidityStart()); 603 assertEquals(null, keyInfo.getKeyValidityForOriginationEnd()); 604 assertEquals(null, keyInfo.getKeyValidityForConsumptionEnd()); 605 MoreAsserts.assertEmpty(Arrays.asList(keyInfo.getBlockModes())); 606 MoreAsserts.assertContentsInAnyOrder(Arrays.asList(keyInfo.getDigests()), 607 KeyProperties.DIGEST_NONE, 608 KeyProperties.DIGEST_MD5, 609 KeyProperties.DIGEST_SHA1, 610 KeyProperties.DIGEST_SHA224, 611 KeyProperties.DIGEST_SHA256, 612 KeyProperties.DIGEST_SHA384, 613 KeyProperties.DIGEST_SHA512); 614 MoreAsserts.assertContentsInAnyOrder(Arrays.asList(keyInfo.getEncryptionPaddings()), 615 KeyProperties.ENCRYPTION_PADDING_NONE, 616 KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1, 617 KeyProperties.ENCRYPTION_PADDING_RSA_OAEP); 618 MoreAsserts.assertContentsInAnyOrder(Arrays.asList(keyInfo.getSignaturePaddings()), 619 KeyProperties.SIGNATURE_PADDING_RSA_PSS, 620 KeyProperties.SIGNATURE_PADDING_RSA_PKCS1); 621 } 622 623 @Test testGenerate_ReplacesOldEntryWithSameAlias()624 public void testGenerate_ReplacesOldEntryWithSameAlias() throws Exception { 625 replacesOldEntryWithSameAliasHelper(false /* useStrongbox */); 626 if (TestUtils.hasStrongBox(getContext())) { 627 replacesOldEntryWithSameAliasHelper(true /* useStrongbox */); 628 } 629 } 630 replacesOldEntryWithSameAliasHelper(boolean useStrongbox)631 private void replacesOldEntryWithSameAliasHelper(boolean useStrongbox) throws Exception { 632 // Generate the first key 633 { 634 KeyPairGenerator generator = getRsaGenerator(); 635 generator.initialize(new KeyGenParameterSpec.Builder( 636 TEST_ALIAS_1, 637 KeyProperties.PURPOSE_SIGN 638 | KeyProperties.PURPOSE_VERIFY 639 | KeyProperties.PURPOSE_ENCRYPT 640 | KeyProperties.PURPOSE_DECRYPT) 641 .setDigests(KeyProperties.DIGEST_NONE) 642 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1) 643 .setCertificateSubject(TEST_DN_1) 644 .setCertificateSerialNumber(TEST_SERIAL_1) 645 .setCertificateNotBefore(NOW) 646 .setCertificateNotAfter(NOW_PLUS_10_YEARS) 647 .setIsStrongBoxBacked(useStrongbox) 648 .build()); 649 assertGeneratedKeyPairAndSelfSignedCertificate( 650 generator.generateKeyPair(), 651 TEST_ALIAS_1, 652 "RSA", 653 2048, 654 TEST_DN_1, 655 TEST_SERIAL_1, 656 NOW, 657 NOW_PLUS_10_YEARS); 658 } 659 660 // Replace the original key 661 { 662 KeyPairGenerator generator = getRsaGenerator(); 663 generator.initialize(new KeyGenParameterSpec.Builder( 664 TEST_ALIAS_1, 665 KeyProperties.PURPOSE_SIGN 666 | KeyProperties.PURPOSE_VERIFY 667 | KeyProperties.PURPOSE_ENCRYPT 668 | KeyProperties.PURPOSE_DECRYPT) 669 .setDigests(KeyProperties.DIGEST_NONE) 670 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1) 671 .setCertificateSubject(TEST_DN_2) 672 .setCertificateSerialNumber(TEST_SERIAL_2) 673 .setCertificateNotBefore(NOW) 674 .setCertificateNotAfter(NOW_PLUS_10_YEARS) 675 .setIsStrongBoxBacked(useStrongbox) 676 .build()); 677 assertGeneratedKeyPairAndSelfSignedCertificate( 678 generator.generateKeyPair(), 679 TEST_ALIAS_1, 680 "RSA", 681 2048, 682 TEST_DN_2, 683 TEST_SERIAL_2, 684 NOW, 685 NOW_PLUS_10_YEARS); 686 } 687 } 688 689 @Test testGenerate_DoesNotReplaceOtherEntries()690 public void testGenerate_DoesNotReplaceOtherEntries() throws Exception { 691 doesNotReplaceOtherEntriesHelper(false /* useStrongbox */); 692 if (TestUtils.hasStrongBox(getContext())) { 693 doesNotReplaceOtherEntriesHelper(true /* useStrongbox */); 694 } 695 } 696 doesNotReplaceOtherEntriesHelper(boolean useStrongbox)697 private void doesNotReplaceOtherEntriesHelper(boolean useStrongbox) throws Exception { 698 // Generate the first key 699 KeyPairGenerator generator = getRsaGenerator(); 700 generator.initialize(new KeyGenParameterSpec.Builder( 701 TEST_ALIAS_1, 702 KeyProperties.PURPOSE_SIGN 703 | KeyProperties.PURPOSE_VERIFY 704 | KeyProperties.PURPOSE_ENCRYPT 705 | KeyProperties.PURPOSE_DECRYPT) 706 .setDigests(KeyProperties.DIGEST_NONE) 707 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1) 708 .setCertificateSubject(TEST_DN_1) 709 .setCertificateSerialNumber(TEST_SERIAL_1) 710 .setCertificateNotBefore(NOW) 711 .setCertificateNotAfter(NOW_PLUS_10_YEARS) 712 .setIsStrongBoxBacked(useStrongbox) 713 .build()); 714 KeyPair keyPair1 = generator.generateKeyPair(); 715 assertGeneratedKeyPairAndSelfSignedCertificate( 716 keyPair1, 717 TEST_ALIAS_1, 718 "RSA", 719 2048, 720 TEST_DN_1, 721 TEST_SERIAL_1, 722 NOW, 723 NOW_PLUS_10_YEARS); 724 725 // Generate the second key 726 generator.initialize(new KeyGenParameterSpec.Builder( 727 TEST_ALIAS_2, 728 KeyProperties.PURPOSE_SIGN 729 | KeyProperties.PURPOSE_VERIFY 730 | KeyProperties.PURPOSE_ENCRYPT 731 | KeyProperties.PURPOSE_DECRYPT) 732 .setDigests(KeyProperties.DIGEST_NONE) 733 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1) 734 .setCertificateSubject(TEST_DN_2) 735 .setCertificateSerialNumber(TEST_SERIAL_2) 736 .setCertificateNotBefore(NOW) 737 .setCertificateNotAfter(NOW_PLUS_10_YEARS) 738 .setIsStrongBoxBacked(useStrongbox) 739 .build()); 740 KeyPair keyPair2 = generator.generateKeyPair(); 741 assertGeneratedKeyPairAndSelfSignedCertificate( 742 keyPair2, 743 TEST_ALIAS_2, 744 "RSA", 745 2048, 746 TEST_DN_2, 747 TEST_SERIAL_2, 748 NOW, 749 NOW_PLUS_10_YEARS); 750 751 // Check the first key pair again 752 assertGeneratedKeyPairAndSelfSignedCertificate( 753 keyPair1, 754 TEST_ALIAS_1, 755 "RSA", 756 2048, 757 TEST_DN_1, 758 TEST_SERIAL_1, 759 NOW, 760 NOW_PLUS_10_YEARS); 761 } 762 763 @Test testGenerate_EC_Different_Keys()764 public void testGenerate_EC_Different_Keys() throws Exception { 765 testGenerate_EC_Different_KeysHelper(false /* useStrongbox */); 766 if (TestUtils.hasStrongBox(getContext())) { 767 testGenerate_EC_Different_KeysHelper(true /* useStrongbox */); 768 } 769 } 770 testGenerate_EC_Different_KeysHelper(boolean useStrongbox)771 private void testGenerate_EC_Different_KeysHelper(boolean useStrongbox) throws Exception { 772 KeyPairGenerator generator = getEcGenerator(); 773 generator.initialize(new KeyGenParameterSpec.Builder( 774 TEST_ALIAS_1, 775 KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY) 776 .setIsStrongBoxBacked(useStrongbox) 777 .build()); 778 KeyPair keyPair1 = generator.generateKeyPair(); 779 PublicKey pub1 = keyPair1.getPublic(); 780 781 generator.initialize(new KeyGenParameterSpec.Builder( 782 TEST_ALIAS_2, 783 KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY) 784 .setIsStrongBoxBacked(useStrongbox) 785 .build()); 786 KeyPair keyPair2 = generator.generateKeyPair(); 787 PublicKey pub2 = keyPair2.getPublic(); 788 if(Arrays.equals(pub1.getEncoded(), pub2.getEncoded())) { 789 fail("The same EC key pair was generated twice"); 790 } 791 } 792 793 @Test testGenerate_RSA_Different_Keys()794 public void testGenerate_RSA_Different_Keys() throws Exception { 795 testGenerate_RSA_Different_KeysHelper(false /* useStrongbox */); 796 if (TestUtils.hasStrongBox(getContext())) { 797 testGenerate_RSA_Different_KeysHelper(true /* useStrongbox */); 798 } 799 } 800 testGenerate_RSA_Different_KeysHelper(boolean useStrongbox)801 private void testGenerate_RSA_Different_KeysHelper(boolean useStrongbox) throws Exception { 802 KeyPairGenerator generator = getRsaGenerator(); 803 generator.initialize(new KeyGenParameterSpec.Builder( 804 TEST_ALIAS_1, 805 KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY) 806 .setIsStrongBoxBacked(useStrongbox) 807 .build()); 808 KeyPair keyPair1 = generator.generateKeyPair(); 809 PublicKey pub1 = keyPair1.getPublic(); 810 811 generator.initialize(new KeyGenParameterSpec.Builder( 812 TEST_ALIAS_2, 813 KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY) 814 .setIsStrongBoxBacked(useStrongbox) 815 .build()); 816 KeyPair keyPair2 = generator.generateKeyPair(); 817 PublicKey pub2 = keyPair2.getPublic(); 818 if(Arrays.equals(pub1.getEncoded(), pub2.getEncoded())) { 819 fail("The same RSA key pair was generated twice"); 820 } 821 } 822 823 @Test testRSA_Key_Quality()824 public void testRSA_Key_Quality() throws NoSuchAlgorithmException, NoSuchProviderException, 825 InvalidAlgorithmParameterException { 826 final int numKeysToGenerate = 10; 827 testRSA_Key_QualityHelper(numKeysToGenerate, false /* useStrongbox */); 828 if (TestUtils.hasStrongBox(getContext())) { 829 testRSA_Key_QualityHelper(numKeysToGenerate, true /* useStrongbox */); 830 } 831 } 832 testRSA_Key_QualityHelper(int numKeysToGenerate, boolean useStrongbox)833 private void testRSA_Key_QualityHelper(int numKeysToGenerate, boolean useStrongbox) 834 throws NoSuchAlgorithmException, NoSuchProviderException, 835 InvalidAlgorithmParameterException { 836 Log.w(TAG, "Starting key quality testing"); 837 List<PublicKey> publicKeys = getPublicKeys(numKeysToGenerate, useStrongbox); 838 839 testRSA_Key_Quality_All_DifferentHelper(publicKeys); 840 testRSA_Key_Quality_Not_Too_Many_ZerosHelper(publicKeys); 841 // Run the GCD test after verifying all keys are distinct. (Identical keys have a trivial 842 // common divisor greater than one.) 843 testRSA_Key_Quality_Not_Perfect_SquareHelper(publicKeys); 844 testRSA_Key_Quality_Public_Modulus_GCD_Is_One_Helper(publicKeys); 845 } 846 testRSA_Key_Quality_Not_Perfect_SquareHelper(Iterable<PublicKey> publicKeys)847 private void testRSA_Key_Quality_Not_Perfect_SquareHelper(Iterable<PublicKey> publicKeys) { 848 for (PublicKey publicKey : publicKeys) { 849 RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey; 850 BigInteger publicModulus = rsaPublicKey.getModulus(); 851 BigInteger[] sqrtAndRemainder = publicModulus.sqrtAndRemainder(); 852 BigInteger sqrt = sqrtAndRemainder[0]; 853 BigInteger remainder = sqrtAndRemainder[1]; 854 if (remainder.equals(BigInteger.ZERO)) { 855 fail( 856 "RSA key public modulus is perfect square. " 857 + HexDump.dumpHexString(publicKey.getEncoded())); 858 } 859 } 860 } 861 testRSA_Key_Quality_Public_Modulus_GCD_Is_One_Helper( Iterable<PublicKey> publicKeys)862 private void testRSA_Key_Quality_Public_Modulus_GCD_Is_One_Helper( 863 Iterable<PublicKey> publicKeys) { 864 // Inspired by Heninger et al 2012 ( https://factorable.net/paper.html ). 865 866 // First, compute the product of all public moduli. 867 BigInteger allProduct = BigInteger.ONE; 868 for (PublicKey publicKey : publicKeys) { 869 RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey; 870 BigInteger publicModulus = rsaPublicKey.getModulus(); 871 allProduct = allProduct.multiply(publicModulus); 872 } 873 // There are better batch GCD algorithms (eg Bernstein 2004 874 // (https://cr.yp.to/factorization/smoothparts-20040510.pdf)). 875 // Since we are dealing with a small set of keys, we just use BigInteger.gcd(). 876 for (PublicKey publicKey : publicKeys) { 877 RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey; 878 BigInteger publicModulus = rsaPublicKey.getModulus(); 879 BigInteger gcd = allProduct.divide(publicModulus).gcd(publicModulus); 880 881 if (!gcd.equals(BigInteger.ONE)) { 882 Log.i(TAG, "Common factor found"); 883 Log.i(TAG, "Key: " + HexDump.dumpHexString(publicKey.getEncoded())); 884 Log.i(TAG, "GCD : " + gcd.toString(16)); 885 fail( 886 "RSA keys have shared prime factor. Key: " 887 + HexDump.dumpHexString(publicKey.getEncoded()) 888 + " GCD: " 889 + gcd.toString()); 890 } 891 } 892 } 893 getPublicKeys(int numKeysToGenerate, boolean useStrongbox)894 private List<PublicKey> getPublicKeys(int numKeysToGenerate, boolean useStrongbox) 895 throws NoSuchAlgorithmException, NoSuchProviderException, 896 InvalidAlgorithmParameterException { 897 List<PublicKey> publicKeys = new ArrayList<PublicKey>(); 898 KeyPairGenerator generator = getRsaGenerator(); 899 for (int i = 0; i < numKeysToGenerate; i++) { 900 generator.initialize( 901 new KeyGenParameterSpec.Builder( 902 "test" + Integer.toString(i), KeyProperties.PURPOSE_SIGN) 903 .setIsStrongBoxBacked(useStrongbox) 904 .build()); 905 KeyPair kp = generator.generateKeyPair(); 906 PublicKey pk = kp.getPublic(); 907 publicKeys.add(pk); 908 Log.v(TAG, "Key generation round " + Integer.toString(i)); 909 } 910 return publicKeys; 911 } 912 testRSA_Key_Quality_All_DifferentHelper(Iterable<PublicKey> publicKeys)913 public void testRSA_Key_Quality_All_DifferentHelper(Iterable<PublicKey> publicKeys) { 914 Log.d(TAG, "Testing all keys different."); 915 Set<Integer> keyHashSet = new HashSet<Integer>(); 916 for (PublicKey pk : publicKeys) { 917 int keyHash = java.util.Arrays.hashCode(pk.getEncoded()); 918 if (keyHashSet.contains(keyHash)) { 919 fail( 920 "The same RSA key was generated twice. Key: " 921 + HexDump.dumpHexString(pk.getEncoded())); 922 } 923 keyHashSet.add(keyHash); 924 } 925 } 926 testRSA_Key_Quality_Not_Too_Many_ZerosHelper(Iterable<PublicKey> publicKeys)927 public void testRSA_Key_Quality_Not_Too_Many_ZerosHelper(Iterable<PublicKey> publicKeys) { 928 // For 256 random bytes, there is less than a 1 in 10^16 chance of there being 17 929 // or more zero bytes. 930 int maxZerosAllowed = 17; 931 932 for (PublicKey pk : publicKeys) { 933 byte[] keyBytes = pk.getEncoded(); 934 int zeroCount = 0; 935 for (int i = 0; i < keyBytes.length; i++) { 936 if (keyBytes[i] == 0x00) { 937 zeroCount++; 938 } 939 } 940 if (zeroCount >= maxZerosAllowed) { 941 fail("RSA public key has " + Integer.toString(zeroCount) 942 + " zeros. Key: " + HexDump.dumpHexString(keyBytes)); 943 } 944 } 945 } 946 947 @Test testGenerate_EC_ModernSpec_Defaults()948 public void testGenerate_EC_ModernSpec_Defaults() throws Exception { 949 testGenerate_EC_ModernSpec_DefaultsHelper(false /* useStrongbox */); 950 if (TestUtils.hasStrongBox(getContext())) { 951 testGenerate_EC_ModernSpec_DefaultsHelper(true /* useStrongbox */); 952 } 953 } 954 testGenerate_EC_ModernSpec_DefaultsHelper(boolean useStrongbox)955 private void testGenerate_EC_ModernSpec_DefaultsHelper(boolean useStrongbox) throws Exception { 956 KeyPairGenerator generator = getEcGenerator(); 957 generator.initialize(new KeyGenParameterSpec.Builder( 958 TEST_ALIAS_1, 959 KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY) 960 .setIsStrongBoxBacked(useStrongbox) 961 .build()); 962 KeyPair keyPair = generator.generateKeyPair(); 963 assertGeneratedKeyPairAndSelfSignedCertificate( 964 keyPair, 965 TEST_ALIAS_1, 966 "EC", 967 256, 968 DEFAULT_CERT_SUBJECT, 969 DEFAULT_CERT_SERIAL_NUMBER, 970 DEFAULT_CERT_NOT_BEFORE, 971 DEFAULT_CERT_NOT_AFTER); 972 TestUtils.assertECParameterSpecEqualsIgnoreSeedIfNotPresent( 973 ECCurves.NIST_P_256_SPEC, ((ECKey) keyPair.getPrivate()).getParams()); 974 KeyInfo keyInfo = TestUtils.getKeyInfo(keyPair.getPrivate()); 975 assertEquals(256, keyInfo.getKeySize()); 976 assertEquals(TEST_ALIAS_1, keyInfo.getKeystoreAlias()); 977 assertOneOf(keyInfo.getOrigin(), 978 KeyProperties.ORIGIN_GENERATED, KeyProperties.ORIGIN_UNKNOWN); 979 assertEquals( 980 KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY, keyInfo.getPurposes()); 981 assertFalse(keyInfo.isUserAuthenticationRequired()); 982 assertEquals(null, keyInfo.getKeyValidityStart()); 983 assertEquals(null, keyInfo.getKeyValidityForOriginationEnd()); 984 assertEquals(null, keyInfo.getKeyValidityForConsumptionEnd()); 985 MoreAsserts.assertEmpty(Arrays.asList(keyInfo.getBlockModes())); 986 MoreAsserts.assertEmpty(Arrays.asList(keyInfo.getDigests())); 987 MoreAsserts.assertEmpty(Arrays.asList(keyInfo.getSignaturePaddings())); 988 MoreAsserts.assertEmpty(Arrays.asList(keyInfo.getEncryptionPaddings())); 989 } 990 991 @Test testGenerate_RSA_ModernSpec_Defaults()992 public void testGenerate_RSA_ModernSpec_Defaults() throws Exception { 993 testGenerate_RSA_ModernSpec_DefaultsHelper(false /* useStrongbox */); 994 if (TestUtils.hasStrongBox(getContext())) { 995 testGenerate_RSA_ModernSpec_DefaultsHelper(true /* useStrongbox */); 996 } 997 } 998 testGenerate_RSA_ModernSpec_DefaultsHelper(boolean useStrongbox)999 private void testGenerate_RSA_ModernSpec_DefaultsHelper(boolean useStrongbox) throws Exception { 1000 KeyPairGenerator generator = getRsaGenerator(); 1001 generator.initialize(new KeyGenParameterSpec.Builder( 1002 TEST_ALIAS_1, 1003 KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) 1004 .setIsStrongBoxBacked(useStrongbox) 1005 .build()); 1006 KeyPair keyPair = generator.generateKeyPair(); 1007 assertGeneratedKeyPairAndSelfSignedCertificate( 1008 keyPair, 1009 TEST_ALIAS_1, 1010 "RSA", 1011 2048, 1012 DEFAULT_CERT_SUBJECT, 1013 DEFAULT_CERT_SERIAL_NUMBER, 1014 DEFAULT_CERT_NOT_BEFORE, 1015 DEFAULT_CERT_NOT_AFTER); 1016 assertEquals(RSAKeyGenParameterSpec.F4, 1017 ((RSAPublicKey) keyPair.getPublic()).getPublicExponent()); 1018 KeyInfo keyInfo = TestUtils.getKeyInfo(keyPair.getPrivate()); 1019 assertEquals(2048, keyInfo.getKeySize()); 1020 assertEquals(TEST_ALIAS_1, keyInfo.getKeystoreAlias()); 1021 assertOneOf(keyInfo.getOrigin(), 1022 KeyProperties.ORIGIN_GENERATED, KeyProperties.ORIGIN_UNKNOWN); 1023 assertEquals( 1024 KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT, 1025 keyInfo.getPurposes()); 1026 assertFalse(keyInfo.isUserAuthenticationRequired()); 1027 assertEquals(null, keyInfo.getKeyValidityStart()); 1028 assertEquals(null, keyInfo.getKeyValidityForOriginationEnd()); 1029 assertEquals(null, keyInfo.getKeyValidityForConsumptionEnd()); 1030 MoreAsserts.assertEmpty(Arrays.asList(keyInfo.getBlockModes())); 1031 MoreAsserts.assertEmpty(Arrays.asList(keyInfo.getDigests())); 1032 MoreAsserts.assertEmpty(Arrays.asList(keyInfo.getSignaturePaddings())); 1033 MoreAsserts.assertEmpty(Arrays.asList(keyInfo.getEncryptionPaddings())); 1034 } 1035 1036 @Test testGenerate_EC_ModernSpec_AsCustomAsPossible()1037 public void testGenerate_EC_ModernSpec_AsCustomAsPossible() throws Exception { 1038 KeyPairGenerator generator = getEcGenerator(); 1039 Date keyValidityStart = new Date(System.currentTimeMillis()); 1040 Date keyValidityEndDateForOrigination = new Date(System.currentTimeMillis() + 1000000); 1041 Date keyValidityEndDateForConsumption = new Date(System.currentTimeMillis() + 10000000); 1042 1043 Date certNotBefore = new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 24 * 7); 1044 Date certNotAfter = new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 7); 1045 BigInteger certSerialNumber = new BigInteger("12345678"); 1046 X500Principal certSubject = new X500Principal("cn=hello"); 1047 generator.initialize(new KeyGenParameterSpec.Builder( 1048 TEST_ALIAS_1, 1049 KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY 1050 | KeyProperties.PURPOSE_ENCRYPT) 1051 .setKeySize(224) 1052 .setDigests(KeyProperties.DIGEST_SHA384, KeyProperties.DIGEST_SHA512) 1053 .setKeyValidityStart(keyValidityStart) 1054 .setKeyValidityForOriginationEnd(keyValidityEndDateForOrigination) 1055 .setKeyValidityForConsumptionEnd(keyValidityEndDateForConsumption) 1056 .setCertificateSerialNumber(certSerialNumber) 1057 .setCertificateSubject(certSubject) 1058 .setCertificateNotBefore(certNotBefore) 1059 .setCertificateNotAfter(certNotAfter) 1060 .build()); 1061 KeyPair keyPair = generator.generateKeyPair(); 1062 assertGeneratedKeyPairAndSelfSignedCertificate( 1063 keyPair, 1064 TEST_ALIAS_1, 1065 "EC", 1066 224, 1067 certSubject, 1068 certSerialNumber, 1069 certNotBefore, 1070 certNotAfter); 1071 TestUtils.assertECParameterSpecEqualsIgnoreSeedIfNotPresent( 1072 ECCurves.NIST_P_224_SPEC, ((ECKey) keyPair.getPrivate()).getParams()); 1073 KeyInfo keyInfo = TestUtils.getKeyInfo(keyPair.getPrivate()); 1074 assertEquals(224, keyInfo.getKeySize()); 1075 assertEquals(TEST_ALIAS_1, keyInfo.getKeystoreAlias()); 1076 assertOneOf(keyInfo.getOrigin(), 1077 KeyProperties.ORIGIN_GENERATED, KeyProperties.ORIGIN_UNKNOWN); 1078 assertEquals( 1079 KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY 1080 | KeyProperties.PURPOSE_ENCRYPT, 1081 keyInfo.getPurposes()); 1082 assertEquals(keyValidityStart, keyInfo.getKeyValidityStart()); 1083 assertEquals(keyValidityEndDateForOrigination, keyInfo.getKeyValidityForOriginationEnd()); 1084 assertEquals(keyValidityEndDateForConsumption, keyInfo.getKeyValidityForConsumptionEnd()); 1085 MoreAsserts.assertEmpty(Arrays.asList(keyInfo.getBlockModes())); 1086 1087 List<String> actualDigests = new ArrayList<String>(Arrays.asList(keyInfo.getDigests())); 1088 // Keystore may have added DIGEST_NONE, to allow software digesting. 1089 actualDigests.remove(KeyProperties.DIGEST_NONE); 1090 TestUtils.assertContentsInAnyOrder( 1091 actualDigests, KeyProperties.DIGEST_SHA384, KeyProperties.DIGEST_SHA512); 1092 1093 MoreAsserts.assertEmpty(Arrays.asList(keyInfo.getSignaturePaddings())); 1094 MoreAsserts.assertEmpty(Arrays.asList(keyInfo.getEncryptionPaddings())); 1095 assertFalse(keyInfo.isUserAuthenticationRequired()); 1096 assertEquals(0, keyInfo.getUserAuthenticationValidityDurationSeconds()); 1097 } 1098 1099 // Strongbox has more restrictions on key properties than general keystore. 1100 // This is a reworking of the generic test to still be as custom as possible while 1101 // respecting the spec constraints. 1102 // Test fails until the resolution of b/113276806 1103 @Test testGenerate_EC_ModernSpec_AsCustomAsPossibleStrongbox()1104 public void testGenerate_EC_ModernSpec_AsCustomAsPossibleStrongbox() throws Exception { 1105 if (!TestUtils.hasStrongBox(getContext())) { 1106 return; 1107 } 1108 KeyPairGenerator generator = getEcGenerator(); 1109 Date keyValidityStart = new Date(System.currentTimeMillis()); 1110 Date keyValidityEndDateForOrigination = new Date(System.currentTimeMillis() + 1000000); 1111 Date keyValidityEndDateForConsumption = new Date(System.currentTimeMillis() + 10000000); 1112 1113 Date certNotBefore = new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 24 * 7); 1114 Date certNotAfter = new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 7); 1115 BigInteger certSerialNumber = new BigInteger("12345678"); 1116 X500Principal certSubject = new X500Principal("cn=hello"); 1117 generator.initialize(new KeyGenParameterSpec.Builder( 1118 TEST_ALIAS_1, 1119 KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY 1120 | KeyProperties.PURPOSE_ENCRYPT) 1121 .setKeySize(256) 1122 .setDigests(KeyProperties.DIGEST_SHA256) 1123 .setKeyValidityStart(keyValidityStart) 1124 .setKeyValidityForOriginationEnd(keyValidityEndDateForOrigination) 1125 .setKeyValidityForConsumptionEnd(keyValidityEndDateForConsumption) 1126 .setCertificateSerialNumber(certSerialNumber) 1127 .setCertificateSubject(certSubject) 1128 .setCertificateNotBefore(certNotBefore) 1129 .setCertificateNotAfter(certNotAfter) 1130 .setIsStrongBoxBacked(true) 1131 .build()); 1132 KeyPair keyPair = generator.generateKeyPair(); 1133 assertGeneratedKeyPairAndSelfSignedCertificate( 1134 keyPair, 1135 TEST_ALIAS_1, 1136 "EC", 1137 256, 1138 certSubject, 1139 certSerialNumber, 1140 certNotBefore, 1141 certNotAfter); 1142 TestUtils.assertECParameterSpecEqualsIgnoreSeedIfNotPresent( 1143 ECCurves.NIST_P_256_SPEC, ((ECKey) keyPair.getPrivate()).getParams()); 1144 KeyInfo keyInfo = TestUtils.getKeyInfo(keyPair.getPrivate()); 1145 assertEquals(256, keyInfo.getKeySize()); 1146 assertEquals(TEST_ALIAS_1, keyInfo.getKeystoreAlias()); 1147 assertOneOf(keyInfo.getOrigin(), 1148 KeyProperties.ORIGIN_GENERATED, KeyProperties.ORIGIN_UNKNOWN); 1149 assertEquals( 1150 KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY 1151 | KeyProperties.PURPOSE_ENCRYPT, 1152 keyInfo.getPurposes()); 1153 assertEquals(keyValidityStart, keyInfo.getKeyValidityStart()); 1154 assertEquals(keyValidityEndDateForOrigination, keyInfo.getKeyValidityForOriginationEnd()); 1155 assertEquals(keyValidityEndDateForConsumption, keyInfo.getKeyValidityForConsumptionEnd()); 1156 MoreAsserts.assertEmpty(Arrays.asList(keyInfo.getBlockModes())); 1157 1158 List<String> actualDigests = new ArrayList<String>(Arrays.asList(keyInfo.getDigests())); 1159 // Keystore may have added DIGEST_NONE, to allow software digesting. 1160 actualDigests.remove(KeyProperties.DIGEST_NONE); 1161 TestUtils.assertContentsInAnyOrder( 1162 actualDigests, KeyProperties.DIGEST_SHA256); 1163 1164 MoreAsserts.assertEmpty(Arrays.asList(keyInfo.getSignaturePaddings())); 1165 MoreAsserts.assertEmpty(Arrays.asList(keyInfo.getEncryptionPaddings())); 1166 assertFalse(keyInfo.isUserAuthenticationRequired()); 1167 assertEquals(0, keyInfo.getUserAuthenticationValidityDurationSeconds()); 1168 } 1169 1170 @Test testGenerate_RSA_ModernSpec_AsCustomAsPossible()1171 public void testGenerate_RSA_ModernSpec_AsCustomAsPossible() throws Exception { 1172 KeyPairGenerator generator = getRsaGenerator(); 1173 Date keyValidityStart = new Date(System.currentTimeMillis()); 1174 Date keyValidityEndDateForOrigination = new Date(System.currentTimeMillis() + 1000000); 1175 Date keyValidityEndDateForConsumption = new Date(System.currentTimeMillis() + 10000000); 1176 1177 Date certNotBefore = new Date(System.currentTimeMillis() - 1000L * 60 * 60 * 24 * 210); 1178 Date certNotAfter = new Date(System.currentTimeMillis() + 1000L * 60 * 60 * 24 * 210); 1179 BigInteger certSerialNumber = new BigInteger("1234567890"); 1180 X500Principal certSubject = new X500Principal("cn=hello2"); 1181 generator.initialize(new KeyGenParameterSpec.Builder( 1182 TEST_ALIAS_1, 1183 KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY 1184 | KeyProperties.PURPOSE_ENCRYPT) 1185 .setAlgorithmParameterSpec( 1186 new RSAKeyGenParameterSpec(3072, RSAKeyGenParameterSpec.F0)) 1187 .setKeySize(3072) 1188 .setDigests(KeyProperties.DIGEST_SHA384, KeyProperties.DIGEST_SHA512) 1189 .setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PSS, 1190 KeyProperties.SIGNATURE_PADDING_RSA_PKCS1) 1191 .setBlockModes(KeyProperties.BLOCK_MODE_ECB) 1192 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_OAEP, 1193 KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1) 1194 .setKeyValidityStart(keyValidityStart) 1195 .setKeyValidityForOriginationEnd(keyValidityEndDateForOrigination) 1196 .setKeyValidityForConsumptionEnd(keyValidityEndDateForConsumption) 1197 .setCertificateSerialNumber(certSerialNumber) 1198 .setCertificateSubject(certSubject) 1199 .setCertificateNotBefore(certNotBefore) 1200 .setCertificateNotAfter(certNotAfter) 1201 .build()); 1202 KeyPair keyPair = generator.generateKeyPair(); 1203 assertGeneratedKeyPairAndSelfSignedCertificate( 1204 keyPair, 1205 TEST_ALIAS_1, 1206 "RSA", 1207 3072, 1208 certSubject, 1209 certSerialNumber, 1210 certNotBefore, 1211 certNotAfter); 1212 assertEquals(RSAKeyGenParameterSpec.F0, 1213 ((RSAPublicKey) keyPair.getPublic()).getPublicExponent()); 1214 KeyInfo keyInfo = TestUtils.getKeyInfo(keyPair.getPrivate()); 1215 assertEquals(3072, keyInfo.getKeySize()); 1216 assertEquals(TEST_ALIAS_1, keyInfo.getKeystoreAlias()); 1217 assertOneOf(keyInfo.getOrigin(), 1218 KeyProperties.ORIGIN_GENERATED, KeyProperties.ORIGIN_UNKNOWN); 1219 assertEquals( 1220 KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY 1221 | KeyProperties.PURPOSE_ENCRYPT, 1222 keyInfo.getPurposes()); 1223 assertEquals(keyValidityStart, keyInfo.getKeyValidityStart()); 1224 assertEquals(keyValidityEndDateForOrigination, keyInfo.getKeyValidityForOriginationEnd()); 1225 assertEquals(keyValidityEndDateForConsumption, keyInfo.getKeyValidityForConsumptionEnd()); 1226 1227 List<String> actualDigests = 1228 new ArrayList<String>(Arrays.asList(keyInfo.getDigests())); 1229 // Keystore may have added DIGEST_NONE, to allow software digesting. 1230 actualDigests.remove(KeyProperties.DIGEST_NONE); 1231 TestUtils.assertContentsInAnyOrder( 1232 actualDigests, KeyProperties.DIGEST_SHA384, KeyProperties.DIGEST_SHA512); 1233 1234 TestUtils.assertContentsInAnyOrder(Arrays.asList(keyInfo.getSignaturePaddings()), 1235 KeyProperties.SIGNATURE_PADDING_RSA_PKCS1, 1236 KeyProperties.SIGNATURE_PADDING_RSA_PSS); 1237 MoreAsserts.assertContentsInAnyOrder(Arrays.asList(keyInfo.getBlockModes()), 1238 KeyProperties.BLOCK_MODE_ECB); 1239 1240 List<String> actualEncryptionPaddings = 1241 new ArrayList<String>(Arrays.asList(keyInfo.getEncryptionPaddings())); 1242 // Keystore may have added ENCRYPTION_PADDING_NONE, to allow software padding. 1243 actualEncryptionPaddings.remove(KeyProperties.ENCRYPTION_PADDING_NONE); 1244 TestUtils.assertContentsInAnyOrder(actualEncryptionPaddings, 1245 KeyProperties.ENCRYPTION_PADDING_RSA_OAEP, 1246 KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1); 1247 1248 assertFalse(keyInfo.isUserAuthenticationRequired()); 1249 assertEquals(0, keyInfo.getUserAuthenticationValidityDurationSeconds()); 1250 } 1251 1252 // Strongbox has more restrictions on key properties than general keystore. 1253 // This is a reworking of the generic test to still be as custom as possible while 1254 // respecting the spec constraints. 1255 // Test fails until the resolution of b/113276806 1256 @Test testGenerate_RSA_ModernSpec_AsCustomAsPossibleStrongbox()1257 public void testGenerate_RSA_ModernSpec_AsCustomAsPossibleStrongbox() throws Exception { 1258 if (!TestUtils.hasStrongBox(getContext())) { 1259 return; 1260 } 1261 KeyPairGenerator generator = getRsaGenerator(); 1262 Date keyValidityStart = new Date(System.currentTimeMillis()); 1263 Date keyValidityEndDateForOrigination = new Date(System.currentTimeMillis() + 1000000); 1264 Date keyValidityEndDateForConsumption = new Date(System.currentTimeMillis() + 10000000); 1265 1266 Date certNotBefore = new Date(System.currentTimeMillis() - 1000L * 60 * 60 * 24 * 210); 1267 Date certNotAfter = new Date(System.currentTimeMillis() + 1000L * 60 * 60 * 24 * 210); 1268 BigInteger certSerialNumber = new BigInteger("1234567890"); 1269 X500Principal certSubject = new X500Principal("cn=hello2"); 1270 generator.initialize(new KeyGenParameterSpec.Builder( 1271 TEST_ALIAS_1, 1272 KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY 1273 | KeyProperties.PURPOSE_ENCRYPT) 1274 .setAlgorithmParameterSpec( 1275 new RSAKeyGenParameterSpec(2048, RSAKeyGenParameterSpec.F4)) 1276 .setKeySize(2048) 1277 .setDigests(KeyProperties.DIGEST_SHA256) 1278 .setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PSS, 1279 KeyProperties.SIGNATURE_PADDING_RSA_PKCS1) 1280 .setBlockModes(KeyProperties.BLOCK_MODE_ECB) 1281 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_OAEP, 1282 KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1) 1283 .setKeyValidityStart(keyValidityStart) 1284 .setKeyValidityForOriginationEnd(keyValidityEndDateForOrigination) 1285 .setKeyValidityForConsumptionEnd(keyValidityEndDateForConsumption) 1286 .setCertificateSerialNumber(certSerialNumber) 1287 .setCertificateSubject(certSubject) 1288 .setCertificateNotBefore(certNotBefore) 1289 .setCertificateNotAfter(certNotAfter) 1290 .setIsStrongBoxBacked(true) 1291 .build()); 1292 KeyPair keyPair = generator.generateKeyPair(); 1293 assertGeneratedKeyPairAndSelfSignedCertificate( 1294 keyPair, 1295 TEST_ALIAS_1, 1296 "RSA", 1297 2048, 1298 certSubject, 1299 certSerialNumber, 1300 certNotBefore, 1301 certNotAfter); 1302 assertEquals(RSAKeyGenParameterSpec.F4, 1303 ((RSAPublicKey) keyPair.getPublic()).getPublicExponent()); 1304 KeyInfo keyInfo = TestUtils.getKeyInfo(keyPair.getPrivate()); 1305 assertEquals(2048, keyInfo.getKeySize()); 1306 assertEquals(TEST_ALIAS_1, keyInfo.getKeystoreAlias()); 1307 assertOneOf(keyInfo.getOrigin(), 1308 KeyProperties.ORIGIN_GENERATED, KeyProperties.ORIGIN_UNKNOWN); 1309 assertEquals( 1310 KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY 1311 | KeyProperties.PURPOSE_ENCRYPT, 1312 keyInfo.getPurposes()); 1313 assertEquals(keyValidityStart, keyInfo.getKeyValidityStart()); 1314 assertEquals(keyValidityEndDateForOrigination, keyInfo.getKeyValidityForOriginationEnd()); 1315 assertEquals(keyValidityEndDateForConsumption, keyInfo.getKeyValidityForConsumptionEnd()); 1316 1317 List<String> actualDigests = 1318 new ArrayList<String>(Arrays.asList(keyInfo.getDigests())); 1319 // Keystore may have added DIGEST_NONE, to allow software digesting. 1320 actualDigests.remove(KeyProperties.DIGEST_NONE); 1321 TestUtils.assertContentsInAnyOrder( 1322 actualDigests, KeyProperties.DIGEST_SHA256); 1323 1324 TestUtils.assertContentsInAnyOrder(Arrays.asList(keyInfo.getSignaturePaddings()), 1325 KeyProperties.SIGNATURE_PADDING_RSA_PKCS1, 1326 KeyProperties.SIGNATURE_PADDING_RSA_PSS); 1327 MoreAsserts.assertContentsInAnyOrder(Arrays.asList(keyInfo.getBlockModes()), 1328 KeyProperties.BLOCK_MODE_ECB); 1329 1330 List<String> actualEncryptionPaddings = 1331 new ArrayList<String>(Arrays.asList(keyInfo.getEncryptionPaddings())); 1332 // Keystore may have added ENCRYPTION_PADDING_NONE, to allow software padding. 1333 actualEncryptionPaddings.remove(KeyProperties.ENCRYPTION_PADDING_NONE); 1334 TestUtils.assertContentsInAnyOrder(actualEncryptionPaddings, 1335 KeyProperties.ENCRYPTION_PADDING_RSA_OAEP, 1336 KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1); 1337 1338 assertFalse(keyInfo.isUserAuthenticationRequired()); 1339 assertEquals(0, keyInfo.getUserAuthenticationValidityDurationSeconds()); 1340 } 1341 1342 @Test testGenerate_EC_ModernSpec_UsableForTLSPeerAuth()1343 public void testGenerate_EC_ModernSpec_UsableForTLSPeerAuth() throws Exception { 1344 testGenerate_EC_ModernSpec_UsableForTLSPeerAuthHelper(false /* useStrongbox */); 1345 if (TestUtils.hasStrongBox(getContext())) { 1346 testGenerate_EC_ModernSpec_UsableForTLSPeerAuthHelper(true /* useStrongbox */); 1347 } 1348 } 1349 testGenerate_EC_ModernSpec_UsableForTLSPeerAuthHelper(boolean useStrongbox)1350 private void testGenerate_EC_ModernSpec_UsableForTLSPeerAuthHelper(boolean useStrongbox) throws Exception { 1351 KeyPairGenerator generator = getEcGenerator(); 1352 generator.initialize(new KeyGenParameterSpec.Builder( 1353 TEST_ALIAS_1, 1354 KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY) 1355 .setDigests(KeyProperties.DIGEST_NONE, KeyProperties.DIGEST_SHA256) 1356 .setIsStrongBoxBacked(useStrongbox) 1357 .build()); 1358 KeyPair keyPair = generator.generateKeyPair(); 1359 assertGeneratedKeyPairAndSelfSignedCertificate( 1360 keyPair, 1361 TEST_ALIAS_1, 1362 "EC", 1363 256, 1364 DEFAULT_CERT_SUBJECT, 1365 DEFAULT_CERT_SERIAL_NUMBER, 1366 DEFAULT_CERT_NOT_BEFORE, 1367 DEFAULT_CERT_NOT_AFTER); 1368 KeyInfo keyInfo = TestUtils.getKeyInfo(keyPair.getPrivate()); 1369 MoreAsserts.assertEmpty(Arrays.asList(keyInfo.getBlockModes())); 1370 MoreAsserts.assertContentsInAnyOrder(Arrays.asList(keyInfo.getDigests()), 1371 KeyProperties.DIGEST_NONE, KeyProperties.DIGEST_SHA256); 1372 MoreAsserts.assertEmpty(Arrays.asList(keyInfo.getSignaturePaddings())); 1373 MoreAsserts.assertEmpty(Arrays.asList(keyInfo.getEncryptionPaddings())); 1374 assertSelfSignedCertificateSignatureVerifies(TEST_ALIAS_1); 1375 assertKeyPairAndCertificateUsableForTLSPeerAuthentication(TEST_ALIAS_1); 1376 } 1377 1378 @Test testGenerate_RSA_ModernSpec_UsableForTLSPeerAuth()1379 public void testGenerate_RSA_ModernSpec_UsableForTLSPeerAuth() throws Exception { 1380 KeyPairGenerator generator = getRsaGenerator(); 1381 generator.initialize(new KeyGenParameterSpec.Builder( 1382 TEST_ALIAS_1, 1383 KeyProperties.PURPOSE_SIGN 1384 | KeyProperties.PURPOSE_VERIFY 1385 | KeyProperties.PURPOSE_DECRYPT) 1386 .setDigests(KeyProperties.DIGEST_NONE, 1387 KeyProperties.DIGEST_SHA256, 1388 KeyProperties.DIGEST_SHA512) 1389 .setEncryptionPaddings( 1390 KeyProperties.ENCRYPTION_PADDING_NONE, 1391 KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1) 1392 .setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1) 1393 .build()); 1394 KeyPair keyPair = generator.generateKeyPair(); 1395 assertGeneratedKeyPairAndSelfSignedCertificate( 1396 keyPair, 1397 TEST_ALIAS_1, 1398 "RSA", 1399 2048, 1400 DEFAULT_CERT_SUBJECT, 1401 DEFAULT_CERT_SERIAL_NUMBER, 1402 DEFAULT_CERT_NOT_BEFORE, 1403 DEFAULT_CERT_NOT_AFTER); 1404 KeyInfo keyInfo = TestUtils.getKeyInfo(keyPair.getPrivate()); 1405 MoreAsserts.assertEmpty(Arrays.asList(keyInfo.getBlockModes())); 1406 MoreAsserts.assertContentsInAnyOrder(Arrays.asList(keyInfo.getDigests()), 1407 KeyProperties.DIGEST_NONE, 1408 KeyProperties.DIGEST_SHA256, 1409 KeyProperties.DIGEST_SHA512); 1410 MoreAsserts.assertContentsInAnyOrder(Arrays.asList(keyInfo.getSignaturePaddings()), 1411 KeyProperties.SIGNATURE_PADDING_RSA_PKCS1); 1412 MoreAsserts.assertContentsInAnyOrder(Arrays.asList(keyInfo.getEncryptionPaddings()), 1413 KeyProperties.ENCRYPTION_PADDING_NONE, 1414 KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1); 1415 assertSelfSignedCertificateSignatureVerifies(TEST_ALIAS_1); 1416 assertKeyPairAndCertificateUsableForTLSPeerAuthentication(TEST_ALIAS_1); 1417 } 1418 1419 // TODO: Test fingerprint-authorized and secure lock screen-authorized keys. These can't 1420 // currently be tested here because CTS does not require that secure lock screen is set up and 1421 // that at least one fingerprint is enrolled. 1422 1423 @Test testGenerate_EC_ModernSpec_KeyNotYetValid()1424 public void testGenerate_EC_ModernSpec_KeyNotYetValid() throws Exception { 1425 testGenerate_EC_ModernSpec_KeyNotYetValidHelper(false /* useStrongbox */); 1426 if (TestUtils.hasStrongBox(getContext())) { 1427 testGenerate_EC_ModernSpec_KeyNotYetValidHelper(true /* useStrongbox */); 1428 } 1429 } 1430 testGenerate_EC_ModernSpec_KeyNotYetValidHelper(boolean useStrongbox)1431 private void testGenerate_EC_ModernSpec_KeyNotYetValidHelper(boolean useStrongbox) throws Exception { 1432 KeyPairGenerator generator = getEcGenerator(); 1433 Date validityStart = new Date(System.currentTimeMillis() + DAY_IN_MILLIS); 1434 generator.initialize(new KeyGenParameterSpec.Builder( 1435 TEST_ALIAS_1, 1436 KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY) 1437 .setKeySize(256) 1438 .setDigests(KeyProperties.DIGEST_SHA256) 1439 .setKeyValidityStart(validityStart) 1440 .setIsStrongBoxBacked(useStrongbox) 1441 .build()); 1442 KeyPair keyPair = generator.generateKeyPair(); 1443 assertGeneratedKeyPairAndSelfSignedCertificate( 1444 keyPair, 1445 TEST_ALIAS_1, 1446 "EC", 1447 256, 1448 DEFAULT_CERT_SUBJECT, 1449 DEFAULT_CERT_SERIAL_NUMBER, 1450 DEFAULT_CERT_NOT_BEFORE, 1451 DEFAULT_CERT_NOT_AFTER); 1452 KeyInfo keyInfo = TestUtils.getKeyInfo(keyPair.getPrivate()); 1453 assertEquals(validityStart, keyInfo.getKeyValidityStart()); 1454 } 1455 1456 @Test testGenerate_RSA_ModernSpec_KeyExpiredForOrigination()1457 public void testGenerate_RSA_ModernSpec_KeyExpiredForOrigination() throws Exception { 1458 KeyPairGenerator generator = getRsaGenerator(); 1459 Date originationEnd = new Date(System.currentTimeMillis() - DAY_IN_MILLIS); 1460 generator.initialize(new KeyGenParameterSpec.Builder( 1461 TEST_ALIAS_1, 1462 KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY) 1463 .setKeySize(1024) 1464 .setDigests(KeyProperties.DIGEST_SHA256) 1465 .setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1) 1466 .setKeyValidityForOriginationEnd(originationEnd) 1467 .build()); 1468 KeyPair keyPair = generator.generateKeyPair(); 1469 assertGeneratedKeyPairAndSelfSignedCertificate( 1470 keyPair, 1471 TEST_ALIAS_1, 1472 "RSA", 1473 1024, 1474 DEFAULT_CERT_SUBJECT, 1475 DEFAULT_CERT_SERIAL_NUMBER, 1476 DEFAULT_CERT_NOT_BEFORE, 1477 DEFAULT_CERT_NOT_AFTER); 1478 KeyInfo keyInfo = TestUtils.getKeyInfo(keyPair.getPrivate()); 1479 assertEquals(originationEnd, keyInfo.getKeyValidityForOriginationEnd()); 1480 } 1481 1482 @Test testGenerate_EC_ModernSpec_SupportedSizes()1483 public void testGenerate_EC_ModernSpec_SupportedSizes() throws Exception { 1484 assertKeyGenUsingECSizeOnlyUsesCorrectCurve(224, ECCurves.NIST_P_224_SPEC); 1485 assertKeyGenUsingECSizeOnlyUsesCorrectCurve(256, ECCurves.NIST_P_256_SPEC); 1486 assertKeyGenUsingECSizeOnlyUsesCorrectCurve(384, ECCurves.NIST_P_384_SPEC); 1487 assertKeyGenUsingECSizeOnlyUsesCorrectCurve(521, ECCurves.NIST_P_521_SPEC); 1488 if (TestUtils.hasStrongBox(getContext())) { 1489 assertKeyGenUsingECSizeOnlyUsesCorrectCurve(256, ECCurves.NIST_P_256_SPEC, true); 1490 } 1491 } 1492 1493 //TODO: Fix b/113108008 so this test will pass for strongbox. 1494 @Test testGenerate_EC_ModernSpec_UnsupportedSizesRejected()1495 public void testGenerate_EC_ModernSpec_UnsupportedSizesRejected() throws Exception { 1496 for (int keySizeBits = 0; keySizeBits <= 1024; keySizeBits++) { 1497 testGenerate_EC_ModernSpec_UnsupportedSizesRejectedHelper(false, keySizeBits); 1498 if (TestUtils.hasStrongBox(getContext())) { 1499 testGenerate_EC_ModernSpec_UnsupportedSizesRejectedHelper(true, keySizeBits); 1500 } 1501 } 1502 } 1503 testGenerate_EC_ModernSpec_UnsupportedSizesRejectedHelper(boolean useStrongbox, int keySizeBits)1504 private void testGenerate_EC_ModernSpec_UnsupportedSizesRejectedHelper(boolean useStrongbox, int keySizeBits) throws Exception { 1505 if (!useStrongbox) { 1506 if ((keySizeBits == 224) || (keySizeBits == 256) || (keySizeBits == 384) 1507 || (keySizeBits == 521)) { 1508 // Skip supported sizes 1509 return; 1510 } 1511 } else { 1512 // Strongbox only supports 256 bit EC key size 1513 if (keySizeBits == 256) { 1514 return; 1515 } 1516 } 1517 KeyPairGenerator generator = getEcGenerator(); 1518 1519 try { 1520 generator.initialize(new KeyGenParameterSpec.Builder( 1521 TEST_ALIAS_1, 1522 KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY) 1523 .setKeySize(keySizeBits) 1524 .setIsStrongBoxBacked(useStrongbox) 1525 .build()); 1526 fail("EC KeyPairGenerator initialized with unsupported key size: " 1527 + keySizeBits + " bits. useStrongbox: " + useStrongbox 1528 + "\nThis test will fail until b/113108008 is resolved"); 1529 } catch (InvalidAlgorithmParameterException expected) { 1530 } 1531 } 1532 1533 @Test testGenerate_EC_ModernSpec_SupportedNamedCurves()1534 public void testGenerate_EC_ModernSpec_SupportedNamedCurves() throws Exception { 1535 assertKeyGenUsingECNamedCurveSupported("P-224", ECCurves.NIST_P_224_SPEC); 1536 assertKeyGenUsingECNamedCurveSupported("p-224", ECCurves.NIST_P_224_SPEC); 1537 assertKeyGenUsingECNamedCurveSupported("secp224r1", ECCurves.NIST_P_224_SPEC); 1538 assertKeyGenUsingECNamedCurveSupported("SECP224R1", ECCurves.NIST_P_224_SPEC); 1539 1540 assertKeyGenUsingECNamedCurveSupported("P-256", ECCurves.NIST_P_256_SPEC); 1541 assertKeyGenUsingECNamedCurveSupported("p-256", ECCurves.NIST_P_256_SPEC); 1542 assertKeyGenUsingECNamedCurveSupported("secp256r1", ECCurves.NIST_P_256_SPEC); 1543 assertKeyGenUsingECNamedCurveSupported("SECP256R1", ECCurves.NIST_P_256_SPEC); 1544 assertKeyGenUsingECNamedCurveSupported("prime256v1", ECCurves.NIST_P_256_SPEC); 1545 assertKeyGenUsingECNamedCurveSupported("PRIME256V1", ECCurves.NIST_P_256_SPEC); 1546 1547 if (TestUtils.hasStrongBox(getContext())) { 1548 assertKeyGenUsingECNamedCurveSupported("P-256", ECCurves.NIST_P_256_SPEC, true); 1549 assertKeyGenUsingECNamedCurveSupported("p-256", ECCurves.NIST_P_256_SPEC, true); 1550 assertKeyGenUsingECNamedCurveSupported("secp256r1", ECCurves.NIST_P_256_SPEC, true); 1551 assertKeyGenUsingECNamedCurveSupported("SECP256R1", ECCurves.NIST_P_256_SPEC, true); 1552 assertKeyGenUsingECNamedCurveSupported("prime256v1", ECCurves.NIST_P_256_SPEC, true); 1553 assertKeyGenUsingECNamedCurveSupported("PRIME256V1", ECCurves.NIST_P_256_SPEC, true); 1554 } 1555 1556 assertKeyGenUsingECNamedCurveSupported("P-384", ECCurves.NIST_P_384_SPEC); 1557 assertKeyGenUsingECNamedCurveSupported("p-384", ECCurves.NIST_P_384_SPEC); 1558 assertKeyGenUsingECNamedCurveSupported("secp384r1", ECCurves.NIST_P_384_SPEC); 1559 assertKeyGenUsingECNamedCurveSupported("SECP384R1", ECCurves.NIST_P_384_SPEC); 1560 1561 assertKeyGenUsingECNamedCurveSupported("P-521", ECCurves.NIST_P_521_SPEC); 1562 assertKeyGenUsingECNamedCurveSupported("p-521", ECCurves.NIST_P_521_SPEC); 1563 assertKeyGenUsingECNamedCurveSupported("secp521r1", ECCurves.NIST_P_521_SPEC); 1564 assertKeyGenUsingECNamedCurveSupported("SECP521R1", ECCurves.NIST_P_521_SPEC); 1565 } 1566 1567 @Test testGenerate_RSA_ModernSpec_SupportedSizes()1568 public void testGenerate_RSA_ModernSpec_SupportedSizes() throws Exception { 1569 assertKeyGenUsingRSASizeOnlySupported(512); 1570 assertKeyGenUsingRSASizeOnlySupported(768); 1571 assertKeyGenUsingRSASizeOnlySupported(1024); 1572 assertKeyGenUsingRSASizeOnlySupported(2048); 1573 if (TestUtils.hasStrongBox(getContext())) { 1574 assertKeyGenUsingRSASizeOnlySupported(2048, true); 1575 } 1576 assertKeyGenUsingRSASizeOnlySupported(3072); 1577 assertKeyGenUsingRSASizeOnlySupported(4096); 1578 1579 // The above use F4. Check that F0 is supported as well, just in case somebody is crazy 1580 // enough. 1581 assertKeyGenUsingRSAKeyGenParameterSpecSupported(new RSAKeyGenParameterSpec( 1582 2048, RSAKeyGenParameterSpec.F0)); 1583 } 1584 1585 @Test testGenerate_RSA_IndCpaEnforced()1586 public void testGenerate_RSA_IndCpaEnforced() throws Exception { 1587 testGenerate_RSA_IndCpaEnforcedHelper(false /* useStrongbox */); 1588 if (TestUtils.hasStrongBox(getContext())) { 1589 testGenerate_RSA_IndCpaEnforcedHelper(true /* useStrongbox */); 1590 } 1591 } 1592 testGenerate_RSA_IndCpaEnforcedHelper(boolean useStrongbox)1593 private void testGenerate_RSA_IndCpaEnforcedHelper(boolean useStrongbox) throws Exception { 1594 KeyGenParameterSpec.Builder goodBuilder = new KeyGenParameterSpec.Builder( 1595 TEST_ALIAS_1, KeyProperties.PURPOSE_ENCRYPT) 1596 .setIsStrongBoxBacked(useStrongbox) 1597 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_OAEP, 1598 KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1); 1599 assertKeyGenInitSucceeds("RSA", goodBuilder.build()); 1600 1601 // Should be fine because IND-CPA restriction applies only to encryption keys 1602 assertKeyGenInitSucceeds("RSA", 1603 TestUtils.buildUpon(goodBuilder, KeyProperties.PURPOSE_DECRYPT) 1604 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) 1605 .build()); 1606 1607 assertKeyGenInitThrowsInvalidAlgorithmParameterException("RSA", 1608 TestUtils.buildUpon(goodBuilder) 1609 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) 1610 .build()); 1611 1612 assertKeyGenInitSucceeds("RSA", 1613 TestUtils.buildUpon(goodBuilder) 1614 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) 1615 .setRandomizedEncryptionRequired(false) 1616 .build()); 1617 1618 // Should fail because PKCS#7 padding doesn't work with RSA 1619 assertKeyGenInitThrowsInvalidAlgorithmParameterException("RSA", 1620 TestUtils.buildUpon(goodBuilder) 1621 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7) 1622 .build()); 1623 } 1624 1625 @Test testGenerate_EC_IndCpaEnforced()1626 public void testGenerate_EC_IndCpaEnforced() throws Exception { 1627 testGenerate_EC_IndCpaEnforcedHelper(false /* useStrongbox */); 1628 if (TestUtils.hasStrongBox(getContext())) { 1629 testGenerate_EC_IndCpaEnforcedHelper(true /* useStrongbox */); 1630 } 1631 } 1632 testGenerate_EC_IndCpaEnforcedHelper(boolean useStrongbox)1633 public void testGenerate_EC_IndCpaEnforcedHelper(boolean useStrongbox) throws Exception { 1634 KeyGenParameterSpec.Builder goodBuilder = new KeyGenParameterSpec.Builder( 1635 TEST_ALIAS_2, KeyProperties.PURPOSE_ENCRYPT) 1636 .setIsStrongBoxBacked(useStrongbox); 1637 assertKeyGenInitSucceeds("EC", goodBuilder.build()); 1638 1639 // Should be fine because IND-CPA restriction applies only to encryption keys 1640 assertKeyGenInitSucceeds("EC", 1641 TestUtils.buildUpon(goodBuilder, KeyProperties.PURPOSE_DECRYPT) 1642 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) 1643 .build()); 1644 1645 assertKeyGenInitThrowsInvalidAlgorithmParameterException("EC", 1646 TestUtils.buildUpon(goodBuilder) 1647 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) 1648 .build()); 1649 1650 assertKeyGenInitSucceeds("EC", 1651 TestUtils.buildUpon(goodBuilder) 1652 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) 1653 .setRandomizedEncryptionRequired(false) 1654 .build()); 1655 } 1656 1657 // http://b/28384942 1658 @Test testGenerateWithFarsiLocale()1659 public void testGenerateWithFarsiLocale() throws Exception { 1660 testGenerateWithFarsiLocaleHelper(false /* useStrongbox */); 1661 if (TestUtils.hasStrongBox(getContext())) { 1662 testGenerateWithFarsiLocaleHelper(true /* useStrongbox */); 1663 } 1664 } 1665 testGenerateWithFarsiLocaleHelper(boolean useStrongbox)1666 private void testGenerateWithFarsiLocaleHelper(boolean useStrongbox) throws Exception { 1667 Locale defaultLocale = Locale.getDefault(); 1668 // Note that we use farsi here because its number formatter doesn't use 1669 // arabic digits. 1670 Locale fa_IR = Locale.forLanguageTag("fa-IR"); 1671 DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(fa_IR); 1672 assertFalse('0' == dfs.getZeroDigit()); 1673 1674 Locale.setDefault(fa_IR); 1675 try { 1676 KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance( 1677 KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore"); 1678 1679 keyGenerator.initialize(new KeyGenParameterSpec.Builder( 1680 TEST_ALIAS_1, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) 1681 .setBlockModes(KeyProperties.BLOCK_MODE_ECB) 1682 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1) 1683 .setIsStrongBoxBacked(useStrongbox) 1684 .build()); 1685 1686 keyGenerator.generateKeyPair(); 1687 } finally { 1688 Locale.setDefault(defaultLocale); 1689 } 1690 } 1691 assertKeyGenInitSucceeds(String algorithm, AlgorithmParameterSpec params)1692 private void assertKeyGenInitSucceeds(String algorithm, AlgorithmParameterSpec params) 1693 throws Exception { 1694 KeyPairGenerator generator = getGenerator(algorithm); 1695 generator.initialize(params); 1696 } 1697 assertKeyGenInitThrowsInvalidAlgorithmParameterException( String algorithm, AlgorithmParameterSpec params)1698 private void assertKeyGenInitThrowsInvalidAlgorithmParameterException( 1699 String algorithm, AlgorithmParameterSpec params) throws Exception { 1700 KeyPairGenerator generator = getGenerator(algorithm); 1701 try { 1702 generator.initialize(params); 1703 fail(); 1704 } catch (InvalidAlgorithmParameterException expected) {} 1705 } 1706 assertKeyGenUsingECSizeOnlyUsesCorrectCurve( int keySizeBits, ECParameterSpec expectedParams)1707 private void assertKeyGenUsingECSizeOnlyUsesCorrectCurve( 1708 int keySizeBits, ECParameterSpec expectedParams) throws Exception { 1709 assertKeyGenUsingECSizeOnlyUsesCorrectCurve(keySizeBits, expectedParams, false); 1710 } 1711 assertKeyGenUsingECSizeOnlyUsesCorrectCurve( int keySizeBits, ECParameterSpec expectedParams, boolean useStrongbox)1712 private void assertKeyGenUsingECSizeOnlyUsesCorrectCurve( 1713 int keySizeBits, ECParameterSpec expectedParams, boolean useStrongbox) throws Exception { 1714 KeyPairGenerator generator = getEcGenerator(); 1715 generator.initialize(new KeyGenParameterSpec.Builder( 1716 TEST_ALIAS_1, 1717 KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY) 1718 .setKeySize(keySizeBits) 1719 .setIsStrongBoxBacked(useStrongbox) 1720 .build(), 1721 mRng); 1722 mRng.resetCounters(); 1723 KeyPair keyPair = generator.generateKeyPair(); 1724 long consumedEntropyAmountBytes = mRng.getOutputSizeBytes(); 1725 int expectedKeySize = expectedParams.getCurve().getField().getFieldSize(); 1726 assertGeneratedKeyPairAndSelfSignedCertificate( 1727 keyPair, 1728 TEST_ALIAS_1, 1729 "EC", 1730 expectedKeySize, 1731 DEFAULT_CERT_SUBJECT, 1732 DEFAULT_CERT_SERIAL_NUMBER, 1733 DEFAULT_CERT_NOT_BEFORE, 1734 DEFAULT_CERT_NOT_AFTER); 1735 KeyInfo keyInfo = TestUtils.getKeyInfo(keyPair.getPrivate()); 1736 assertEquals(expectedKeySize, keyInfo.getKeySize()); 1737 TestUtils.assertECParameterSpecEqualsIgnoreSeedIfNotPresent( 1738 expectedParams, 1739 ((ECKey) keyPair.getPublic()).getParams()); 1740 assertEquals(((keySizeBits + 7) / 8) * 8, consumedEntropyAmountBytes * 8); 1741 } 1742 assertKeyGenUsingECNamedCurveSupported( String curveName, ECParameterSpec expectedParams)1743 private void assertKeyGenUsingECNamedCurveSupported( 1744 String curveName, ECParameterSpec expectedParams) throws Exception { 1745 assertKeyGenUsingECNamedCurveSupported(curveName, expectedParams, false); 1746 } assertKeyGenUsingECNamedCurveSupported( String curveName, ECParameterSpec expectedParams, boolean useStrongbox)1747 private void assertKeyGenUsingECNamedCurveSupported( 1748 String curveName, ECParameterSpec expectedParams, boolean useStrongbox) throws Exception { 1749 KeyPairGenerator generator = getEcGenerator(); 1750 generator.initialize(new KeyGenParameterSpec.Builder( 1751 TEST_ALIAS_1, 1752 KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY) 1753 .setAlgorithmParameterSpec(new ECGenParameterSpec(curveName)) 1754 .setIsStrongBoxBacked(useStrongbox) 1755 .build(), 1756 mRng); 1757 mRng.resetCounters(); 1758 KeyPair keyPair = generator.generateKeyPair(); 1759 long consumedEntropyAmountBytes = mRng.getOutputSizeBytes(); 1760 int expectedKeySize = expectedParams.getCurve().getField().getFieldSize(); 1761 assertGeneratedKeyPairAndSelfSignedCertificate( 1762 keyPair, 1763 TEST_ALIAS_1, 1764 "EC", 1765 expectedKeySize, 1766 DEFAULT_CERT_SUBJECT, 1767 DEFAULT_CERT_SERIAL_NUMBER, 1768 DEFAULT_CERT_NOT_BEFORE, 1769 DEFAULT_CERT_NOT_AFTER); 1770 KeyInfo keyInfo = TestUtils.getKeyInfo(keyPair.getPrivate()); 1771 assertEquals(expectedKeySize, keyInfo.getKeySize()); 1772 TestUtils.assertECParameterSpecEqualsIgnoreSeedIfNotPresent( 1773 expectedParams, 1774 ((ECKey) keyPair.getPublic()).getParams()); 1775 assertEquals(((expectedKeySize + 7) / 8) * 8, consumedEntropyAmountBytes * 8); 1776 } 1777 assertKeyGenUsingRSASizeOnlySupported(int keySizeBits)1778 private void assertKeyGenUsingRSASizeOnlySupported(int keySizeBits) throws Exception { 1779 assertKeyGenUsingRSASizeOnlySupported(keySizeBits, false); 1780 } 1781 assertKeyGenUsingRSASizeOnlySupported(int keySizeBits, boolean useStrongbox)1782 private void assertKeyGenUsingRSASizeOnlySupported(int keySizeBits, boolean useStrongbox) throws Exception { 1783 KeyPairGenerator generator = getRsaGenerator(); 1784 generator.initialize(new KeyGenParameterSpec.Builder( 1785 TEST_ALIAS_1, 1786 KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY) 1787 .setKeySize(keySizeBits) 1788 .setIsStrongBoxBacked(useStrongbox) 1789 .build(), 1790 mRng); 1791 mRng.resetCounters(); 1792 KeyPair keyPair = generator.generateKeyPair(); 1793 long consumedEntropyAmountBytes = mRng.getOutputSizeBytes(); 1794 assertGeneratedKeyPairAndSelfSignedCertificate( 1795 keyPair, 1796 TEST_ALIAS_1, 1797 "RSA", 1798 keySizeBits, 1799 DEFAULT_CERT_SUBJECT, 1800 DEFAULT_CERT_SERIAL_NUMBER, 1801 DEFAULT_CERT_NOT_BEFORE, 1802 DEFAULT_CERT_NOT_AFTER); 1803 KeyInfo keyInfo = TestUtils.getKeyInfo(keyPair.getPrivate()); 1804 assertEquals(keySizeBits, keyInfo.getKeySize()); 1805 assertEquals(((keySizeBits + 7) / 8) * 8, consumedEntropyAmountBytes * 8); 1806 } 1807 assertKeyGenUsingRSAKeyGenParameterSpecSupported( RSAKeyGenParameterSpec spec)1808 private void assertKeyGenUsingRSAKeyGenParameterSpecSupported( 1809 RSAKeyGenParameterSpec spec) throws Exception { 1810 KeyPairGenerator generator = getRsaGenerator(); 1811 generator.initialize(new KeyGenParameterSpec.Builder( 1812 TEST_ALIAS_1, 1813 KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY) 1814 .setAlgorithmParameterSpec(spec) 1815 .build(), 1816 mRng); 1817 mRng.resetCounters(); 1818 KeyPair keyPair = generator.generateKeyPair(); 1819 long consumedEntropyAmountBytes = mRng.getOutputSizeBytes(); 1820 assertGeneratedKeyPairAndSelfSignedCertificate( 1821 keyPair, 1822 TEST_ALIAS_1, 1823 "RSA", 1824 spec.getKeysize(), 1825 DEFAULT_CERT_SUBJECT, 1826 DEFAULT_CERT_SERIAL_NUMBER, 1827 DEFAULT_CERT_NOT_BEFORE, 1828 DEFAULT_CERT_NOT_AFTER); 1829 assertEquals(spec.getPublicExponent(), 1830 ((RSAPublicKey) keyPair.getPublic()).getPublicExponent()); 1831 KeyInfo keyInfo = TestUtils.getKeyInfo(keyPair.getPrivate()); 1832 assertEquals(spec.getKeysize(), keyInfo.getKeySize()); 1833 assertEquals(((spec.getKeysize() + 7) / 8) * 8, consumedEntropyAmountBytes * 8); 1834 } 1835 assertSelfSignedCertificateSignatureVerifies(Certificate certificate)1836 private static void assertSelfSignedCertificateSignatureVerifies(Certificate certificate) { 1837 try { 1838 Log.i(TAG, HexDump.dumpHexString(certificate.getEncoded())); 1839 certificate.verify(certificate.getPublicKey()); 1840 } catch (Exception e) { 1841 throw new RuntimeException("Failed to verify self-signed certificate signature", e); 1842 } 1843 } 1844 assertGeneratedKeyPairAndSelfSignedCertificate( KeyPair keyPair, String alias, String expectedKeyAlgorithm, int expectedKeySize, X500Principal expectedCertSubject, BigInteger expectedCertSerialNumber, Date expectedCertNotBefore, Date expectedCertNotAfter)1845 private void assertGeneratedKeyPairAndSelfSignedCertificate( 1846 KeyPair keyPair, String alias, 1847 String expectedKeyAlgorithm, 1848 int expectedKeySize, 1849 X500Principal expectedCertSubject, 1850 BigInteger expectedCertSerialNumber, 1851 Date expectedCertNotBefore, 1852 Date expectedCertNotAfter) 1853 throws Exception { 1854 assertNotNull(keyPair); 1855 TestUtils.assertKeyPairSelfConsistent(keyPair); 1856 TestUtils.assertKeySize(expectedKeySize, keyPair); 1857 assertEquals(expectedKeyAlgorithm, keyPair.getPublic().getAlgorithm()); 1858 TestUtils.assertKeyStoreKeyPair(mKeyStore, alias, keyPair); 1859 1860 X509Certificate cert = (X509Certificate) mKeyStore.getCertificate(alias); 1861 assertTrue(Arrays.equals(keyPair.getPublic().getEncoded(), 1862 cert.getPublicKey().getEncoded())); 1863 assertX509CertificateParameters(cert, 1864 expectedCertSubject, 1865 expectedCertSerialNumber, 1866 expectedCertNotBefore, 1867 expectedCertNotAfter); 1868 // Assert that the certificate chain consists only of the above certificate 1869 MoreAsserts.assertContentsInOrder( 1870 Arrays.asList(mKeyStore.getCertificateChain(alias)), cert); 1871 } 1872 assertSelfSignedCertificateSignatureVerifies(String alias)1873 private void assertSelfSignedCertificateSignatureVerifies(String alias) throws Exception { 1874 assertSelfSignedCertificateSignatureVerifies(mKeyStore.getCertificate(alias)); 1875 } 1876 assertKeyPairAndCertificateUsableForTLSPeerAuthentication(String alias)1877 private void assertKeyPairAndCertificateUsableForTLSPeerAuthentication(String alias) 1878 throws Exception { 1879 assertUsableForTLSPeerAuthentication( 1880 (PrivateKey) mKeyStore.getKey(alias, null), 1881 mKeyStore.getCertificateChain(alias)); 1882 } 1883 assertX509CertificateParameters( X509Certificate actualCert, X500Principal expectedSubject, BigInteger expectedSerialNumber, Date expectedNotBefore, Date expectedNotAfter)1884 private static void assertX509CertificateParameters( 1885 X509Certificate actualCert, 1886 X500Principal expectedSubject, BigInteger expectedSerialNumber, 1887 Date expectedNotBefore, Date expectedNotAfter) { 1888 assertEquals(expectedSubject, actualCert.getSubjectDN()); 1889 assertEquals(expectedSubject, actualCert.getIssuerDN()); 1890 assertEquals(expectedSerialNumber, actualCert.getSerialNumber()); 1891 assertDateEquals(expectedNotBefore, actualCert.getNotBefore()); 1892 assertDateEquals(expectedNotAfter, actualCert.getNotAfter()); 1893 } 1894 assertUsableForTLSPeerAuthentication( PrivateKey privateKey, Certificate[] certificateChain)1895 private static void assertUsableForTLSPeerAuthentication( 1896 PrivateKey privateKey, 1897 Certificate[] certificateChain) throws Exception { 1898 // Set up both client and server to use the same private key + cert, and to trust that cert 1899 // when it's presented by peer. This exercises the use of the private key both in client 1900 // and server scenarios. 1901 X509Certificate[] x509CertificateChain = new X509Certificate[certificateChain.length]; 1902 for (int i = 0; i < certificateChain.length; i++) { 1903 x509CertificateChain[i] = (X509Certificate) certificateChain[i]; 1904 } 1905 TestKeyStore serverKeyStore = TestKeyStore.getServer(); 1906 // Make the peer trust the root certificate in the chain. As opposed to making the peer 1907 // trust the leaf certificate, this will ensure that the whole chain verifies. 1908 serverKeyStore.keyStore.setCertificateEntry( 1909 "trusted", certificateChain[certificateChain.length - 1]); 1910 SSLContext serverContext = TestSSLContext.createSSLContext("TLS", 1911 new KeyManager[] { 1912 TestKeyManager.wrap(new MyKeyManager(privateKey, x509CertificateChain)) 1913 }, 1914 TestKeyStore.createTrustManagers(serverKeyStore.keyStore)); 1915 SSLContext clientContext = serverContext; 1916 1917 if ("EC".equalsIgnoreCase(privateKey.getAlgorithm())) { 1918 // As opposed to RSA (see below) EC keys are used in the same way in all cipher suites. 1919 // Assert that the key works with the default list of cipher suites. 1920 assertSSLConnectionWithClientAuth( 1921 clientContext, serverContext, null, x509CertificateChain, x509CertificateChain); 1922 } else if ("RSA".equalsIgnoreCase(privateKey.getAlgorithm())) { 1923 // RSA keys are used differently between Forward Secure and non-Forward Secure cipher 1924 // suites. For example, RSA key exchange requires the server to decrypt using its RSA 1925 // private key, whereas ECDHE_RSA key exchange requires the server to sign usnig its 1926 // RSA private key. We thus assert that the key works with Forward Secure cipher suites 1927 // and that it works with non-Forward Secure cipher suites. 1928 List<String> fsCipherSuites = new ArrayList<String>(); 1929 List<String> nonFsCipherSuites = new ArrayList<String>(); 1930 for (String cipherSuite : clientContext.getDefaultSSLParameters().getCipherSuites()) { 1931 if (cipherSuite.contains("_ECDHE_RSA_") || cipherSuite.contains("_DHE_RSA_")) { 1932 fsCipherSuites.add(cipherSuite); 1933 } else if (cipherSuite.contains("_RSA_WITH_")) { 1934 nonFsCipherSuites.add(cipherSuite); 1935 } 1936 } 1937 assertFalse("No FS RSA cipher suites enabled by default", fsCipherSuites.isEmpty()); 1938 assertFalse("No non-FS RSA cipher suites enabled", nonFsCipherSuites.isEmpty()); 1939 1940 // Assert that the key works with RSA Forward Secure cipher suites. 1941 assertSSLConnectionWithClientAuth( 1942 clientContext, serverContext, fsCipherSuites.toArray(new String[0]), 1943 x509CertificateChain, x509CertificateChain); 1944 // Assert that the key works with RSA non-Forward Secure cipher suites. 1945 assertSSLConnectionWithClientAuth( 1946 clientContext, serverContext, nonFsCipherSuites.toArray(new String[0]), 1947 x509CertificateChain, x509CertificateChain); 1948 } else { 1949 fail("Unsupported key algorithm: " + privateKey.getAlgorithm()); 1950 } 1951 } 1952 assertSSLConnectionWithClientAuth( SSLContext clientContext, SSLContext serverContext, String[] enabledCipherSuites, X509Certificate[] expectedClientCertChain, X509Certificate[] expectedServerCertChain)1953 private static void assertSSLConnectionWithClientAuth( 1954 SSLContext clientContext, SSLContext serverContext, String[] enabledCipherSuites, 1955 X509Certificate[] expectedClientCertChain, X509Certificate[] expectedServerCertChain) 1956 throws Exception { 1957 SSLServerSocket serverSocket = (SSLServerSocket) serverContext.getServerSocketFactory() 1958 .createServerSocket(0); 1959 InetAddress host = InetAddress.getLocalHost(); 1960 int port = serverSocket.getLocalPort(); 1961 SSLSocket client = (SSLSocket) clientContext.getSocketFactory().createSocket(host, port); 1962 1963 final SSLSocket server = (SSLSocket) serverSocket.accept(); 1964 ExecutorService executor = Executors.newSingleThreadExecutor(); 1965 Future<Certificate[]> future = executor.submit(new Callable<Certificate[]>() { 1966 @Override 1967 public Certificate[] call() throws Exception { 1968 server.setNeedClientAuth(true); 1969 server.setWantClientAuth(true); 1970 server.startHandshake(); 1971 return server.getSession().getPeerCertificates(); 1972 } 1973 }); 1974 executor.shutdown(); 1975 if (enabledCipherSuites != null) { 1976 client.setEnabledCipherSuites(enabledCipherSuites); 1977 } 1978 client.startHandshake(); 1979 Certificate[] usedServerCerts = client.getSession().getPeerCertificates(); 1980 Certificate[] usedClientCerts = future.get(); 1981 client.close(); 1982 server.close(); 1983 1984 assertNotNull(usedServerCerts); 1985 assertEquals(Arrays.asList(expectedServerCertChain), Arrays.asList(usedServerCerts)); 1986 1987 assertNotNull(usedClientCerts); 1988 assertEquals(Arrays.asList(expectedClientCertChain), Arrays.asList(usedClientCerts)); 1989 } 1990 1991 private static class MyKeyManager extends X509ExtendedKeyManager { 1992 private final PrivateKey key; 1993 private final X509Certificate[] chain; 1994 MyKeyManager(PrivateKey key, X509Certificate[] certChain)1995 public MyKeyManager(PrivateKey key, X509Certificate[] certChain) { 1996 this.key = key; 1997 this.chain = certChain; 1998 } 1999 2000 @Override chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket)2001 public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) { 2002 return "fake"; 2003 } 2004 2005 @Override chooseEngineClientAlias(String[] keyType, Principal[] issuers, SSLEngine engine)2006 public String chooseEngineClientAlias(String[] keyType, Principal[] issuers, 2007 SSLEngine engine) { 2008 throw new IllegalStateException(); 2009 } 2010 2011 @Override chooseServerAlias(String keyType, Principal[] issuers, Socket socket)2012 public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) { 2013 return "fake"; 2014 } 2015 2016 @Override chooseEngineServerAlias(String keyType, Principal[] issuers, SSLEngine engine)2017 public String chooseEngineServerAlias(String keyType, Principal[] issuers, 2018 SSLEngine engine) { 2019 throw new IllegalStateException(); 2020 } 2021 2022 @Override getCertificateChain(String alias)2023 public X509Certificate[] getCertificateChain(String alias) { 2024 return chain; 2025 } 2026 2027 @Override getClientAliases(String keyType, Principal[] issuers)2028 public String[] getClientAliases(String keyType, Principal[] issuers) { 2029 return new String[] { "fake" }; 2030 } 2031 2032 @Override getServerAliases(String keyType, Principal[] issuers)2033 public String[] getServerAliases(String keyType, Principal[] issuers) { 2034 return new String[] { "fake" }; 2035 } 2036 2037 @Override getPrivateKey(String alias)2038 public PrivateKey getPrivateKey(String alias) { 2039 return key; 2040 } 2041 } 2042 2043 assertDateEquals(Date date1, Date date2)2044 private static void assertDateEquals(Date date1, Date date2) { 2045 assertDateEquals(null, date1, date2); 2046 } 2047 assertDateEquals(String message, Date date1, Date date2)2048 private static void assertDateEquals(String message, Date date1, Date date2) { 2049 SimpleDateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss"); 2050 2051 String result1 = formatter.format(date1); 2052 String result2 = formatter.format(date2); 2053 2054 assertEquals(message, result1, result2); 2055 } 2056 getRsaGenerator()2057 private KeyPairGenerator getRsaGenerator() 2058 throws NoSuchAlgorithmException, NoSuchProviderException { 2059 return getGenerator("RSA"); 2060 } 2061 getEcGenerator()2062 private KeyPairGenerator getEcGenerator() 2063 throws NoSuchAlgorithmException, NoSuchProviderException { 2064 return getGenerator("EC"); 2065 } 2066 getGenerator(String algorithm)2067 private KeyPairGenerator getGenerator(String algorithm) 2068 throws NoSuchAlgorithmException, NoSuchProviderException { 2069 return KeyPairGenerator.getInstance(algorithm, "AndroidKeyStore"); 2070 } 2071 assertOneOf(int actual, int... expected)2072 private static void assertOneOf(int actual, int... expected) { 2073 assertOneOf(null, actual, expected); 2074 } 2075 assertOneOf(String message, int actual, int... expected)2076 private static void assertOneOf(String message, int actual, int... expected) { 2077 for (int expectedValue : expected) { 2078 if (actual == expectedValue) { 2079 return; 2080 } 2081 } 2082 fail(((message != null) ? message + ". " : "") 2083 + "Expected one of " + Arrays.toString(expected) 2084 + ", actual: <" + actual + ">"); 2085 } 2086 getWorkingSpec()2087 private KeyGenParameterSpec.Builder getWorkingSpec() { 2088 return getWorkingSpec(0); 2089 } 2090 getWorkingSpec(int purposes)2091 private KeyGenParameterSpec.Builder getWorkingSpec(int purposes) { 2092 return new KeyGenParameterSpec.Builder(TEST_ALIAS_1, purposes); 2093 } 2094 2095 @Test testUniquenessOfRsaKeys()2096 public void testUniquenessOfRsaKeys() throws Exception { 2097 KeyGenParameterSpec.Builder specBuilder = getWorkingSpec(KeyProperties.PURPOSE_SIGN) 2098 .setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1) 2099 .setDigests(KeyProperties.DIGEST_SHA256); 2100 testUniquenessOfAsymmetricKeys("RSA", "SHA256WithRSA", 2101 specBuilder.build()); 2102 } 2103 2104 @Test testUniquenessOfRsaKeysInStrongBox()2105 public void testUniquenessOfRsaKeysInStrongBox() throws Exception { 2106 TestUtils.assumeStrongBox(); 2107 KeyGenParameterSpec.Builder specBuilder = getWorkingSpec(KeyProperties.PURPOSE_SIGN) 2108 .setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1) 2109 .setDigests(KeyProperties.DIGEST_SHA256); 2110 specBuilder.setIsStrongBoxBacked(true); 2111 testUniquenessOfAsymmetricKeys("RSA", "SHA256WithRSA", 2112 specBuilder.build()); 2113 } 2114 2115 @Test testUniquenessOfEcKeys()2116 public void testUniquenessOfEcKeys() throws Exception { 2117 KeyGenParameterSpec.Builder specBuilder = getWorkingSpec(KeyProperties.PURPOSE_SIGN) 2118 .setDigests(KeyProperties.DIGEST_SHA256); 2119 testUniquenessOfAsymmetricKeys("EC", "SHA256WithECDSA", 2120 specBuilder.build()); 2121 } 2122 2123 @Test testUniquenessOfEcKeysInStrongBox()2124 public void testUniquenessOfEcKeysInStrongBox() throws Exception { 2125 TestUtils.assumeStrongBox(); 2126 KeyGenParameterSpec.Builder specBuilder = getWorkingSpec(KeyProperties.PURPOSE_SIGN) 2127 .setDigests(KeyProperties.DIGEST_SHA256); 2128 specBuilder.setIsStrongBoxBacked(true); 2129 testUniquenessOfAsymmetricKeys("EC", "SHA256WithECDSA", 2130 specBuilder.build()); 2131 } 2132 2133 @Test testUniquenessOfEd25519Keys()2134 public void testUniquenessOfEd25519Keys() throws Exception { 2135 KeyGenParameterSpec.Builder specBuilder = getWorkingSpec(KeyProperties.PURPOSE_SIGN) 2136 .setAlgorithmParameterSpec(new ECGenParameterSpec("ed25519")) 2137 .setDigests(KeyProperties.DIGEST_NONE); 2138 testUniquenessOfAsymmetricKeys("EC", "Ed25519", 2139 specBuilder.build()); 2140 } 2141 testUniquenessOfAsymmetricKeys(String keyAlgo, String signAlgo, KeyGenParameterSpec spec)2142 private void testUniquenessOfAsymmetricKeys(String keyAlgo, String signAlgo, 2143 KeyGenParameterSpec spec) throws Exception { 2144 byte []randomMsg = new byte[20]; 2145 SecureRandom.getInstance("SHA1PRNG").nextBytes(randomMsg); 2146 byte[][] msgArr = new byte[][]{ 2147 {}, 2148 "message".getBytes(StandardCharsets.UTF_8), 2149 randomMsg 2150 }; 2151 for (byte[] msg : msgArr) { 2152 int numberOfKeysToTest = 10; 2153 Set results = new HashSet(); 2154 for (int i = 0; i < numberOfKeysToTest; i++) { 2155 KeyPairGenerator generator = getGenerator(keyAlgo); 2156 generator.initialize(spec); 2157 KeyPair keyPair = generator.generateKeyPair(); 2158 Signature signer = Signature.getInstance(signAlgo, 2159 TestUtils.EXPECTED_CRYPTO_OP_PROVIDER_NAME); 2160 signer.initSign(keyPair.getPrivate()); 2161 signer.update(msg); 2162 byte[] signature = signer.sign(); 2163 // Add generated signature to HashSet so that only unique signatures will be 2164 // counted. 2165 results.add(new String(signature)); 2166 } 2167 // Verify different signatures are generated for fixed message with all different keys 2168 assertEquals(TextUtils.formatSimple("%d different signature should have been generated" 2169 + " for %d different keys.", numberOfKeysToTest, numberOfKeysToTest), 2170 numberOfKeysToTest, results.size()); 2171 } 2172 } 2173 2174 @Test testUniquenessOfEcdhKeys()2175 public void testUniquenessOfEcdhKeys() throws Exception { 2176 testUniquenessOfECAgreementKeys("secp256r1", "ECDH", false /* useStrongbox */); 2177 } 2178 2179 @Test testUniquenessOfEcdhKeysInStrongBox()2180 public void testUniquenessOfEcdhKeysInStrongBox() throws Exception { 2181 TestUtils.assumeStrongBox(); 2182 testUniquenessOfECAgreementKeys("secp256r1", "ECDH", true /* useStrongbox */); 2183 } 2184 2185 @Test testUniquenessOfX25519Keys()2186 public void testUniquenessOfX25519Keys() throws Exception { 2187 testUniquenessOfECAgreementKeys("x25519", "XDH", false /* useStrongbox */); 2188 } 2189 testUniquenessOfECAgreementKeys(String curve, String agreeAlgo, boolean useStrongbox)2190 private void testUniquenessOfECAgreementKeys(String curve, String agreeAlgo, 2191 boolean useStrongbox) throws Exception { 2192 int numberOfKeysToTest = 10; 2193 Set results = new HashSet(); 2194 KeyGenParameterSpec spec = getWorkingSpec(KeyProperties.PURPOSE_AGREE_KEY) 2195 .setIsStrongBoxBacked(useStrongbox) 2196 .setAlgorithmParameterSpec(new ECGenParameterSpec(curve)) 2197 .build(); 2198 // Generate a local key pair 2199 KeyPairGenerator generator = getGenerator("EC"); 2200 generator.initialize(spec); 2201 KeyPair keyPairA = generator.generateKeyPair(); 2202 2203 for (int i = 0; i < numberOfKeysToTest; i++) { 2204 // Generate remote key 2205 generator.initialize(spec); 2206 KeyPair keyPairB = generator.generateKeyPair(); 2207 KeyAgreement keyAgreement = KeyAgreement.getInstance(agreeAlgo, 2208 EXPECTED_PROVIDER_NAME); 2209 keyAgreement.init(keyPairB.getPrivate()); 2210 keyAgreement.doPhase(keyPairA.getPublic(), true); 2211 byte[] secret = keyAgreement.generateSecret(); 2212 // Add generated secret to HashSet so that only unique secrets will be counted. 2213 results.add(new String(secret)); 2214 } 2215 // Verify different key agreement secrets generated for all different keys 2216 assertEquals(TextUtils.formatSimple("%d different secrets should have been generated for " 2217 + "%d different keys.", numberOfKeysToTest, numberOfKeysToTest), 2218 numberOfKeysToTest, results.size()); 2219 } 2220 } 2221