1 /* 2 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.security.pkcs11; 27 28 import java.math.BigInteger; 29 30 import java.security.*; 31 import java.security.interfaces.*; 32 import java.security.spec.*; 33 34 import static sun.security.pkcs11.TemplateManager.*; 35 import sun.security.pkcs11.wrapper.*; 36 import static sun.security.pkcs11.wrapper.PKCS11Constants.*; 37 38 /** 39 * DSA KeyFactory implementation. 40 * 41 * @author Andreas Sterbenz 42 * @since 1.5 43 */ 44 final class P11DSAKeyFactory extends P11KeyFactory { 45 46 P11DSAKeyFactory(Token token, String algorithm) { 47 super(token, algorithm); 48 } 49 50 PublicKey implTranslatePublicKey(PublicKey key) throws InvalidKeyException { 51 try { 52 if (key instanceof DSAPublicKey) { 53 DSAPublicKey dsaKey = (DSAPublicKey)key; 54 DSAParams params = dsaKey.getParams(); 55 return generatePublic( 56 dsaKey.getY(), 57 params.getP(), 58 params.getQ(), 59 params.getG() 60 ); 61 } else if ("X.509".equals(key.getFormat())) { 62 // let Sun provider parse for us, then recurse 63 byte[] encoded = key.getEncoded(); 64 key = new sun.security.provider.DSAPublicKey(encoded); 65 return implTranslatePublicKey(key); 66 } else { 67 throw new InvalidKeyException("PublicKey must be instance " 68 + "of DSAPublicKey or have X.509 encoding"); 69 } 70 } catch (PKCS11Exception e) { 71 throw new InvalidKeyException("Could not create DSA public key", e); 72 } 73 } 74 75 PrivateKey implTranslatePrivateKey(PrivateKey key) 76 throws InvalidKeyException { 77 try { 78 if (key instanceof DSAPrivateKey) { 79 DSAPrivateKey dsaKey = (DSAPrivateKey)key; 80 DSAParams params = dsaKey.getParams(); 81 return generatePrivate( 82 dsaKey.getX(), 83 params.getP(), 84 params.getQ(), 85 params.getG() 86 ); 87 } else if ("PKCS#8".equals(key.getFormat())) { 88 // let Sun provider parse for us, then recurse 89 byte[] encoded = key.getEncoded(); 90 key = new sun.security.provider.DSAPrivateKey(encoded); 91 return implTranslatePrivateKey(key); 92 } else { 93 throw new InvalidKeyException("PrivateKey must be instance " 94 + "of DSAPrivateKey or have PKCS#8 encoding"); 95 } 96 } catch (PKCS11Exception e) { 97 throw new InvalidKeyException("Could not create DSA private key", e); 98 } 99 } 100 101 // see JCA spec 102 protected PublicKey engineGeneratePublic(KeySpec keySpec) 103 throws InvalidKeySpecException { 104 token.ensureValid(); 105 if (keySpec instanceof X509EncodedKeySpec) { 106 try { 107 byte[] encoded = ((X509EncodedKeySpec)keySpec).getEncoded(); 108 PublicKey key = new sun.security.provider.DSAPublicKey(encoded); 109 return implTranslatePublicKey(key); 110 } catch (InvalidKeyException e) { 111 throw new InvalidKeySpecException 112 ("Could not create DSA public key", e); 113 } 114 } 115 if (keySpec instanceof DSAPublicKeySpec == false) { 116 throw new InvalidKeySpecException("Only DSAPublicKeySpec and " 117 + "X509EncodedKeySpec supported for DSA public keys"); 118 } 119 try { 120 DSAPublicKeySpec ds = (DSAPublicKeySpec)keySpec; 121 return generatePublic( 122 ds.getY(), 123 ds.getP(), 124 ds.getQ(), 125 ds.getG() 126 ); 127 } catch (PKCS11Exception e) { 128 throw new InvalidKeySpecException 129 ("Could not create DSA public key", e); 130 } 131 } 132 133 // see JCA spec 134 protected PrivateKey engineGeneratePrivate(KeySpec keySpec) 135 throws InvalidKeySpecException { 136 token.ensureValid(); 137 if (keySpec instanceof PKCS8EncodedKeySpec) { 138 try { 139 byte[] encoded = ((PKCS8EncodedKeySpec)keySpec).getEncoded(); 140 PrivateKey key = new sun.security.provider.DSAPrivateKey(encoded); 141 return implTranslatePrivateKey(key); 142 } catch (GeneralSecurityException e) { 143 throw new InvalidKeySpecException 144 ("Could not create DSA private key", e); 145 } 146 } 147 if (keySpec instanceof DSAPrivateKeySpec == false) { 148 throw new InvalidKeySpecException("Only DSAPrivateKeySpec and " 149 + "PKCS8EncodedKeySpec supported for DSA private keys"); 150 } 151 try { 152 DSAPrivateKeySpec ds = (DSAPrivateKeySpec)keySpec; 153 return generatePrivate( 154 ds.getX(), 155 ds.getP(), 156 ds.getQ(), 157 ds.getG() 158 ); 159 } catch (PKCS11Exception e) { 160 throw new InvalidKeySpecException 161 ("Could not create DSA private key", e); 162 } 163 } 164 165 private PublicKey generatePublic(BigInteger y, BigInteger p, BigInteger q, 166 BigInteger g) throws PKCS11Exception { 167 CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] { 168 new CK_ATTRIBUTE(CKA_CLASS, CKO_PUBLIC_KEY), 169 new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_DSA), 170 new CK_ATTRIBUTE(CKA_VALUE, y), 171 new CK_ATTRIBUTE(CKA_PRIME, p), 172 new CK_ATTRIBUTE(CKA_SUBPRIME, q), 173 new CK_ATTRIBUTE(CKA_BASE, g), 174 }; 175 attributes = token.getAttributes 176 (O_IMPORT, CKO_PUBLIC_KEY, CKK_DSA, attributes); 177 Session session = null; 178 try { 179 session = token.getObjSession(); 180 long keyID = token.p11.C_CreateObject(session.id(), attributes); 181 return P11Key.publicKey 182 (session, keyID, "DSA", p.bitLength(), attributes); 183 } finally { 184 token.releaseSession(session); 185 } 186 } 187 188 private PrivateKey generatePrivate(BigInteger x, BigInteger p, 189 BigInteger q, BigInteger g) throws PKCS11Exception { 190 CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] { 191 new CK_ATTRIBUTE(CKA_CLASS, CKO_PRIVATE_KEY), 192 new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_DSA), 193 new CK_ATTRIBUTE(CKA_VALUE, x), 194 new CK_ATTRIBUTE(CKA_PRIME, p), 195 new CK_ATTRIBUTE(CKA_SUBPRIME, q), 196 new CK_ATTRIBUTE(CKA_BASE, g), 197 }; 198 attributes = token.getAttributes 199 (O_IMPORT, CKO_PRIVATE_KEY, CKK_DSA, attributes); 200 Session session = null; 201 try { 202 session = token.getObjSession(); 203 long keyID = token.p11.C_CreateObject(session.id(), attributes); 204 return P11Key.privateKey 205 (session, keyID, "DSA", p.bitLength(), attributes); 206 } finally { 207 token.releaseSession(session); 208 } 209 } 210 211 <T extends KeySpec> T implGetPublicKeySpec(P11Key key, Class<T> keySpec, 212 Session[] session) throws PKCS11Exception, InvalidKeySpecException { 213 if (DSAPublicKeySpec.class.isAssignableFrom(keySpec)) { 214 session[0] = token.getObjSession(); 215 CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] { 216 new CK_ATTRIBUTE(CKA_VALUE), 217 new CK_ATTRIBUTE(CKA_PRIME), 218 new CK_ATTRIBUTE(CKA_SUBPRIME), 219 new CK_ATTRIBUTE(CKA_BASE), 220 }; 221 token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes); 222 KeySpec spec = new DSAPublicKeySpec( 223 attributes[0].getBigInteger(), 224 attributes[1].getBigInteger(), 225 attributes[2].getBigInteger(), 226 attributes[3].getBigInteger() 227 ); 228 return keySpec.cast(spec); 229 } else { // X.509 handled in superclass 230 throw new InvalidKeySpecException("Only DSAPublicKeySpec and " 231 + "X509EncodedKeySpec supported for DSA public keys"); 232 } 233 } 234 235 <T extends KeySpec> T implGetPrivateKeySpec(P11Key key, Class<T> keySpec, 236 Session[] session) throws PKCS11Exception, InvalidKeySpecException { 237 if (DSAPrivateKeySpec.class.isAssignableFrom(keySpec)) { 238 session[0] = token.getObjSession(); 239 CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] { 240 new CK_ATTRIBUTE(CKA_VALUE), 241 new CK_ATTRIBUTE(CKA_PRIME), 242 new CK_ATTRIBUTE(CKA_SUBPRIME), 243 new CK_ATTRIBUTE(CKA_BASE), 244 }; 245 token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes); 246 KeySpec spec = new DSAPrivateKeySpec( 247 attributes[0].getBigInteger(), 248 attributes[1].getBigInteger(), 249 attributes[2].getBigInteger(), 250 attributes[3].getBigInteger() 251 ); 252 return keySpec.cast(spec); 253 } else { // PKCS#8 handled in superclass 254 throw new InvalidKeySpecException("Only DSAPrivateKeySpec " 255 + "and PKCS8EncodedKeySpec supported for DSA private keys"); 256 } 257 } 258 259 KeyFactory implGetSoftwareFactory() throws GeneralSecurityException { 260 return KeyFactory.getInstance("DSA", P11Util.getSunProvider()); 261 } 262 263 }