author | coffeys |
Tue, 20 Nov 2018 13:12:48 +0000 | |
changeset 52621 | f7309a1491d9 |
parent 51272 | 9d92ff04a29c |
permissions | -rw-r--r-- |
2 | 1 |
/* |
51272
9d92ff04a29c
8208602: Cannot read PEM X.509 cert if there is whitespace after the header or footer
weijun
parents:
47216
diff
changeset
|
2 |
* Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved. |
2 | 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 |
|
5506 | 7 |
* published by the Free Software Foundation. Oracle designates this |
2 | 8 |
* particular file as subject to the "Classpath" exception as provided |
5506 | 9 |
* by Oracle in the LICENSE file that accompanied this code. |
2 | 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 |
* |
|
5506 | 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. |
|
2 | 24 |
*/ |
25 |
||
26 |
package sun.security.provider; |
|
27 |
||
28 |
import java.io.*; |
|
52621
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
29 |
import java.security.PublicKey; |
2 | 30 |
import java.util.*; |
31 |
import java.security.cert.*; |
|
29596
70399c7a7f5a
8074935: jdk8 keytool doesn't validate pem files for RFC 1421 correctness, as jdk7 did
weijun
parents:
27091
diff
changeset
|
32 |
|
52621
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
33 |
import jdk.internal.event.EventHelper; |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
34 |
import jdk.internal.event.X509CertificateEvent; |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
35 |
import sun.security.util.KeyUtil; |
29596
70399c7a7f5a
8074935: jdk8 keytool doesn't validate pem files for RFC 1421 correctness, as jdk7 did
weijun
parents:
27091
diff
changeset
|
36 |
import sun.security.util.Pem; |
52621
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
37 |
import sun.security.x509.*; |
2 | 38 |
import sun.security.pkcs.PKCS7; |
39 |
import sun.security.provider.certpath.X509CertPath; |
|
40 |
import sun.security.provider.certpath.X509CertificatePair; |
|
41 |
import sun.security.util.DerValue; |
|
42 |
import sun.security.util.Cache; |
|
16020
b57c48f16179
8006182: cleanup to use java.util.Base64 in java security component, providers, and regression tests
msheppar
parents:
10786
diff
changeset
|
43 |
import java.util.Base64; |
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
44 |
import sun.security.pkcs.ParsingException; |
2 | 45 |
|
46 |
/** |
|
30374 | 47 |
* This class defines a certificate factory for X.509 v3 certificates {@literal &} |
2 | 48 |
* certification paths, and X.509 v2 certificate revocation lists (CRLs). |
49 |
* |
|
50 |
* @author Jan Luehe |
|
51 |
* @author Hemma Prafullchandra |
|
52 |
* @author Sean Mullan |
|
53 |
* |
|
54 |
* |
|
55 |
* @see java.security.cert.CertificateFactorySpi |
|
56 |
* @see java.security.cert.Certificate |
|
57 |
* @see java.security.cert.CertPath |
|
58 |
* @see java.security.cert.CRL |
|
59 |
* @see java.security.cert.X509Certificate |
|
60 |
* @see java.security.cert.X509CRL |
|
61 |
* @see sun.security.x509.X509CertImpl |
|
62 |
* @see sun.security.x509.X509CRLImpl |
|
63 |
*/ |
|
64 |
||
65 |
public class X509Factory extends CertificateFactorySpi { |
|
66 |
||
67 |
public static final String BEGIN_CERT = "-----BEGIN CERTIFICATE-----"; |
|
68 |
public static final String END_CERT = "-----END CERTIFICATE-----"; |
|
69 |
||
70 |
private static final int ENC_MAX_LENGTH = 4096 * 1024; // 4 MB MAX |
|
71 |
||
10785
1d42311b6355
7092897: sun.security.util.Cache should be generified
mullan
parents:
9035
diff
changeset
|
72 |
private static final Cache<Object, X509CertImpl> certCache |
1d42311b6355
7092897: sun.security.util.Cache should be generified
mullan
parents:
9035
diff
changeset
|
73 |
= Cache.newSoftMemoryCache(750); |
1d42311b6355
7092897: sun.security.util.Cache should be generified
mullan
parents:
9035
diff
changeset
|
74 |
private static final Cache<Object, X509CRLImpl> crlCache |
1d42311b6355
7092897: sun.security.util.Cache should be generified
mullan
parents:
9035
diff
changeset
|
75 |
= Cache.newSoftMemoryCache(750); |
2 | 76 |
|
77 |
/** |
|
78 |
* Generates an X.509 certificate object and initializes it with |
|
79 |
* the data read from the input stream <code>is</code>. |
|
80 |
* |
|
81 |
* @param is an input stream with the certificate data. |
|
82 |
* |
|
83 |
* @return an X.509 certificate object initialized with the data |
|
84 |
* from the input stream. |
|
85 |
* |
|
86 |
* @exception CertificateException on parsing errors. |
|
87 |
*/ |
|
27091
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
88 |
@Override |
2 | 89 |
public Certificate engineGenerateCertificate(InputStream is) |
90 |
throws CertificateException |
|
91 |
{ |
|
92 |
if (is == null) { |
|
93 |
// clear the caches (for debugging) |
|
94 |
certCache.clear(); |
|
95 |
X509CertificatePair.clearCache(); |
|
96 |
throw new CertificateException("Missing input stream"); |
|
97 |
} |
|
98 |
try { |
|
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
99 |
byte[] encoding = readOneBlock(is); |
2 | 100 |
if (encoding != null) { |
10785
1d42311b6355
7092897: sun.security.util.Cache should be generified
mullan
parents:
9035
diff
changeset
|
101 |
X509CertImpl cert = getFromCache(certCache, encoding); |
2 | 102 |
if (cert != null) { |
103 |
return cert; |
|
104 |
} |
|
105 |
cert = new X509CertImpl(encoding); |
|
106 |
addToCache(certCache, cert.getEncodedInternal(), cert); |
|
52621
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
107 |
// record cert details if necessary |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
108 |
commitEvent(cert); |
2 | 109 |
return cert; |
110 |
} else { |
|
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
111 |
throw new IOException("Empty input"); |
2 | 112 |
} |
113 |
} catch (IOException ioe) { |
|
27091
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
114 |
throw new CertificateException("Could not parse certificate: " + |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
115 |
ioe.toString(), ioe); |
2 | 116 |
} |
117 |
} |
|
118 |
||
119 |
/** |
|
120 |
* Read from the stream until length bytes have been read or EOF has |
|
121 |
* been reached. Return the number of bytes actually read. |
|
122 |
*/ |
|
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
123 |
private static int readFully(InputStream in, ByteArrayOutputStream bout, |
2 | 124 |
int length) throws IOException { |
125 |
int read = 0; |
|
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
126 |
byte[] buffer = new byte[2048]; |
2 | 127 |
while (length > 0) { |
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
128 |
int n = in.read(buffer, 0, length<2048?length:2048); |
2 | 129 |
if (n <= 0) { |
130 |
break; |
|
131 |
} |
|
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
132 |
bout.write(buffer, 0, n); |
2 | 133 |
read += n; |
134 |
length -= n; |
|
135 |
} |
|
136 |
return read; |
|
137 |
} |
|
138 |
||
139 |
/** |
|
140 |
* Return an interned X509CertImpl for the given certificate. |
|
141 |
* If the given X509Certificate or X509CertImpl is already present |
|
142 |
* in the cert cache, the cached object is returned. Otherwise, |
|
143 |
* if it is a X509Certificate, it is first converted to a X509CertImpl. |
|
144 |
* Then the X509CertImpl is added to the cache and returned. |
|
145 |
* |
|
146 |
* Note that all certificates created via generateCertificate(InputStream) |
|
147 |
* are already interned and this method does not need to be called. |
|
148 |
* It is useful for certificates that cannot be created via |
|
149 |
* generateCertificate() and for converting other X509Certificate |
|
150 |
* implementations to an X509CertImpl. |
|
27091
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
151 |
* |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
152 |
* @param c The source X509Certificate |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
153 |
* @return An X509CertImpl object that is either a cached certificate or a |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
154 |
* newly built X509CertImpl from the provided X509Certificate |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
155 |
* @throws CertificateException if failures occur while obtaining the DER |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
156 |
* encoding for certificate data. |
2 | 157 |
*/ |
158 |
public static synchronized X509CertImpl intern(X509Certificate c) |
|
159 |
throws CertificateException { |
|
160 |
if (c == null) { |
|
161 |
return null; |
|
162 |
} |
|
163 |
boolean isImpl = c instanceof X509CertImpl; |
|
164 |
byte[] encoding; |
|
165 |
if (isImpl) { |
|
166 |
encoding = ((X509CertImpl)c).getEncodedInternal(); |
|
167 |
} else { |
|
168 |
encoding = c.getEncoded(); |
|
169 |
} |
|
10785
1d42311b6355
7092897: sun.security.util.Cache should be generified
mullan
parents:
9035
diff
changeset
|
170 |
X509CertImpl newC = getFromCache(certCache, encoding); |
2 | 171 |
if (newC != null) { |
172 |
return newC; |
|
173 |
} |
|
174 |
if (isImpl) { |
|
175 |
newC = (X509CertImpl)c; |
|
176 |
} else { |
|
177 |
newC = new X509CertImpl(encoding); |
|
178 |
encoding = newC.getEncodedInternal(); |
|
179 |
} |
|
180 |
addToCache(certCache, encoding, newC); |
|
181 |
return newC; |
|
182 |
} |
|
183 |
||
184 |
/** |
|
185 |
* Return an interned X509CRLImpl for the given certificate. |
|
186 |
* For more information, see intern(X509Certificate). |
|
27091
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
187 |
* |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
188 |
* @param c The source X509CRL |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
189 |
* @return An X509CRLImpl object that is either a cached CRL or a |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
190 |
* newly built X509CRLImpl from the provided X509CRL |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
191 |
* @throws CRLException if failures occur while obtaining the DER |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
192 |
* encoding for CRL data. |
2 | 193 |
*/ |
194 |
public static synchronized X509CRLImpl intern(X509CRL c) |
|
195 |
throws CRLException { |
|
196 |
if (c == null) { |
|
197 |
return null; |
|
198 |
} |
|
199 |
boolean isImpl = c instanceof X509CRLImpl; |
|
200 |
byte[] encoding; |
|
201 |
if (isImpl) { |
|
202 |
encoding = ((X509CRLImpl)c).getEncodedInternal(); |
|
203 |
} else { |
|
204 |
encoding = c.getEncoded(); |
|
205 |
} |
|
10785
1d42311b6355
7092897: sun.security.util.Cache should be generified
mullan
parents:
9035
diff
changeset
|
206 |
X509CRLImpl newC = getFromCache(crlCache, encoding); |
2 | 207 |
if (newC != null) { |
208 |
return newC; |
|
209 |
} |
|
210 |
if (isImpl) { |
|
211 |
newC = (X509CRLImpl)c; |
|
212 |
} else { |
|
213 |
newC = new X509CRLImpl(encoding); |
|
214 |
encoding = newC.getEncodedInternal(); |
|
215 |
} |
|
216 |
addToCache(crlCache, encoding, newC); |
|
217 |
return newC; |
|
218 |
} |
|
219 |
||
220 |
/** |
|
221 |
* Get the X509CertImpl or X509CRLImpl from the cache. |
|
222 |
*/ |
|
10785
1d42311b6355
7092897: sun.security.util.Cache should be generified
mullan
parents:
9035
diff
changeset
|
223 |
private static synchronized <K,V> V getFromCache(Cache<K,V> cache, |
2 | 224 |
byte[] encoding) { |
225 |
Object key = new Cache.EqualByteArray(encoding); |
|
10785
1d42311b6355
7092897: sun.security.util.Cache should be generified
mullan
parents:
9035
diff
changeset
|
226 |
return cache.get(key); |
2 | 227 |
} |
228 |
||
229 |
/** |
|
230 |
* Add the X509CertImpl or X509CRLImpl to the cache. |
|
231 |
*/ |
|
10785
1d42311b6355
7092897: sun.security.util.Cache should be generified
mullan
parents:
9035
diff
changeset
|
232 |
private static synchronized <V> void addToCache(Cache<Object, V> cache, |
1d42311b6355
7092897: sun.security.util.Cache should be generified
mullan
parents:
9035
diff
changeset
|
233 |
byte[] encoding, V value) { |
2 | 234 |
if (encoding.length > ENC_MAX_LENGTH) { |
235 |
return; |
|
236 |
} |
|
237 |
Object key = new Cache.EqualByteArray(encoding); |
|
238 |
cache.put(key, value); |
|
239 |
} |
|
240 |
||
241 |
/** |
|
242 |
* Generates a <code>CertPath</code> object and initializes it with |
|
243 |
* the data read from the <code>InputStream</code> inStream. The data |
|
244 |
* is assumed to be in the default encoding. |
|
245 |
* |
|
246 |
* @param inStream an <code>InputStream</code> containing the data |
|
247 |
* @return a <code>CertPath</code> initialized with the data from the |
|
248 |
* <code>InputStream</code> |
|
249 |
* @exception CertificateException if an exception occurs while decoding |
|
250 |
* @since 1.4 |
|
251 |
*/ |
|
27091
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
252 |
@Override |
2 | 253 |
public CertPath engineGenerateCertPath(InputStream inStream) |
254 |
throws CertificateException |
|
255 |
{ |
|
256 |
if (inStream == null) { |
|
257 |
throw new CertificateException("Missing input stream"); |
|
258 |
} |
|
259 |
try { |
|
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
260 |
byte[] encoding = readOneBlock(inStream); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
261 |
if (encoding != null) { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
262 |
return new X509CertPath(new ByteArrayInputStream(encoding)); |
2 | 263 |
} else { |
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
264 |
throw new IOException("Empty input"); |
2 | 265 |
} |
266 |
} catch (IOException ioe) { |
|
267 |
throw new CertificateException(ioe.getMessage()); |
|
268 |
} |
|
269 |
} |
|
270 |
||
271 |
/** |
|
272 |
* Generates a <code>CertPath</code> object and initializes it with |
|
273 |
* the data read from the <code>InputStream</code> inStream. The data |
|
274 |
* is assumed to be in the specified encoding. |
|
275 |
* |
|
276 |
* @param inStream an <code>InputStream</code> containing the data |
|
277 |
* @param encoding the encoding used for the data |
|
278 |
* @return a <code>CertPath</code> initialized with the data from the |
|
279 |
* <code>InputStream</code> |
|
280 |
* @exception CertificateException if an exception occurs while decoding or |
|
281 |
* the encoding requested is not supported |
|
282 |
* @since 1.4 |
|
283 |
*/ |
|
27091
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
284 |
@Override |
2 | 285 |
public CertPath engineGenerateCertPath(InputStream inStream, |
286 |
String encoding) throws CertificateException |
|
287 |
{ |
|
288 |
if (inStream == null) { |
|
289 |
throw new CertificateException("Missing input stream"); |
|
290 |
} |
|
291 |
try { |
|
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
292 |
byte[] data = readOneBlock(inStream); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
293 |
if (data != null) { |
2 | 294 |
return new X509CertPath(new ByteArrayInputStream(data), encoding); |
295 |
} else { |
|
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
296 |
throw new IOException("Empty input"); |
2 | 297 |
} |
298 |
} catch (IOException ioe) { |
|
299 |
throw new CertificateException(ioe.getMessage()); |
|
300 |
} |
|
301 |
} |
|
302 |
||
303 |
/** |
|
304 |
* Generates a <code>CertPath</code> object and initializes it with |
|
305 |
* a <code>List</code> of <code>Certificate</code>s. |
|
306 |
* <p> |
|
307 |
* The certificates supplied must be of a type supported by the |
|
308 |
* <code>CertificateFactory</code>. They will be copied out of the supplied |
|
309 |
* <code>List</code> object. |
|
310 |
* |
|
311 |
* @param certificates a <code>List</code> of <code>Certificate</code>s |
|
312 |
* @return a <code>CertPath</code> initialized with the supplied list of |
|
313 |
* certificates |
|
314 |
* @exception CertificateException if an exception occurs |
|
315 |
* @since 1.4 |
|
316 |
*/ |
|
27091
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
317 |
@Override |
2 | 318 |
public CertPath |
319 |
engineGenerateCertPath(List<? extends Certificate> certificates) |
|
320 |
throws CertificateException |
|
321 |
{ |
|
322 |
return(new X509CertPath(certificates)); |
|
323 |
} |
|
324 |
||
325 |
/** |
|
326 |
* Returns an iteration of the <code>CertPath</code> encodings supported |
|
327 |
* by this certificate factory, with the default encoding first. |
|
328 |
* <p> |
|
329 |
* Attempts to modify the returned <code>Iterator</code> via its |
|
330 |
* <code>remove</code> method result in an |
|
331 |
* <code>UnsupportedOperationException</code>. |
|
332 |
* |
|
333 |
* @return an <code>Iterator</code> over the names of the supported |
|
334 |
* <code>CertPath</code> encodings (as <code>String</code>s) |
|
335 |
* @since 1.4 |
|
336 |
*/ |
|
27091
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
337 |
@Override |
2 | 338 |
public Iterator<String> engineGetCertPathEncodings() { |
339 |
return(X509CertPath.getEncodingsStatic()); |
|
340 |
} |
|
341 |
||
342 |
/** |
|
343 |
* Returns a (possibly empty) collection view of X.509 certificates read |
|
344 |
* from the given input stream <code>is</code>. |
|
345 |
* |
|
346 |
* @param is the input stream with the certificates. |
|
347 |
* |
|
348 |
* @return a (possibly empty) collection view of X.509 certificate objects |
|
349 |
* initialized with the data from the input stream. |
|
350 |
* |
|
351 |
* @exception CertificateException on parsing errors. |
|
352 |
*/ |
|
27091
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
353 |
@Override |
2 | 354 |
public Collection<? extends java.security.cert.Certificate> |
355 |
engineGenerateCertificates(InputStream is) |
|
356 |
throws CertificateException { |
|
357 |
if (is == null) { |
|
358 |
throw new CertificateException("Missing input stream"); |
|
359 |
} |
|
360 |
try { |
|
361 |
return parseX509orPKCS7Cert(is); |
|
362 |
} catch (IOException ioe) { |
|
363 |
throw new CertificateException(ioe); |
|
364 |
} |
|
365 |
} |
|
366 |
||
367 |
/** |
|
368 |
* Generates an X.509 certificate revocation list (CRL) object and |
|
369 |
* initializes it with the data read from the given input stream |
|
370 |
* <code>is</code>. |
|
371 |
* |
|
372 |
* @param is an input stream with the CRL data. |
|
373 |
* |
|
374 |
* @return an X.509 CRL object initialized with the data |
|
375 |
* from the input stream. |
|
376 |
* |
|
377 |
* @exception CRLException on parsing errors. |
|
378 |
*/ |
|
27091
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
379 |
@Override |
2 | 380 |
public CRL engineGenerateCRL(InputStream is) |
381 |
throws CRLException |
|
382 |
{ |
|
383 |
if (is == null) { |
|
384 |
// clear the cache (for debugging) |
|
385 |
crlCache.clear(); |
|
386 |
throw new CRLException("Missing input stream"); |
|
387 |
} |
|
388 |
try { |
|
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
389 |
byte[] encoding = readOneBlock(is); |
2 | 390 |
if (encoding != null) { |
10785
1d42311b6355
7092897: sun.security.util.Cache should be generified
mullan
parents:
9035
diff
changeset
|
391 |
X509CRLImpl crl = getFromCache(crlCache, encoding); |
2 | 392 |
if (crl != null) { |
393 |
return crl; |
|
394 |
} |
|
395 |
crl = new X509CRLImpl(encoding); |
|
396 |
addToCache(crlCache, crl.getEncodedInternal(), crl); |
|
397 |
return crl; |
|
398 |
} else { |
|
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
399 |
throw new IOException("Empty input"); |
2 | 400 |
} |
401 |
} catch (IOException ioe) { |
|
402 |
throw new CRLException(ioe.getMessage()); |
|
403 |
} |
|
404 |
} |
|
405 |
||
406 |
/** |
|
407 |
* Returns a (possibly empty) collection view of X.509 CRLs read |
|
408 |
* from the given input stream <code>is</code>. |
|
409 |
* |
|
410 |
* @param is the input stream with the CRLs. |
|
411 |
* |
|
412 |
* @return a (possibly empty) collection view of X.509 CRL objects |
|
413 |
* initialized with the data from the input stream. |
|
414 |
* |
|
415 |
* @exception CRLException on parsing errors. |
|
416 |
*/ |
|
27091
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
417 |
@Override |
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
418 |
public Collection<? extends java.security.cert.CRL> engineGenerateCRLs( |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
419 |
InputStream is) throws CRLException |
2 | 420 |
{ |
421 |
if (is == null) { |
|
422 |
throw new CRLException("Missing input stream"); |
|
423 |
} |
|
424 |
try { |
|
425 |
return parseX509orPKCS7CRL(is); |
|
426 |
} catch (IOException ioe) { |
|
427 |
throw new CRLException(ioe.getMessage()); |
|
428 |
} |
|
429 |
} |
|
430 |
||
431 |
/* |
|
432 |
* Parses the data in the given input stream as a sequence of DER |
|
433 |
* encoded X.509 certificates (in binary or base 64 encoded format) OR |
|
434 |
* as a single PKCS#7 encoded blob (in binary or base64 encoded format). |
|
435 |
*/ |
|
436 |
private Collection<? extends java.security.cert.Certificate> |
|
437 |
parseX509orPKCS7Cert(InputStream is) |
|
438 |
throws CertificateException, IOException |
|
439 |
{ |
|
27091
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
440 |
int peekByte; |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
441 |
byte[] data; |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
442 |
PushbackInputStream pbis = new PushbackInputStream(is); |
7973
dffe8439eb20
7005608: diamond conversion of JCA and crypto providers
smarks
parents:
5627
diff
changeset
|
443 |
Collection<X509CertImpl> coll = new ArrayList<>(); |
27091
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
444 |
|
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
445 |
// Test the InputStream for end-of-stream. If the stream's |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
446 |
// initial state is already at end-of-stream then return |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
447 |
// an empty collection. Otherwise, push the byte back into the |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
448 |
// stream and let readOneBlock look for the first certificate. |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
449 |
peekByte = pbis.read(); |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
450 |
if (peekByte == -1) { |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
451 |
return new ArrayList<>(0); |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
452 |
} else { |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
453 |
pbis.unread(peekByte); |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
454 |
data = readOneBlock(pbis); |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
455 |
} |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
456 |
|
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
457 |
// If we end up with a null value after reading the first block |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
458 |
// then we know the end-of-stream has been reached and no certificate |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
459 |
// data has been found. |
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
460 |
if (data == null) { |
27091
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
461 |
throw new CertificateException("No certificate data found"); |
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
462 |
} |
27091
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
463 |
|
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
464 |
try { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
465 |
PKCS7 pkcs7 = new PKCS7(data); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
466 |
X509Certificate[] certs = pkcs7.getCertificates(); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
467 |
// certs are optional in PKCS #7 |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
468 |
if (certs != null) { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
469 |
return Arrays.asList(certs); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
470 |
} else { |
27091
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
471 |
// no certificates provided |
7973
dffe8439eb20
7005608: diamond conversion of JCA and crypto providers
smarks
parents:
5627
diff
changeset
|
472 |
return new ArrayList<>(0); |
2 | 473 |
} |
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
474 |
} catch (ParsingException e) { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
475 |
while (data != null) { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
476 |
coll.add(new X509CertImpl(data)); |
27091
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
477 |
data = readOneBlock(pbis); |
2 | 478 |
} |
479 |
} |
|
480 |
return coll; |
|
481 |
} |
|
482 |
||
483 |
/* |
|
484 |
* Parses the data in the given input stream as a sequence of DER encoded |
|
485 |
* X.509 CRLs (in binary or base 64 encoded format) OR as a single PKCS#7 |
|
486 |
* encoded blob (in binary or base 64 encoded format). |
|
487 |
*/ |
|
488 |
private Collection<? extends java.security.cert.CRL> |
|
489 |
parseX509orPKCS7CRL(InputStream is) |
|
490 |
throws CRLException, IOException |
|
491 |
{ |
|
27091
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
492 |
int peekByte; |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
493 |
byte[] data; |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
494 |
PushbackInputStream pbis = new PushbackInputStream(is); |
7973
dffe8439eb20
7005608: diamond conversion of JCA and crypto providers
smarks
parents:
5627
diff
changeset
|
495 |
Collection<X509CRLImpl> coll = new ArrayList<>(); |
27091
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
496 |
|
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
497 |
// Test the InputStream for end-of-stream. If the stream's |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
498 |
// initial state is already at end-of-stream then return |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
499 |
// an empty collection. Otherwise, push the byte back into the |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
500 |
// stream and let readOneBlock look for the first CRL. |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
501 |
peekByte = pbis.read(); |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
502 |
if (peekByte == -1) { |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
503 |
return new ArrayList<>(0); |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
504 |
} else { |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
505 |
pbis.unread(peekByte); |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
506 |
data = readOneBlock(pbis); |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
507 |
} |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
508 |
|
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
509 |
// If we end up with a null value after reading the first block |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
510 |
// then we know the end-of-stream has been reached and no CRL |
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
511 |
// data has been found. |
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
512 |
if (data == null) { |
27091
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
513 |
throw new CRLException("No CRL data found"); |
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
514 |
} |
27091
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
515 |
|
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
516 |
try { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
517 |
PKCS7 pkcs7 = new PKCS7(data); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
518 |
X509CRL[] crls = pkcs7.getCRLs(); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
519 |
// CRLs are optional in PKCS #7 |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
520 |
if (crls != null) { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
521 |
return Arrays.asList(crls); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
522 |
} else { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
523 |
// no crls provided |
7973
dffe8439eb20
7005608: diamond conversion of JCA and crypto providers
smarks
parents:
5627
diff
changeset
|
524 |
return new ArrayList<>(0); |
2 | 525 |
} |
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
526 |
} catch (ParsingException e) { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
527 |
while (data != null) { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
528 |
coll.add(new X509CRLImpl(data)); |
27091
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
529 |
data = readOneBlock(pbis); |
2 | 530 |
} |
531 |
} |
|
532 |
return coll; |
|
533 |
} |
|
534 |
||
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
535 |
/** |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
536 |
* Returns an ASN.1 SEQUENCE from a stream, which might be a BER-encoded |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
537 |
* binary block or a PEM-style BASE64-encoded ASCII data. In the latter |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
538 |
* case, it's de-BASE64'ed before return. |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
539 |
* |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
540 |
* After the reading, the input stream pointer is after the BER block, or |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
541 |
* after the newline character after the -----END SOMETHING----- line. |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
542 |
* |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
543 |
* @param is the InputStream |
30374 | 544 |
* @return byte block or null if end of stream |
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
545 |
* @throws IOException If any parsing error |
2 | 546 |
*/ |
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
547 |
private static byte[] readOneBlock(InputStream is) throws IOException { |
2 | 548 |
|
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
549 |
// The first character of a BLOCK. |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
550 |
int c = is.read(); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
551 |
if (c == -1) { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
552 |
return null; |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
553 |
} |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
554 |
if (c == DerValue.tag_Sequence) { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
555 |
ByteArrayOutputStream bout = new ByteArrayOutputStream(2048); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
556 |
bout.write(c); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
557 |
readBERInternal(is, bout, c); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
558 |
return bout.toByteArray(); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
559 |
} else { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
560 |
// Read BASE64 encoded data, might skip info at the beginning |
45063
0909d3bcbacb
8179389: X509Certificate generateCRLs is extremely slow using a PEM crl list
weijun
parents:
30374
diff
changeset
|
561 |
ByteArrayOutputStream data = new ByteArrayOutputStream(); |
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
562 |
|
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
563 |
// Step 1: Read until header is found |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
564 |
int hyphen = (c=='-') ? 1: 0; // count of consequent hyphens |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
565 |
int last = (c=='-') ? -1: c; // the char before hyphen |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
566 |
while (true) { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
567 |
int next = is.read(); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
568 |
if (next == -1) { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
569 |
// We accept useless data after the last block, |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
570 |
// say, empty lines. |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
571 |
return null; |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
572 |
} |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
573 |
if (next == '-') { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
574 |
hyphen++; |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
575 |
} else { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
576 |
hyphen = 0; |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
577 |
last = next; |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
578 |
} |
16020
b57c48f16179
8006182: cleanup to use java.util.Base64 in java security component, providers, and regression tests
msheppar
parents:
10786
diff
changeset
|
579 |
if (hyphen == 5 && (last == -1 || last == '\r' || last == '\n')) { |
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
580 |
break; |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
581 |
} |
2063
8ad79de28190
6535697: keytool can be more flexible on format of PEM-encoded X.509 certificates
weijun
parents:
2
diff
changeset
|
582 |
} |
2 | 583 |
|
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
584 |
// Step 2: Read the rest of header, determine the line end |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
585 |
int end; |
24969
afa6934dd8e8
8041679: Replace uses of StringBuffer with StringBuilder within core library classes
psandoz
parents:
23010
diff
changeset
|
586 |
StringBuilder header = new StringBuilder("-----"); |
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
587 |
while (true) { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
588 |
int next = is.read(); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
589 |
if (next == -1) { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
590 |
throw new IOException("Incomplete data"); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
591 |
} |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
592 |
if (next == '\n') { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
593 |
end = '\n'; |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
594 |
break; |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
595 |
} |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
596 |
if (next == '\r') { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
597 |
next = is.read(); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
598 |
if (next == -1) { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
599 |
throw new IOException("Incomplete data"); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
600 |
} |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
601 |
if (next == '\n') { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
602 |
end = '\n'; |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
603 |
} else { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
604 |
end = '\r'; |
45063
0909d3bcbacb
8179389: X509Certificate generateCRLs is extremely slow using a PEM crl list
weijun
parents:
30374
diff
changeset
|
605 |
// Skip all white space chars |
0909d3bcbacb
8179389: X509Certificate generateCRLs is extremely slow using a PEM crl list
weijun
parents:
30374
diff
changeset
|
606 |
if (next != 9 && next != 10 && next != 13 && next != 32) { |
0909d3bcbacb
8179389: X509Certificate generateCRLs is extremely slow using a PEM crl list
weijun
parents:
30374
diff
changeset
|
607 |
data.write(next); |
0909d3bcbacb
8179389: X509Certificate generateCRLs is extremely slow using a PEM crl list
weijun
parents:
30374
diff
changeset
|
608 |
} |
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
609 |
} |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
610 |
break; |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
611 |
} |
5616
6f3f39ddc2c2
6948781: CertificateFactory.generateCertificate doesn't throw CertificateException for malformed certificate
weijun
parents:
5164
diff
changeset
|
612 |
header.append((char)next); |
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
613 |
} |
2 | 614 |
|
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
615 |
// Step 3: Read the data |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
616 |
while (true) { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
617 |
int next = is.read(); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
618 |
if (next == -1) { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
619 |
throw new IOException("Incomplete data"); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
620 |
} |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
621 |
if (next != '-') { |
45063
0909d3bcbacb
8179389: X509Certificate generateCRLs is extremely slow using a PEM crl list
weijun
parents:
30374
diff
changeset
|
622 |
// Skip all white space chars |
0909d3bcbacb
8179389: X509Certificate generateCRLs is extremely slow using a PEM crl list
weijun
parents:
30374
diff
changeset
|
623 |
if (next != 9 && next != 10 && next != 13 && next != 32) { |
0909d3bcbacb
8179389: X509Certificate generateCRLs is extremely slow using a PEM crl list
weijun
parents:
30374
diff
changeset
|
624 |
data.write(next); |
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
625 |
} |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
626 |
} else { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
627 |
break; |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
628 |
} |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
629 |
} |
2 | 630 |
|
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
631 |
// Step 4: Consume the footer |
24969
afa6934dd8e8
8041679: Replace uses of StringBuffer with StringBuilder within core library classes
psandoz
parents:
23010
diff
changeset
|
632 |
StringBuilder footer = new StringBuilder("-"); |
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
633 |
while (true) { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
634 |
int next = is.read(); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
635 |
// Add next == '\n' for maximum safety, in case endline |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
636 |
// is not consistent. |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
637 |
if (next == -1 || next == end || next == '\n') { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
638 |
break; |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
639 |
} |
5616
6f3f39ddc2c2
6948781: CertificateFactory.generateCertificate doesn't throw CertificateException for malformed certificate
weijun
parents:
5164
diff
changeset
|
640 |
if (next != '\r') footer.append((char)next); |
2 | 641 |
} |
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
642 |
|
51272
9d92ff04a29c
8208602: Cannot read PEM X.509 cert if there is whitespace after the header or footer
weijun
parents:
47216
diff
changeset
|
643 |
checkHeaderFooter(header.toString().stripTrailing(), |
9d92ff04a29c
8208602: Cannot read PEM X.509 cert if there is whitespace after the header or footer
weijun
parents:
47216
diff
changeset
|
644 |
footer.toString().stripTrailing()); |
5616
6f3f39ddc2c2
6948781: CertificateFactory.generateCertificate doesn't throw CertificateException for malformed certificate
weijun
parents:
5164
diff
changeset
|
645 |
|
45063
0909d3bcbacb
8179389: X509Certificate generateCRLs is extremely slow using a PEM crl list
weijun
parents:
30374
diff
changeset
|
646 |
try { |
0909d3bcbacb
8179389: X509Certificate generateCRLs is extremely slow using a PEM crl list
weijun
parents:
30374
diff
changeset
|
647 |
return Base64.getDecoder().decode(data.toByteArray()); |
0909d3bcbacb
8179389: X509Certificate generateCRLs is extremely slow using a PEM crl list
weijun
parents:
30374
diff
changeset
|
648 |
} catch (IllegalArgumentException e) { |
0909d3bcbacb
8179389: X509Certificate generateCRLs is extremely slow using a PEM crl list
weijun
parents:
30374
diff
changeset
|
649 |
throw new IOException(e); |
0909d3bcbacb
8179389: X509Certificate generateCRLs is extremely slow using a PEM crl list
weijun
parents:
30374
diff
changeset
|
650 |
} |
2 | 651 |
} |
652 |
} |
|
653 |
||
5616
6f3f39ddc2c2
6948781: CertificateFactory.generateCertificate doesn't throw CertificateException for malformed certificate
weijun
parents:
5164
diff
changeset
|
654 |
private static void checkHeaderFooter(String header, |
6f3f39ddc2c2
6948781: CertificateFactory.generateCertificate doesn't throw CertificateException for malformed certificate
weijun
parents:
5164
diff
changeset
|
655 |
String footer) throws IOException { |
6f3f39ddc2c2
6948781: CertificateFactory.generateCertificate doesn't throw CertificateException for malformed certificate
weijun
parents:
5164
diff
changeset
|
656 |
if (header.length() < 16 || !header.startsWith("-----BEGIN ") || |
6f3f39ddc2c2
6948781: CertificateFactory.generateCertificate doesn't throw CertificateException for malformed certificate
weijun
parents:
5164
diff
changeset
|
657 |
!header.endsWith("-----")) { |
6f3f39ddc2c2
6948781: CertificateFactory.generateCertificate doesn't throw CertificateException for malformed certificate
weijun
parents:
5164
diff
changeset
|
658 |
throw new IOException("Illegal header: " + header); |
6f3f39ddc2c2
6948781: CertificateFactory.generateCertificate doesn't throw CertificateException for malformed certificate
weijun
parents:
5164
diff
changeset
|
659 |
} |
6f3f39ddc2c2
6948781: CertificateFactory.generateCertificate doesn't throw CertificateException for malformed certificate
weijun
parents:
5164
diff
changeset
|
660 |
if (footer.length() < 14 || !footer.startsWith("-----END ") || |
6f3f39ddc2c2
6948781: CertificateFactory.generateCertificate doesn't throw CertificateException for malformed certificate
weijun
parents:
5164
diff
changeset
|
661 |
!footer.endsWith("-----")) { |
6f3f39ddc2c2
6948781: CertificateFactory.generateCertificate doesn't throw CertificateException for malformed certificate
weijun
parents:
5164
diff
changeset
|
662 |
throw new IOException("Illegal footer: " + footer); |
6f3f39ddc2c2
6948781: CertificateFactory.generateCertificate doesn't throw CertificateException for malformed certificate
weijun
parents:
5164
diff
changeset
|
663 |
} |
6f3f39ddc2c2
6948781: CertificateFactory.generateCertificate doesn't throw CertificateException for malformed certificate
weijun
parents:
5164
diff
changeset
|
664 |
String headerType = header.substring(11, header.length()-5); |
6f3f39ddc2c2
6948781: CertificateFactory.generateCertificate doesn't throw CertificateException for malformed certificate
weijun
parents:
5164
diff
changeset
|
665 |
String footerType = footer.substring(9, footer.length()-5); |
6f3f39ddc2c2
6948781: CertificateFactory.generateCertificate doesn't throw CertificateException for malformed certificate
weijun
parents:
5164
diff
changeset
|
666 |
if (!headerType.equals(footerType)) { |
6f3f39ddc2c2
6948781: CertificateFactory.generateCertificate doesn't throw CertificateException for malformed certificate
weijun
parents:
5164
diff
changeset
|
667 |
throw new IOException("Header and footer do not match: " + |
6f3f39ddc2c2
6948781: CertificateFactory.generateCertificate doesn't throw CertificateException for malformed certificate
weijun
parents:
5164
diff
changeset
|
668 |
header + " " + footer); |
6f3f39ddc2c2
6948781: CertificateFactory.generateCertificate doesn't throw CertificateException for malformed certificate
weijun
parents:
5164
diff
changeset
|
669 |
} |
6f3f39ddc2c2
6948781: CertificateFactory.generateCertificate doesn't throw CertificateException for malformed certificate
weijun
parents:
5164
diff
changeset
|
670 |
} |
6f3f39ddc2c2
6948781: CertificateFactory.generateCertificate doesn't throw CertificateException for malformed certificate
weijun
parents:
5164
diff
changeset
|
671 |
|
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
672 |
/** |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
673 |
* Read one BER data block. This method is aware of indefinite-length BER |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
674 |
* encoding and will read all of the sub-sections in a recursive way |
2 | 675 |
* |
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
676 |
* @param is Read from this InputStream |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
677 |
* @param bout Write into this OutputStream |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
678 |
* @param tag Tag already read (-1 mean not read) |
30374 | 679 |
* @return The current tag, used to check EOC in indefinite-length BER |
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
680 |
* @throws IOException Any parsing error |
2 | 681 |
*/ |
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
682 |
private static int readBERInternal(InputStream is, |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
683 |
ByteArrayOutputStream bout, int tag) throws IOException { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
684 |
|
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
685 |
if (tag == -1) { // Not read before the call, read now |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
686 |
tag = is.read(); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
687 |
if (tag == -1) { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
688 |
throw new IOException("BER/DER tag info absent"); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
689 |
} |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
690 |
if ((tag & 0x1f) == 0x1f) { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
691 |
throw new IOException("Multi octets tag not supported"); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
692 |
} |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
693 |
bout.write(tag); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
694 |
} |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
695 |
|
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
696 |
int n = is.read(); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
697 |
if (n == -1) { |
27091
c068bd1064e0
8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input
ascarpino
parents:
25859
diff
changeset
|
698 |
throw new IOException("BER/DER length info absent"); |
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
699 |
} |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
700 |
bout.write(n); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
701 |
|
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
702 |
int length; |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
703 |
|
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
704 |
if (n == 0x80) { // Indefinite-length encoding |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
705 |
if ((tag & 0x20) != 0x20) { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
706 |
throw new IOException( |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
707 |
"Non constructed encoding must have definite length"); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
708 |
} |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
709 |
while (true) { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
710 |
int subTag = readBERInternal(is, bout, -1); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
711 |
if (subTag == 0) { // EOC, end of indefinite-length section |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
712 |
break; |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
713 |
} |
2 | 714 |
} |
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
715 |
} else { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
716 |
if (n < 0x80) { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
717 |
length = n; |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
718 |
} else if (n == 0x81) { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
719 |
length = is.read(); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
720 |
if (length == -1) { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
721 |
throw new IOException("Incomplete BER/DER length info"); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
722 |
} |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
723 |
bout.write(length); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
724 |
} else if (n == 0x82) { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
725 |
int highByte = is.read(); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
726 |
int lowByte = is.read(); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
727 |
if (lowByte == -1) { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
728 |
throw new IOException("Incomplete BER/DER length info"); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
729 |
} |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
730 |
bout.write(highByte); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
731 |
bout.write(lowByte); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
732 |
length = (highByte << 8) | lowByte; |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
733 |
} else if (n == 0x83) { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
734 |
int highByte = is.read(); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
735 |
int midByte = is.read(); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
736 |
int lowByte = is.read(); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
737 |
if (lowByte == -1) { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
738 |
throw new IOException("Incomplete BER/DER length info"); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
739 |
} |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
740 |
bout.write(highByte); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
741 |
bout.write(midByte); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
742 |
bout.write(lowByte); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
743 |
length = (highByte << 16) | (midByte << 8) | lowByte; |
10784
f800232d1474
7099399: cannot deal with CRL file larger than 16MB
weijun
parents:
9035
diff
changeset
|
744 |
} else if (n == 0x84) { |
f800232d1474
7099399: cannot deal with CRL file larger than 16MB
weijun
parents:
9035
diff
changeset
|
745 |
int highByte = is.read(); |
f800232d1474
7099399: cannot deal with CRL file larger than 16MB
weijun
parents:
9035
diff
changeset
|
746 |
int nextByte = is.read(); |
f800232d1474
7099399: cannot deal with CRL file larger than 16MB
weijun
parents:
9035
diff
changeset
|
747 |
int midByte = is.read(); |
f800232d1474
7099399: cannot deal with CRL file larger than 16MB
weijun
parents:
9035
diff
changeset
|
748 |
int lowByte = is.read(); |
f800232d1474
7099399: cannot deal with CRL file larger than 16MB
weijun
parents:
9035
diff
changeset
|
749 |
if (lowByte == -1) { |
f800232d1474
7099399: cannot deal with CRL file larger than 16MB
weijun
parents:
9035
diff
changeset
|
750 |
throw new IOException("Incomplete BER/DER length info"); |
f800232d1474
7099399: cannot deal with CRL file larger than 16MB
weijun
parents:
9035
diff
changeset
|
751 |
} |
f800232d1474
7099399: cannot deal with CRL file larger than 16MB
weijun
parents:
9035
diff
changeset
|
752 |
if (highByte > 127) { |
f800232d1474
7099399: cannot deal with CRL file larger than 16MB
weijun
parents:
9035
diff
changeset
|
753 |
throw new IOException("Invalid BER/DER data (a little huge?)"); |
f800232d1474
7099399: cannot deal with CRL file larger than 16MB
weijun
parents:
9035
diff
changeset
|
754 |
} |
f800232d1474
7099399: cannot deal with CRL file larger than 16MB
weijun
parents:
9035
diff
changeset
|
755 |
bout.write(highByte); |
f800232d1474
7099399: cannot deal with CRL file larger than 16MB
weijun
parents:
9035
diff
changeset
|
756 |
bout.write(nextByte); |
f800232d1474
7099399: cannot deal with CRL file larger than 16MB
weijun
parents:
9035
diff
changeset
|
757 |
bout.write(midByte); |
f800232d1474
7099399: cannot deal with CRL file larger than 16MB
weijun
parents:
9035
diff
changeset
|
758 |
bout.write(lowByte); |
f800232d1474
7099399: cannot deal with CRL file larger than 16MB
weijun
parents:
9035
diff
changeset
|
759 |
length = (highByte << 24 ) | (nextByte << 16) | |
f800232d1474
7099399: cannot deal with CRL file larger than 16MB
weijun
parents:
9035
diff
changeset
|
760 |
(midByte << 8) | lowByte; |
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
761 |
} else { // ignore longer length forms |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
762 |
throw new IOException("Invalid BER/DER data (too huge?)"); |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
763 |
} |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
764 |
if (readFully(is, bout, length) != length) { |
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
765 |
throw new IOException("Incomplete BER/DER data"); |
2 | 766 |
} |
767 |
} |
|
5164
337ae296b6d6
6813340: X509Factory should not depend on is.available()==0
weijun
parents:
2063
diff
changeset
|
768 |
return tag; |
2 | 769 |
} |
52621
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
770 |
|
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
771 |
private void commitEvent(X509CertImpl info) { |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
772 |
X509CertificateEvent xce = new X509CertificateEvent(); |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
773 |
if (xce.shouldCommit() || EventHelper.isLoggingSecurity()) { |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
774 |
PublicKey pKey = info.getPublicKey(); |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
775 |
String algId = info.getSigAlgName(); |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
776 |
String serNum = info.getSerialNumber().toString(16); |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
777 |
String subject = info.getSubjectDN().getName(); |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
778 |
String issuer = info.getIssuerDN().getName(); |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
779 |
String keyType = pKey.getAlgorithm(); |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
780 |
int length = KeyUtil.getKeySize(pKey); |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
781 |
int hashCode = info.hashCode(); |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
782 |
long beginDate = info.getNotBefore().getTime(); |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
783 |
long endDate = info.getNotAfter().getTime(); |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
784 |
if (xce.shouldCommit()) { |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
785 |
xce.algorithm = algId; |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
786 |
xce.serialNumber = serNum; |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
787 |
xce.subject = subject; |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
788 |
xce.issuer = issuer; |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
789 |
xce.keyType = keyType; |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
790 |
xce.keyLength = length; |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
791 |
xce.certificateId = hashCode; |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
792 |
xce.validFrom = beginDate; |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
793 |
xce.validUntil = endDate; |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
794 |
xce.commit(); |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
795 |
} |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
796 |
if (EventHelper.isLoggingSecurity()) { |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
797 |
EventHelper.logX509CertificateEvent(algId, |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
798 |
serNum, |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
799 |
subject, |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
800 |
issuer, |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
801 |
keyType, |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
802 |
length, |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
803 |
hashCode, |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
804 |
beginDate, |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
805 |
endDate); |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
806 |
} |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
807 |
} |
f7309a1491d9
8148188: Enhance the security libraries to record events of interest
coffeys
parents:
51272
diff
changeset
|
808 |
} |
2 | 809 |
} |