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.DSAParams;
     26 import java.security.interfaces.DSAPrivateKey;
     27 import java.security.interfaces.DSAPublicKey;
     28 import java.security.spec.DSAPrivateKeySpec;
     29 import java.security.spec.DSAPublicKeySpec;
     30 import java.security.spec.InvalidKeySpecException;
     31 import java.security.spec.KeySpec;
     32 import java.security.spec.PKCS8EncodedKeySpec;
     33 import java.security.spec.X509EncodedKeySpec;
     34 
     35 public class OpenSSLDSAKeyFactory extends KeyFactorySpi {
     36 
     37     @Override
     38     protected PublicKey engineGeneratePublic(KeySpec keySpec) throws InvalidKeySpecException {
     39         if (keySpec == null) {
     40             throw new InvalidKeySpecException("keySpec == null");
     41         }
     42 
     43         if (keySpec instanceof DSAPublicKeySpec) {
     44             return new OpenSSLDSAPublicKey((DSAPublicKeySpec) keySpec);
     45         } else if (keySpec instanceof X509EncodedKeySpec) {
     46             return OpenSSLKey.getPublicKey((X509EncodedKeySpec) keySpec, NativeCrypto.EVP_PKEY_DSA);
     47         }
     48         throw new InvalidKeySpecException("Must use DSAPublicKeySpec or X509EncodedKeySpec; was "
     49                 + keySpec.getClass().getName());
     50     }
     51 
     52     @Override
     53     protected PrivateKey engineGeneratePrivate(KeySpec keySpec) throws InvalidKeySpecException {
     54         if (keySpec == null) {
     55             throw new InvalidKeySpecException("keySpec == null");
     56         }
     57 
     58         if (keySpec instanceof DSAPrivateKeySpec) {
     59             return new OpenSSLDSAPrivateKey((DSAPrivateKeySpec) keySpec);
     60         } else if (keySpec instanceof PKCS8EncodedKeySpec) {
     61             return OpenSSLKey.getPrivateKey((PKCS8EncodedKeySpec) keySpec,
     62                     NativeCrypto.EVP_PKEY_DSA);
     63         }
     64         throw new InvalidKeySpecException("Must use DSAPrivateKeySpec or PKCS8EncodedKeySpec; was "
     65                 + keySpec.getClass().getName());
     66     }
     67 
     68     @Override
     69     protected <T extends KeySpec> T engineGetKeySpec(Key key, Class<T> keySpec)
     70             throws InvalidKeySpecException {
     71         if (key == null) {
     72             throw new InvalidKeySpecException("key == null");
     73         }
     74 
     75         if (keySpec == null) {
     76             throw new InvalidKeySpecException("keySpec == null");
     77         }
     78 
     79         if (!"DSA".equals(key.getAlgorithm())) {
     80             throw new InvalidKeySpecException("Key must be a DSA key");
     81         }
     82 
     83         if (key instanceof DSAPublicKey && DSAPublicKeySpec.class.isAssignableFrom(keySpec)) {
     84             DSAPublicKey dsaKey = (DSAPublicKey) key;
     85             DSAParams params = dsaKey.getParams();
     86             return (T) new DSAPublicKeySpec(dsaKey.getY(), params.getP(), params.getQ(),
     87                     params.getG());
     88         } else if (key instanceof PublicKey && DSAPublicKeySpec.class.isAssignableFrom(keySpec)) {
     89             final byte[] encoded = key.getEncoded();
     90             if (!"X.509".equals(key.getFormat()) || encoded == null) {
     91                 throw new InvalidKeySpecException("Not a valid X.509 encoding");
     92             }
     93             DSAPublicKey dsaKey =
     94                     (DSAPublicKey) engineGeneratePublic(new X509EncodedKeySpec(encoded));
     95             DSAParams params = dsaKey.getParams();
     96             return (T) new DSAPublicKeySpec(dsaKey.getY(), params.getP(), params.getQ(),
     97                     params.getG());
     98         } else if (key instanceof DSAPrivateKey
     99                 && DSAPrivateKeySpec.class.isAssignableFrom(keySpec)) {
    100             DSAPrivateKey dsaKey = (DSAPrivateKey) key;
    101             DSAParams params = dsaKey.getParams();
    102             return (T) new DSAPrivateKeySpec(dsaKey.getX(), params.getP(), params.getQ(),
    103                     params.getG());
    104         } else if (key instanceof PrivateKey && DSAPrivateKeySpec.class.isAssignableFrom(keySpec)) {
    105             final byte[] encoded = key.getEncoded();
    106             if (!"PKCS#8".equals(key.getFormat()) || encoded == null) {
    107                 throw new InvalidKeySpecException("Not a valid PKCS#8 encoding");
    108             }
    109             DSAPrivateKey dsaKey =
    110                     (DSAPrivateKey) engineGeneratePrivate(new PKCS8EncodedKeySpec(encoded));
    111             DSAParams params = dsaKey.getParams();
    112             return (T) new DSAPrivateKeySpec(dsaKey.getX(), params.getP(), params.getQ(),
    113                     params.getG());
    114         } else if (key instanceof PrivateKey
    115                 && PKCS8EncodedKeySpec.class.isAssignableFrom(keySpec)) {
    116             final byte[] encoded = key.getEncoded();
    117             if (!"PKCS#8".equals(key.getFormat())) {
    118                 throw new InvalidKeySpecException("Encoding type must be PKCS#8; was "
    119                         + key.getFormat());
    120             } else if (encoded == null) {
    121                 throw new InvalidKeySpecException("Key is not encodable");
    122             }
    123             return (T) new PKCS8EncodedKeySpec(encoded);
    124         } else if (key instanceof PublicKey && X509EncodedKeySpec.class.isAssignableFrom(keySpec)) {
    125             final byte[] encoded = key.getEncoded();
    126             if (!"X.509".equals(key.getFormat())) {
    127                 throw new InvalidKeySpecException("Encoding type must be X.509; was "
    128                         + key.getFormat());
    129             } else if (encoded == null) {
    130                 throw new InvalidKeySpecException("Key is not encodable");
    131             }
    132             return (T) new X509EncodedKeySpec(encoded);
    133         } else {
    134             throw new InvalidKeySpecException("Unsupported key type and key spec combination; key="
    135                     + key.getClass().getName() + ", keySpec=" + keySpec.getName());
    136         }
    137     }
    138 
    139     @Override
    140     protected Key engineTranslateKey(Key key) throws InvalidKeyException {
    141         if (key == null) {
    142             throw new InvalidKeyException("key == null");
    143         }
    144         if ((key instanceof OpenSSLDSAPublicKey) || (key instanceof OpenSSLDSAPrivateKey)) {
    145             return key;
    146         } else if (key instanceof DSAPublicKey) {
    147             DSAPublicKey dsaKey = (DSAPublicKey) key;
    148 
    149             BigInteger y = dsaKey.getY();
    150 
    151             DSAParams params = dsaKey.getParams();
    152             BigInteger p = params.getP();
    153             BigInteger q = params.getQ();
    154             BigInteger g = params.getG();
    155 
    156             try {
    157                 return engineGeneratePublic(new DSAPublicKeySpec(y, p, q, g));
    158             } catch (InvalidKeySpecException e) {
    159                 throw new InvalidKeyException(e);
    160             }
    161         } else if (key instanceof DSAPrivateKey) {
    162             DSAPrivateKey dsaKey = (DSAPrivateKey) key;
    163 
    164             BigInteger x = dsaKey.getX();
    165 
    166             DSAParams params = dsaKey.getParams();
    167             BigInteger p = params.getP();
    168             BigInteger q = params.getQ();
    169             BigInteger g = params.getG();
    170 
    171             try {
    172                 return engineGeneratePrivate(new DSAPrivateKeySpec(x, p, q, g));
    173             } catch (InvalidKeySpecException e) {
    174                 throw new InvalidKeyException(e);
    175             }
    176         } else if ((key instanceof PrivateKey) && ("PKCS#8".equals(key.getFormat()))) {
    177             byte[] encoded = key.getEncoded();
    178             if (encoded == null) {
    179                 throw new InvalidKeyException("Key does not support encoding");
    180             }
    181             try {
    182                 return engineGeneratePrivate(new PKCS8EncodedKeySpec(encoded));
    183             } catch (InvalidKeySpecException e) {
    184                 throw new InvalidKeyException(e);
    185             }
    186         } else if ((key instanceof PublicKey) && ("X.509".equals(key.getFormat()))) {
    187             byte[] encoded = key.getEncoded();
    188             if (encoded == null) {
    189                 throw new InvalidKeyException("Key does not support encoding");
    190             }
    191             try {
    192                 return engineGeneratePublic(new X509EncodedKeySpec(encoded));
    193             } catch (InvalidKeySpecException e) {
    194                 throw new InvalidKeyException(e);
    195             }
    196         } else {
    197             throw new InvalidKeyException("Key must be DSA public or private key; was "
    198                     + key.getClass().getName());
    199         }
    200     }
    201 }
    202