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