xref: /aosp_15_r20/external/wycheproof/keystore-cts/java/android/keystore/cts/util/KeyStoreUtil.java (revision 3d322d526be0ef039eebde10aa6ae75db8cc3a3d)
1 /**
2  * Licensed under the Apache License, Version 2.0 (the "License");
3  * you may not use this file except in compliance with the License.
4  * You may obtain a copy of the License at
5  *
6  *   http://www.apache.org/licenses/LICENSE-2.0
7  *
8  * Unless required by applicable law or agreed to in writing, software
9  * distributed under the License is distributed on an "AS IS" BASIS,
10  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11  * See the License for the specific language governing permissions and
12  * limitations under the License.
13  */
14 package android.keystore.cts.util;
15 
16 import static org.junit.Assume.assumeTrue;
17 import android.content.Context;
18 import android.security.keystore.KeyProtection;
19 import android.keystore.cts.util.TestUtils;
20 import androidx.test.core.app.ApplicationProvider;
21 import org.bouncycastle.asn1.x500.X500Name;
22 import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
23 import org.bouncycastle.cert.X509CertificateHolder;
24 import org.bouncycastle.cert.X509v3CertificateBuilder;
25 import org.bouncycastle.operator.OperatorCreationException;
26 import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
27 import java.io.ByteArrayInputStream;
28 import java.io.IOException;
29 import java.math.BigInteger;
30 import java.security.GeneralSecurityException;
31 import java.security.KeyPair;
32 import java.security.KeyStore;
33 import java.security.PrivateKey;
34 import java.security.PublicKey;
35 import java.security.SecureRandom;
36 import java.security.cert.Certificate;
37 import java.security.cert.CertificateException;
38 import java.security.cert.CertificateFactory;
39 import java.security.cert.X509Certificate;
40 import java.util.Date;
41 import java.util.Enumeration;
42 import java.util.List;
43 import javax.crypto.spec.SecretKeySpec;
44 import javax.security.auth.x500.X500Principal;
45 
46 /** Keystore utilities */
47 public class KeyStoreUtil {
48     // Known KeyMaster/KeyMint versions. This is the version number
49     // which appear in the keymasterVersion field.
50     public static final int KM_VERSION_KEYMASTER_1 = 10;
51     public static final int KM_VERSION_KEYMASTER_1_1 = 11;
52     public static final int KM_VERSION_KEYMASTER_2 = 20;
53     public static final int KM_VERSION_KEYMASTER_3 = 30;
54     public static final int KM_VERSION_KEYMASTER_4 = 40;
55     public static final int KM_VERSION_KEYMASTER_4_1 = 41;
56     public static final int KM_VERSION_KEYMINT_1 = 100;
57     public static final int KM_VERSION_KEYMINT_2 = 200;
58     public static final int KM_VERSION_KEYMINT_3 = 300;
59 
60     private static final List kmSupportedDigests = List.of("md5","sha-1","sha-224","sha-384",
61                                                         "sha-256","sha-512");
62 
saveKeysToKeystore(String alias, PublicKey pubKey, PrivateKey privKey, KeyProtection keyProtection)63     public static KeyStore saveKeysToKeystore(String alias, PublicKey pubKey, PrivateKey privKey,
64             KeyProtection keyProtection) throws Exception {
65         KeyPair keyPair = new KeyPair(pubKey, privKey);
66         X509Certificate certificate = createCertificate(keyPair,
67                                                         new X500Principal("CN=Test1"),
68                                                         new X500Principal("CN=Test1"));
69         Certificate[] certChain = new Certificate[]{certificate};
70         KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
71         keyStore.load(null);
72         keyStore.setEntry(alias,
73                         new KeyStore.PrivateKeyEntry(privKey, certChain),
74                         keyProtection);
75         return keyStore;
76     }
77 
saveSecretKeyToKeystore(String alias, SecretKeySpec keySpec, KeyProtection keyProtection)78     public static KeyStore saveSecretKeyToKeystore(String alias, SecretKeySpec keySpec,
79             KeyProtection keyProtection) throws Exception {
80         KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
81         keyStore.load(null);
82         keyStore.setEntry(alias,
83                         new KeyStore.SecretKeyEntry(keySpec),
84                         keyProtection);
85          return keyStore;
86     }
87 
cleanUpKeyStore()88     public static void cleanUpKeyStore() throws Exception {
89         KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
90         keyStore.load(null);
91         for (Enumeration<String> aliases = keyStore.aliases(); aliases.hasMoreElements();) {
92             String alias = aliases.nextElement();
93             keyStore.deleteEntry(alias);
94         }
95     }
96 
hasStrongBox()97     public static boolean hasStrongBox() {
98         Context context = ApplicationProvider.getApplicationContext();
99         return TestUtils.hasStrongBox(context);
100     }
101 
assumeStrongBox()102     public static void assumeStrongBox() {
103         TestUtils.assumeStrongBox();
104     }
105 
isSupportedDigest(String digest, boolean isStrongBox)106     public static boolean isSupportedDigest(String digest, boolean isStrongBox) {
107         if (isStrongBox) {
108             return digest.equalsIgnoreCase("sha-256");
109         }
110         return kmSupportedDigests.contains(digest.toLowerCase());
111     }
112 
isSupportedMgfDigest(String digest, boolean isStrongBox)113     public static boolean isSupportedMgfDigest(String digest, boolean isStrongBox) {
114         if (isStrongBox) {
115             return digest.equalsIgnoreCase("sha-1")
116                     || digest.equalsIgnoreCase("sha-256");
117         }
118         return kmSupportedDigests.contains(digest.toLowerCase());
119     }
120 
isSupportedRsaKeySize(int keySize, boolean isStrongBox)121     public static boolean isSupportedRsaKeySize(int keySize, boolean isStrongBox) {
122         if (isStrongBox) {
123             return keySize == 2048;
124         }
125         return keySize == 2048 || keySize == 3072 || keySize == 4096;
126     }
127 
createCertificate( KeyPair keyPair, X500Principal subject, X500Principal issuer)128     public static X509Certificate createCertificate(
129             KeyPair keyPair, X500Principal subject, X500Principal issuer)
130             throws OperatorCreationException, CertificateException, IOException {
131         // Make the certificate valid for two days.
132         long millisPerDay = 24 * 60 * 60 * 1000;
133         long now = System.currentTimeMillis();
134         Date start = new Date(now - millisPerDay);
135         Date end = new Date(now + millisPerDay);
136 
137         // Assign a random serial number.
138         byte[] serialBytes = new byte[16];
139         new SecureRandom().nextBytes(serialBytes);
140         BigInteger serialNumber = new BigInteger(1, serialBytes);
141 
142         // Create the certificate builder
143         X509v3CertificateBuilder x509cg =
144                 new X509v3CertificateBuilder(
145                         X500Name.getInstance(issuer.getEncoded()),
146                         serialNumber,
147                         start,
148                         end,
149                         X500Name.getInstance(subject.getEncoded()),
150                         SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded()));
151 
152         // Choose a signature algorithm matching the key format.
153         String keyAlgorithm = keyPair.getPrivate().getAlgorithm();
154         String signatureAlgorithm;
155         if (keyAlgorithm.equals("RSA")) {
156             signatureAlgorithm = "SHA256withRSA";
157         } else if (keyAlgorithm.equals("EC")) {
158             signatureAlgorithm = "SHA256withECDSA";
159         } else {
160             throw new IllegalArgumentException("Unknown key algorithm " + keyAlgorithm);
161         }
162 
163         // Sign the certificate and generate it.
164         X509CertificateHolder x509holder =
165                 x509cg.build(
166                         new JcaContentSignerBuilder(signatureAlgorithm)
167                                 .build(keyPair.getPrivate()));
168         CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
169         X509Certificate x509c =
170                 (X509Certificate)
171                         certFactory.generateCertificate(
172                                 new ByteArrayInputStream(x509holder.getEncoded()));
173         return x509c;
174     }
175 
assumeKeyMintV1OrNewer(boolean isStrongBox)176     public static void assumeKeyMintV1OrNewer(boolean isStrongBox) {
177         assumeTrue("Test can only run on KeyMint v1 and above",
178             TestUtils.hasKeystoreVersion(isStrongBox, KM_VERSION_KEYMINT_1));
179     }
180 }
181