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 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 /** 97 * If the key is not encodable (PKCS11-like key), then wrap it and use 98 * JNI upcalls to satisfy requests. 99 */ 100 if (rsaPrivateKey.getFormat() == null) { 101 return wrapPlatformKey(rsaPrivateKey); 102 } 103 104 BigInteger modulus = rsaPrivateKey.getModulus(); 105 BigInteger privateExponent = rsaPrivateKey.getPrivateExponent(); 106 107 if (modulus == null) { 108 throw new InvalidKeyException("modulus == null"); 109 } else if (privateExponent == null) { 110 throw new InvalidKeyException("privateExponent == null"); 111 } 112 113 try { 114 /* 115 * OpenSSL uses the public modulus to do RSA blinding. If 116 * the public modulus is not available, the call to 117 * EVP_PKEY_new_RSA will turn off blinding for this key 118 * instance. 119 */ 120 final BigInteger publicExponent = rsaPrivateKey.getPublicExponent(); 121 final BigInteger primeP = rsaPrivateKey.getPrimeP(); 122 final BigInteger primeQ = rsaPrivateKey.getPrimeQ(); 123 final BigInteger primeExponentP = rsaPrivateKey.getPrimeExponentP(); 124 final BigInteger primeExponentQ = rsaPrivateKey.getPrimeExponentQ(); 125 final BigInteger crtCoefficient = rsaPrivateKey.getCrtCoefficient(); 126 127 return new OpenSSLKey(NativeCrypto.EVP_PKEY_new_RSA( 128 modulus.toByteArray(), 129 publicExponent == null ? null : publicExponent.toByteArray(), 130 privateExponent.toByteArray(), 131 primeP == null ? null : primeP.toByteArray(), 132 primeQ == null ? null : primeQ.toByteArray(), 133 primeExponentP == null ? null : primeExponentP.toByteArray(), 134 primeExponentQ == null ? null : primeExponentQ.toByteArray(), 135 crtCoefficient == null ? null : crtCoefficient.toByteArray())); 136 } catch (Exception e) { 137 throw new InvalidKeyException(e); 138 } 139 } 140 141 @Override 142 synchronized void readParams(byte[][] params) { 143 super.readParams(params); 144 // params[0] read in super.readParams 145 if (params[1] != null) { 146 publicExponent = new BigInteger(params[1]); 147 } 148 // params[2] read in super.readParams 149 if (params[3] != null) { 150 primeP = new BigInteger(params[3]); 151 } 152 if (params[4] != null) { 153 primeQ = new BigInteger(params[4]); 154 } 155 if (params[5] != null) { 156 primeExponentP = new BigInteger(params[5]); 157 } 158 if (params[6] != null) { 159 primeExponentQ = new BigInteger(params[6]); 160 } 161 if (params[7] != null) { 162 crtCoefficient = new BigInteger(params[7]); 163 } 164 } 165 166 @Override 167 public BigInteger getPublicExponent() { 168 ensureReadParams(); 169 return publicExponent; 170 } 171 172 @Override 173 public BigInteger getPrimeP() { 174 ensureReadParams(); 175 return primeP; 176 } 177 178 @Override 179 public BigInteger getPrimeQ() { 180 ensureReadParams(); 181 return primeQ; 182 } 183 184 @Override 185 public BigInteger getPrimeExponentP() { 186 ensureReadParams(); 187 return primeExponentP; 188 } 189 190 @Override 191 public BigInteger getPrimeExponentQ() { 192 ensureReadParams(); 193 return primeExponentQ; 194 } 195 196 @Override 197 public BigInteger getCrtCoefficient() { 198 ensureReadParams(); 199 return crtCoefficient; 200 } 201 202 @Override 203 public boolean equals(Object o) { 204 if (o == this) { 205 return true; 206 } 207 208 if (o instanceof OpenSSLRSAPrivateKey) { 209 OpenSSLRSAPrivateKey other = (OpenSSLRSAPrivateKey) o; 210 return getOpenSSLKey().equals(other.getOpenSSLKey()); 211 } 212 213 if (o instanceof RSAPrivateCrtKey) { 214 ensureReadParams(); 215 RSAPrivateCrtKey other = (RSAPrivateCrtKey) o; 216 217 if (getOpenSSLKey().isEngineBased()) { 218 return getModulus().equals(other.getModulus()) 219 && publicExponent.equals(other.getPublicExponent()); 220 } else { 221 return getModulus().equals(other.getModulus()) 222 && publicExponent.equals(other.getPublicExponent()) 223 && getPrivateExponent().equals(other.getPrivateExponent()) 224 && primeP.equals(other.getPrimeP()) && primeQ.equals(other.getPrimeQ()) 225 && primeExponentP.equals(other.getPrimeExponentP()) 226 && primeExponentQ.equals(other.getPrimeExponentQ()) 227 && crtCoefficient.equals(other.getCrtCoefficient()); 228 } 229 } else if (o instanceof RSAPrivateKey) { 230 ensureReadParams(); 231 RSAPrivateKey other = (RSAPrivateKey) o; 232 233 if (getOpenSSLKey().isEngineBased()) { 234 return getModulus().equals(other.getModulus()); 235 } else { 236 return getModulus().equals(other.getModulus()) 237 && getPrivateExponent().equals(other.getPrivateExponent()); 238 } 239 } 240 241 return false; 242 } 243 244 @Override 245 public final int hashCode() { 246 int hashCode = super.hashCode(); 247 if (publicExponent != null) { 248 hashCode ^= publicExponent.hashCode(); 249 } 250 return hashCode; 251 } 252 253 @Override 254 public String toString() { 255 final StringBuilder sb = new StringBuilder("OpenSSLRSAPrivateCrtKey{"); 256 257 final boolean engineBased = getOpenSSLKey().isEngineBased(); 258 if (engineBased) { 259 sb.append("key="); 260 sb.append(getOpenSSLKey()); 261 sb.append('}'); 262 } 263 264 ensureReadParams(); 265 sb.append("modulus="); 266 sb.append(getModulus().toString(16)); 267 sb.append(','); 268 269 if (publicExponent != null) { 270 sb.append("publicExponent="); 271 sb.append(publicExponent.toString(16)); 272 sb.append(','); 273 } 274 275 if (!engineBased) { 276 sb.append("privateExponent="); 277 sb.append(getPrivateExponent().toString(16)); 278 sb.append(','); 279 } 280 281 if (primeP != null) { 282 sb.append("primeP="); 283 sb.append(primeP.toString(16)); 284 sb.append(','); 285 } 286 287 if (primeQ != null) { 288 sb.append("primeQ="); 289 sb.append(primeQ.toString(16)); 290 sb.append(','); 291 } 292 293 if (primeExponentP != null) { 294 sb.append("primeExponentP="); 295 sb.append(primeExponentP.toString(16)); 296 sb.append(','); 297 } 298 299 if (primeExponentQ != null) { 300 sb.append("primeExponentQ="); 301 sb.append(primeExponentQ.toString(16)); 302 sb.append(','); 303 } 304 305 if (crtCoefficient != null) { 306 sb.append("crtCoefficient="); 307 sb.append(crtCoefficient.toString(16)); 308 sb.append(','); 309 } 310 311 return sb.toString(); 312 } 313 314 private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { 315 stream.defaultReadObject(); 316 317 key = new OpenSSLKey(NativeCrypto.EVP_PKEY_new_RSA( 318 modulus.toByteArray(), 319 publicExponent == null ? null : publicExponent.toByteArray(), 320 privateExponent.toByteArray(), 321 primeP == null ? null : primeP.toByteArray(), 322 primeQ == null ? null : primeQ.toByteArray(), 323 primeExponentP == null ? null : primeExponentP.toByteArray(), 324 primeExponentQ == null ? null : primeExponentQ.toByteArray(), 325 crtCoefficient == null ? null : crtCoefficient.toByteArray())); 326 fetchedParams = true; 327 } 328 329 private void writeObject(ObjectOutputStream stream) throws IOException { 330 if (getOpenSSLKey().isEngineBased()) { 331 throw new NotSerializableException("engine-based keys can not be serialized"); 332 } 333 334 ensureReadParams(); 335 stream.defaultWriteObject(); 336 } 337 } 338