1db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root/*
2db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root * Copyright (C) 2012 The Android Open Source Project
3db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root *
4db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root * Licensed under the Apache License, Version 2.0 (the "License");
5db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root * you may not use this file except in compliance with the License.
6db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root * You may obtain a copy of the License at
7db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root *
8db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root *      http://www.apache.org/licenses/LICENSE-2.0
9db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root *
10db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root * Unless required by applicable law or agreed to in writing, software
11db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root * distributed under the License is distributed on an "AS IS" BASIS,
12db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root * See the License for the specific language governing permissions and
14db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root * limitations under the License.
15db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root */
16db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
17db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Rootpackage android.security;
18db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
19db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Rootimport com.android.org.bouncycastle.x509.X509V3CertificateGenerator;
20db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
21f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Rootimport com.android.org.conscrypt.NativeCrypto;
2212e752225aa96888358294be0d725d499a1c9f03Kenny Rootimport com.android.org.conscrypt.OpenSSLEngine;
23db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
24db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Rootimport java.security.InvalidAlgorithmParameterException;
25db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Rootimport java.security.InvalidKeyException;
26db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Rootimport java.security.KeyFactory;
27db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Rootimport java.security.KeyPair;
28db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Rootimport java.security.KeyPairGenerator;
29db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Rootimport java.security.KeyPairGeneratorSpi;
30db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Rootimport java.security.NoSuchAlgorithmException;
31db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Rootimport java.security.PrivateKey;
32db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Rootimport java.security.PublicKey;
33db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Rootimport java.security.SecureRandom;
34db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Rootimport java.security.cert.CertificateEncodingException;
35db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Rootimport java.security.cert.X509Certificate;
36db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Rootimport java.security.spec.AlgorithmParameterSpec;
37f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Rootimport java.security.spec.DSAParameterSpec;
38db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Rootimport java.security.spec.InvalidKeySpecException;
39f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Rootimport java.security.spec.RSAKeyGenParameterSpec;
40db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Rootimport java.security.spec.X509EncodedKeySpec;
41db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
42db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root/**
43db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root * Provides a way to create instances of a KeyPair which will be placed in the
44db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root * Android keystore service usable only by the application that called it. This
45db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root * can be used in conjunction with
46db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root * {@link java.security.KeyStore#getInstance(String)} using the
47db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root * {@code "AndroidKeyStore"} type.
48db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root * <p>
49db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root * This class can not be directly instantiated and must instead be used via the
50db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root * {@link KeyPairGenerator#getInstance(String)
51db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root * KeyPairGenerator.getInstance("AndroidKeyPairGenerator")} API.
52db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root *
53db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root * {@hide}
54db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root */
55db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Rootpublic class AndroidKeyPairGenerator extends KeyPairGeneratorSpi {
56db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    private android.security.KeyStore mKeyStore;
57db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
581c219f619291ba818bc2542390a2988539d94ed0Kenny Root    private KeyPairGeneratorSpec mSpec;
59db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
60db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    /**
61db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root     * Generate a KeyPair which is backed by the Android keystore service. You
62db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root     * must call {@link KeyPairGenerator#initialize(AlgorithmParameterSpec)}
631c219f619291ba818bc2542390a2988539d94ed0Kenny Root     * with an {@link KeyPairGeneratorSpec} as the {@code params}
64db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root     * argument before calling this otherwise an {@code IllegalStateException}
65db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root     * will be thrown.
66db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root     * <p>
67db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root     * This will create an entry in the Android keystore service with a
68db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root     * self-signed certificate using the {@code params} specified in the
69db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root     * {@code initialize(params)} call.
70db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root     *
71db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root     * @throws IllegalStateException when called before calling
72db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root     *             {@link KeyPairGenerator#initialize(AlgorithmParameterSpec)}
73db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root     * @see java.security.KeyPairGeneratorSpi#generateKeyPair()
74db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root     */
75db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    @Override
76db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    public KeyPair generateKeyPair() {
77db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        if (mKeyStore == null || mSpec == null) {
78db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root            throw new IllegalStateException(
791c219f619291ba818bc2542390a2988539d94ed0Kenny Root                    "Must call initialize with an android.security.KeyPairGeneratorSpec first");
80db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        }
81db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
822eeda7286f3c7cb79f7eb71ae6464cad213d12a3Kenny Root        if (((mSpec.getFlags() & KeyStore.FLAG_ENCRYPTED) != 0)
832eeda7286f3c7cb79f7eb71ae6464cad213d12a3Kenny Root                && (mKeyStore.state() != KeyStore.State.UNLOCKED)) {
842eeda7286f3c7cb79f7eb71ae6464cad213d12a3Kenny Root            throw new IllegalStateException(
852eeda7286f3c7cb79f7eb71ae6464cad213d12a3Kenny Root                    "Android keystore must be in initialized and unlocked state "
862eeda7286f3c7cb79f7eb71ae6464cad213d12a3Kenny Root                            + "if encryption is required");
872eeda7286f3c7cb79f7eb71ae6464cad213d12a3Kenny Root        }
882eeda7286f3c7cb79f7eb71ae6464cad213d12a3Kenny Root
89db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        final String alias = mSpec.getKeystoreAlias();
90db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
91db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        Credentials.deleteAllTypesForAlias(mKeyStore, alias);
92db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
93f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root        final int keyType = KeyStore.getKeyTypeForAlgorithm(mSpec.getKeyType());
94f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root        byte[][] args = getArgsForKeyType(keyType, mSpec.getAlgorithmParameterSpec());
95f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root
96db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        final String privateKeyAlias = Credentials.USER_PRIVATE_KEY + alias;
97f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root        if (!mKeyStore.generate(privateKeyAlias, KeyStore.UID_SELF, keyType,
98f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root                mSpec.getKeySize(), mSpec.getFlags(), args)) {
992eeda7286f3c7cb79f7eb71ae6464cad213d12a3Kenny Root            throw new IllegalStateException("could not generate key in keystore");
1002eeda7286f3c7cb79f7eb71ae6464cad213d12a3Kenny Root        }
101db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
102db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        final PrivateKey privKey;
103db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        final OpenSSLEngine engine = OpenSSLEngine.getInstance("keystore");
104db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        try {
105db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root            privKey = engine.getPrivateKeyById(privateKeyAlias);
106db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        } catch (InvalidKeyException e) {
107db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root            throw new RuntimeException("Can't get key", e);
108db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        }
109db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
110db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        final byte[] pubKeyBytes = mKeyStore.getPubkey(privateKeyAlias);
111db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
112db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        final PublicKey pubKey;
113db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        try {
114f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root            final KeyFactory keyFact = KeyFactory.getInstance(mSpec.getKeyType());
115db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root            pubKey = keyFact.generatePublic(new X509EncodedKeySpec(pubKeyBytes));
116db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        } catch (NoSuchAlgorithmException e) {
117f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root            throw new IllegalStateException("Can't instantiate key generator", e);
118db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        } catch (InvalidKeySpecException e) {
119db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root            throw new IllegalStateException("keystore returned invalid key encoding", e);
120db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        }
121db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
122db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        final X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
123db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        certGen.setPublicKey(pubKey);
124db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        certGen.setSerialNumber(mSpec.getSerialNumber());
125db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        certGen.setSubjectDN(mSpec.getSubjectDN());
126db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        certGen.setIssuerDN(mSpec.getSubjectDN());
127db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        certGen.setNotBefore(mSpec.getStartDate());
128db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        certGen.setNotAfter(mSpec.getEndDate());
129f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root        certGen.setSignatureAlgorithm(getDefaultSignatureAlgorithmForKeyType(mSpec.getKeyType()));
130db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
131db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        final X509Certificate cert;
132db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        try {
133db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root            cert = certGen.generate(privKey);
134db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        } catch (Exception e) {
135db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root            Credentials.deleteAllTypesForAlias(mKeyStore, alias);
136db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root            throw new IllegalStateException("Can't generate certificate", e);
137db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        }
138db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
139db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        byte[] certBytes;
140db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        try {
141db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root            certBytes = cert.getEncoded();
142db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        } catch (CertificateEncodingException e) {
143db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root            Credentials.deleteAllTypesForAlias(mKeyStore, alias);
144db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root            throw new IllegalStateException("Can't get encoding of certificate", e);
145db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        }
146db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
1472eeda7286f3c7cb79f7eb71ae6464cad213d12a3Kenny Root        if (!mKeyStore.put(Credentials.USER_CERTIFICATE + alias, certBytes, KeyStore.UID_SELF,
1482eeda7286f3c7cb79f7eb71ae6464cad213d12a3Kenny Root                mSpec.getFlags())) {
149db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root            Credentials.deleteAllTypesForAlias(mKeyStore, alias);
150db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root            throw new IllegalStateException("Can't store certificate in AndroidKeyStore");
151db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        }
152db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
153db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        return new KeyPair(pubKey, privKey);
154db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    }
155db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
156f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root    private static String getDefaultSignatureAlgorithmForKeyType(String keyType) {
157f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root        if ("RSA".equalsIgnoreCase(keyType)) {
158f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root            return "sha256WithRSA";
159f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root        } else if ("DSA".equalsIgnoreCase(keyType)) {
160f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root            return "sha1WithDSA";
161f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root        } else if ("EC".equalsIgnoreCase(keyType)) {
162f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root            return "sha256WithECDSA";
163f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root        } else {
164f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root            throw new IllegalArgumentException("Unsupported key type " + keyType);
165f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root        }
166f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root    }
167f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root
168f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root    private static byte[][] getArgsForKeyType(int keyType, AlgorithmParameterSpec spec) {
169f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root        switch (keyType) {
170f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root            case NativeCrypto.EVP_PKEY_RSA:
171f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root                if (spec instanceof RSAKeyGenParameterSpec) {
172f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root                    RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec) spec;
173f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root                    return new byte[][] { rsaSpec.getPublicExponent().toByteArray() };
174f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root                }
175f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root                break;
176f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root            case NativeCrypto.EVP_PKEY_DSA:
177f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root                if (spec instanceof DSAParameterSpec) {
178f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root                    DSAParameterSpec dsaSpec = (DSAParameterSpec) spec;
179f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root                    return new byte[][] { dsaSpec.getG().toByteArray(),
180f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root                            dsaSpec.getP().toByteArray(), dsaSpec.getQ().toByteArray() };
181f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root                }
182f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root                break;
183f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root        }
184f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root        return null;
185f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root    }
186f64386fc26efeb245fd90fabaa47b8c8bf9b4613Kenny Root
187db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    @Override
188db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    public void initialize(int keysize, SecureRandom random) {
189db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        throw new IllegalArgumentException("cannot specify keysize with AndroidKeyPairGenerator");
190db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    }
191db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
192db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    @Override
193db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    public void initialize(AlgorithmParameterSpec params, SecureRandom random)
194db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root            throws InvalidAlgorithmParameterException {
195db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        if (params == null) {
196db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root            throw new InvalidAlgorithmParameterException(
1971c219f619291ba818bc2542390a2988539d94ed0Kenny Root                    "must supply params of type android.security.KeyPairGeneratorSpec");
1981c219f619291ba818bc2542390a2988539d94ed0Kenny Root        } else if (!(params instanceof KeyPairGeneratorSpec)) {
199db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root            throw new InvalidAlgorithmParameterException(
2001c219f619291ba818bc2542390a2988539d94ed0Kenny Root                    "params must be of type android.security.KeyPairGeneratorSpec");
201db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        }
202db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
2031c219f619291ba818bc2542390a2988539d94ed0Kenny Root        KeyPairGeneratorSpec spec = (KeyPairGeneratorSpec) params;
204db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root
205db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        mSpec = spec;
206db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root        mKeyStore = android.security.KeyStore.getInstance();
207db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root    }
208db026710ec0adcf7f72dfb24c65d38a882ee26d8Kenny Root}
209