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