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 }