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 token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes); 267 KeySpec spec = new RSAPublicKeySpec( 268 attributes[0].getBigInteger(), 269 attributes[1].getBigInteger() 270 ); 271 return keySpec.cast(spec); 272 } else { // X.509 handled in superclass 273 throw new InvalidKeySpecException("Only RSAPublicKeySpec and " 274 + "X509EncodedKeySpec supported for RSA public keys"); 275 } 276 } 277 implGetPrivateKeySpec(P11Key key, Class<T> keySpec, Session[] session)278 <T extends KeySpec> T implGetPrivateKeySpec(P11Key key, Class<T> keySpec, 279 Session[] session) throws PKCS11Exception, InvalidKeySpecException { 280 if (RSAPrivateCrtKeySpec.class.isAssignableFrom(keySpec)) { 281 session[0] = token.getObjSession(); 282 CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] { 283 new CK_ATTRIBUTE(CKA_MODULUS), 284 new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT), 285 new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT), 286 new CK_ATTRIBUTE(CKA_PRIME_1), 287 new CK_ATTRIBUTE(CKA_PRIME_2), 288 new CK_ATTRIBUTE(CKA_EXPONENT_1), 289 new CK_ATTRIBUTE(CKA_EXPONENT_2), 290 new CK_ATTRIBUTE(CKA_COEFFICIENT), 291 }; 292 token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes); 293 KeySpec spec = new RSAPrivateCrtKeySpec( 294 attributes[0].getBigInteger(), 295 attributes[1].getBigInteger(), 296 attributes[2].getBigInteger(), 297 attributes[3].getBigInteger(), 298 attributes[4].getBigInteger(), 299 attributes[5].getBigInteger(), 300 attributes[6].getBigInteger(), 301 attributes[7].getBigInteger() 302 ); 303 return keySpec.cast(spec); 304 } else if (RSAPrivateKeySpec.class.isAssignableFrom(keySpec)) { 305 session[0] = token.getObjSession(); 306 CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] { 307 new CK_ATTRIBUTE(CKA_MODULUS), 308 new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT), 309 }; 310 token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes); 311 KeySpec spec = new RSAPrivateKeySpec( 312 attributes[0].getBigInteger(), 313 attributes[1].getBigInteger() 314 ); 315 return keySpec.cast(spec); 316 } else { // PKCS#8 handled in superclass 317 throw new InvalidKeySpecException("Only RSAPrivate(Crt)KeySpec " 318 + "and PKCS8EncodedKeySpec supported for RSA private keys"); 319 } 320 } 321 implGetSoftwareFactory()322 KeyFactory implGetSoftwareFactory() throws GeneralSecurityException { 323 return KeyFactory.getInstance("RSA", P11Util.getSunRsaSignProvider()); 324 } 325 326 } 327