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.rsa;
  27 
  28 import java.io.IOException;
  29 import java.math.BigInteger;
  30 
  31 import java.security.*;
  32 import java.security.spec.*;
  33 import java.security.interfaces.*;
  34 
  35 import sun.security.util.*;
  36 
  37 import sun.security.x509.AlgorithmId;
  38 import sun.security.pkcs.PKCS8Key;
  39 
  40 import static sun.security.rsa.RSAUtil.KeyType;
  41 
  42 /**
  43  * RSA private key implementation for "RSA", "RSASSA-PSS" algorithms in CRT form.
  44  * For non-CRT private keys, see RSAPrivateKeyImpl. We need separate classes
  45  * to ensure correct behavior in instanceof checks, etc.
  46  *
  47  * Note: RSA keys must be at least 512 bits long
  48  *
  49  * @see RSAPrivateKeyImpl
  50  * @see RSAKeyFactory
  51  *
  52  * @since   1.5
  53  * @author  Andreas Sterbenz
  54  */
  55 public final class RSAPrivateCrtKeyImpl
  56         extends PKCS8Key implements RSAPrivateCrtKey {
  57 
  58     private static final long serialVersionUID = -1326088454257084918L;
  59 
  60     private BigInteger n;       // modulus
  61     private BigInteger e;       // public exponent
  62     private BigInteger d;       // private exponent
  63     private BigInteger p;       // prime p
  64     private BigInteger q;       // prime q
  65     private BigInteger pe;      // prime exponent p
  66     private BigInteger qe;      // prime exponent q
  67     private BigInteger coeff;   // CRT coeffcient
  68 
  69     // Optional parameters associated with this RSA key
  70     // specified in the encoding of its AlgorithmId.
  71     // Must be null for "RSA" keys.
  72     private AlgorithmParameterSpec keyParams;
  73 
  74     /**
  75      * Generate a new key from its encoding. Returns a CRT key if possible
  76      * and a non-CRT key otherwise. Used by RSAKeyFactory.
  77      */
  78     public static RSAPrivateKey newKey(byte[] encoded)
  79             throws InvalidKeyException {
  80         RSAPrivateCrtKeyImpl key = new RSAPrivateCrtKeyImpl(encoded);
  81         // check all CRT-specific components are available, if any one
  82         // missing, return a non-CRT key instead
  83         if ((key.getPublicExponent().signum() == 0) ||
  84             (key.getPrimeExponentP().signum() == 0) ||
  85             (key.getPrimeExponentQ().signum() == 0) ||
  86             (key.getPrimeP().signum() == 0) ||
  87             (key.getPrimeQ().signum() == 0) ||
  88             (key.getCrtCoefficient().signum() == 0)) {
  89             return new RSAPrivateKeyImpl(
  90                 key.algid,
  91                 key.getModulus(),
  92                 key.getPrivateExponent()
  93             );
  94         } else {
  95             return key;
  96         }
  97     }
  98 
  99     /**
 100      * Generate a new key from the specified type and components.
 101      * Returns a CRT key if possible and a non-CRT key otherwise. 
 102      * Used by SunPKCS11 provider.
 103      */
 104     public static RSAPrivateKey newKey(KeyType type,
 105             AlgorithmParameterSpec params,
 106             BigInteger n, BigInteger e, BigInteger d,
 107             BigInteger p, BigInteger q, BigInteger pe, BigInteger qe,
 108             BigInteger coeff) throws InvalidKeyException {
 109         RSAPrivateKey key;
 110         AlgorithmId rsaId = RSAUtil.createAlgorithmId(type, params);
 111         if ((e.signum() == 0) || (p.signum() == 0) ||
 112             (q.signum() == 0) || (pe.signum() == 0) ||
 113             (qe.signum() == 0) || (coeff.signum() == 0)) {
 114             // if any component is missing, return a non-CRT key
 115             return new RSAPrivateKeyImpl(rsaId, n, d);
 116         } else {
 117             return new RSAPrivateCrtKeyImpl(rsaId, n, e, d,
 118                 p, q, pe, qe, coeff);
 119         }
 120     }
 121 
 122     /**
 123      * Construct a key from its encoding. Called from newKey above.
 124      */
 125     RSAPrivateCrtKeyImpl(byte[] encoded) throws InvalidKeyException {
 126         decode(encoded);
 127         RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e);
 128         try {
 129             // this will check the validity of params
 130             this.keyParams = RSAUtil.getParamSpec(algid);
 131         } catch (ProviderException e) {
 132             throw new InvalidKeyException(e);
 133         }
 134     }
 135 
 136     /**
 137      * Construct a RSA key from its components. Used by the
 138      * RSAKeyFactory and the RSAKeyPairGenerator.
 139      */
 140     RSAPrivateCrtKeyImpl(AlgorithmId rsaId,
 141             BigInteger n, BigInteger e, BigInteger d,
 142             BigInteger p, BigInteger q, BigInteger pe, BigInteger qe,
 143             BigInteger coeff) throws InvalidKeyException {
 144         RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e);
 145 
 146         this.n = n;
 147         this.e = e;
 148         this.d = d;
 149         this.p = p;
 150         this.q = q;
 151         this.pe = pe;
 152         this.qe = qe;
 153         this.coeff = coeff;
 154         this.keyParams = RSAUtil.getParamSpec(rsaId);
 155 
 156         // generate the encoding
 157         algid = rsaId;
 158         try {
 159             DerOutputStream out = new DerOutputStream();
 160             out.putInteger(0); // version must be 0
 161             out.putInteger(n);
 162             out.putInteger(e);
 163             out.putInteger(d);
 164             out.putInteger(p);
 165             out.putInteger(q);
 166             out.putInteger(pe);
 167             out.putInteger(qe);
 168             out.putInteger(coeff);
 169             DerValue val =
 170                 new DerValue(DerValue.tag_Sequence, out.toByteArray());
 171             key = val.toByteArray();
 172         } catch (IOException exc) {
 173             // should never occur
 174             throw new InvalidKeyException(exc);
 175         }
 176     }
 177 
 178     // see JCA doc
 179     @Override
 180     public String getAlgorithm() {
 181         return algid.getName();
 182     }
 183 
 184     // see JCA doc
 185     @Override
 186     public BigInteger getModulus() {
 187         return n;
 188     }
 189 
 190     // see JCA doc
 191     @Override
 192     public BigInteger getPublicExponent() {
 193         return e;
 194     }
 195 
 196     // see JCA doc
 197     @Override
 198     public BigInteger getPrivateExponent() {
 199         return d;
 200     }
 201 
 202     // see JCA doc
 203     @Override
 204     public BigInteger getPrimeP() {
 205         return p;
 206     }
 207 
 208     // see JCA doc
 209     @Override
 210     public BigInteger getPrimeQ() {
 211         return q;
 212     }
 213 
 214     // see JCA doc
 215     @Override
 216     public BigInteger getPrimeExponentP() {
 217         return pe;
 218     }
 219 
 220     // see JCA doc
 221     @Override
 222     public BigInteger getPrimeExponentQ() {
 223         return qe;
 224     }
 225 
 226     // see JCA doc
 227     @Override
 228     public BigInteger getCrtCoefficient() {
 229         return coeff;
 230     }
 231 
 232     // see JCA doc
 233     @Override
 234     public AlgorithmParameterSpec getParams() {
 235         return keyParams;
 236     }
 237 
 238     // return a string representation of this key for debugging
 239     @Override
 240     public String toString() {
 241         return "SunRsaSign " + getAlgorithm() + " private CRT key, " + n.bitLength()
 242                + " bits" + "\n  params: " + keyParams + "\n  modulus: " + n
 243                + "\n  private exponent: " + d;
 244     }
 245 
 246     /**
 247      * Parse the key. Called by PKCS8Key.
 248      */
 249     protected void parseKeyBits() throws InvalidKeyException {
 250         try {
 251             DerInputStream in = new DerInputStream(key);
 252             DerValue derValue = in.getDerValue();
 253             if (derValue.tag != DerValue.tag_Sequence) {
 254                 throw new IOException("Not a SEQUENCE");
 255             }
 256             DerInputStream data = derValue.data;
 257             int version = data.getInteger();
 258             if (version != 0) {
 259                 throw new IOException("Version must be 0");
 260             }
 261 
 262             /*
 263              * Some implementations do not correctly encode ASN.1 INTEGER values
 264              * in 2's complement format, resulting in a negative integer when
 265              * decoded. Correct the error by converting it to a positive integer.
 266              *
 267              * See CR 6255949
 268              */
 269             n = data.getPositiveBigInteger();
 270             e = data.getPositiveBigInteger();
 271             d = data.getPositiveBigInteger();
 272             p = data.getPositiveBigInteger();
 273             q = data.getPositiveBigInteger();
 274             pe = data.getPositiveBigInteger();
 275             qe = data.getPositiveBigInteger();
 276             coeff = data.getPositiveBigInteger();
 277             if (derValue.data.available() != 0) {
 278                 throw new IOException("Extra data available");
 279             }
 280         } catch (IOException e) {
 281             throw new InvalidKeyException("Invalid RSA private key", e);
 282         }
 283     }
 284 }