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