Home | History | Annotate | Download | only in conscrypt
      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