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