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