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