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