blob: 6d18bbdafe8b245cf0197cfa5156fe7067b65564 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2003 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.security.pkcs11;
27
28import java.math.BigInteger;
29
30import java.security.*;
31import java.security.spec.*;
32
33import javax.crypto.interfaces.*;
34import javax.crypto.spec.*;
35
36import static sun.security.pkcs11.TemplateManager.*;
37import sun.security.pkcs11.wrapper.*;
38import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
39
40/**
41 * DH KeyFactory implemenation.
42 *
43 * @author Andreas Sterbenz
44 * @since 1.5
45 */
46final class P11DHKeyFactory extends P11KeyFactory {
47
48 P11DHKeyFactory(Token token, String algorithm) {
49 super(token, algorithm);
50 }
51
52 PublicKey implTranslatePublicKey(PublicKey key) throws InvalidKeyException {
53 try {
54 if (key instanceof DHPublicKey) {
55 DHPublicKey dhKey = (DHPublicKey)key;
56 DHParameterSpec params = dhKey.getParams();
57 return generatePublic(
58 dhKey.getY(),
59 params.getP(),
60 params.getG()
61 );
62 } else if ("X.509".equals(key.getFormat())) {
63 // let SunJCE provider parse for us, then recurse
64 try {
65 KeyFactory factory = implGetSoftwareFactory();
66 key = (PublicKey)factory.translateKey(key);
67 return implTranslatePublicKey(key);
68 } catch (GeneralSecurityException e) {
69 throw new InvalidKeyException("Could not translate key", e);
70 }
71 } else {
72 throw new InvalidKeyException("PublicKey must be instance "
73 + "of DHPublicKey or have X.509 encoding");
74 }
75 } catch (PKCS11Exception e) {
76 throw new InvalidKeyException("Could not create DH public key", e);
77 }
78 }
79
80 PrivateKey implTranslatePrivateKey(PrivateKey key)
81 throws InvalidKeyException {
82 try {
83 if (key instanceof DHPrivateKey) {
84 DHPrivateKey dhKey = (DHPrivateKey)key;
85 DHParameterSpec params = dhKey.getParams();
86 return generatePrivate(
87 dhKey.getX(),
88 params.getP(),
89 params.getG()
90 );
91 } else if ("PKCS#8".equals(key.getFormat())) {
92 // let SunJCE provider parse for us, then recurse
93 try {
94 KeyFactory factory = implGetSoftwareFactory();
95 key = (PrivateKey)factory.translateKey(key);
96 return implTranslatePrivateKey(key);
97 } catch (GeneralSecurityException e) {
98 throw new InvalidKeyException("Could not translate key", e);
99 }
100 } else {
101 throw new InvalidKeyException("PrivateKey must be instance "
102 + "of DHPrivateKey or have PKCS#8 encoding");
103 }
104 } catch (PKCS11Exception e) {
105 throw new InvalidKeyException("Could not create DH private key", e);
106 }
107 }
108
109 // see JCA spec
110 protected PublicKey engineGeneratePublic(KeySpec keySpec)
111 throws InvalidKeySpecException {
112 token.ensureValid();
113 if (keySpec instanceof X509EncodedKeySpec) {
114 try {
115 KeyFactory factory = implGetSoftwareFactory();
116 PublicKey key = factory.generatePublic(keySpec);
117 return implTranslatePublicKey(key);
118 } catch (GeneralSecurityException e) {
119 throw new InvalidKeySpecException
120 ("Could not create DH public key", e);
121 }
122 }
123 if (keySpec instanceof DHPublicKeySpec == false) {
124 throw new InvalidKeySpecException("Only DHPublicKeySpec and "
125 + "X509EncodedKeySpec supported for DH public keys");
126 }
127 try {
128 DHPublicKeySpec ds = (DHPublicKeySpec)keySpec;
129 return generatePublic(
130 ds.getY(),
131 ds.getP(),
132 ds.getG()
133 );
134 } catch (PKCS11Exception e) {
135 throw new InvalidKeySpecException
136 ("Could not create DH public key", e);
137 }
138 }
139
140 // see JCA spec
141 protected PrivateKey engineGeneratePrivate(KeySpec keySpec)
142 throws InvalidKeySpecException {
143 token.ensureValid();
144 if (keySpec instanceof PKCS8EncodedKeySpec) {
145 try {
146 KeyFactory factory = implGetSoftwareFactory();
147 PrivateKey key = factory.generatePrivate(keySpec);
148 return implTranslatePrivateKey(key);
149 } catch (GeneralSecurityException e) {
150 throw new InvalidKeySpecException
151 ("Could not create DH private key", e);
152 }
153 }
154 if (keySpec instanceof DHPrivateKeySpec == false) {
155 throw new InvalidKeySpecException("Only DHPrivateKeySpec and "
156 + "PKCS8EncodedKeySpec supported for DH private keys");
157 }
158 try {
159 DHPrivateKeySpec ds = (DHPrivateKeySpec)keySpec;
160 return generatePrivate(
161 ds.getX(),
162 ds.getP(),
163 ds.getG()
164 );
165 } catch (PKCS11Exception e) {
166 throw new InvalidKeySpecException
167 ("Could not create DH private key", e);
168 }
169 }
170
171 private PublicKey generatePublic(BigInteger y, BigInteger p, BigInteger g)
172 throws PKCS11Exception {
173 CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
174 new CK_ATTRIBUTE(CKA_CLASS, CKO_PUBLIC_KEY),
175 new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_DH),
176 new CK_ATTRIBUTE(CKA_VALUE, y),
177 new CK_ATTRIBUTE(CKA_PRIME, p),
178 new CK_ATTRIBUTE(CKA_BASE, g),
179 };
180 attributes = token.getAttributes
181 (O_IMPORT, CKO_PUBLIC_KEY, CKK_DH, attributes);
182 Session session = null;
183 try {
184 session = token.getObjSession();
185 long keyID = token.p11.C_CreateObject(session.id(), attributes);
186 return P11Key.publicKey
187 (session, keyID, "DH", p.bitLength(), attributes);
188 } finally {
189 token.releaseSession(session);
190 }
191 }
192
193 private PrivateKey generatePrivate(BigInteger x, BigInteger p,
194 BigInteger g) throws PKCS11Exception {
195 CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
196 new CK_ATTRIBUTE(CKA_CLASS, CKO_PRIVATE_KEY),
197 new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_DH),
198 new CK_ATTRIBUTE(CKA_VALUE, x),
199 new CK_ATTRIBUTE(CKA_PRIME, p),
200 new CK_ATTRIBUTE(CKA_BASE, g),
201 };
202 attributes = token.getAttributes
203 (O_IMPORT, CKO_PRIVATE_KEY, CKK_DH, attributes);
204 Session session = null;
205 try {
206 session = token.getObjSession();
207 long keyID = token.p11.C_CreateObject(session.id(), attributes);
208 return P11Key.privateKey
209 (session, keyID, "DH", p.bitLength(), attributes);
210 } finally {
211 token.releaseSession(session);
212 }
213 }
214
215 KeySpec implGetPublicKeySpec(P11Key key, Class keySpec, Session[] session)
216 throws PKCS11Exception, InvalidKeySpecException {
217 if (DHPublicKeySpec.class.isAssignableFrom(keySpec)) {
218 session[0] = token.getObjSession();
219 CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
220 new CK_ATTRIBUTE(CKA_VALUE),
221 new CK_ATTRIBUTE(CKA_PRIME),
222 new CK_ATTRIBUTE(CKA_BASE),
223 };
224 token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
225 KeySpec spec = new DHPublicKeySpec(
226 attributes[0].getBigInteger(),
227 attributes[1].getBigInteger(),
228 attributes[2].getBigInteger()
229 );
230 return spec;
231 } else { // X.509 handled in superclass
232 throw new InvalidKeySpecException("Only DHPublicKeySpec and "
233 + "X509EncodedKeySpec supported for DH public keys");
234 }
235 }
236
237 KeySpec implGetPrivateKeySpec(P11Key key, Class keySpec, Session[] session)
238 throws PKCS11Exception, InvalidKeySpecException {
239 if (DHPrivateKeySpec.class.isAssignableFrom(keySpec)) {
240 session[0] = token.getObjSession();
241 CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
242 new CK_ATTRIBUTE(CKA_VALUE),
243 new CK_ATTRIBUTE(CKA_PRIME),
244 new CK_ATTRIBUTE(CKA_BASE),
245 };
246 token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
247 KeySpec spec = new DHPrivateKeySpec(
248 attributes[0].getBigInteger(),
249 attributes[1].getBigInteger(),
250 attributes[2].getBigInteger()
251 );
252 return spec;
253 } else { // PKCS#8 handled in superclass
254 throw new InvalidKeySpecException("Only DHPrivateKeySpec "
255 + "and PKCS8EncodedKeySpec supported for DH private keys");
256 }
257 }
258
259 KeyFactory implGetSoftwareFactory() throws GeneralSecurityException {
260 return KeyFactory.getInstance("DH", P11Util.getSunJceProvider());
261 }
262
263}