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