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.conscrypt; 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 /** 31 * An implementation of {@link java.security.PrivateKey} for RSA keys which uses BoringSSL to 32 * perform all the operations. 33 */ 34 final class OpenSSLRSAPrivateCrtKey extends OpenSSLRSAPrivateKey implements RSAPrivateCrtKey { 35 private static final long serialVersionUID = 3785291944868707197L; 36 37 private BigInteger publicExponent; 38 39 private BigInteger primeP; 40 41 private BigInteger primeQ; 42 43 private BigInteger primeExponentP; 44 45 private BigInteger primeExponentQ; 46 47 private BigInteger crtCoefficient; 48 OpenSSLRSAPrivateCrtKey(OpenSSLKey key)49 OpenSSLRSAPrivateCrtKey(OpenSSLKey key) { 50 super(key); 51 } 52 OpenSSLRSAPrivateCrtKey(OpenSSLKey key, byte[][] params)53 OpenSSLRSAPrivateCrtKey(OpenSSLKey key, byte[][] params) { 54 super(key, params); 55 } 56 OpenSSLRSAPrivateCrtKey(RSAPrivateCrtKeySpec rsaKeySpec)57 OpenSSLRSAPrivateCrtKey(RSAPrivateCrtKeySpec rsaKeySpec) throws InvalidKeySpecException { 58 super(init(rsaKeySpec)); 59 } 60 init(RSAPrivateCrtKeySpec rsaKeySpec)61 private static OpenSSLKey init(RSAPrivateCrtKeySpec rsaKeySpec) throws InvalidKeySpecException { 62 BigInteger modulus = rsaKeySpec.getModulus(); 63 BigInteger privateExponent = rsaKeySpec.getPrivateExponent(); 64 65 if (modulus == null) { 66 throw new InvalidKeySpecException("modulus == null"); 67 } else if (privateExponent == null) { 68 throw new InvalidKeySpecException("privateExponent == null"); 69 } 70 71 try { 72 /* 73 * OpenSSL uses the public modulus to do RSA blinding. If 74 * the public modulus is not available, the call to 75 * EVP_PKEY_new_RSA will turn off blinding for this key 76 * instance. 77 */ 78 final BigInteger publicExponent = rsaKeySpec.getPublicExponent(); 79 final BigInteger primeP = rsaKeySpec.getPrimeP(); 80 final BigInteger primeQ = rsaKeySpec.getPrimeQ(); 81 final BigInteger primeExponentP = rsaKeySpec.getPrimeExponentP(); 82 final BigInteger primeExponentQ = rsaKeySpec.getPrimeExponentQ(); 83 final BigInteger crtCoefficient = rsaKeySpec.getCrtCoefficient(); 84 85 return new OpenSSLKey(NativeCrypto.EVP_PKEY_new_RSA( 86 modulus.toByteArray(), 87 publicExponent == null ? null : publicExponent.toByteArray(), 88 privateExponent.toByteArray(), 89 primeP == null ? null : primeP.toByteArray(), 90 primeQ == null ? null : primeQ.toByteArray(), 91 primeExponentP == null ? null : primeExponentP.toByteArray(), 92 primeExponentQ == null ? null : primeExponentQ.toByteArray(), 93 crtCoefficient == null ? null : crtCoefficient.toByteArray())); 94 } catch (Exception e) { 95 throw new InvalidKeySpecException(e); 96 } 97 } 98 getInstance(RSAPrivateCrtKey rsaPrivateKey)99 static OpenSSLKey getInstance(RSAPrivateCrtKey rsaPrivateKey) throws InvalidKeyException { 100 /* 101 * If the key is not encodable (PKCS11-like key), then wrap it and use 102 * JNI upcalls to satisfy requests. 103 */ 104 if (rsaPrivateKey.getFormat() == null) { 105 return wrapPlatformKey(rsaPrivateKey); 106 } 107 108 BigInteger modulus = rsaPrivateKey.getModulus(); 109 BigInteger privateExponent = rsaPrivateKey.getPrivateExponent(); 110 111 if (modulus == null) { 112 throw new InvalidKeyException("modulus == null"); 113 } else if (privateExponent == null) { 114 throw new InvalidKeyException("privateExponent == null"); 115 } 116 117 try { 118 /* 119 * OpenSSL uses the public modulus to do RSA blinding. If 120 * the public modulus is not available, the call to 121 * EVP_PKEY_new_RSA will turn off blinding for this key 122 * instance. 123 */ 124 final BigInteger publicExponent = rsaPrivateKey.getPublicExponent(); 125 final BigInteger primeP = rsaPrivateKey.getPrimeP(); 126 final BigInteger primeQ = rsaPrivateKey.getPrimeQ(); 127 final BigInteger primeExponentP = rsaPrivateKey.getPrimeExponentP(); 128 final BigInteger primeExponentQ = rsaPrivateKey.getPrimeExponentQ(); 129 final BigInteger crtCoefficient = rsaPrivateKey.getCrtCoefficient(); 130 131 return new OpenSSLKey(NativeCrypto.EVP_PKEY_new_RSA( 132 modulus.toByteArray(), 133 publicExponent == null ? null : publicExponent.toByteArray(), 134 privateExponent.toByteArray(), 135 primeP == null ? null : primeP.toByteArray(), 136 primeQ == null ? null : primeQ.toByteArray(), 137 primeExponentP == null ? null : primeExponentP.toByteArray(), 138 primeExponentQ == null ? null : primeExponentQ.toByteArray(), 139 crtCoefficient == null ? null : crtCoefficient.toByteArray())); 140 } catch (Exception e) { 141 throw new InvalidKeyException(e); 142 } 143 } 144 145 @Override readParams(byte[][] params)146 synchronized void readParams(byte[][] params) { 147 super.readParams(params); 148 // params[0] read in super.readParams 149 if (params[1] != null) { 150 publicExponent = new BigInteger(params[1]); 151 } 152 // params[2] read in super.readParams 153 if (params[3] != null) { 154 primeP = new BigInteger(params[3]); 155 } 156 if (params[4] != null) { 157 primeQ = new BigInteger(params[4]); 158 } 159 if (params[5] != null) { 160 primeExponentP = new BigInteger(params[5]); 161 } 162 if (params[6] != null) { 163 primeExponentQ = new BigInteger(params[6]); 164 } 165 if (params[7] != null) { 166 crtCoefficient = new BigInteger(params[7]); 167 } 168 } 169 170 @Override getPublicExponent()171 public BigInteger getPublicExponent() { 172 ensureReadParams(); 173 return publicExponent; 174 } 175 176 @Override getPrimeP()177 public BigInteger getPrimeP() { 178 ensureReadParams(); 179 return primeP; 180 } 181 182 @Override getPrimeQ()183 public BigInteger getPrimeQ() { 184 ensureReadParams(); 185 return primeQ; 186 } 187 188 @Override getPrimeExponentP()189 public BigInteger getPrimeExponentP() { 190 ensureReadParams(); 191 return primeExponentP; 192 } 193 194 @Override getPrimeExponentQ()195 public BigInteger getPrimeExponentQ() { 196 ensureReadParams(); 197 return primeExponentQ; 198 } 199 200 @Override getCrtCoefficient()201 public BigInteger getCrtCoefficient() { 202 ensureReadParams(); 203 return crtCoefficient; 204 } 205 206 @Override equals(Object o)207 public boolean equals(Object o) { 208 if (o == this) { 209 return true; 210 } 211 212 if (o instanceof OpenSSLRSAPrivateKey) { 213 OpenSSLRSAPrivateKey other = (OpenSSLRSAPrivateKey) o; 214 return getOpenSSLKey().equals(other.getOpenSSLKey()); 215 } 216 217 if (o instanceof RSAPrivateCrtKey) { 218 ensureReadParams(); 219 RSAPrivateCrtKey other = (RSAPrivateCrtKey) o; 220 221 if (getOpenSSLKey().isHardwareBacked()) { 222 return getModulus().equals(other.getModulus()) 223 && publicExponent.equals(other.getPublicExponent()); 224 } else { 225 return getModulus().equals(other.getModulus()) 226 && publicExponent.equals(other.getPublicExponent()) 227 && getPrivateExponent().equals(other.getPrivateExponent()) 228 && primeP.equals(other.getPrimeP()) && primeQ.equals(other.getPrimeQ()) 229 && primeExponentP.equals(other.getPrimeExponentP()) 230 && primeExponentQ.equals(other.getPrimeExponentQ()) 231 && crtCoefficient.equals(other.getCrtCoefficient()); 232 } 233 } else if (o instanceof RSAPrivateKey) { 234 ensureReadParams(); 235 RSAPrivateKey other = (RSAPrivateKey) o; 236 237 if (getOpenSSLKey().isHardwareBacked()) { 238 return getModulus().equals(other.getModulus()); 239 } else { 240 return getModulus().equals(other.getModulus()) 241 && getPrivateExponent().equals(other.getPrivateExponent()); 242 } 243 } 244 245 return false; 246 } 247 248 @Override hashCode()249 public int hashCode() { 250 int hashCode = super.hashCode(); 251 if (publicExponent != null) { 252 hashCode ^= publicExponent.hashCode(); 253 } 254 return hashCode; 255 } 256 257 @Override toString()258 public String toString() { 259 final StringBuilder sb = new StringBuilder("OpenSSLRSAPrivateCrtKey{"); 260 261 ensureReadParams(); 262 sb.append("modulus="); 263 sb.append(getModulus().toString(16)); 264 265 if (publicExponent != null) { 266 sb.append(','); 267 sb.append("publicExponent="); 268 sb.append(publicExponent.toString(16)); 269 } 270 271 sb.append('}'); 272 return sb.toString(); 273 } 274 readObject(ObjectInputStream stream)275 private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { 276 stream.defaultReadObject(); 277 278 key = new OpenSSLKey(NativeCrypto.EVP_PKEY_new_RSA( 279 modulus.toByteArray(), 280 publicExponent == null ? null : publicExponent.toByteArray(), 281 privateExponent.toByteArray(), 282 primeP == null ? null : primeP.toByteArray(), 283 primeQ == null ? null : primeQ.toByteArray(), 284 primeExponentP == null ? null : primeExponentP.toByteArray(), 285 primeExponentQ == null ? null : primeExponentQ.toByteArray(), 286 crtCoefficient == null ? null : crtCoefficient.toByteArray())); 287 fetchedParams = true; 288 } 289 writeObject(ObjectOutputStream stream)290 private void writeObject(ObjectOutputStream stream) throws IOException { 291 if (getOpenSSLKey().isHardwareBacked()) { 292 throw new NotSerializableException("Hardware backed keys cannot be serialized"); 293 } 294 295 ensureReadParams(); 296 stream.defaultWriteObject(); 297 } 298 } 299