Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/provider/certpath/X509CertPath.java
38923 views
1
/*
2
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
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
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
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
*
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.
24
*/
25
26
package sun.security.provider.certpath;
27
28
import java.io.ByteArrayInputStream;
29
import java.io.ByteArrayOutputStream;
30
import java.io.IOException;
31
import java.io.InputStream;
32
import java.security.cert.CertificateEncodingException;
33
import java.security.cert.Certificate;
34
import java.security.cert.CertificateException;
35
import java.security.cert.CertificateFactory;
36
import java.security.cert.CertPath;
37
import java.security.cert.X509Certificate;
38
import java.util.*;
39
40
import sun.security.pkcs.ContentInfo;
41
import sun.security.pkcs.PKCS7;
42
import sun.security.pkcs.SignerInfo;
43
import sun.security.x509.AlgorithmId;
44
import sun.security.util.DerValue;
45
import sun.security.util.DerOutputStream;
46
import sun.security.util.DerInputStream;
47
48
/**
49
* A {@link java.security.cert.CertPath CertPath} (certification path)
50
* consisting exclusively of
51
* {@link java.security.cert.X509Certificate X509Certificate}s.
52
* <p>
53
* By convention, X.509 <code>CertPath</code>s are stored from target
54
* to trust anchor.
55
* That is, the issuer of one certificate is the subject of the following
56
* one. However, unvalidated X.509 <code>CertPath</code>s may not follow
57
* this convention. PKIX <code>CertPathValidator</code>s will detect any
58
* departure from this convention and throw a
59
* <code>CertPathValidatorException</code>.
60
*
61
* @author Yassir Elley
62
* @since 1.4
63
*/
64
public class X509CertPath extends CertPath {
65
66
private static final long serialVersionUID = 4989800333263052980L;
67
68
/**
69
* List of certificates in this chain
70
*/
71
private List<X509Certificate> certs;
72
73
/**
74
* The names of our encodings. PkiPath is the default.
75
*/
76
private static final String COUNT_ENCODING = "count";
77
private static final String PKCS7_ENCODING = "PKCS7";
78
private static final String PKIPATH_ENCODING = "PkiPath";
79
80
/**
81
* List of supported encodings
82
*/
83
private static final Collection<String> encodingList;
84
85
static {
86
List<String> list = new ArrayList<>(2);
87
list.add(PKIPATH_ENCODING);
88
list.add(PKCS7_ENCODING);
89
encodingList = Collections.unmodifiableCollection(list);
90
}
91
92
/**
93
* Creates an <code>X509CertPath</code> from a <code>List</code> of
94
* <code>X509Certificate</code>s.
95
* <p>
96
* The certificates are copied out of the supplied <code>List</code>
97
* object.
98
*
99
* @param certs a <code>List</code> of <code>X509Certificate</code>s
100
* @exception CertificateException if <code>certs</code> contains an element
101
* that is not an <code>X509Certificate</code>
102
*/
103
@SuppressWarnings("unchecked")
104
public X509CertPath(List<? extends Certificate> certs) throws CertificateException {
105
super("X.509");
106
107
// Ensure that the List contains only X509Certificates
108
//
109
// Note; The certs parameter is not necessarily to be of Certificate
110
// for some old code. For compatibility, to make sure the exception
111
// is CertificateException, rather than ClassCastException, please
112
// don't use
113
// for (Certificate obj : certs)
114
for (Object obj : certs) {
115
if (obj instanceof X509Certificate == false) {
116
throw new CertificateException
117
("List is not all X509Certificates: "
118
+ obj.getClass().getName());
119
}
120
}
121
122
// Assumes that the resulting List is thread-safe. This is true
123
// because we ensure that it cannot be modified after construction
124
// and the methods in the Sun JDK 1.4 implementation of ArrayList that
125
// allow read-only access are thread-safe.
126
this.certs = Collections.unmodifiableList(
127
new ArrayList<X509Certificate>((List<X509Certificate>)certs));
128
}
129
130
/**
131
* Creates an <code>X509CertPath</code>, reading the encoded form
132
* from an <code>InputStream</code>. The data is assumed to be in
133
* the default encoding.
134
*
135
* @param is the <code>InputStream</code> to read the data from
136
* @exception CertificateException if an exception occurs while decoding
137
*/
138
public X509CertPath(InputStream is) throws CertificateException {
139
this(is, PKIPATH_ENCODING);
140
}
141
142
/**
143
* Creates an <code>X509CertPath</code>, reading the encoded form
144
* from an InputStream. The data is assumed to be in the specified
145
* encoding.
146
*
147
* @param is the <code>InputStream</code> to read the data from
148
* @param encoding the encoding used
149
* @exception CertificateException if an exception occurs while decoding or
150
* the encoding requested is not supported
151
*/
152
public X509CertPath(InputStream is, String encoding)
153
throws CertificateException {
154
super("X.509");
155
156
switch (encoding) {
157
case PKIPATH_ENCODING:
158
certs = parsePKIPATH(is);
159
break;
160
case PKCS7_ENCODING:
161
certs = parsePKCS7(is);
162
break;
163
default:
164
throw new CertificateException("unsupported encoding");
165
}
166
}
167
168
/**
169
* Parse a PKIPATH format CertPath from an InputStream. Return an
170
* unmodifiable List of the certificates.
171
*
172
* @param is the <code>InputStream</code> to read the data from
173
* @return an unmodifiable List of the certificates
174
* @exception CertificateException if an exception occurs
175
*/
176
private static List<X509Certificate> parsePKIPATH(InputStream is)
177
throws CertificateException {
178
List<X509Certificate> certList = null;
179
CertificateFactory certFac = null;
180
181
if (is == null) {
182
throw new CertificateException("input stream is null");
183
}
184
185
try {
186
DerInputStream dis = new DerInputStream(readAllBytes(is));
187
DerValue[] seq = dis.getSequence(3);
188
if (seq.length == 0) {
189
return Collections.<X509Certificate>emptyList();
190
}
191
192
certFac = CertificateFactory.getInstance("X.509");
193
certList = new ArrayList<X509Certificate>(seq.length);
194
195
// append certs in reverse order (target to trust anchor)
196
for (int i = seq.length-1; i >= 0; i--) {
197
certList.add((X509Certificate)certFac.generateCertificate
198
(new ByteArrayInputStream(seq[i].toByteArray())));
199
}
200
201
return Collections.unmodifiableList(certList);
202
203
} catch (IOException ioe) {
204
throw new CertificateException("IOException parsing PkiPath data: "
205
+ ioe, ioe);
206
}
207
}
208
209
/**
210
* Parse a PKCS#7 format CertPath from an InputStream. Return an
211
* unmodifiable List of the certificates.
212
*
213
* @param is the <code>InputStream</code> to read the data from
214
* @return an unmodifiable List of the certificates
215
* @exception CertificateException if an exception occurs
216
*/
217
private static List<X509Certificate> parsePKCS7(InputStream is)
218
throws CertificateException {
219
List<X509Certificate> certList;
220
221
if (is == null) {
222
throw new CertificateException("input stream is null");
223
}
224
225
try {
226
if (is.markSupported() == false) {
227
// Copy the entire input stream into an InputStream that does
228
// support mark
229
is = new ByteArrayInputStream(readAllBytes(is));
230
}
231
PKCS7 pkcs7 = new PKCS7(is);
232
233
X509Certificate[] certArray = pkcs7.getCertificates();
234
// certs are optional in PKCS #7
235
if (certArray != null) {
236
certList = Arrays.asList(certArray);
237
} else {
238
// no certs provided
239
certList = new ArrayList<X509Certificate>(0);
240
}
241
} catch (IOException ioe) {
242
throw new CertificateException("IOException parsing PKCS7 data: " +
243
ioe);
244
}
245
// Assumes that the resulting List is thread-safe. This is true
246
// because we ensure that it cannot be modified after construction
247
// and the methods in the Sun JDK 1.4 implementation of ArrayList that
248
// allow read-only access are thread-safe.
249
return Collections.unmodifiableList(certList);
250
}
251
252
/*
253
* Reads the entire contents of an InputStream into a byte array.
254
*
255
* @param is the InputStream to read from
256
* @return the bytes read from the InputStream
257
*/
258
private static byte[] readAllBytes(InputStream is) throws IOException {
259
byte[] buffer = new byte[8192];
260
ByteArrayOutputStream baos = new ByteArrayOutputStream(2048);
261
int n;
262
while ((n = is.read(buffer)) != -1) {
263
baos.write(buffer, 0, n);
264
}
265
return baos.toByteArray();
266
}
267
268
/**
269
* Returns the encoded form of this certification path, using the
270
* default encoding.
271
*
272
* @return the encoded bytes
273
* @exception CertificateEncodingException if an encoding error occurs
274
*/
275
@Override
276
public byte[] getEncoded() throws CertificateEncodingException {
277
// @@@ Should cache the encoded form
278
return encodePKIPATH();
279
}
280
281
/**
282
* Encode the CertPath using PKIPATH format.
283
*
284
* @return a byte array containing the binary encoding of the PkiPath object
285
* @exception CertificateEncodingException if an exception occurs
286
*/
287
private byte[] encodePKIPATH() throws CertificateEncodingException {
288
289
ListIterator<X509Certificate> li = certs.listIterator(certs.size());
290
try {
291
DerOutputStream bytes = new DerOutputStream();
292
// encode certs in reverse order (trust anchor to target)
293
// according to PkiPath format
294
while (li.hasPrevious()) {
295
X509Certificate cert = li.previous();
296
// check for duplicate cert
297
if (certs.lastIndexOf(cert) != certs.indexOf(cert)) {
298
throw new CertificateEncodingException
299
("Duplicate Certificate");
300
}
301
// get encoded certificates
302
byte[] encoded = cert.getEncoded();
303
bytes.write(encoded);
304
}
305
306
// Wrap the data in a SEQUENCE
307
DerOutputStream derout = new DerOutputStream();
308
derout.write(DerValue.tag_SequenceOf, bytes);
309
return derout.toByteArray();
310
311
} catch (IOException ioe) {
312
throw new CertificateEncodingException("IOException encoding " +
313
"PkiPath data: " + ioe, ioe);
314
}
315
}
316
317
/**
318
* Encode the CertPath using PKCS#7 format.
319
*
320
* @return a byte array containing the binary encoding of the PKCS#7 object
321
* @exception CertificateEncodingException if an exception occurs
322
*/
323
private byte[] encodePKCS7() throws CertificateEncodingException {
324
PKCS7 p7 = new PKCS7(new AlgorithmId[0],
325
new ContentInfo(ContentInfo.DATA_OID, null),
326
certs.toArray(new X509Certificate[certs.size()]),
327
new SignerInfo[0]);
328
DerOutputStream derout = new DerOutputStream();
329
try {
330
p7.encodeSignedData(derout);
331
} catch (IOException ioe) {
332
throw new CertificateEncodingException(ioe.getMessage());
333
}
334
return derout.toByteArray();
335
}
336
337
/**
338
* Returns the encoded form of this certification path, using the
339
* specified encoding.
340
*
341
* @param encoding the name of the encoding to use
342
* @return the encoded bytes
343
* @exception CertificateEncodingException if an encoding error occurs or
344
* the encoding requested is not supported
345
*/
346
@Override
347
public byte[] getEncoded(String encoding)
348
throws CertificateEncodingException {
349
switch (encoding) {
350
case PKIPATH_ENCODING:
351
return encodePKIPATH();
352
case PKCS7_ENCODING:
353
return encodePKCS7();
354
default:
355
throw new CertificateEncodingException("unsupported encoding");
356
}
357
}
358
359
/**
360
* Returns the encodings supported by this certification path, with the
361
* default encoding first.
362
*
363
* @return an <code>Iterator</code> over the names of the supported
364
* encodings (as Strings)
365
*/
366
public static Iterator<String> getEncodingsStatic() {
367
return encodingList.iterator();
368
}
369
370
/**
371
* Returns an iteration of the encodings supported by this certification
372
* path, with the default encoding first.
373
* <p>
374
* Attempts to modify the returned <code>Iterator</code> via its
375
* <code>remove</code> method result in an
376
* <code>UnsupportedOperationException</code>.
377
*
378
* @return an <code>Iterator</code> over the names of the supported
379
* encodings (as Strings)
380
*/
381
@Override
382
public Iterator<String> getEncodings() {
383
return getEncodingsStatic();
384
}
385
386
/**
387
* Returns the list of certificates in this certification path.
388
* The <code>List</code> returned must be immutable and thread-safe.
389
*
390
* @return an immutable <code>List</code> of <code>X509Certificate</code>s
391
* (may be empty, but not null)
392
*/
393
@Override
394
public List<X509Certificate> getCertificates() {
395
return certs;
396
}
397
}
398
399