1746a236e2be5dee62c482e27f4c682496d071d8bKenny Root/*
2746a236e2be5dee62c482e27f4c682496d071d8bKenny Root * Copyright (C) 2012 The Android Open Source Project
3746a236e2be5dee62c482e27f4c682496d071d8bKenny Root *
4746a236e2be5dee62c482e27f4c682496d071d8bKenny Root * Licensed under the Apache License, Version 2.0 (the "License");
5746a236e2be5dee62c482e27f4c682496d071d8bKenny Root * you may not use this file except in compliance with the License.
6746a236e2be5dee62c482e27f4c682496d071d8bKenny Root * You may obtain a copy of the License at
7746a236e2be5dee62c482e27f4c682496d071d8bKenny Root *
8746a236e2be5dee62c482e27f4c682496d071d8bKenny Root *      http://www.apache.org/licenses/LICENSE-2.0
9746a236e2be5dee62c482e27f4c682496d071d8bKenny Root *
10746a236e2be5dee62c482e27f4c682496d071d8bKenny Root * Unless required by applicable law or agreed to in writing, software
11746a236e2be5dee62c482e27f4c682496d071d8bKenny Root * distributed under the License is distributed on an "AS IS" BASIS,
12746a236e2be5dee62c482e27f4c682496d071d8bKenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13746a236e2be5dee62c482e27f4c682496d071d8bKenny Root * See the License for the specific language governing permissions and
14746a236e2be5dee62c482e27f4c682496d071d8bKenny Root * limitations under the License.
15746a236e2be5dee62c482e27f4c682496d071d8bKenny Root */
16746a236e2be5dee62c482e27f4c682496d071d8bKenny Root
17746a236e2be5dee62c482e27f4c682496d071d8bKenny Rootpackage org.apache.harmony.xnet.provider.jsse;
18746a236e2be5dee62c482e27f4c682496d071d8bKenny Root
19746a236e2be5dee62c482e27f4c682496d071d8bKenny Rootimport java.math.BigInteger;
20746a236e2be5dee62c482e27f4c682496d071d8bKenny Rootimport java.security.InvalidKeyException;
21746a236e2be5dee62c482e27f4c682496d071d8bKenny Rootimport java.security.Key;
22746a236e2be5dee62c482e27f4c682496d071d8bKenny Rootimport java.security.KeyFactorySpi;
23746a236e2be5dee62c482e27f4c682496d071d8bKenny Rootimport java.security.PrivateKey;
24746a236e2be5dee62c482e27f4c682496d071d8bKenny Rootimport java.security.PublicKey;
25746a236e2be5dee62c482e27f4c682496d071d8bKenny Rootimport java.security.interfaces.RSAPrivateCrtKey;
26746a236e2be5dee62c482e27f4c682496d071d8bKenny Rootimport java.security.interfaces.RSAPrivateKey;
27746a236e2be5dee62c482e27f4c682496d071d8bKenny Rootimport java.security.interfaces.RSAPublicKey;
28746a236e2be5dee62c482e27f4c682496d071d8bKenny Rootimport java.security.spec.InvalidKeySpecException;
29746a236e2be5dee62c482e27f4c682496d071d8bKenny Rootimport java.security.spec.KeySpec;
30746a236e2be5dee62c482e27f4c682496d071d8bKenny Rootimport java.security.spec.PKCS8EncodedKeySpec;
31746a236e2be5dee62c482e27f4c682496d071d8bKenny Rootimport java.security.spec.RSAPrivateCrtKeySpec;
32746a236e2be5dee62c482e27f4c682496d071d8bKenny Rootimport java.security.spec.RSAPrivateKeySpec;
33746a236e2be5dee62c482e27f4c682496d071d8bKenny Rootimport java.security.spec.RSAPublicKeySpec;
34746a236e2be5dee62c482e27f4c682496d071d8bKenny Rootimport java.security.spec.X509EncodedKeySpec;
35746a236e2be5dee62c482e27f4c682496d071d8bKenny Root
36746a236e2be5dee62c482e27f4c682496d071d8bKenny Rootpublic class OpenSSLRSAKeyFactory<T, S> extends KeyFactorySpi {
37746a236e2be5dee62c482e27f4c682496d071d8bKenny Root
38746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    @Override
39746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    protected PublicKey engineGeneratePublic(KeySpec keySpec) throws InvalidKeySpecException {
40746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        if (keySpec instanceof RSAPublicKeySpec) {
41746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            RSAPublicKeySpec rsaKeySpec = (RSAPublicKeySpec) keySpec;
42746a236e2be5dee62c482e27f4c682496d071d8bKenny Root
43746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            return new OpenSSLRSAPublicKey(rsaKeySpec);
44746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        } else if (keySpec instanceof X509EncodedKeySpec) {
45746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            X509EncodedKeySpec x509KeySpec = (X509EncodedKeySpec) keySpec;
46746a236e2be5dee62c482e27f4c682496d071d8bKenny Root
47746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            try {
48746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                final OpenSSLKey key = new OpenSSLKey(
49746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                        NativeCrypto.d2i_PUBKEY(x509KeySpec.getEncoded()));
50746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                return new OpenSSLRSAPublicKey(key);
51746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            } catch (Exception e) {
52746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                throw new InvalidKeySpecException(e);
53746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            }
54746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        }
55746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        throw new InvalidKeySpecException("Must use RSAPublicKeySpec or X509EncodedKeySpec; was "
56746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                + keySpec.getClass().getName());
57746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    }
58746a236e2be5dee62c482e27f4c682496d071d8bKenny Root
59746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    @Override
60746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    protected PrivateKey engineGeneratePrivate(KeySpec keySpec) throws InvalidKeySpecException {
61746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        if (keySpec instanceof RSAPrivateCrtKeySpec) {
62746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            RSAPrivateCrtKeySpec rsaKeySpec = (RSAPrivateCrtKeySpec) keySpec;
63746a236e2be5dee62c482e27f4c682496d071d8bKenny Root
645b7f91c1e6e208187cef57ab8a5de0a7f35e817fBrian Carlstrom            return new OpenSSLRSAPrivateCrtKey(rsaKeySpec);
65746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        } else if (keySpec instanceof RSAPrivateKeySpec) {
66746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            RSAPrivateKeySpec rsaKeySpec = (RSAPrivateKeySpec) keySpec;
67746a236e2be5dee62c482e27f4c682496d071d8bKenny Root
68746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            return new OpenSSLRSAPrivateKey(rsaKeySpec);
69746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        } else if (keySpec instanceof PKCS8EncodedKeySpec) {
70746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            PKCS8EncodedKeySpec pkcs8KeySpec = (PKCS8EncodedKeySpec) keySpec;
71746a236e2be5dee62c482e27f4c682496d071d8bKenny Root
72746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            try {
73746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                final OpenSSLKey key = new OpenSSLKey(
74746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                        NativeCrypto.d2i_PKCS8_PRIV_KEY_INFO(pkcs8KeySpec.getEncoded()));
755b7f91c1e6e208187cef57ab8a5de0a7f35e817fBrian Carlstrom                return OpenSSLRSAPrivateKey.getInstance(key);
76746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            } catch (Exception e) {
77746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                throw new InvalidKeySpecException(e);
78746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            }
79746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        }
80746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        throw new InvalidKeySpecException("Must use RSAPublicKeySpec or PKCS8EncodedKeySpec; was "
81746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                + keySpec.getClass().getName());
82746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    }
83746a236e2be5dee62c482e27f4c682496d071d8bKenny Root
84746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    @Override
85746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    protected <T extends KeySpec> T engineGetKeySpec(Key key, Class<T> keySpec)
86746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            throws InvalidKeySpecException {
87746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        if (key == null) {
88746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            throw new InvalidKeySpecException("key == null");
89746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        }
90746a236e2be5dee62c482e27f4c682496d071d8bKenny Root
91746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        if (keySpec == null) {
92746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            throw new InvalidKeySpecException("keySpec == null");
93746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        }
94746a236e2be5dee62c482e27f4c682496d071d8bKenny Root
95746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        if (key instanceof RSAPublicKey) {
96746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            RSAPublicKey rsaKey = (RSAPublicKey) key;
97746a236e2be5dee62c482e27f4c682496d071d8bKenny Root
98746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            if (RSAPublicKeySpec.class.equals(keySpec)) {
99746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                BigInteger modulus = rsaKey.getModulus();
100746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                BigInteger publicExponent = rsaKey.getPublicExponent();
101746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                return (T) new RSAPublicKeySpec(modulus, publicExponent);
102746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            } else if (X509EncodedKeySpec.class.equals(keySpec)) {
103746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                return (T) new X509EncodedKeySpec(key.getEncoded());
104746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            } else {
105746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                throw new InvalidKeySpecException("Must be RSAPublicKeySpec or X509EncodedKeySpec");
106746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            }
107746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        } else if (key instanceof RSAPrivateCrtKey) {
108746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            RSAPrivateCrtKey rsaKey = (RSAPrivateCrtKey) key;
109746a236e2be5dee62c482e27f4c682496d071d8bKenny Root
110746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            if (RSAPrivateKeySpec.class.equals(keySpec)) {
111746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                BigInteger modulus = rsaKey.getModulus();
112746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                BigInteger privateExponent = rsaKey.getPrivateExponent();
1135b7f91c1e6e208187cef57ab8a5de0a7f35e817fBrian Carlstrom                return (T) new RSAPrivateKeySpec(modulus, privateExponent);
114746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            } else if (RSAPrivateCrtKeySpec.class.equals(keySpec)) {
115746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                BigInteger modulus = rsaKey.getModulus();
116746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                BigInteger publicExponent = rsaKey.getPublicExponent();
117746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                BigInteger privateExponent = rsaKey.getPrivateExponent();
118746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                BigInteger primeP = rsaKey.getPrimeP();
119746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                BigInteger primeQ = rsaKey.getPrimeQ();
120746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                BigInteger primeExponentP = rsaKey.getPrimeExponentP();
121746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                BigInteger primeExponentQ = rsaKey.getPrimeExponentQ();
122746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                BigInteger crtCoefficient = rsaKey.getCrtCoefficient();
123746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                return (T) new RSAPrivateCrtKeySpec(modulus, publicExponent, privateExponent,
124746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                        primeP, primeQ, primeExponentP, primeExponentQ, crtCoefficient);
125746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            } else if (PKCS8EncodedKeySpec.class.equals(keySpec)) {
126746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                return (T) new PKCS8EncodedKeySpec(rsaKey.getEncoded());
127746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            } else {
128746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                throw new InvalidKeySpecException(
129746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                        "Must be RSAPrivateKeySpec or or RSAPrivateCrtKeySpec or PKCS8EncodedKeySpec");
130746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            }
131746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        } else if (key instanceof RSAPrivateKey) {
132746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            RSAPrivateKey rsaKey = (RSAPrivateKey) key;
133746a236e2be5dee62c482e27f4c682496d071d8bKenny Root
134746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            if (RSAPrivateKeySpec.class.equals(keySpec)) {
135746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                BigInteger modulus = rsaKey.getModulus();
136746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                BigInteger privateExponent = rsaKey.getPrivateExponent();
137746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                return (T) new RSAPrivateKeySpec(modulus, privateExponent);
138746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            } else if (RSAPrivateCrtKeySpec.class.equals(keySpec)) {
139746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                BigInteger modulus = rsaKey.getModulus();
140746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                BigInteger privateExponent = rsaKey.getPrivateExponent();
141746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                return (T) new RSAPrivateCrtKeySpec(modulus, null, privateExponent, null, null,
142746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                        null, null, null);
143746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            } else if (PKCS8EncodedKeySpec.class.equals(keySpec)) {
144746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                return (T) new PKCS8EncodedKeySpec(rsaKey.getEncoded());
145746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            } else {
146746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                throw new InvalidKeySpecException(
147746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                        "Must be RSAPrivateKeySpec or PKCS8EncodedKeySpec");
148746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            }
149746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        } else {
150746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            throw new InvalidKeySpecException("Must be RSAPublicKey or RSAPrivateKey");
151746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        }
152746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    }
153746a236e2be5dee62c482e27f4c682496d071d8bKenny Root
154746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    @Override
155746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    protected Key engineTranslateKey(Key key) throws InvalidKeyException {
156746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        if (key == null) {
157746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            throw new InvalidKeyException("key == null");
158746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        }
159746a236e2be5dee62c482e27f4c682496d071d8bKenny Root
160746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        if (key instanceof RSAPublicKey) {
161746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            RSAPublicKey rsaKey = (RSAPublicKey) key;
162746a236e2be5dee62c482e27f4c682496d071d8bKenny Root
163746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            try {
164746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                return engineGeneratePublic(new RSAPublicKeySpec(rsaKey.getModulus(),
165746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                        rsaKey.getPublicExponent()));
166746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            } catch (InvalidKeySpecException e) {
167746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                throw new InvalidKeyException(e);
168746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            }
169746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        } else if (key instanceof RSAPrivateCrtKey) {
170746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            RSAPrivateCrtKey rsaKey = (RSAPrivateCrtKey) key;
171746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            BigInteger modulus = rsaKey.getModulus();
172746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            BigInteger publicExponent = rsaKey.getPublicExponent();
173746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            BigInteger privateExponent = rsaKey.getPrivateExponent();
174746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            BigInteger primeP = rsaKey.getPrimeP();
175746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            BigInteger primeQ = rsaKey.getPrimeQ();
176746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            BigInteger primeExponentP = rsaKey.getPrimeExponentP();
177746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            BigInteger primeExponentQ = rsaKey.getPrimeExponentQ();
178746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            BigInteger crtCoefficient = rsaKey.getCrtCoefficient();
179746a236e2be5dee62c482e27f4c682496d071d8bKenny Root
180746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            try {
181746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                return engineGeneratePrivate(new RSAPrivateCrtKeySpec(modulus, publicExponent,
182746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                        privateExponent, primeP, primeQ, primeExponentP, primeExponentQ,
183746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                        crtCoefficient));
184746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            } catch (InvalidKeySpecException e) {
185746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                throw new InvalidKeyException(e);
186746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            }
187746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        } else if (key instanceof RSAPrivateKey) {
188746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            RSAPrivateKey rsaKey = (RSAPrivateKey) key;
189746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            BigInteger modulus = rsaKey.getModulus();
190746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            BigInteger privateExponent = rsaKey.getPrivateExponent();
191746a236e2be5dee62c482e27f4c682496d071d8bKenny Root
192746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            try {
193746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                return engineGeneratePrivate(new RSAPrivateKeySpec(modulus, privateExponent));
194746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            } catch (InvalidKeySpecException e) {
195746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                throw new InvalidKeyException(e);
196746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            }
197746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        } else {
198746a236e2be5dee62c482e27f4c682496d071d8bKenny Root            throw new InvalidKeyException(
199746a236e2be5dee62c482e27f4c682496d071d8bKenny Root                    "Key must be RSAPublicKey or RSAPrivateCrtKey or RSAPrivateKey");
200746a236e2be5dee62c482e27f4c682496d071d8bKenny Root        }
201746a236e2be5dee62c482e27f4c682496d071d8bKenny Root    }
202746a236e2be5dee62c482e27f4c682496d071d8bKenny Root}
203