1 /*
   2  * Copyright (c) 2003, 2017, 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.interfaces.*;
  33 
  34 import sun.security.util.*;
  35 import sun.security.x509.AlgorithmId;
  36 import sun.security.pkcs.PKCS8Key;
  37 
  38 /**
  39  * Key implementation for RSA private keys, CRT form. For non-CRT private
  40  * keys, see RSAPrivateKeyImpl. We need separate classes to ensure
  41  * correct behavior in instanceof checks, etc.
  42  *
  43  * Note: RSA keys must be at least 512 bits long
  44  *
  45  * @see RSAPrivateKeyImpl
  46  * @see RSAKeyFactory
  47  *
  48  * @since   1.5
  49  * @author  Andreas Sterbenz
  50  */
  51 public final class RSAPrivateCrtKeyImpl
  52         extends PKCS8Key implements RSAPrivateCrtKey {
  53 
  54     private static final long serialVersionUID = -1326088454257084918L;
  55 
  56     private BigInteger n;       // modulus
  57     private BigInteger e;       // public exponent
  58     private BigInteger d;       // private exponent
  59     private BigInteger p;       // prime p
  60     private BigInteger q;       // prime q
  61     private BigInteger pe;      // prime exponent p
  62     private BigInteger qe;      // prime exponent q
  63     private BigInteger coeff;   // CRT coeffcient
  64 
  65     // algorithmId used to identify RSA keys
  66     static final AlgorithmId rsaId =
  67         new AlgorithmId(AlgorithmId.RSAEncryption_oid);
  68 
  69     /**
  70      * Generate a new key from its encoding. Returns a CRT key if possible
  71      * and a non-CRT key otherwise. Used by RSAKeyFactory.
  72      */
  73     public static RSAPrivateKey newKey(byte[] encoded)
  74             throws InvalidKeyException {
  75         RSAPrivateCrtKeyImpl key = new RSAPrivateCrtKeyImpl(encoded);
  76         if (key.getPublicExponent().signum() == 0) {
  77             // public exponent is missing, return a non-CRT key
  78             return new RSAPrivateKeyImpl(
  79                 key.getModulus(),
  80                 key.getPrivateExponent()
  81             );
  82         } else {
  83             return key;
  84         }
  85     }
  86 
  87     /**
  88      * Construct a key from its encoding. Called from newKey above.
  89      */
  90     RSAPrivateCrtKeyImpl(byte[] encoded) throws InvalidKeyException {
  91         decode(encoded);
  92         RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e);
  93     }
  94 
  95     /**
  96      * Construct a key from its components. Used by the
  97      * RSAKeyFactory and the RSAKeyPairGenerator.
  98      */
  99     RSAPrivateCrtKeyImpl(BigInteger n, BigInteger e, BigInteger d,
 100             BigInteger p, BigInteger q, BigInteger pe, BigInteger qe,
 101             BigInteger coeff) throws InvalidKeyException {
 102         this.n = n;
 103         this.e = e;
 104         this.d = d;
 105         this.p = p;
 106         this.q = q;
 107         this.pe = pe;
 108         this.qe = qe;
 109         this.coeff = coeff;
 110         RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e);
 111 
 112         // generate the encoding
 113         algid = rsaId;
 114         try {
 115             DerOutputStream out = new DerOutputStream();
 116             out.putInteger(0); // version must be 0
 117             out.putInteger(n);
 118             out.putInteger(e);
 119             out.putInteger(d);
 120             out.putInteger(p);
 121             out.putInteger(q);
 122             out.putInteger(pe);
 123             out.putInteger(qe);
 124             out.putInteger(coeff);
 125             DerValue val =
 126                 new DerValue(DerValue.tag_Sequence, out.toByteArray());
 127             key = val.toByteArray();
 128         } catch (IOException exc) {
 129             // should never occur
 130             throw new InvalidKeyException(exc);
 131         }
 132     }
 133 
 134     // see JCA doc
 135     public String getAlgorithm() {
 136         return "RSA";
 137     }
 138 
 139     // see JCA doc
 140     public BigInteger getModulus() {
 141         return n;
 142     }
 143 
 144     // see JCA doc
 145     public BigInteger getPublicExponent() {
 146         return e;
 147     }
 148 
 149     // see JCA doc
 150     public BigInteger getPrivateExponent() {
 151         return d;
 152     }
 153 
 154     // see JCA doc
 155     public BigInteger getPrimeP() {
 156         return p;
 157     }
 158 
 159     // see JCA doc
 160     public BigInteger getPrimeQ() {
 161         return q;
 162     }
 163 
 164     // see JCA doc
 165     public BigInteger getPrimeExponentP() {
 166         return pe;
 167     }
 168 
 169     // see JCA doc
 170     public BigInteger getPrimeExponentQ() {
 171         return qe;
 172     }
 173 
 174     // see JCA doc
 175     public BigInteger getCrtCoefficient() {
 176         return coeff;
 177     }
 178 
 179     /**
 180      * Parse the key. Called by PKCS8Key.
 181      */
 182     protected void parseKeyBits() throws InvalidKeyException {
 183         try {
 184             DerInputStream in = new DerInputStream(key);
 185             DerValue derValue = in.getDerValue();
 186             if (derValue.tag != DerValue.tag_Sequence) {
 187                 throw new IOException("Not a SEQUENCE");
 188             }
 189             DerInputStream data = derValue.data;
 190             int version = data.getInteger();
 191             if (version != 0) {
 192                 throw new IOException("Version must be 0");
 193             }
 194 
 195             /*
 196              * Some implementations do not correctly encode ASN.1 INTEGER values
 197              * in 2's complement format, resulting in a negative integer when
 198              * decoded. Correct the error by converting it to a positive integer.
 199              *
 200              * See CR 6255949
 201              */
 202             n = data.getPositiveBigInteger();
 203             e = data.getPositiveBigInteger();
 204             d = data.getPositiveBigInteger();
 205             p = data.getPositiveBigInteger();
 206             q = data.getPositiveBigInteger();
 207             pe = data.getPositiveBigInteger();
 208             qe = data.getPositiveBigInteger();
 209             coeff = data.getPositiveBigInteger();
 210             if (derValue.data.available() != 0) {
 211                 throw new IOException("Extra data available");
 212             }
 213         } catch (IOException e) {
 214             throw new InvalidKeyException("Invalid RSA private key", e);
 215         }
 216     }
 217 }