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