AndroidKeyStoreKeyPairGeneratorSpi.java revision 6e90ade5dd7a3c3cd8a3949c863c6e72f9912233
1e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk/*
2e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * Copyright (C) 2012 The Android Open Source Project
3e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk *
4e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * Licensed under the Apache License, Version 2.0 (the "License");
5e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * you may not use this file except in compliance with the License.
6e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * You may obtain a copy of the License at
7e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk *
8e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk *      http://www.apache.org/licenses/LICENSE-2.0
9e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk *
10e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * Unless required by applicable law or agreed to in writing, software
11e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * distributed under the License is distributed on an "AS IS" BASIS,
12e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * See the License for the specific language governing permissions and
14e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * limitations under the License.
15e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk */
16e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
17e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkpackage android.security.keystore;
18e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
19e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport android.annotation.Nullable;
20e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport android.security.Credentials;
21e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport android.security.KeyPairGeneratorSpec;
22e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport android.security.KeyStore;
23e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport android.security.keymaster.KeyCharacteristics;
24e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport android.security.keymaster.KeymasterArguments;
25e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport android.security.keymaster.KeymasterDefs;
26e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
27e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport com.android.org.bouncycastle.asn1.ASN1EncodableVector;
28e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport com.android.org.bouncycastle.asn1.ASN1InputStream;
29e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport com.android.org.bouncycastle.asn1.ASN1Integer;
30e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport com.android.org.bouncycastle.asn1.ASN1ObjectIdentifier;
31e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport com.android.org.bouncycastle.asn1.DERBitString;
324510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkimport com.android.org.bouncycastle.asn1.DERInteger;
334510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkimport com.android.org.bouncycastle.asn1.DERNull;
34e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport com.android.org.bouncycastle.asn1.DERSequence;
354510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkimport com.android.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
36e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport com.android.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
374510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkimport com.android.org.bouncycastle.asn1.x509.Certificate;
38e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport com.android.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
394510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkimport com.android.org.bouncycastle.asn1.x509.TBSCertificate;
40e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport com.android.org.bouncycastle.asn1.x509.Time;
414510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkimport com.android.org.bouncycastle.asn1.x509.V3TBSCertificateGenerator;
42e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport com.android.org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
434510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkimport com.android.org.bouncycastle.jce.X509Principal;
44e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport com.android.org.bouncycastle.jce.provider.X509CertificateObject;
45e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport com.android.org.bouncycastle.x509.X509V3CertificateGenerator;
46e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
47e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport libcore.util.EmptyArray;
48e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
49e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.math.BigInteger;
50e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.security.InvalidAlgorithmParameterException;
51e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.security.KeyPair;
52e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.security.KeyPairGenerator;
53e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.security.KeyPairGeneratorSpi;
54e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.security.PrivateKey;
55e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.security.ProviderException;
56e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.security.PublicKey;
57e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.security.SecureRandom;
58e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.security.UnrecoverableKeyException;
59e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.security.cert.CertificateEncodingException;
60e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.security.cert.X509Certificate;
61e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.security.spec.AlgorithmParameterSpec;
62e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.security.spec.ECGenParameterSpec;
63e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.security.spec.RSAKeyGenParameterSpec;
64e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.util.ArrayList;
65e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.util.Collections;
66e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.util.Date;
67e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.util.HashMap;
68e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.util.HashSet;
69e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.util.List;
70e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.util.Locale;
71e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.util.Map;
72e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.util.Set;
73e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
74e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk/**
75e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * Provides a way to create instances of a KeyPair which will be placed in the
76e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * Android keystore service usable only by the application that called it. This
77e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * can be used in conjunction with
78e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * {@link java.security.KeyStore#getInstance(String)} using the
79e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * {@code "AndroidKeyStore"} type.
80e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * <p>
81e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * This class can not be directly instantiated and must instead be used via the
82e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * {@link KeyPairGenerator#getInstance(String)
83e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * KeyPairGenerator.getInstance("AndroidKeyStore")} API.
84e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk *
85e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * @hide
86e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk */
87e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkpublic abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGeneratorSpi {
88e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
89e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    public static class RSA extends AndroidKeyStoreKeyPairGeneratorSpi {
90e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        public RSA() {
91e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            super(KeymasterDefs.KM_ALGORITHM_RSA);
92e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        }
93e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
94e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
95e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    public static class EC extends AndroidKeyStoreKeyPairGeneratorSpi {
96e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        public EC() {
97e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            super(KeymasterDefs.KM_ALGORITHM_EC);
98e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        }
99e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
100e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
101e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    /*
102e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk     * These must be kept in sync with system/security/keystore/defaults.h
103e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk     */
104e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
105e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    /* EC */
106e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    private static final int EC_DEFAULT_KEY_SIZE = 256;
107e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
108e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    /* RSA */
109e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    private static final int RSA_DEFAULT_KEY_SIZE = 2048;
110e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    private static final int RSA_MIN_KEY_SIZE = 512;
111e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    private static final int RSA_MAX_KEY_SIZE = 8192;
112e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
113e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    private static final Map<String, Integer> SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE =
114e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            new HashMap<String, Integer>();
115e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    private static final List<String> SUPPORTED_EC_NIST_CURVE_NAMES = new ArrayList<String>();
116e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    private static final List<Integer> SUPPORTED_EC_NIST_CURVE_SIZES = new ArrayList<Integer>();
117e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    static {
118e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        // Aliases for NIST P-224
119e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("p-224", 224);
120e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("secp224r1", 224);
121e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
122e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
123e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        // Aliases for NIST P-256
124e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("p-256", 256);
125e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("secp256r1", 256);
126e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("prime256v1", 256);
127e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
128e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        // Aliases for NIST P-384
129e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("p-384", 384);
130e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("secp384r1", 384);
131e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
132e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        // Aliases for NIST P-521
133e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("p-521", 521);
134e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("secp521r1", 521);
135e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
136e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        SUPPORTED_EC_NIST_CURVE_NAMES.addAll(SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.keySet());
137e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        Collections.sort(SUPPORTED_EC_NIST_CURVE_NAMES);
138e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
139e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        SUPPORTED_EC_NIST_CURVE_SIZES.addAll(
140e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                new HashSet<Integer>(SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.values()));
141e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        Collections.sort(SUPPORTED_EC_NIST_CURVE_SIZES);
142e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
143e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
144e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    private final int mOriginalKeymasterAlgorithm;
145e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
146e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    private KeyStore mKeyStore;
147e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
148e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    private KeyGenParameterSpec mSpec;
149e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
150e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    private String mEntryAlias;
151e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    private boolean mEncryptionAtRestRequired;
152e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    private @KeyProperties.KeyAlgorithmEnum String mJcaKeyAlgorithm;
153e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    private int mKeymasterAlgorithm = -1;
154e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    private int mKeySizeBits;
155e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    private SecureRandom mRng;
156e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
157e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    private int[] mKeymasterPurposes;
158e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    private int[] mKeymasterBlockModes;
159e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    private int[] mKeymasterEncryptionPaddings;
160e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    private int[] mKeymasterSignaturePaddings;
161e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    private int[] mKeymasterDigests;
162e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
163e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    private long mRSAPublicExponent;
164e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
165e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    protected AndroidKeyStoreKeyPairGeneratorSpi(int keymasterAlgorithm) {
166e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        mOriginalKeymasterAlgorithm = keymasterAlgorithm;
167e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
168e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
169e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    @Override
170e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    public void initialize(int keysize, SecureRandom random) {
171e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        throw new IllegalArgumentException(
172e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                KeyGenParameterSpec.class.getName() + " or " + KeyPairGeneratorSpec.class.getName()
173e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                + " required to initialize this KeyPairGenerator");
174e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
175e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
176e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    @Override
177ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk    public void initialize(AlgorithmParameterSpec params, SecureRandom random)
178e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            throws InvalidAlgorithmParameterException {
179e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        resetAll();
180ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk
181ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk        boolean success = false;
182ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk        try {
183ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk            if (params == null) {
184ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk                throw new InvalidAlgorithmParameterException(
1854510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                        "Must supply params of type " + KeyGenParameterSpec.class.getName()
1864510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                        + " or " + KeyPairGeneratorSpec.class.getName());
1874510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            }
1884510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
1894510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            KeyGenParameterSpec spec;
1904510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            boolean encryptionAtRestRequired = false;
1914510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            int keymasterAlgorithm = mOriginalKeymasterAlgorithm;
1924510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            if (params instanceof KeyGenParameterSpec) {
193e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                spec = (KeyGenParameterSpec) params;
194e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            } else if (params instanceof KeyPairGeneratorSpec) {
195e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                // Legacy/deprecated spec
19645a599d79a1a1b74b959d98eccfbec9c6a5aa237Eino-Ville Talvala                KeyPairGeneratorSpec legacySpec = (KeyPairGeneratorSpec) params;
19745a599d79a1a1b74b959d98eccfbec9c6a5aa237Eino-Ville Talvala                try {
19845a599d79a1a1b74b959d98eccfbec9c6a5aa237Eino-Ville Talvala                    KeyGenParameterSpec.Builder specBuilder;
19945a599d79a1a1b74b959d98eccfbec9c6a5aa237Eino-Ville Talvala                    String specKeyAlgorithm = legacySpec.getKeyType();
20045a599d79a1a1b74b959d98eccfbec9c6a5aa237Eino-Ville Talvala                    if (specKeyAlgorithm != null) {
20145a599d79a1a1b74b959d98eccfbec9c6a5aa237Eino-Ville Talvala                        // Spec overrides the generator's default key algorithm
20245a599d79a1a1b74b959d98eccfbec9c6a5aa237Eino-Ville Talvala                        try {
20345a599d79a1a1b74b959d98eccfbec9c6a5aa237Eino-Ville Talvala                            keymasterAlgorithm =
20445a599d79a1a1b74b959d98eccfbec9c6a5aa237Eino-Ville Talvala                                    KeyProperties.KeyAlgorithm.toKeymasterAsymmetricKeyAlgorithm(
20545a599d79a1a1b74b959d98eccfbec9c6a5aa237Eino-Ville Talvala                                            specKeyAlgorithm);
20645a599d79a1a1b74b959d98eccfbec9c6a5aa237Eino-Ville Talvala                        } catch (IllegalArgumentException e) {
20745a599d79a1a1b74b959d98eccfbec9c6a5aa237Eino-Ville Talvala                            throw new InvalidAlgorithmParameterException(
208e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                                    "Invalid key type in parameters", e);
209e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        }
210e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    }
211e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    switch (keymasterAlgorithm) {
2124510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                        case KeymasterDefs.KM_ALGORITHM_EC:
213e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                            specBuilder = new KeyGenParameterSpec.Builder(
214e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                                    legacySpec.getKeystoreAlias(),
215e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                                    KeyProperties.PURPOSE_SIGN
216e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                                    | KeyProperties.PURPOSE_VERIFY);
217e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                            // Authorized to be used with any digest (including no digest).
218e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                            specBuilder.setDigests(KeyProperties.DIGEST_NONE);
219e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                            break;
2204510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                        case KeymasterDefs.KM_ALGORITHM_RSA:
221e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                            specBuilder = new KeyGenParameterSpec.Builder(
222e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                                    legacySpec.getKeystoreAlias(),
223e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                                    KeyProperties.PURPOSE_ENCRYPT
224e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                                    | KeyProperties.PURPOSE_DECRYPT
225e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                                    | KeyProperties.PURPOSE_SIGN
226e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                                    | KeyProperties.PURPOSE_VERIFY);
227e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                            // Authorized to be used with any digest (including no digest).
2284510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                            specBuilder.setDigests(KeyProperties.DIGEST_NONE);
229e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                            // Authorized to be used with any encryption and signature padding
230e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                            // scheme (including no padding).
231e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                            specBuilder.setEncryptionPaddings(
232e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                                    KeyProperties.ENCRYPTION_PADDING_NONE);
233e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                            // Disable randomized encryption requirement to support encryption
234e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                            // padding NONE above.
235e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                            specBuilder.setRandomizedEncryptionRequired(false);
2364510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                            break;
237e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        default:
238e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                            throw new ProviderException(
239e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                                    "Unsupported algorithm: " + mKeymasterAlgorithm);
240e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    }
241e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
242e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    if (legacySpec.getKeySize() != -1) {
243ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk                        specBuilder.setKeySize(legacySpec.getKeySize());
2444510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                    }
245ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk                    if (legacySpec.getAlgorithmParameterSpec() != null) {
246ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk                        specBuilder.setAlgorithmParameterSpec(
247ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk                                legacySpec.getAlgorithmParameterSpec());
248ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk                    }
249ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk                    specBuilder.setCertificateSubject(legacySpec.getSubjectDN());
250ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk                    specBuilder.setCertificateSerialNumber(legacySpec.getSerialNumber());
251ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk                    specBuilder.setCertificateNotBefore(legacySpec.getStartDate());
2524510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                    specBuilder.setCertificateNotAfter(legacySpec.getEndDate());
253ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk                    encryptionAtRestRequired = legacySpec.isEncryptionRequired();
254ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk                    specBuilder.setUserAuthenticationRequired(false);
255ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk
256ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk                    spec = specBuilder.build();
257ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk                } catch (NullPointerException | IllegalArgumentException e) {
258ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk                    throw new InvalidAlgorithmParameterException(e);
259ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk                }
2604510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            } else {
261ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk                throw new InvalidAlgorithmParameterException(
262ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk                        "Unsupported params class: " + params.getClass().getName()
263ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk                        + ". Supported: " + KeyGenParameterSpec.class.getName()
264ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk                        + ", " + KeyPairGeneratorSpec.class.getName());
265ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk            }
266ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk
267ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk            mEntryAlias = spec.getKeystoreAlias();
2684510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            mSpec = spec;
269ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk            mKeymasterAlgorithm = keymasterAlgorithm;
270ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk            mEncryptionAtRestRequired = encryptionAtRestRequired;
271ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk            mKeySizeBits = spec.getKeySize();
272ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk            initAlgorithmSpecificParameters();
273ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk            if (mKeySizeBits == -1) {
274ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk                mKeySizeBits = getDefaultKeySize(keymasterAlgorithm);
275ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk            }
2764510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            checkValidKeySize(keymasterAlgorithm, mKeySizeBits);
277ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk
278ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk            if (spec.getKeystoreAlias() == null) {
279ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk                throw new InvalidAlgorithmParameterException("KeyStore entry alias not provided");
280ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk            }
281ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk
282ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk            String jcaKeyAlgorithm;
283ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk            try {
2844510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                jcaKeyAlgorithm = KeyProperties.KeyAlgorithm.fromKeymasterAsymmetricKeyAlgorithm(
285ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk                        keymasterAlgorithm);
286ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk                mKeymasterPurposes = KeyProperties.Purpose.allToKeymaster(spec.getPurposes());
287ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk                mKeymasterBlockModes = KeyProperties.BlockMode.allToKeymaster(spec.getBlockModes());
288ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk                mKeymasterEncryptionPaddings = KeyProperties.EncryptionPadding.allToKeymaster(
289ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk                        spec.getEncryptionPaddings());
290ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk                mKeymasterSignaturePaddings = KeyProperties.SignaturePadding.allToKeymaster(
2914510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                        spec.getSignaturePaddings());
2924510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                if (spec.isDigestsSpecified()) {
2934510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                    mKeymasterDigests = KeyProperties.Digest.allToKeymaster(spec.getDigests());
2944510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                } else {
2954510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                    mKeymasterDigests = EmptyArray.INT;
2964510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                }
2974510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            } catch (IllegalArgumentException e) {
2984510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                throw new InvalidAlgorithmParameterException(e);
2994510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            }
3004510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
3014510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            mJcaKeyAlgorithm = jcaKeyAlgorithm;
3024510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            mRng = random;
3034510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            mKeyStore = KeyStore.getInstance();
3044510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            success = true;
3054510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        } finally {
3064510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            if (!success) {
3074510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                resetAll();
3084510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            }
3094510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        }
3104510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    }
3114510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
3124510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    private void resetAll() {
3134510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        mEntryAlias = null;
3144510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        mJcaKeyAlgorithm = null;
3154510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        mKeymasterAlgorithm = -1;
3164510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        mKeymasterPurposes = null;
3174510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        mKeymasterBlockModes = null;
3184510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        mKeymasterEncryptionPaddings = null;
3194510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        mKeymasterSignaturePaddings = null;
3204510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        mKeymasterDigests = null;
3214510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        mKeySizeBits = 0;
3224510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        mSpec = null;
3234510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        mRSAPublicExponent = -1;
3244510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        mEncryptionAtRestRequired = false;
3254510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        mRng = null;
3264510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        mKeyStore = null;
3274510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    }
3284510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
3294510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    private void initAlgorithmSpecificParameters() throws InvalidAlgorithmParameterException {
3304510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        AlgorithmParameterSpec algSpecificSpec = mSpec.getAlgorithmParameterSpec();
3314510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        switch (mKeymasterAlgorithm) {
3324510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            case KeymasterDefs.KM_ALGORITHM_RSA:
3334510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            {
3344510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                BigInteger publicExponent = null;
3354510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                if (algSpecificSpec instanceof RSAKeyGenParameterSpec) {
3364510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                    RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec) algSpecificSpec;
3374510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                    if (mKeySizeBits == -1) {
3384510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                        mKeySizeBits = rsaSpec.getKeysize();
3394510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                    } else if (mKeySizeBits != rsaSpec.getKeysize()) {
3404510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                        throw new InvalidAlgorithmParameterException("RSA key size must match "
3414510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                                + " between " + mSpec + " and " + algSpecificSpec
3424510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                                + ": " + mKeySizeBits + " vs " + rsaSpec.getKeysize());
3434510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                    }
3444510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                    publicExponent = rsaSpec.getPublicExponent();
3454510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                } else if (algSpecificSpec != null) {
3464510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                    throw new InvalidAlgorithmParameterException(
347e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        "RSA may only use RSAKeyGenParameterSpec");
348e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                }
349e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                if (publicExponent == null) {
350e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    publicExponent = RSAKeyGenParameterSpec.F4;
351e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                }
352e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                if (publicExponent.compareTo(BigInteger.ZERO) < 1) {
353e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    throw new InvalidAlgorithmParameterException(
354e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                            "RSA public exponent must be positive: " + publicExponent);
3554510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                }
356e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                if (publicExponent.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0) {
357e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    throw new InvalidAlgorithmParameterException(
358e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                            "Unsupported RSA public exponent: " + publicExponent
359e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                            + ". Only exponents <= " + Long.MAX_VALUE + " supported");
360e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                }
361e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                mRSAPublicExponent = publicExponent.longValue();
3624510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                break;
3634510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            }
3644510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            case KeymasterDefs.KM_ALGORITHM_EC:
3654510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                if (algSpecificSpec instanceof ECGenParameterSpec) {
3664510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                    ECGenParameterSpec ecSpec = (ECGenParameterSpec) algSpecificSpec;
3674510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                    String curveName = ecSpec.getName();
3684510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                    Integer ecSpecKeySizeBits = SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.get(
3694510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                            curveName.toLowerCase(Locale.US));
370e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    if (ecSpecKeySizeBits == null) {
371e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        throw new InvalidAlgorithmParameterException(
372e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                                "Unsupported EC curve name: " + curveName
373e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                                + ". Supported: " + SUPPORTED_EC_NIST_CURVE_NAMES);
374e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    }
375e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    if (mKeySizeBits == -1) {
376e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        mKeySizeBits = ecSpecKeySizeBits;
377e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    } else if (mKeySizeBits != ecSpecKeySizeBits) {
3784510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                        throw new InvalidAlgorithmParameterException("EC key size must match "
379e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                                + " between " + mSpec + " and " + algSpecificSpec
380e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                                + ": " + mKeySizeBits + " vs " + ecSpecKeySizeBits);
381e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    }
382e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                } else if (algSpecificSpec != null) {
383e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    throw new InvalidAlgorithmParameterException(
384e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        "EC may only use ECGenParameterSpec");
385e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                }
3864510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                break;
387e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            default:
388e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                throw new ProviderException("Unsupported algorithm: " + mKeymasterAlgorithm);
389e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        }
390e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
391e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
392e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    @Override
393e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    public KeyPair generateKeyPair() {
3944510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        if (mKeyStore == null || mSpec == null) {
395e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            throw new IllegalStateException("Not initialized");
396e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        }
397e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
398e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        final int flags = (mEncryptionAtRestRequired) ? KeyStore.FLAG_ENCRYPTED : 0;
399e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        if (((flags & KeyStore.FLAG_ENCRYPTED) != 0)
400e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                && (mKeyStore.state() != KeyStore.State.UNLOCKED)) {
401e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            throw new IllegalStateException(
4024510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                    "Encryption at rest using secure lock screen credential requested for key pair"
403e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    + ", but the user has not yet entered the credential");
404e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        }
405e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
406e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        KeymasterArguments args = new KeymasterArguments();
407e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        args.addInt(KeymasterDefs.KM_TAG_KEY_SIZE, mKeySizeBits);
408e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        args.addInt(KeymasterDefs.KM_TAG_ALGORITHM, mKeymasterAlgorithm);
409e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        args.addInts(KeymasterDefs.KM_TAG_PURPOSE, mKeymasterPurposes);
4104510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        args.addInts(KeymasterDefs.KM_TAG_BLOCK_MODE, mKeymasterBlockModes);
411e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        args.addInts(KeymasterDefs.KM_TAG_PADDING, mKeymasterEncryptionPaddings);
412e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        args.addInts(KeymasterDefs.KM_TAG_PADDING, mKeymasterSignaturePaddings);
413e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        args.addInts(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigests);
414e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
415e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        KeymasterUtils.addUserAuthArgs(args,
416e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                mSpec.isUserAuthenticationRequired(),
417e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                mSpec.getUserAuthenticationValidityDurationSeconds());
4184510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        args.addDate(KeymasterDefs.KM_TAG_ACTIVE_DATETIME,
419e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                (mSpec.getKeyValidityStart() != null)
420e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                ? mSpec.getKeyValidityStart() : new Date(0));
421e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        args.addDate(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
422e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                (mSpec.getKeyValidityForOriginationEnd() != null)
423e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                ? mSpec.getKeyValidityForOriginationEnd() : new Date(Long.MAX_VALUE));
424e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        args.addDate(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME,
425e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                (mSpec.getKeyValidityForConsumptionEnd() != null)
4264510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                ? mSpec.getKeyValidityForConsumptionEnd() : new Date(Long.MAX_VALUE));
427e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        addAlgorithmSpecificParameters(args);
428e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
429e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        byte[] additionalEntropy =
430e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng(
431e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        mRng, (mKeySizeBits + 7) / 8);
432e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
433e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        final String privateKeyAlias = Credentials.USER_PRIVATE_KEY + mEntryAlias;
4344510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        boolean success = false;
435e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        try {
436e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            Credentials.deleteAllTypesForAlias(mKeyStore, mEntryAlias);
437e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            KeyCharacteristics resultingKeyCharacteristics = new KeyCharacteristics();
438e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            int errorCode = mKeyStore.generateKey(
439e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    privateKeyAlias,
440e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    args,
441e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    additionalEntropy,
4424510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                    flags,
443e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    resultingKeyCharacteristics);
444e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            if (errorCode != KeyStore.NO_ERROR) {
445e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                throw new ProviderException(
446e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        "Failed to generate key pair", KeyStore.getKeyStoreException(errorCode));
447e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            }
448e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
449e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            KeyPair result;
4504510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            try {
451e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                result = AndroidKeyStoreProvider.loadAndroidKeyStoreKeyPairFromKeystore(
452e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        mKeyStore, privateKeyAlias);
453e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            } catch (UnrecoverableKeyException e) {
454e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                throw new ProviderException("Failed to load generated key pair from keystore", e);
455e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            }
456e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
457e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            if (!mJcaKeyAlgorithm.equalsIgnoreCase(result.getPrivate().getAlgorithm())) {
4584510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                throw new ProviderException(
459e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        "Generated key pair algorithm does not match requested algorithm: "
460e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        + result.getPrivate().getAlgorithm() + " vs " + mJcaKeyAlgorithm);
461e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            }
462e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
463e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            final X509Certificate cert;
464e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            try {
465e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                cert = generateSelfSignedCertificate(result.getPrivate(), result.getPublic());
4664510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            } catch (Exception e) {
467e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                throw new ProviderException("Failed to generate self-signed certificate", e);
468e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            }
469e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
470e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            byte[] certBytes;
471e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            try {
472e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                certBytes = cert.getEncoded();
473e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            } catch (CertificateEncodingException e) {
4744510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                throw new ProviderException(
475e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        "Failed to obtain encoded form of self-signed certificate", e);
476e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            }
477e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
478e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            int insertErrorCode = mKeyStore.insert(
479e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    Credentials.USER_CERTIFICATE + mEntryAlias,
480e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    certBytes,
481e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    KeyStore.UID_SELF,
4824510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                    flags);
483e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            if (insertErrorCode != KeyStore.NO_ERROR) {
484e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                throw new ProviderException("Failed to store self-signed certificate",
485e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        KeyStore.getKeyStoreException(insertErrorCode));
486e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            }
487e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
488e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            success = true;
489e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            return result;
4904510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        } finally {
491e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            if (!success) {
492e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                Credentials.deleteAllTypesForAlias(mKeyStore, mEntryAlias);
493e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            }
494e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        }
495e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
496e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
497e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    private void addAlgorithmSpecificParameters(KeymasterArguments keymasterArgs) {
4984510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        switch (mKeymasterAlgorithm) {
499e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            case KeymasterDefs.KM_ALGORITHM_RSA:
500e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                keymasterArgs.addLong(KeymasterDefs.KM_TAG_RSA_PUBLIC_EXPONENT, mRSAPublicExponent);
501e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                break;
502e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            case KeymasterDefs.KM_ALGORITHM_EC:
503e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                break;
504e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            default:
505e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                throw new ProviderException("Unsupported algorithm: " + mKeymasterAlgorithm);
5064510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        }
507e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
508e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
509e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    private X509Certificate generateSelfSignedCertificate(
510e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            PrivateKey privateKey, PublicKey publicKey) throws Exception {
511e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        String signatureAlgorithm =
512e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                getCertificateSignatureAlgorithm(mKeymasterAlgorithm, mKeySizeBits, mSpec);
513e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        if (signatureAlgorithm == null) {
5144510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            // Key cannot be used to sign a certificate
515e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            return generateSelfSignedCertificateWithFakeSignature(publicKey);
516e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        } else {
517e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            // Key can be used to sign a certificate
518e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            return generateSelfSignedCertificateWithValidSignature(
519e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    privateKey, publicKey, signatureAlgorithm);
520e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        }
521e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
5224510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
523e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    @SuppressWarnings("deprecation")
524e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    private X509Certificate generateSelfSignedCertificateWithValidSignature(
525e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            PrivateKey privateKey, PublicKey publicKey, String signatureAlgorithm)
526e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    throws Exception {
527e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        final X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
528e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        certGen.setPublicKey(publicKey);
529e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        certGen.setSerialNumber(mSpec.getCertificateSerialNumber());
5304510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        certGen.setSubjectDN(mSpec.getCertificateSubject());
531e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        certGen.setIssuerDN(mSpec.getCertificateSubject());
532e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        certGen.setNotBefore(mSpec.getCertificateNotBefore());
533e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        certGen.setNotAfter(mSpec.getCertificateNotAfter());
534e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        certGen.setSignatureAlgorithm(signatureAlgorithm);
535e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        return certGen.generate(privateKey);
536e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
537e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
5384510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    @SuppressWarnings("deprecation")
539e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    private X509Certificate generateSelfSignedCertificateWithFakeSignature(
540e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            PublicKey publicKey) throws Exception {
541e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        V3TBSCertificateGenerator tbsGenerator = new V3TBSCertificateGenerator();
542e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        ASN1ObjectIdentifier sigAlgOid;
543e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        AlgorithmIdentifier sigAlgId;
544e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        byte[] signature;
545e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        switch (mKeymasterAlgorithm) {
5464510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            case KeymasterDefs.KM_ALGORITHM_EC:
547e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                sigAlgOid = X9ObjectIdentifiers.ecdsa_with_SHA256;
548e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                sigAlgId = new AlgorithmIdentifier(sigAlgOid);
549e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                ASN1EncodableVector v = new ASN1EncodableVector();
550e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                v.add(new DERInteger(0));
551e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                v.add(new DERInteger(0));
552e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                signature = new DERSequence().getEncoded();
553e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                break;
5544510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            case KeymasterDefs.KM_ALGORITHM_RSA:
555e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                sigAlgOid = PKCSObjectIdentifiers.sha256WithRSAEncryption;
556e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                sigAlgId = new AlgorithmIdentifier(sigAlgOid, DERNull.INSTANCE);
557e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                signature = new byte[1];
558e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                break;
559e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            default:
560e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                throw new ProviderException("Unsupported key algorithm: " + mKeymasterAlgorithm);
561e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        }
5624510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
563e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        try (ASN1InputStream publicKeyInfoIn = new ASN1InputStream(publicKey.getEncoded())) {
564e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            tbsGenerator.setSubjectPublicKeyInfo(
565e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    SubjectPublicKeyInfo.getInstance(publicKeyInfoIn.readObject()));
566e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        }
567e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        tbsGenerator.setSerialNumber(new ASN1Integer(mSpec.getCertificateSerialNumber()));
568e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        X509Principal subject =
569e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                new X509Principal(mSpec.getCertificateSubject().getEncoded());
5704510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        tbsGenerator.setSubject(subject);
571e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        tbsGenerator.setIssuer(subject);
572e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        tbsGenerator.setStartDate(new Time(mSpec.getCertificateNotBefore()));
573e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        tbsGenerator.setEndDate(new Time(mSpec.getCertificateNotAfter()));
574e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        tbsGenerator.setSignature(sigAlgId);
575e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        TBSCertificate tbsCertificate = tbsGenerator.generateTBSCertificate();
576e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
577e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        ASN1EncodableVector result = new ASN1EncodableVector();
5784510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        result.add(tbsCertificate);
579e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        result.add(sigAlgId);
580e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        result.add(new DERBitString(signature));
581e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        return new X509CertificateObject(Certificate.getInstance(new DERSequence(result)));
582e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
583e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
584e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    private static int getDefaultKeySize(int keymasterAlgorithm) {
585e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        switch (keymasterAlgorithm) {
5864510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            case KeymasterDefs.KM_ALGORITHM_EC:
587e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                return EC_DEFAULT_KEY_SIZE;
588e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            case KeymasterDefs.KM_ALGORITHM_RSA:
589e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                return RSA_DEFAULT_KEY_SIZE;
590e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            default:
591e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                throw new ProviderException("Unsupported algorithm: " + keymasterAlgorithm);
592e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        }
593e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
5944510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
595e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    private static void checkValidKeySize(int keymasterAlgorithm, int keySize)
596e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            throws InvalidAlgorithmParameterException {
597e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        switch (keymasterAlgorithm) {
598e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            case KeymasterDefs.KM_ALGORITHM_EC:
599e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                if (!SUPPORTED_EC_NIST_CURVE_SIZES.contains(keySize)) {
600e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    throw new InvalidAlgorithmParameterException("Unsupported EC key size: "
601e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                            + keySize + " bits. Supported: " + SUPPORTED_EC_NIST_CURVE_SIZES);
6024510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                }
603e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                break;
604e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            case KeymasterDefs.KM_ALGORITHM_RSA:
605e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                if (keySize < RSA_MIN_KEY_SIZE || keySize > RSA_MAX_KEY_SIZE) {
606e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    throw new InvalidAlgorithmParameterException("RSA key size must be >= "
607e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                            + RSA_MIN_KEY_SIZE + " and <= " + RSA_MAX_KEY_SIZE);
608e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                }
609e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                break;
6104510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            default:
611e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                throw new ProviderException("Unsupported algorithm: " + keymasterAlgorithm);
612e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        }
613e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
614e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
615e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    /**
616e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk     * Returns the {@code Signature} algorithm to be used for signing a certificate using the
617e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk     * specified key or {@code null} if the key cannot be used for signing a certificate.
6184510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk     */
619e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    @Nullable
620e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    private static String getCertificateSignatureAlgorithm(
621e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            int keymasterAlgorithm,
622e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            int keySizeBits,
623e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            KeyGenParameterSpec spec) {
624e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        // Constraints:
625e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        // 1. Key must be authorized for signing without user authentication.
6264510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        // 2. Signature digest must be one of key's authorized digests.
627e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        // 3. For RSA keys, the digest output size must not exceed modulus size minus space overhead
628e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        //    of RSA PKCS#1 signature padding scheme (about 30 bytes).
629e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        // 4. For EC keys, the there is no point in using a digest whose output size is longer than
630e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        //    key/field size because the digest will be truncated to that size.
631e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
632e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        if ((spec.getPurposes() & KeyProperties.PURPOSE_SIGN) == 0) {
633e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            // Key not authorized for signing
6344510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            return null;
635e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        }
636e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        if (spec.isUserAuthenticationRequired()) {
637e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            // Key not authorized for use without user authentication
638e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            return null;
639e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        }
640e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        if (!spec.isDigestsSpecified()) {
641e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            // Key not authorized for any digests -- can't sign
6424510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            return null;
643e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        }
644e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        switch (keymasterAlgorithm) {
645e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            case KeymasterDefs.KM_ALGORITHM_EC:
646e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            {
647e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                Set<Integer> availableKeymasterDigests = getAvailableKeymasterSignatureDigests(
648e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        spec.getDigests(),
649e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        AndroidKeyStoreBCWorkaroundProvider.getSupportedEcdsaSignatureDigests());
6504510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
651e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                int bestKeymasterDigest = -1;
652e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                int bestDigestOutputSizeBits = -1;
653e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                for (int keymasterDigest : availableKeymasterDigests) {
654e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    int outputSizeBits = KeymasterUtils.getDigestOutputSizeBits(keymasterDigest);
655e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    if (outputSizeBits == keySizeBits) {
656e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        // Perfect match -- use this digest
657e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        bestKeymasterDigest = keymasterDigest;
6584510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                        bestDigestOutputSizeBits = outputSizeBits;
659e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        break;
660e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    }
661e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    // Not a perfect match -- check against the best digest so far
662e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    if (bestKeymasterDigest == -1) {
663e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        // First digest tested -- definitely the best so far
664e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        bestKeymasterDigest = keymasterDigest;
665e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        bestDigestOutputSizeBits = outputSizeBits;
6664510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                    } else {
667e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        // Prefer output size to be as close to key size as possible, with output
668e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        // sizes larger than key size preferred to those smaller than key size.
669e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        if (bestDigestOutputSizeBits < keySizeBits) {
670e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                            // Output size of the best digest so far is smaller than key size.
671e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                            // Anything larger is a win.
672e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                            if (outputSizeBits > bestDigestOutputSizeBits) {
673e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                                bestKeymasterDigest = keymasterDigest;
674e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                                bestDigestOutputSizeBits = outputSizeBits;
675e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                            }
676e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        } else {
677e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                            // Output size of the best digest so far is larger than key size.
678e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                            // Anything smaller is a win, as long as it's not smaller than key size.
679e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                            if ((outputSizeBits < bestDigestOutputSizeBits)
6804510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                                    && (outputSizeBits >= keySizeBits)) {
681e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                                bestKeymasterDigest = keymasterDigest;
682e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                                bestDigestOutputSizeBits = outputSizeBits;
683e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                            }
684e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        }
685e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    }
686e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                }
687e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                if (bestKeymasterDigest == -1) {
6884510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                    return null;
689e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                }
690e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                return KeyProperties.Digest.fromKeymasterToSignatureAlgorithmDigest(
691e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        bestKeymasterDigest) + "WithECDSA";
692e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            }
693e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            case KeymasterDefs.KM_ALGORITHM_RSA:
694e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            {
695e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                // Check whether this key is authorized for PKCS#1 signature padding.
6964510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                // We use Bouncy Castle to generate self-signed RSA certificates. Bouncy Castle
697e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                // only supports RSA certificates signed using PKCS#1 padding scheme. The key needs
698e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                // to be authorized for PKCS#1 padding or padding NONE which means any padding.
699e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                boolean pkcs1SignaturePaddingSupported = false;
700e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                for (int keymasterPadding : KeyProperties.SignaturePadding.allToKeymaster(
701e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        spec.getSignaturePaddings())) {
702e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    if ((keymasterPadding == KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN)
703e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                            || (keymasterPadding == KeymasterDefs.KM_PAD_NONE)) {
7044510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                        pkcs1SignaturePaddingSupported = true;
705e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        break;
706e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    }
707e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                }
708e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                if (!pkcs1SignaturePaddingSupported) {
709e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    // Keymaster doesn't distinguish between encryption padding NONE and signature
710e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    // padding NONE. In the Android Keystore API only encryption padding NONE is
711e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    // exposed.
7124510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                    for (int keymasterPadding : KeyProperties.EncryptionPadding.allToKeymaster(
713e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                            spec.getEncryptionPaddings())) {
714e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        if (keymasterPadding == KeymasterDefs.KM_PAD_NONE) {
715e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                            pkcs1SignaturePaddingSupported = true;
716e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                            break;
717e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        }
718e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    }
719e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                }
7204510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                if (!pkcs1SignaturePaddingSupported) {
721e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    // Key not authorized for PKCS#1 signature padding -- can't sign
722e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    return null;
723e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                }
724e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
725e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                Set<Integer> availableKeymasterDigests = getAvailableKeymasterSignatureDigests(
726e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        spec.getDigests(),
727e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        AndroidKeyStoreBCWorkaroundProvider.getSupportedEcdsaSignatureDigests());
7284510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
729e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                // The amount of space available for the digest is less than modulus size by about
730e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                // 30 bytes because padding must be at least 11 bytes long (00 || 01 || PS || 00,
731e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                // where PS must be at least 8 bytes long), and then there's also the 15--19 bytes
732e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                // overhead (depending the on chosen digest) for encoding digest OID and digest
733e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                // value in DER.
734e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                int maxDigestOutputSizeBits = keySizeBits - 30 * 8;
735e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                int bestKeymasterDigest = -1;
7364510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                int bestDigestOutputSizeBits = -1;
737e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                for (int keymasterDigest : availableKeymasterDigests) {
738e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    int outputSizeBits = KeymasterUtils.getDigestOutputSizeBits(keymasterDigest);
739e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    if (outputSizeBits > maxDigestOutputSizeBits) {
740e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        // Digest too long (signature generation will fail) -- skip
741e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        continue;
742e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    }
743e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    if (bestKeymasterDigest == -1) {
7444510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                        // First digest tested -- definitely the best so far
745e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        bestKeymasterDigest = keymasterDigest;
74645a599d79a1a1b74b959d98eccfbec9c6a5aa237Eino-Ville Talvala                        bestDigestOutputSizeBits = outputSizeBits;
747e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    } else {
748e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        // The longer the better
749e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        if (outputSizeBits > bestDigestOutputSizeBits) {
750e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                            bestKeymasterDigest = keymasterDigest;
751e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                            bestDigestOutputSizeBits = outputSizeBits;
7524510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                        }
753e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    }
754e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                }
755e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                if (bestKeymasterDigest == -1) {
756e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                    return null;
757e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                }
758e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                return KeyProperties.Digest.fromKeymasterToSignatureAlgorithmDigest(
759e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                        bestKeymasterDigest) + "WithRSA";
7604510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            }
761e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            default:
762e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                throw new ProviderException("Unsupported algorithm: " + keymasterAlgorithm);
763e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        }
764e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
765e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
766e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    private static Set<Integer> getAvailableKeymasterSignatureDigests(
767e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            @KeyProperties.DigestEnum String[] authorizedKeyDigests,
7684510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            @KeyProperties.DigestEnum String[] supportedSignatureDigests) {
769e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        Set<Integer> authorizedKeymasterKeyDigests = new HashSet<Integer>();
770e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        for (int keymasterDigest : KeyProperties.Digest.allToKeymaster(authorizedKeyDigests)) {
771e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            authorizedKeymasterKeyDigests.add(keymasterDigest);
772e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        }
773e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        Set<Integer> supportedKeymasterSignatureDigests = new HashSet<Integer>();
774e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        for (int keymasterDigest
775e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk                : KeyProperties.Digest.allToKeymaster(supportedSignatureDigests)) {
7764510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            supportedKeymasterSignatureDigests.add(keymasterDigest);
777e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        }
778e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        if (authorizedKeymasterKeyDigests.contains(KeymasterDefs.KM_DIGEST_NONE)) {
779e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            // Key is authorized to be used with any digest
780e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            return supportedKeymasterSignatureDigests;
781e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        } else {
782e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            // Key is authorized to be used only with specific digests.
783e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            Set<Integer> result = new HashSet<Integer>(supportedKeymasterSignatureDigests);
7844510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            result.retainAll(authorizedKeymasterKeyDigests);
785e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            return result;
786e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        }
787e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
788e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk}
789e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk