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