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