Home | History | Annotate | Download | only in jsse
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package org.apache.harmony.xnet.provider.jsse;
     18 
     19 import java.io.IOException;
     20 import java.io.NotSerializableException;
     21 import java.io.ObjectInputStream;
     22 import java.io.ObjectOutputStream;
     23 import java.math.BigInteger;
     24 import java.security.InvalidKeyException;
     25 import java.security.interfaces.RSAPrivateCrtKey;
     26 import java.security.interfaces.RSAPrivateKey;
     27 import java.security.spec.InvalidKeySpecException;
     28 import java.security.spec.RSAPrivateCrtKeySpec;
     29 
     30 public class OpenSSLRSAPrivateCrtKey extends OpenSSLRSAPrivateKey implements RSAPrivateCrtKey {
     31     private static final long serialVersionUID = 3785291944868707197L;
     32 
     33     private BigInteger publicExponent;
     34 
     35     private BigInteger primeP;
     36 
     37     private BigInteger primeQ;
     38 
     39     private BigInteger primeExponentP;
     40 
     41     private BigInteger primeExponentQ;
     42 
     43     private BigInteger crtCoefficient;
     44 
     45     OpenSSLRSAPrivateCrtKey(OpenSSLKey key) {
     46         super(key);
     47     }
     48 
     49     OpenSSLRSAPrivateCrtKey(OpenSSLKey key, byte[][] params) {
     50         super(key, params);
     51     }
     52 
     53     public OpenSSLRSAPrivateCrtKey(RSAPrivateCrtKeySpec rsaKeySpec) throws InvalidKeySpecException {
     54         super(init(rsaKeySpec));
     55     }
     56 
     57     private static OpenSSLKey init(RSAPrivateCrtKeySpec rsaKeySpec) throws InvalidKeySpecException {
     58         BigInteger modulus = rsaKeySpec.getModulus();
     59         BigInteger privateExponent = rsaKeySpec.getPrivateExponent();
     60 
     61         if (modulus == null) {
     62             throw new InvalidKeySpecException("modulus == null");
     63         } else if (privateExponent == null) {
     64             throw new InvalidKeySpecException("privateExponent == null");
     65         }
     66 
     67         try {
     68             /*
     69              * OpenSSL uses the public modulus to do RSA blinding. If
     70              * the public modulus is not available, the call to
     71              * EVP_PKEY_new_RSA will turn off blinding for this key
     72              * instance.
     73              */
     74             final BigInteger publicExponent = rsaKeySpec.getPublicExponent();
     75             final BigInteger primeP = rsaKeySpec.getPrimeP();
     76             final BigInteger primeQ = rsaKeySpec.getPrimeQ();
     77             final BigInteger primeExponentP = rsaKeySpec.getPrimeExponentP();
     78             final BigInteger primeExponentQ = rsaKeySpec.getPrimeExponentQ();
     79             final BigInteger crtCoefficient = rsaKeySpec.getCrtCoefficient();
     80 
     81             return new OpenSSLKey(NativeCrypto.EVP_PKEY_new_RSA(
     82                     modulus.toByteArray(),
     83                     publicExponent == null ? null : publicExponent.toByteArray(),
     84                     privateExponent.toByteArray(),
     85                     primeP == null ? null : primeP.toByteArray(),
     86                     primeQ == null ? null : primeQ.toByteArray(),
     87                     primeExponentP == null ? null : primeExponentP.toByteArray(),
     88                     primeExponentQ == null ? null : primeExponentQ.toByteArray(),
     89                     crtCoefficient == null ? null : crtCoefficient.toByteArray()));
     90         } catch (Exception e) {
     91             throw new InvalidKeySpecException(e);
     92         }
     93     }
     94 
     95     static OpenSSLKey getInstance(RSAPrivateCrtKey rsaPrivateKey) throws InvalidKeyException {
     96         BigInteger modulus = rsaPrivateKey.getModulus();
     97         BigInteger privateExponent = rsaPrivateKey.getPrivateExponent();
     98 
     99         if (modulus == null) {
    100             throw new InvalidKeyException("modulus == null");
    101         } else if (privateExponent == null) {
    102             throw new InvalidKeyException("privateExponent == null");
    103         }
    104 
    105         try {
    106             /*
    107              * OpenSSL uses the public modulus to do RSA blinding. If
    108              * the public modulus is not available, the call to
    109              * EVP_PKEY_new_RSA will turn off blinding for this key
    110              * instance.
    111              */
    112             final BigInteger publicExponent = rsaPrivateKey.getPublicExponent();
    113             final BigInteger primeP = rsaPrivateKey.getPrimeP();
    114             final BigInteger primeQ = rsaPrivateKey.getPrimeQ();
    115             final BigInteger primeExponentP = rsaPrivateKey.getPrimeExponentP();
    116             final BigInteger primeExponentQ = rsaPrivateKey.getPrimeExponentQ();
    117             final BigInteger crtCoefficient = rsaPrivateKey.getCrtCoefficient();
    118 
    119             return new OpenSSLKey(NativeCrypto.EVP_PKEY_new_RSA(
    120                     modulus.toByteArray(),
    121                     publicExponent == null ? null : publicExponent.toByteArray(),
    122                     privateExponent.toByteArray(),
    123                     primeP == null ? null : primeP.toByteArray(),
    124                     primeQ == null ? null : primeQ.toByteArray(),
    125                     primeExponentP == null ? null : primeExponentP.toByteArray(),
    126                     primeExponentQ == null ? null : primeExponentQ.toByteArray(),
    127                     crtCoefficient == null ? null : crtCoefficient.toByteArray()));
    128         } catch (Exception e) {
    129             throw new InvalidKeyException(e);
    130         }
    131     }
    132 
    133     @Override
    134     synchronized void readParams(byte[][] params) {
    135         super.readParams(params);
    136         // params[0] read in super.readParams
    137         if (params[1] != null) {
    138             publicExponent = new BigInteger(params[1]);
    139         }
    140         // params[2] read in super.readParams
    141         if (params[3] != null) {
    142             primeP = new BigInteger(params[3]);
    143         }
    144         if (params[4] != null) {
    145             primeQ = new BigInteger(params[4]);
    146         }
    147         if (params[5] != null) {
    148             primeExponentP = new BigInteger(params[5]);
    149         }
    150         if (params[6] != null) {
    151             primeExponentQ = new BigInteger(params[6]);
    152         }
    153         if (params[7] != null) {
    154             crtCoefficient = new BigInteger(params[7]);
    155         }
    156     }
    157 
    158     @Override
    159     public BigInteger getPublicExponent() {
    160         ensureReadParams();
    161         return publicExponent;
    162     }
    163 
    164     @Override
    165     public BigInteger getPrimeP() {
    166         ensureReadParams();
    167         return primeP;
    168     }
    169 
    170     @Override
    171     public BigInteger getPrimeQ() {
    172         ensureReadParams();
    173         return primeQ;
    174     }
    175 
    176     @Override
    177     public BigInteger getPrimeExponentP() {
    178         ensureReadParams();
    179         return primeExponentP;
    180     }
    181 
    182     @Override
    183     public BigInteger getPrimeExponentQ() {
    184         ensureReadParams();
    185         return primeExponentQ;
    186     }
    187 
    188     @Override
    189     public BigInteger getCrtCoefficient() {
    190         ensureReadParams();
    191         return crtCoefficient;
    192     }
    193 
    194     @Override
    195     public boolean equals(Object o) {
    196         if (o == this) {
    197             return true;
    198         }
    199 
    200         if (o instanceof OpenSSLRSAPrivateKey) {
    201             OpenSSLRSAPrivateKey other = (OpenSSLRSAPrivateKey) o;
    202             return getOpenSSLKey().equals(other.getOpenSSLKey());
    203         }
    204 
    205         if (o instanceof RSAPrivateCrtKey) {
    206             ensureReadParams();
    207             RSAPrivateCrtKey other = (RSAPrivateCrtKey) o;
    208 
    209             if (getOpenSSLKey().isEngineBased()) {
    210                 return getModulus().equals(other.getModulus())
    211                         && publicExponent.equals(other.getPublicExponent());
    212             } else {
    213                 return getModulus().equals(other.getModulus())
    214                         && publicExponent.equals(other.getPublicExponent())
    215                         && getPrivateExponent().equals(other.getPrivateExponent())
    216                         && primeP.equals(other.getPrimeP()) && primeQ.equals(other.getPrimeQ())
    217                         && primeExponentP.equals(other.getPrimeExponentP())
    218                         && primeExponentQ.equals(other.getPrimeExponentQ())
    219                         && crtCoefficient.equals(other.getCrtCoefficient());
    220             }
    221         } else if (o instanceof RSAPrivateKey) {
    222             ensureReadParams();
    223             RSAPrivateKey other = (RSAPrivateKey) o;
    224 
    225             if (getOpenSSLKey().isEngineBased()) {
    226                 return getModulus().equals(other.getModulus());
    227             } else {
    228                 return getModulus().equals(other.getModulus())
    229                         && getPrivateExponent().equals(other.getPrivateExponent());
    230             }
    231         }
    232 
    233         return false;
    234     }
    235 
    236     @Override
    237     public final int hashCode() {
    238         int hashCode = super.hashCode();
    239         if (publicExponent != null) {
    240             hashCode ^= publicExponent.hashCode();
    241         }
    242         return hashCode;
    243     }
    244 
    245     @Override
    246     public String toString() {
    247         final StringBuilder sb = new StringBuilder("OpenSSLRSAPrivateCrtKey{");
    248 
    249         final boolean engineBased = getOpenSSLKey().isEngineBased();
    250         if (engineBased) {
    251             sb.append("key=");
    252             sb.append(getOpenSSLKey());
    253             sb.append('}');
    254         }
    255 
    256         ensureReadParams();
    257         sb.append("modulus=");
    258         sb.append(getModulus().toString(16));
    259         sb.append(',');
    260 
    261         if (publicExponent != null) {
    262             sb.append("publicExponent=");
    263             sb.append(publicExponent.toString(16));
    264             sb.append(',');
    265         }
    266 
    267         if (!engineBased) {
    268             sb.append("privateExponent=");
    269             sb.append(getPrivateExponent().toString(16));
    270             sb.append(',');
    271         }
    272 
    273         if (primeP != null) {
    274             sb.append("primeP=");
    275             sb.append(primeP.toString(16));
    276             sb.append(',');
    277         }
    278 
    279         if (primeQ != null) {
    280             sb.append("primeQ=");
    281             sb.append(primeQ.toString(16));
    282             sb.append(',');
    283         }
    284 
    285         if (primeExponentP != null) {
    286             sb.append("primeExponentP=");
    287             sb.append(primeExponentP.toString(16));
    288             sb.append(',');
    289         }
    290 
    291         if (primeExponentQ != null) {
    292             sb.append("primeExponentQ=");
    293             sb.append(primeExponentQ.toString(16));
    294             sb.append(',');
    295         }
    296 
    297         if (crtCoefficient != null) {
    298             sb.append("crtCoefficient=");
    299             sb.append(crtCoefficient.toString(16));
    300             sb.append(',');
    301         }
    302 
    303         return sb.toString();
    304     }
    305 
    306     private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
    307         stream.defaultReadObject();
    308 
    309         key = new OpenSSLKey(NativeCrypto.EVP_PKEY_new_RSA(
    310                 modulus.toByteArray(),
    311                 publicExponent == null ? null : publicExponent.toByteArray(),
    312                 privateExponent.toByteArray(),
    313                 primeP == null ? null : primeP.toByteArray(),
    314                 primeQ == null ? null : primeQ.toByteArray(),
    315                 primeExponentP == null ? null : primeExponentP.toByteArray(),
    316                 primeExponentQ == null ? null : primeExponentQ.toByteArray(),
    317                 crtCoefficient == null ? null : crtCoefficient.toByteArray()));
    318         fetchedParams = true;
    319     }
    320 
    321     private void writeObject(ObjectOutputStream stream) throws IOException {
    322         if (getOpenSSLKey().isEngineBased()) {
    323             throw new NotSerializableException("engine-based keys can not be serialized");
    324         }
    325 
    326         ensureReadParams();
    327         stream.defaultWriteObject();
    328     }
    329 }
    330