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.apache.harmony.xnet.provider.jsse;
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<T, S> extends KeyFactorySpi {
37
38    @Override
39    protected PublicKey engineGeneratePublic(KeySpec keySpec) throws InvalidKeySpecException {
40        if (keySpec instanceof RSAPublicKeySpec) {
41            RSAPublicKeySpec rsaKeySpec = (RSAPublicKeySpec) keySpec;
42
43            return new OpenSSLRSAPublicKey(rsaKeySpec);
44        } else if (keySpec instanceof X509EncodedKeySpec) {
45            X509EncodedKeySpec x509KeySpec = (X509EncodedKeySpec) keySpec;
46
47            try {
48                final OpenSSLKey key = new OpenSSLKey(
49                        NativeCrypto.d2i_PUBKEY(x509KeySpec.getEncoded()));
50                return new OpenSSLRSAPublicKey(key);
51            } catch (Exception e) {
52                throw new InvalidKeySpecException(e);
53            }
54        }
55        throw new InvalidKeySpecException("Must use RSAPublicKeySpec or X509EncodedKeySpec; was "
56                + keySpec.getClass().getName());
57    }
58
59    @Override
60    protected PrivateKey engineGeneratePrivate(KeySpec keySpec) throws InvalidKeySpecException {
61        if (keySpec instanceof RSAPrivateCrtKeySpec) {
62            RSAPrivateCrtKeySpec rsaKeySpec = (RSAPrivateCrtKeySpec) keySpec;
63
64            return new OpenSSLRSAPrivateCrtKey(rsaKeySpec);
65        } else if (keySpec instanceof RSAPrivateKeySpec) {
66            RSAPrivateKeySpec rsaKeySpec = (RSAPrivateKeySpec) keySpec;
67
68            return new OpenSSLRSAPrivateKey(rsaKeySpec);
69        } else if (keySpec instanceof PKCS8EncodedKeySpec) {
70            PKCS8EncodedKeySpec pkcs8KeySpec = (PKCS8EncodedKeySpec) keySpec;
71
72            try {
73                final OpenSSLKey key = new OpenSSLKey(
74                        NativeCrypto.d2i_PKCS8_PRIV_KEY_INFO(pkcs8KeySpec.getEncoded()));
75                return OpenSSLRSAPrivateKey.getInstance(key);
76            } catch (Exception e) {
77                throw new InvalidKeySpecException(e);
78            }
79        }
80        throw new InvalidKeySpecException("Must use RSAPublicKeySpec or PKCS8EncodedKeySpec; was "
81                + keySpec.getClass().getName());
82    }
83
84    @Override
85    protected <T extends KeySpec> T engineGetKeySpec(Key key, Class<T> keySpec)
86            throws InvalidKeySpecException {
87        if (key == null) {
88            throw new InvalidKeySpecException("key == null");
89        }
90
91        if (keySpec == null) {
92            throw new InvalidKeySpecException("keySpec == null");
93        }
94
95        if (key instanceof RSAPublicKey) {
96            RSAPublicKey rsaKey = (RSAPublicKey) key;
97
98            if (RSAPublicKeySpec.class.equals(keySpec)) {
99                BigInteger modulus = rsaKey.getModulus();
100                BigInteger publicExponent = rsaKey.getPublicExponent();
101                return (T) new RSAPublicKeySpec(modulus, publicExponent);
102            } else if (X509EncodedKeySpec.class.equals(keySpec)) {
103                return (T) new X509EncodedKeySpec(key.getEncoded());
104            } else {
105                throw new InvalidKeySpecException("Must be RSAPublicKeySpec or X509EncodedKeySpec");
106            }
107        } else if (key instanceof RSAPrivateCrtKey) {
108            RSAPrivateCrtKey rsaKey = (RSAPrivateCrtKey) key;
109
110            if (RSAPrivateKeySpec.class.equals(keySpec)) {
111                BigInteger modulus = rsaKey.getModulus();
112                BigInteger privateExponent = rsaKey.getPrivateExponent();
113                return (T) new RSAPrivateKeySpec(modulus, privateExponent);
114            } else if (RSAPrivateCrtKeySpec.class.equals(keySpec)) {
115                BigInteger modulus = rsaKey.getModulus();
116                BigInteger publicExponent = rsaKey.getPublicExponent();
117                BigInteger privateExponent = rsaKey.getPrivateExponent();
118                BigInteger primeP = rsaKey.getPrimeP();
119                BigInteger primeQ = rsaKey.getPrimeQ();
120                BigInteger primeExponentP = rsaKey.getPrimeExponentP();
121                BigInteger primeExponentQ = rsaKey.getPrimeExponentQ();
122                BigInteger crtCoefficient = rsaKey.getCrtCoefficient();
123                return (T) new RSAPrivateCrtKeySpec(modulus, publicExponent, privateExponent,
124                        primeP, primeQ, primeExponentP, primeExponentQ, crtCoefficient);
125            } else if (PKCS8EncodedKeySpec.class.equals(keySpec)) {
126                return (T) new PKCS8EncodedKeySpec(rsaKey.getEncoded());
127            } else {
128                throw new InvalidKeySpecException(
129                        "Must be RSAPrivateKeySpec or or RSAPrivateCrtKeySpec or PKCS8EncodedKeySpec");
130            }
131        } else if (key instanceof RSAPrivateKey) {
132            RSAPrivateKey rsaKey = (RSAPrivateKey) key;
133
134            if (RSAPrivateKeySpec.class.equals(keySpec)) {
135                BigInteger modulus = rsaKey.getModulus();
136                BigInteger privateExponent = rsaKey.getPrivateExponent();
137                return (T) new RSAPrivateKeySpec(modulus, privateExponent);
138            } else if (RSAPrivateCrtKeySpec.class.equals(keySpec)) {
139                BigInteger modulus = rsaKey.getModulus();
140                BigInteger privateExponent = rsaKey.getPrivateExponent();
141                return (T) new RSAPrivateCrtKeySpec(modulus, null, privateExponent, null, null,
142                        null, null, null);
143            } else if (PKCS8EncodedKeySpec.class.equals(keySpec)) {
144                return (T) new PKCS8EncodedKeySpec(rsaKey.getEncoded());
145            } else {
146                throw new InvalidKeySpecException(
147                        "Must be RSAPrivateKeySpec or PKCS8EncodedKeySpec");
148            }
149        } else {
150            throw new InvalidKeySpecException("Must be RSAPublicKey or RSAPrivateKey");
151        }
152    }
153
154    @Override
155    protected Key engineTranslateKey(Key key) throws InvalidKeyException {
156        if (key == null) {
157            throw new InvalidKeyException("key == null");
158        }
159
160        if (key instanceof RSAPublicKey) {
161            RSAPublicKey rsaKey = (RSAPublicKey) key;
162
163            try {
164                return engineGeneratePublic(new RSAPublicKeySpec(rsaKey.getModulus(),
165                        rsaKey.getPublicExponent()));
166            } catch (InvalidKeySpecException e) {
167                throw new InvalidKeyException(e);
168            }
169        } else if (key instanceof RSAPrivateCrtKey) {
170            RSAPrivateCrtKey rsaKey = (RSAPrivateCrtKey) key;
171            BigInteger modulus = rsaKey.getModulus();
172            BigInteger publicExponent = rsaKey.getPublicExponent();
173            BigInteger privateExponent = rsaKey.getPrivateExponent();
174            BigInteger primeP = rsaKey.getPrimeP();
175            BigInteger primeQ = rsaKey.getPrimeQ();
176            BigInteger primeExponentP = rsaKey.getPrimeExponentP();
177            BigInteger primeExponentQ = rsaKey.getPrimeExponentQ();
178            BigInteger crtCoefficient = rsaKey.getCrtCoefficient();
179
180            try {
181                return engineGeneratePrivate(new RSAPrivateCrtKeySpec(modulus, publicExponent,
182                        privateExponent, primeP, primeQ, primeExponentP, primeExponentQ,
183                        crtCoefficient));
184            } catch (InvalidKeySpecException e) {
185                throw new InvalidKeyException(e);
186            }
187        } else if (key instanceof RSAPrivateKey) {
188            RSAPrivateKey rsaKey = (RSAPrivateKey) key;
189            BigInteger modulus = rsaKey.getModulus();
190            BigInteger privateExponent = rsaKey.getPrivateExponent();
191
192            try {
193                return engineGeneratePrivate(new RSAPrivateKeySpec(modulus, privateExponent));
194            } catch (InvalidKeySpecException e) {
195                throw new InvalidKeyException(e);
196            }
197        } else {
198            throw new InvalidKeyException(
199                    "Key must be RSAPublicKey or RSAPrivateCrtKey or RSAPrivateKey");
200        }
201    }
202}
203