blob: 5f3cbbf93c9eac09928339f8f317c008c6dda188 [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.interfaces.*;
32import java.security.spec.*;
33
34import static sun.security.pkcs11.TemplateManager.*;
35import sun.security.pkcs11.wrapper.*;
36import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
37
38/**
39 * RSA KeyFactory implemenation.
40 *
41 * @author Andreas Sterbenz
42 * @since 1.5
43 */
44final class P11RSAKeyFactory extends P11KeyFactory {
45
46 P11RSAKeyFactory(Token token, String algorithm) {
47 super(token, algorithm);
48 }
49
50 PublicKey implTranslatePublicKey(PublicKey key) throws InvalidKeyException {
51 try {
52 if (key instanceof RSAPublicKey) {
53 RSAPublicKey rsaKey = (RSAPublicKey)key;
54 return generatePublic(
55 rsaKey.getModulus(),
56 rsaKey.getPublicExponent()
57 );
58 } else if ("X.509".equals(key.getFormat())) {
59 // let SunRsaSign provider parse for us, then recurse
60 byte[] encoded = key.getEncoded();
61 key = new sun.security.rsa.RSAPublicKeyImpl(encoded);
62 return implTranslatePublicKey(key);
63 } else {
64 throw new InvalidKeyException("PublicKey must be instance "
65 + "of RSAPublicKey or have X.509 encoding");
66 }
67 } catch (PKCS11Exception e) {
68 throw new InvalidKeyException("Could not create RSA public key", e);
69 }
70 }
71
72 PrivateKey implTranslatePrivateKey(PrivateKey key)
73 throws InvalidKeyException {
74 try {
75 if (key instanceof RSAPrivateCrtKey) {
76 RSAPrivateCrtKey rsaKey = (RSAPrivateCrtKey)key;
77 return generatePrivate(
78 rsaKey.getModulus(),
79 rsaKey.getPublicExponent(),
80 rsaKey.getPrivateExponent(),
81 rsaKey.getPrimeP(),
82 rsaKey.getPrimeQ(),
83 rsaKey.getPrimeExponentP(),
84 rsaKey.getPrimeExponentQ(),
85 rsaKey.getCrtCoefficient()
86 );
87 } else if (key instanceof RSAPrivateKey) {
88 RSAPrivateKey rsaKey = (RSAPrivateKey)key;
89 return generatePrivate(
90 rsaKey.getModulus(),
91 rsaKey.getPrivateExponent()
92 );
93 } else if ("PKCS#8".equals(key.getFormat())) {
94 // let SunRsaSign provider parse for us, then recurse
95 byte[] encoded = key.getEncoded();
96 key = sun.security.rsa.RSAPrivateCrtKeyImpl.newKey(encoded);
97 return implTranslatePrivateKey(key);
98 } else {
99 throw new InvalidKeyException("Private key must be instance "
100 + "of RSAPrivate(Crt)Key or have PKCS#8 encoding");
101 }
102 } catch (PKCS11Exception e) {
103 throw new InvalidKeyException("Could not create RSA private key", e);
104 }
105 }
106
107 // see JCA spec
108 protected PublicKey engineGeneratePublic(KeySpec keySpec)
109 throws InvalidKeySpecException {
110 token.ensureValid();
111 if (keySpec instanceof X509EncodedKeySpec) {
112 try {
113 byte[] encoded = ((X509EncodedKeySpec)keySpec).getEncoded();
114 PublicKey key = new sun.security.rsa.RSAPublicKeyImpl(encoded);
115 return implTranslatePublicKey(key);
116 } catch (InvalidKeyException e) {
117 throw new InvalidKeySpecException
118 ("Could not create RSA public key", e);
119 }
120 }
121 if (keySpec instanceof RSAPublicKeySpec == false) {
122 throw new InvalidKeySpecException("Only RSAPublicKeySpec and "
123 + "X509EncodedKeySpec supported for RSA public keys");
124 }
125 try {
126 RSAPublicKeySpec rs = (RSAPublicKeySpec)keySpec;
127 return generatePublic(
128 rs.getModulus(),
129 rs.getPublicExponent()
130 );
131 } catch (PKCS11Exception e) {
132 throw new InvalidKeySpecException
133 ("Could not create RSA public key", e);
134 }
135 }
136
137 // see JCA spec
138 protected PrivateKey engineGeneratePrivate(KeySpec keySpec)
139 throws InvalidKeySpecException {
140 token.ensureValid();
141 if (keySpec instanceof PKCS8EncodedKeySpec) {
142 try {
143 byte[] encoded = ((PKCS8EncodedKeySpec)keySpec).getEncoded();
144 PrivateKey key =
145 sun.security.rsa.RSAPrivateCrtKeyImpl.newKey(encoded);
146 return implTranslatePrivateKey(key);
147 } catch (GeneralSecurityException e) {
148 throw new InvalidKeySpecException
149 ("Could not create RSA private key", e);
150 }
151 }
152 try {
153 if (keySpec instanceof RSAPrivateCrtKeySpec) {
154 RSAPrivateCrtKeySpec rs = (RSAPrivateCrtKeySpec)keySpec;
155 return generatePrivate(
156 rs.getModulus(),
157 rs.getPublicExponent(),
158 rs.getPrivateExponent(),
159 rs.getPrimeP(),
160 rs.getPrimeQ(),
161 rs.getPrimeExponentP(),
162 rs.getPrimeExponentQ(),
163 rs.getCrtCoefficient()
164 );
165 } else if (keySpec instanceof RSAPrivateKeySpec) {
166 RSAPrivateKeySpec rs = (RSAPrivateKeySpec)keySpec;
167 return generatePrivate(
168 rs.getModulus(),
169 rs.getPrivateExponent()
170 );
171 } else {
172 throw new InvalidKeySpecException("Only RSAPrivate(Crt)KeySpec "
173 + "and PKCS8EncodedKeySpec supported for RSA private keys");
174 }
175 } catch (PKCS11Exception e) {
176 throw new InvalidKeySpecException
177 ("Could not create RSA private key", e);
178 }
179 }
180
181 private PublicKey generatePublic(BigInteger n, BigInteger e)
182 throws PKCS11Exception {
183 CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
184 new CK_ATTRIBUTE(CKA_CLASS, CKO_PUBLIC_KEY),
185 new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_RSA),
186 new CK_ATTRIBUTE(CKA_MODULUS, n),
187 new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT, e),
188 };
189 attributes = token.getAttributes
190 (O_IMPORT, CKO_PUBLIC_KEY, CKK_RSA, attributes);
191 Session session = null;
192 try {
193 session = token.getObjSession();
194 long keyID = token.p11.C_CreateObject(session.id(), attributes);
195 return P11Key.publicKey
196 (session, keyID, "RSA", n.bitLength(), attributes);
197 } finally {
198 token.releaseSession(session);
199 }
200 }
201
202 private PrivateKey generatePrivate(BigInteger n, BigInteger d)
203 throws PKCS11Exception {
204 CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
205 new CK_ATTRIBUTE(CKA_CLASS, CKO_PRIVATE_KEY),
206 new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_RSA),
207 new CK_ATTRIBUTE(CKA_MODULUS, n),
208 new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT, d),
209 };
210 attributes = token.getAttributes
211 (O_IMPORT, CKO_PRIVATE_KEY, CKK_RSA, attributes);
212 Session session = null;
213 try {
214 session = token.getObjSession();
215 long keyID = token.p11.C_CreateObject(session.id(), attributes);
216 return P11Key.privateKey
217 (session, keyID, "RSA", n.bitLength(), attributes);
218 } finally {
219 token.releaseSession(session);
220 }
221 }
222
223 private PrivateKey generatePrivate(BigInteger n, BigInteger e,
224 BigInteger d, BigInteger p, BigInteger q, BigInteger pe,
225 BigInteger qe, BigInteger coeff) throws PKCS11Exception {
226 CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
227 new CK_ATTRIBUTE(CKA_CLASS, CKO_PRIVATE_KEY),
228 new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_RSA),
229 new CK_ATTRIBUTE(CKA_MODULUS, n),
230 new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT, e),
231 new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT, d),
232 new CK_ATTRIBUTE(CKA_PRIME_1, p),
233 new CK_ATTRIBUTE(CKA_PRIME_2, q),
234 new CK_ATTRIBUTE(CKA_EXPONENT_1, pe),
235 new CK_ATTRIBUTE(CKA_EXPONENT_2, qe),
236 new CK_ATTRIBUTE(CKA_COEFFICIENT, coeff),
237 };
238 attributes = token.getAttributes
239 (O_IMPORT, CKO_PRIVATE_KEY, CKK_RSA, attributes);
240 Session session = null;
241 try {
242 session = token.getObjSession();
243 long keyID = token.p11.C_CreateObject(session.id(), attributes);
244 return P11Key.privateKey
245 (session, keyID, "RSA", n.bitLength(), attributes);
246 } finally {
247 token.releaseSession(session);
248 }
249 }
250
251 KeySpec implGetPublicKeySpec(P11Key key, Class keySpec, Session[] session)
252 throws PKCS11Exception, InvalidKeySpecException {
253 if (RSAPublicKeySpec.class.isAssignableFrom(keySpec)) {
254 session[0] = token.getObjSession();
255 CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
256 new CK_ATTRIBUTE(CKA_MODULUS),
257 new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT),
258 };
259 token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
260 KeySpec spec = new RSAPublicKeySpec(
261 attributes[0].getBigInteger(),
262 attributes[1].getBigInteger()
263 );
264 return spec;
265 } else { // X.509 handled in superclass
266 throw new InvalidKeySpecException("Only RSAPublicKeySpec and "
267 + "X509EncodedKeySpec supported for RSA public keys");
268 }
269 }
270
271 KeySpec implGetPrivateKeySpec(P11Key key, Class keySpec, Session[] session)
272 throws PKCS11Exception, InvalidKeySpecException {
273 if (RSAPrivateCrtKeySpec.class.isAssignableFrom(keySpec)) {
274 session[0] = token.getObjSession();
275 CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
276 new CK_ATTRIBUTE(CKA_MODULUS),
277 new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT),
278 new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT),
279 new CK_ATTRIBUTE(CKA_PRIME_1),
280 new CK_ATTRIBUTE(CKA_PRIME_2),
281 new CK_ATTRIBUTE(CKA_EXPONENT_1),
282 new CK_ATTRIBUTE(CKA_EXPONENT_2),
283 new CK_ATTRIBUTE(CKA_COEFFICIENT),
284 };
285 token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
286 KeySpec spec = new RSAPrivateCrtKeySpec(
287 attributes[0].getBigInteger(),
288 attributes[1].getBigInteger(),
289 attributes[2].getBigInteger(),
290 attributes[3].getBigInteger(),
291 attributes[4].getBigInteger(),
292 attributes[5].getBigInteger(),
293 attributes[6].getBigInteger(),
294 attributes[7].getBigInteger()
295 );
296 return spec;
297 } else if (RSAPrivateKeySpec.class.isAssignableFrom(keySpec)) {
298 session[0] = token.getObjSession();
299 CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
300 new CK_ATTRIBUTE(CKA_MODULUS),
301 new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT),
302 };
303 token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
304 KeySpec spec = new RSAPrivateKeySpec(
305 attributes[0].getBigInteger(),
306 attributes[1].getBigInteger()
307 );
308 return spec;
309 } else { // PKCS#8 handled in superclass
310 throw new InvalidKeySpecException("Only RSAPrivate(Crt)KeySpec "
311 + "and PKCS8EncodedKeySpec supported for RSA private keys");
312 }
313 }
314
315 KeyFactory implGetSoftwareFactory() throws GeneralSecurityException {
316 return KeyFactory.getInstance("RSA", P11Util.getSunRsaSignProvider());
317 }
318
319}