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.DSAParams; 26import java.security.interfaces.DSAPrivateKey; 27import java.security.interfaces.DSAPublicKey; 28import java.security.spec.DSAPrivateKeySpec; 29import java.security.spec.DSAPublicKeySpec; 30import java.security.spec.InvalidKeySpecException; 31import java.security.spec.KeySpec; 32import java.security.spec.PKCS8EncodedKeySpec; 33import java.security.spec.X509EncodedKeySpec; 34 35public 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