• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.security.keystore2;
18 
19 import android.security.keystore.KeyGenParameterSpec;
20 import android.security.keystore.KeyInfo;
21 
22 import java.security.InvalidKeyException;
23 import java.security.Key;
24 import java.security.KeyFactorySpi;
25 import java.security.PrivateKey;
26 import java.security.PublicKey;
27 import java.security.spec.ECPublicKeySpec;
28 import java.security.spec.InvalidKeySpecException;
29 import java.security.spec.KeySpec;
30 import java.security.spec.PKCS8EncodedKeySpec;
31 import java.security.spec.RSAPublicKeySpec;
32 import java.security.spec.X509EncodedKeySpec;
33 
34 /**
35  * {@link KeyFactorySpi} backed by Android KeyStore.
36  *
37  * @hide
38  */
39 public class AndroidKeyStoreKeyFactorySpi extends KeyFactorySpi {
40 
41     @Override
engineGetKeySpec(Key key, Class<T> keySpecClass)42     protected <T extends KeySpec> T engineGetKeySpec(Key key, Class<T> keySpecClass)
43             throws InvalidKeySpecException {
44         if (key == null) {
45             throw new InvalidKeySpecException("key == null");
46         } else if ((!(key instanceof AndroidKeyStorePrivateKey))
47             && (!(key instanceof AndroidKeyStorePublicKey))) {
48             throw new InvalidKeySpecException(
49                     "Unsupported key type: " + key.getClass().getName()
50                     + ". This KeyFactory supports only Android Keystore asymmetric keys");
51         }
52 
53         // key is an Android Keystore private or public key
54 
55         if (keySpecClass == null) {
56             throw new InvalidKeySpecException("keySpecClass == null");
57         } else if (KeyInfo.class.equals(keySpecClass)) {
58             if (!(key instanceof AndroidKeyStorePrivateKey)) {
59                 throw new InvalidKeySpecException(
60                         "Unsupported key type: " + key.getClass().getName()
61                         + ". KeyInfo can be obtained only for Android Keystore private keys");
62             }
63             AndroidKeyStorePrivateKey keystorePrivateKey = (AndroidKeyStorePrivateKey) key;
64             @SuppressWarnings("unchecked")
65             T result = (T) AndroidKeyStoreSecretKeyFactorySpi.getKeyInfo(keystorePrivateKey);
66             return result;
67         } else if (X509EncodedKeySpec.class.equals(keySpecClass)) {
68             if (!(key instanceof AndroidKeyStorePublicKey)) {
69                 throw new InvalidKeySpecException(
70                         "Unsupported key type: " + key.getClass().getName()
71                         + ". X509EncodedKeySpec can be obtained only for Android Keystore public"
72                         + " keys");
73             }
74             @SuppressWarnings("unchecked")
75             T result = (T) new X509EncodedKeySpec(((AndroidKeyStorePublicKey) key).getEncoded());
76             return result;
77         } else if (PKCS8EncodedKeySpec.class.equals(keySpecClass)) {
78             if (key instanceof AndroidKeyStorePrivateKey) {
79                 throw new InvalidKeySpecException(
80                         "Key material export of Android Keystore private keys is not supported");
81             } else {
82                 throw new InvalidKeySpecException(
83                         "Cannot export key material of public key in PKCS#8 format."
84                         + " Only X.509 format (X509EncodedKeySpec) supported for public keys.");
85             }
86         } else if (RSAPublicKeySpec.class.equals(keySpecClass)) {
87             if (key instanceof AndroidKeyStoreRSAPublicKey) {
88                 AndroidKeyStoreRSAPublicKey rsaKey = (AndroidKeyStoreRSAPublicKey) key;
89                 @SuppressWarnings("unchecked")
90                 T result =
91                         (T) new RSAPublicKeySpec(rsaKey.getModulus(), rsaKey.getPublicExponent());
92                 return result;
93             } else {
94                 throw new InvalidKeySpecException(
95                         "Obtaining RSAPublicKeySpec not supported for " + key.getAlgorithm() + " "
96                         + ((key instanceof AndroidKeyStorePrivateKey) ? "private" : "public")
97                         + " key");
98             }
99         } else if (ECPublicKeySpec.class.equals(keySpecClass)) {
100             if (key instanceof AndroidKeyStoreECPublicKey) {
101                 AndroidKeyStoreECPublicKey ecKey = (AndroidKeyStoreECPublicKey) key;
102                 @SuppressWarnings("unchecked")
103                 T result = (T) new ECPublicKeySpec(ecKey.getW(), ecKey.getParams());
104                 return result;
105             } else {
106                 throw new InvalidKeySpecException(
107                         "Obtaining ECPublicKeySpec not supported for " + key.getAlgorithm() + " "
108                         + ((key instanceof AndroidKeyStorePrivateKey) ? "private" : "public")
109                         + " key");
110             }
111         } else {
112             throw new InvalidKeySpecException("Unsupported key spec: " + keySpecClass.getName());
113         }
114     }
115 
116     @Override
engineGeneratePrivate(KeySpec spec)117     protected PrivateKey engineGeneratePrivate(KeySpec spec) throws InvalidKeySpecException {
118         throw new InvalidKeySpecException(
119                 "To generate a key pair in Android Keystore, use KeyPairGenerator initialized with"
120                 + " " + KeyGenParameterSpec.class.getName());
121     }
122 
123     @Override
engineGeneratePublic(KeySpec spec)124     protected PublicKey engineGeneratePublic(KeySpec spec) throws InvalidKeySpecException {
125         throw new InvalidKeySpecException(
126                 "To generate a key pair in Android Keystore, use KeyPairGenerator initialized with"
127                 + " " + KeyGenParameterSpec.class.getName());
128     }
129 
130     @Override
engineTranslateKey(Key key)131     protected Key engineTranslateKey(Key key) throws InvalidKeyException {
132         if (key == null) {
133             throw new InvalidKeyException("key == null");
134         } else if ((!(key instanceof AndroidKeyStorePrivateKey))
135                 && (!(key instanceof AndroidKeyStorePublicKey))) {
136             throw new InvalidKeyException(
137                     "To import a key into Android Keystore, use KeyStore.setEntry");
138         }
139         return key;
140     }
141 }
142