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 
  49     P11RSAKeyFactory(Token token, String algorithm) {
  50         super(token, algorithm);
  51     }
  52 
  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 
  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
 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
 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 
 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 
 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 
 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 
 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 
 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 
 322     KeyFactory implGetSoftwareFactory() throws GeneralSecurityException {
 323         return KeyFactory.getInstance("RSA", P11Util.getSunRsaSignProvider());
 324     }
 325 
 326 }