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