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