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