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/validator/EndEntityChecker.java
38831 views
1
/*
2
* Copyright (c) 2002, 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.validator;
27
28
import java.util.*;
29
30
import java.security.cert.*;
31
32
import sun.security.x509.NetscapeCertTypeExtension;
33
34
/**
35
* Class to check if an end entity cert is suitable for use in some
36
* context.<p>
37
*
38
* This class is used internally by the validator. Currently, seven variants
39
* are supported defined as VAR_XXX constants in the Validator class:
40
* <ul>
41
* <li>Generic. No additional requirements, all certificates are ok.
42
*
43
* <li>TLS server. Requires that a String parameter is passed to
44
* validate that specifies the name of the TLS key exchange algorithm
45
* in use. See the JSSE X509TrustManager spec for details.
46
*
47
* <li>TLS client.
48
*
49
* <li>Code signing.
50
*
51
* <li>JCE code signing. Some early JCE code signing certs issued to
52
* providers had incorrect extensions. In this mode the checks
53
* are relaxed compared to standard code signing checks in order to
54
* allow these certificates to pass.
55
*
56
* <li>Plugin code signing. WebStart and Plugin require their own variant
57
* which is equivalent to VAR_CODE_SIGNING with additional checks for
58
* compatibility/special cases. See also PKIXValidator.
59
*
60
* <li>TSA Server (see RFC 3161, section 2.3).
61
*
62
* </ul>
63
*
64
* @author Andreas Sterbenz
65
*/
66
class EndEntityChecker {
67
68
// extended key usage OIDs for TLS server, TLS client, code signing
69
// and any usage
70
71
private final static String OID_EXTENDED_KEY_USAGE =
72
SimpleValidator.OID_EXTENDED_KEY_USAGE;
73
74
private final static String OID_EKU_TLS_SERVER = "1.3.6.1.5.5.7.3.1";
75
76
private final static String OID_EKU_TLS_CLIENT = "1.3.6.1.5.5.7.3.2";
77
78
private final static String OID_EKU_CODE_SIGNING = "1.3.6.1.5.5.7.3.3";
79
80
private final static String OID_EKU_TIME_STAMPING = "1.3.6.1.5.5.7.3.8";
81
82
private final static String OID_EKU_ANY_USAGE = "2.5.29.37.0";
83
84
// the Netscape Server-Gated-Cryptography EKU extension OID
85
private final static String OID_EKU_NS_SGC = "2.16.840.1.113730.4.1";
86
87
// the Microsoft Server-Gated-Cryptography EKU extension OID
88
private final static String OID_EKU_MS_SGC = "1.3.6.1.4.1.311.10.3.3";
89
90
// the recognized extension OIDs
91
private final static String OID_SUBJECT_ALT_NAME = "2.5.29.17";
92
93
private final static String NSCT_SSL_CLIENT =
94
NetscapeCertTypeExtension.SSL_CLIENT;
95
96
private final static String NSCT_SSL_SERVER =
97
NetscapeCertTypeExtension.SSL_SERVER;
98
99
private final static String NSCT_CODE_SIGNING =
100
NetscapeCertTypeExtension.OBJECT_SIGNING;
101
102
// bit numbers in the key usage extension
103
private final static int KU_SIGNATURE = 0;
104
private final static int KU_KEY_ENCIPHERMENT = 2;
105
private final static int KU_KEY_AGREEMENT = 4;
106
107
// TLS key exchange algorithms requiring digitalSignature key usage
108
private final static Collection<String> KU_SERVER_SIGNATURE =
109
Arrays.asList("DHE_DSS", "DHE_RSA", "ECDHE_ECDSA", "ECDHE_RSA",
110
"RSA_EXPORT", "UNKNOWN");
111
112
// TLS key exchange algorithms requiring keyEncipherment key usage
113
private final static Collection<String> KU_SERVER_ENCRYPTION =
114
Arrays.asList("RSA");
115
116
// TLS key exchange algorithms requiring keyAgreement key usage
117
private final static Collection<String> KU_SERVER_KEY_AGREEMENT =
118
Arrays.asList("DH_DSS", "DH_RSA", "ECDH_ECDSA", "ECDH_RSA");
119
120
// variant of this end entity cert checker
121
private final String variant;
122
123
// type of the validator this checker belongs to
124
private final String type;
125
126
private EndEntityChecker(String type, String variant) {
127
this.type = type;
128
this.variant = variant;
129
}
130
131
static EndEntityChecker getInstance(String type, String variant) {
132
return new EndEntityChecker(type, variant);
133
}
134
135
void check(X509Certificate[] chain, Object parameter,
136
boolean checkUnresolvedCritExts)
137
throws CertificateException {
138
if (variant.equals(Validator.VAR_GENERIC)) {
139
return; // no checks
140
}
141
142
Set<String> exts = getCriticalExtensions(chain[0]);
143
if (variant.equals(Validator.VAR_TLS_SERVER)) {
144
checkTLSServer(chain[0], (String)parameter, exts);
145
} else if (variant.equals(Validator.VAR_TLS_CLIENT)) {
146
checkTLSClient(chain[0], exts);
147
} else if (variant.equals(Validator.VAR_CODE_SIGNING)) {
148
checkCodeSigning(chain[0], exts);
149
} else if (variant.equals(Validator.VAR_JCE_SIGNING)) {
150
checkCodeSigning(chain[0], exts);
151
} else if (variant.equals(Validator.VAR_PLUGIN_CODE_SIGNING)) {
152
checkCodeSigning(chain[0], exts);
153
} else if (variant.equals(Validator.VAR_TSA_SERVER)) {
154
checkTSAServer(chain[0], exts);
155
} else {
156
throw new CertificateException("Unknown variant: " + variant);
157
}
158
159
// if neither VAR_GENERIC variant nor unknown variant
160
if (checkUnresolvedCritExts) {
161
checkRemainingExtensions(exts);
162
}
163
164
// check if certificate should be distrusted according to policies
165
// set in the jdk.security.caDistrustPolicies security property
166
for (CADistrustPolicy policy : CADistrustPolicy.POLICIES) {
167
policy.checkDistrust(variant, chain);
168
}
169
}
170
171
/**
172
* Utility method returning the Set of critical extensions for
173
* certificate cert (never null).
174
*/
175
private Set<String> getCriticalExtensions(X509Certificate cert) {
176
Set<String> exts = cert.getCriticalExtensionOIDs();
177
if (exts == null) {
178
exts = Collections.emptySet();
179
}
180
return exts;
181
}
182
183
/**
184
* Utility method checking if there are any unresolved critical extensions.
185
* @throws CertificateException if so.
186
*/
187
private void checkRemainingExtensions(Set<String> exts)
188
throws CertificateException {
189
// basic constraints irrelevant in EE certs
190
exts.remove(SimpleValidator.OID_BASIC_CONSTRAINTS);
191
192
// If the subject field contains an empty sequence, the subjectAltName
193
// extension MUST be marked critical.
194
// We do not check the validity of the critical extension, just mark
195
// it recognizable here.
196
exts.remove(OID_SUBJECT_ALT_NAME);
197
198
if (!exts.isEmpty()) {
199
throw new CertificateException("Certificate contains unsupported "
200
+ "critical extensions: " + exts);
201
}
202
}
203
204
/**
205
* Utility method checking if the extended key usage extension in
206
* certificate cert allows use for expectedEKU.
207
*/
208
private boolean checkEKU(X509Certificate cert, Set<String> exts,
209
String expectedEKU) throws CertificateException {
210
List<String> eku = cert.getExtendedKeyUsage();
211
if (eku == null) {
212
return true;
213
}
214
return eku.contains(expectedEKU) || eku.contains(OID_EKU_ANY_USAGE);
215
}
216
217
/**
218
* Utility method checking if bit 'bit' is set in this certificates
219
* key usage extension.
220
* @throws CertificateException if not
221
*/
222
private boolean checkKeyUsage(X509Certificate cert, int bit)
223
throws CertificateException {
224
boolean[] keyUsage = cert.getKeyUsage();
225
if (keyUsage == null) {
226
return true;
227
}
228
return (keyUsage.length > bit) && keyUsage[bit];
229
}
230
231
/**
232
* Check whether this certificate can be used for TLS client
233
* authentication.
234
* @throws CertificateException if not.
235
*/
236
private void checkTLSClient(X509Certificate cert, Set<String> exts)
237
throws CertificateException {
238
if (checkKeyUsage(cert, KU_SIGNATURE) == false) {
239
throw new ValidatorException
240
("KeyUsage does not allow digital signatures",
241
ValidatorException.T_EE_EXTENSIONS, cert);
242
}
243
244
if (checkEKU(cert, exts, OID_EKU_TLS_CLIENT) == false) {
245
throw new ValidatorException("Extended key usage does not "
246
+ "permit use for TLS client authentication",
247
ValidatorException.T_EE_EXTENSIONS, cert);
248
}
249
250
if (!SimpleValidator.getNetscapeCertTypeBit(cert, NSCT_SSL_CLIENT)) {
251
throw new ValidatorException
252
("Netscape cert type does not permit use for SSL client",
253
ValidatorException.T_EE_EXTENSIONS, cert);
254
}
255
256
// remove extensions we checked
257
exts.remove(SimpleValidator.OID_KEY_USAGE);
258
exts.remove(SimpleValidator.OID_EXTENDED_KEY_USAGE);
259
exts.remove(SimpleValidator.OID_NETSCAPE_CERT_TYPE);
260
}
261
262
/**
263
* Check whether this certificate can be used for TLS server authentication
264
* using the specified authentication type parameter. See X509TrustManager
265
* specification for details.
266
* @throws CertificateException if not.
267
*/
268
private void checkTLSServer(X509Certificate cert, String parameter,
269
Set<String> exts) throws CertificateException {
270
if (KU_SERVER_ENCRYPTION.contains(parameter)) {
271
if (checkKeyUsage(cert, KU_KEY_ENCIPHERMENT) == false) {
272
throw new ValidatorException
273
("KeyUsage does not allow key encipherment",
274
ValidatorException.T_EE_EXTENSIONS, cert);
275
}
276
} else if (KU_SERVER_SIGNATURE.contains(parameter)) {
277
if (checkKeyUsage(cert, KU_SIGNATURE) == false) {
278
throw new ValidatorException
279
("KeyUsage does not allow digital signatures",
280
ValidatorException.T_EE_EXTENSIONS, cert);
281
}
282
} else if (KU_SERVER_KEY_AGREEMENT.contains(parameter)) {
283
if (checkKeyUsage(cert, KU_KEY_AGREEMENT) == false) {
284
throw new ValidatorException
285
("KeyUsage does not allow key agreement",
286
ValidatorException.T_EE_EXTENSIONS, cert);
287
}
288
} else {
289
throw new CertificateException("Unknown authType: " + parameter);
290
}
291
292
if (checkEKU(cert, exts, OID_EKU_TLS_SERVER) == false) {
293
// check for equivalent but now obsolete Server-Gated-Cryptography
294
// (aka Step-Up, 128 bit) EKU OIDs
295
if ((checkEKU(cert, exts, OID_EKU_MS_SGC) == false) &&
296
(checkEKU(cert, exts, OID_EKU_NS_SGC) == false)) {
297
throw new ValidatorException
298
("Extended key usage does not permit use for TLS "
299
+ "server authentication",
300
ValidatorException.T_EE_EXTENSIONS, cert);
301
}
302
}
303
304
if (!SimpleValidator.getNetscapeCertTypeBit(cert, NSCT_SSL_SERVER)) {
305
throw new ValidatorException
306
("Netscape cert type does not permit use for SSL server",
307
ValidatorException.T_EE_EXTENSIONS, cert);
308
}
309
310
// remove extensions we checked
311
exts.remove(SimpleValidator.OID_KEY_USAGE);
312
exts.remove(SimpleValidator.OID_EXTENDED_KEY_USAGE);
313
exts.remove(SimpleValidator.OID_NETSCAPE_CERT_TYPE);
314
}
315
316
/**
317
* Check whether this certificate can be used for code signing.
318
* @throws CertificateException if not.
319
*/
320
private void checkCodeSigning(X509Certificate cert, Set<String> exts)
321
throws CertificateException {
322
if (checkKeyUsage(cert, KU_SIGNATURE) == false) {
323
throw new ValidatorException
324
("KeyUsage does not allow digital signatures",
325
ValidatorException.T_EE_EXTENSIONS, cert);
326
}
327
328
if (checkEKU(cert, exts, OID_EKU_CODE_SIGNING) == false) {
329
throw new ValidatorException
330
("Extended key usage does not permit use for code signing",
331
ValidatorException.T_EE_EXTENSIONS, cert);
332
}
333
334
// do not check Netscape cert type for JCE code signing checks
335
// (some certs were issued with incorrect extensions)
336
if (variant.equals(Validator.VAR_JCE_SIGNING) == false) {
337
if (!SimpleValidator.getNetscapeCertTypeBit(cert, NSCT_CODE_SIGNING)) {
338
throw new ValidatorException
339
("Netscape cert type does not permit use for code signing",
340
ValidatorException.T_EE_EXTENSIONS, cert);
341
}
342
exts.remove(SimpleValidator.OID_NETSCAPE_CERT_TYPE);
343
}
344
345
// remove extensions we checked
346
exts.remove(SimpleValidator.OID_KEY_USAGE);
347
exts.remove(SimpleValidator.OID_EXTENDED_KEY_USAGE);
348
}
349
350
/**
351
* Check whether this certificate can be used by a time stamping authority
352
* server (see RFC 3161, section 2.3).
353
* @throws CertificateException if not.
354
*/
355
private void checkTSAServer(X509Certificate cert, Set<String> exts)
356
throws CertificateException {
357
if (checkKeyUsage(cert, KU_SIGNATURE) == false) {
358
throw new ValidatorException
359
("KeyUsage does not allow digital signatures",
360
ValidatorException.T_EE_EXTENSIONS, cert);
361
}
362
363
if (cert.getExtendedKeyUsage() == null) {
364
throw new ValidatorException
365
("Certificate does not contain an extended key usage " +
366
"extension required for a TSA server",
367
ValidatorException.T_EE_EXTENSIONS, cert);
368
}
369
370
if (checkEKU(cert, exts, OID_EKU_TIME_STAMPING) == false) {
371
throw new ValidatorException
372
("Extended key usage does not permit use for TSA server",
373
ValidatorException.T_EE_EXTENSIONS, cert);
374
}
375
376
// remove extensions we checked
377
exts.remove(SimpleValidator.OID_KEY_USAGE);
378
exts.remove(SimpleValidator.OID_EXTENDED_KEY_USAGE);
379
}
380
}
381
382