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 (keySpec.isAssignableFrom(RSAPublicKeySpec.class)) {
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 (key.sensitive || !key.extractable) {
286             throw new InvalidKeySpecException("Key is sensitive or not extractable");
287         }
288         // If the key is both extractable and not sensitive, then when it was converted into a P11Key
289         // it was also converted into subclass of RSAPrivateKey which encapsulates all of the logic
290         // necessary to retrieve the attributes we need. This sub-class will also cache these attributes
291         // so that we do not need to query them more than once.
292         // Rather than rewrite this logic and make possibly slow calls to the token, we'll just use
293         // that existing logic.
294         if (keySpec.isAssignableFrom(RSAPrivateCrtKeySpec.class)) {
295             // All supported keyspecs (other than PKCS8EncodedKeySpec) descend from RSAPrivateCrtKeySpec
296             if (key instanceof RSAPrivateCrtKey) {
297                 RSAPrivateCrtKey crtKey = (RSAPrivateCrtKey)key;
298                 return keySpec.cast(new RSAPrivateCrtKeySpec(
299                     crtKey.getModulus(),
300                     crtKey.getPublicExponent(),
301                     crtKey.getPrivateExponent(),
302                     crtKey.getPrimeP(),
303                     crtKey.getPrimeQ(),
304                     crtKey.getPrimeExponentP(),
305                     crtKey.getPrimeExponentQ(),
306                     crtKey.getCrtCoefficient(),
307                     crtKey.getParams()
308                 ));
309             } else { // RSAPrivateKey (non-CRT)
310                 if (!keySpec.isAssignableFrom(RSAPrivateKeySpec.class)) {
311                     throw new InvalidKeySpecException
312                         ("RSAPrivateCrtKeySpec can only be used with CRT keys");
313                 }
314 
315                 if (!(key instanceof RSAPrivateKey)) {
316                     // We should never reach here as P11Key.privateKey() should always produce an instance
317                     // of RSAPrivateKey when the RSA key is both extractable and non-sensitive.
318                     throw new InvalidKeySpecException
319                     ("Key must be an instance of RSAPrivateKeySpec. Was " + key.getClass());
320                 }
321 
322                 // fall through to RSAPrivateKey (non-CRT)
323                 RSAPrivateKey rsaKey = (RSAPrivateKey) key;
324                 return keySpec.cast(new RSAPrivateKeySpec(
325                     rsaKey.getModulus(),
326                     rsaKey.getPrivateExponent(),
327                     rsaKey.getParams()
328                 ));
329             }
330         } else { // PKCS#8 handled in superclass
331             throw new InvalidKeySpecException("Only RSAPrivate(Crt)KeySpec "
332                 + "and PKCS8EncodedKeySpec supported for RSA private keys");
333         }
334     }
335 
implGetSoftwareFactory()336     KeyFactory implGetSoftwareFactory() throws GeneralSecurityException {
337         return KeyFactory.getInstance("RSA", P11Util.getSunRsaSignProvider());
338     }
339 
340 }
341