1/*
2 * Copyright (C) 2012 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
17package org.conscrypt;
18
19import java.math.BigInteger;
20import java.security.InvalidKeyException;
21import java.security.Key;
22import java.security.KeyFactorySpi;
23import java.security.PrivateKey;
24import java.security.PublicKey;
25import java.security.interfaces.RSAPrivateCrtKey;
26import java.security.interfaces.RSAPrivateKey;
27import java.security.interfaces.RSAPublicKey;
28import java.security.spec.InvalidKeySpecException;
29import java.security.spec.KeySpec;
30import java.security.spec.PKCS8EncodedKeySpec;
31import java.security.spec.RSAPrivateCrtKeySpec;
32import java.security.spec.RSAPrivateKeySpec;
33import java.security.spec.RSAPublicKeySpec;
34import java.security.spec.X509EncodedKeySpec;
35
36public class OpenSSLRSAKeyFactory extends KeyFactorySpi {
37
38    @Override
39    protected PublicKey engineGeneratePublic(KeySpec keySpec) throws InvalidKeySpecException {
40        if (keySpec == null) {
41            throw new InvalidKeySpecException("keySpec == null");
42        }
43
44        if (keySpec instanceof RSAPublicKeySpec) {
45            return new OpenSSLRSAPublicKey((RSAPublicKeySpec) keySpec);
46        } else if (keySpec instanceof X509EncodedKeySpec) {
47            return OpenSSLKey.getPublicKey((X509EncodedKeySpec) keySpec, NativeCrypto.EVP_PKEY_RSA);
48        }
49        throw new InvalidKeySpecException("Must use RSAPublicKeySpec or X509EncodedKeySpec; was "
50                + keySpec.getClass().getName());
51    }
52
53    @Override
54    protected PrivateKey engineGeneratePrivate(KeySpec keySpec) throws InvalidKeySpecException {
55        if (keySpec == null) {
56            throw new InvalidKeySpecException("keySpec == null");
57        }
58
59        if (keySpec instanceof RSAPrivateCrtKeySpec) {
60            return new OpenSSLRSAPrivateCrtKey((RSAPrivateCrtKeySpec) keySpec);
61        } else if (keySpec instanceof RSAPrivateKeySpec) {
62            return new OpenSSLRSAPrivateKey((RSAPrivateKeySpec) keySpec);
63        } else if (keySpec instanceof PKCS8EncodedKeySpec) {
64            return OpenSSLKey.getPrivateKey((PKCS8EncodedKeySpec) keySpec,
65                    NativeCrypto.EVP_PKEY_RSA);
66        }
67        throw new InvalidKeySpecException("Must use RSAPublicKeySpec or PKCS8EncodedKeySpec; was "
68                + keySpec.getClass().getName());
69    }
70
71    @Override
72    protected <T extends KeySpec> T engineGetKeySpec(Key key, Class<T> keySpec)
73            throws InvalidKeySpecException {
74        if (key == null) {
75            throw new InvalidKeySpecException("key == null");
76        }
77
78        if (keySpec == null) {
79            throw new InvalidKeySpecException("keySpec == null");
80        }
81
82        if (!"RSA".equals(key.getAlgorithm())) {
83            throw new InvalidKeySpecException("Key must be a RSA key");
84        }
85
86        if (key instanceof RSAPublicKey && RSAPublicKeySpec.class.isAssignableFrom(keySpec)) {
87            RSAPublicKey rsaKey = (RSAPublicKey) key;
88            return (T) new RSAPublicKeySpec(rsaKey.getModulus(), rsaKey.getPublicExponent());
89        } else if (key instanceof PublicKey && RSAPublicKeySpec.class.isAssignableFrom(keySpec)) {
90            final byte[] encoded = key.getEncoded();
91            if (!"X.509".equals(key.getFormat()) || encoded == null) {
92                throw new InvalidKeySpecException("Not a valid X.509 encoding");
93            }
94            RSAPublicKey rsaKey =
95                    (RSAPublicKey) engineGeneratePublic(new X509EncodedKeySpec(encoded));
96            return (T) new RSAPublicKeySpec(rsaKey.getModulus(), rsaKey.getPublicExponent());
97        } else if (key instanceof RSAPrivateCrtKey
98                && RSAPrivateCrtKeySpec.class.isAssignableFrom(keySpec)) {
99            RSAPrivateCrtKey rsaKey = (RSAPrivateCrtKey) key;
100            return (T) new RSAPrivateCrtKeySpec(rsaKey.getModulus(), rsaKey.getPublicExponent(),
101                    rsaKey.getPrivateExponent(), rsaKey.getPrimeP(), rsaKey.getPrimeQ(),
102                    rsaKey.getPrimeExponentP(), rsaKey.getPrimeExponentQ(),
103                    rsaKey.getCrtCoefficient());
104        } else if (key instanceof RSAPrivateCrtKey
105                && RSAPrivateKeySpec.class.isAssignableFrom(keySpec)) {
106            RSAPrivateCrtKey rsaKey = (RSAPrivateCrtKey) key;
107            return (T) new RSAPrivateKeySpec(rsaKey.getModulus(), rsaKey.getPrivateExponent());
108        } else if (key instanceof RSAPrivateKey
109                && RSAPrivateKeySpec.class.isAssignableFrom(keySpec)) {
110            RSAPrivateKey rsaKey = (RSAPrivateKey) key;
111            return (T) new RSAPrivateKeySpec(rsaKey.getModulus(), rsaKey.getPrivateExponent());
112        } else if (key instanceof PrivateKey
113                && RSAPrivateCrtKeySpec.class.isAssignableFrom(keySpec)) {
114            final byte[] encoded = key.getEncoded();
115            if (!"PKCS#8".equals(key.getFormat()) || encoded == null) {
116                throw new InvalidKeySpecException("Not a valid PKCS#8 encoding");
117            }
118            RSAPrivateKey privKey =
119                    (RSAPrivateKey) engineGeneratePrivate(new PKCS8EncodedKeySpec(encoded));
120            if (privKey instanceof RSAPrivateCrtKey) {
121                RSAPrivateCrtKey rsaKey = (RSAPrivateCrtKey) privKey;
122                return (T) new RSAPrivateCrtKeySpec(rsaKey.getModulus(),
123                        rsaKey.getPublicExponent(), rsaKey.getPrivateExponent(),
124                        rsaKey.getPrimeP(), rsaKey.getPrimeQ(), rsaKey.getPrimeExponentP(),
125                        rsaKey.getPrimeExponentQ(), rsaKey.getCrtCoefficient());
126            } else {
127                throw new InvalidKeySpecException("Encoded key is not an RSAPrivateCrtKey");
128            }
129        } else if (key instanceof PrivateKey && RSAPrivateKeySpec.class.isAssignableFrom(keySpec)) {
130            final byte[] encoded = key.getEncoded();
131            if (!"PKCS#8".equals(key.getFormat()) || encoded == null) {
132                throw new InvalidKeySpecException("Not a valid PKCS#8 encoding");
133            }
134            RSAPrivateKey rsaKey =
135                    (RSAPrivateKey) engineGeneratePrivate(new PKCS8EncodedKeySpec(encoded));
136            return (T) new RSAPrivateKeySpec(rsaKey.getModulus(), rsaKey.getPrivateExponent());
137        } else if (key instanceof PrivateKey
138                && PKCS8EncodedKeySpec.class.isAssignableFrom(keySpec)) {
139            final byte[] encoded = key.getEncoded();
140            if (!"PKCS#8".equals(key.getFormat())) {
141                throw new InvalidKeySpecException("Encoding type must be PKCS#8; was "
142                        + key.getFormat());
143            } else if (encoded == null) {
144                throw new InvalidKeySpecException("Key is not encodable");
145            }
146            return (T) new PKCS8EncodedKeySpec(encoded);
147        } else if (key instanceof PublicKey && X509EncodedKeySpec.class.isAssignableFrom(keySpec)) {
148            final byte[] encoded = key.getEncoded();
149            if (!"X.509".equals(key.getFormat())) {
150                throw new InvalidKeySpecException("Encoding type must be X.509; was "
151                        + key.getFormat());
152            } else if (encoded == null) {
153                throw new InvalidKeySpecException("Key is not encodable");
154            }
155            return (T) new X509EncodedKeySpec(encoded);
156        } else {
157            throw new InvalidKeySpecException("Unsupported key type and key spec combination; key="
158                    + key.getClass().getName() + ", keySpec=" + keySpec.getName());
159        }
160    }
161
162    @Override
163    protected Key engineTranslateKey(Key key) throws InvalidKeyException {
164        if (key == null) {
165            throw new InvalidKeyException("key == null");
166        }
167
168        if ((key instanceof OpenSSLRSAPublicKey) || (key instanceof OpenSSLRSAPrivateKey)) {
169            return key;
170        } else if (key instanceof RSAPublicKey) {
171            RSAPublicKey rsaKey = (RSAPublicKey) key;
172
173            try {
174                return engineGeneratePublic(new RSAPublicKeySpec(rsaKey.getModulus(),
175                        rsaKey.getPublicExponent()));
176            } catch (InvalidKeySpecException e) {
177                throw new InvalidKeyException(e);
178            }
179        } else if (key instanceof RSAPrivateCrtKey) {
180            RSAPrivateCrtKey rsaKey = (RSAPrivateCrtKey) key;
181            BigInteger modulus = rsaKey.getModulus();
182            BigInteger publicExponent = rsaKey.getPublicExponent();
183            BigInteger privateExponent = rsaKey.getPrivateExponent();
184            BigInteger primeP = rsaKey.getPrimeP();
185            BigInteger primeQ = rsaKey.getPrimeQ();
186            BigInteger primeExponentP = rsaKey.getPrimeExponentP();
187            BigInteger primeExponentQ = rsaKey.getPrimeExponentQ();
188            BigInteger crtCoefficient = rsaKey.getCrtCoefficient();
189
190            try {
191                return engineGeneratePrivate(new RSAPrivateCrtKeySpec(modulus, publicExponent,
192                        privateExponent, primeP, primeQ, primeExponentP, primeExponentQ,
193                        crtCoefficient));
194            } catch (InvalidKeySpecException e) {
195                throw new InvalidKeyException(e);
196            }
197        } else if (key instanceof RSAPrivateKey) {
198            RSAPrivateKey rsaKey = (RSAPrivateKey) key;
199            BigInteger modulus = rsaKey.getModulus();
200            BigInteger privateExponent = rsaKey.getPrivateExponent();
201
202            try {
203                return engineGeneratePrivate(new RSAPrivateKeySpec(modulus, privateExponent));
204            } catch (InvalidKeySpecException e) {
205                throw new InvalidKeyException(e);
206            }
207        } else if ((key instanceof PrivateKey) && ("PKCS#8".equals(key.getFormat()))) {
208            byte[] encoded = key.getEncoded();
209            if (encoded == null) {
210                throw new InvalidKeyException("Key does not support encoding");
211            }
212            try {
213                return engineGeneratePrivate(new PKCS8EncodedKeySpec(encoded));
214            } catch (InvalidKeySpecException e) {
215                throw new InvalidKeyException(e);
216            }
217        } else if ((key instanceof PublicKey) && ("X.509".equals(key.getFormat()))) {
218            byte[] encoded = key.getEncoded();
219            if (encoded == null) {
220                throw new InvalidKeyException("Key does not support encoding");
221            }
222            try {
223                return engineGeneratePublic(new X509EncodedKeySpec(encoded));
224            } catch (InvalidKeySpecException e) {
225                throw new InvalidKeyException(e);
226            }
227        } else {
228            throw new InvalidKeyException("Key must be an RSA public or private key; was "
229                    + key.getClass().getName());
230        }
231    }
232}
233