• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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