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