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/DistributionPointFetcher.java
38923 views
1
/*
2
* Copyright (c) 2002, 2017, 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.*;
29
import java.net.URI;
30
import java.security.*;
31
import java.security.cert.*;
32
import javax.security.auth.x500.X500Principal;
33
import java.util.*;
34
35
import sun.security.util.Debug;
36
import sun.security.validator.Validator;
37
import static sun.security.x509.PKIXExtensions.*;
38
import sun.security.x509.*;
39
40
/**
41
* Class to obtain CRLs via the CRLDistributionPoints extension.
42
* Note that the functionality of this class must be explicitly enabled
43
* via a system property, see the USE_CRLDP variable below.
44
*
45
* This class uses the URICertStore class to fetch CRLs. The URICertStore
46
* class also implements CRL caching: see the class description for more
47
* information.
48
*
49
* @author Andreas Sterbenz
50
* @author Sean Mullan
51
* @since 1.4.2
52
*/
53
public class DistributionPointFetcher {
54
55
private static final Debug debug = Debug.getInstance("certpath");
56
57
private static final boolean[] ALL_REASONS =
58
{true, true, true, true, true, true, true, true, true};
59
60
/**
61
* Private instantiation only.
62
*/
63
private DistributionPointFetcher() {}
64
65
/**
66
* Return the X509CRLs matching this selector. The selector must be
67
* an X509CRLSelector with certificateChecking set.
68
*/
69
public static Collection<X509CRL> getCRLs(X509CRLSelector selector,
70
boolean signFlag, PublicKey prevKey, String provider,
71
List<CertStore> certStores, boolean[] reasonsMask,
72
Set<TrustAnchor> trustAnchors, Date validity, String variant)
73
throws CertStoreException
74
{
75
return getCRLs(selector, signFlag, prevKey, null, provider, certStores,
76
reasonsMask, trustAnchors, validity, variant, null);
77
}
78
/**
79
* Return the X509CRLs matching this selector. The selector must be
80
* an X509CRLSelector with certificateChecking set.
81
*/
82
// Called by com.sun.deploy.security.RevocationChecker
83
public static Collection<X509CRL> getCRLs(X509CRLSelector selector,
84
boolean signFlag,
85
PublicKey prevKey,
86
String provider,
87
List<CertStore> certStores,
88
boolean[] reasonsMask,
89
Set<TrustAnchor> trustAnchors,
90
Date validity)
91
throws CertStoreException
92
{
93
if (trustAnchors.isEmpty()) {
94
throw new CertStoreException(
95
"at least one TrustAnchor must be specified");
96
}
97
TrustAnchor anchor = trustAnchors.iterator().next();
98
return getCRLs(selector, signFlag, prevKey, null, provider, certStores,
99
reasonsMask, trustAnchors, validity,
100
Validator.VAR_PLUGIN_CODE_SIGNING, anchor);
101
}
102
103
/**
104
* Return the X509CRLs matching this selector. The selector must be
105
* an X509CRLSelector with certificateChecking set.
106
*/
107
public static Collection<X509CRL> getCRLs(X509CRLSelector selector,
108
boolean signFlag,
109
PublicKey prevKey,
110
X509Certificate prevCert,
111
String provider,
112
List<CertStore> certStores,
113
boolean[] reasonsMask,
114
Set<TrustAnchor> trustAnchors,
115
Date validity,
116
String variant,
117
TrustAnchor anchor)
118
throws CertStoreException
119
{
120
X509Certificate cert = selector.getCertificateChecking();
121
if (cert == null) {
122
return Collections.emptySet();
123
}
124
try {
125
X509CertImpl certImpl = X509CertImpl.toImpl(cert);
126
if (debug != null) {
127
debug.println("DistributionPointFetcher.getCRLs: Checking "
128
+ "CRLDPs for " + certImpl.getSubjectX500Principal());
129
}
130
CRLDistributionPointsExtension ext =
131
certImpl.getCRLDistributionPointsExtension();
132
if (ext == null) {
133
if (debug != null) {
134
debug.println("No CRLDP ext");
135
}
136
return Collections.emptySet();
137
}
138
List<DistributionPoint> points =
139
ext.get(CRLDistributionPointsExtension.POINTS);
140
Set<X509CRL> results = new HashSet<>();
141
for (Iterator<DistributionPoint> t = points.iterator();
142
t.hasNext() && !Arrays.equals(reasonsMask, ALL_REASONS); ) {
143
DistributionPoint point = t.next();
144
Collection<X509CRL> crls = getCRLs(selector, certImpl,
145
point, reasonsMask, signFlag, prevKey, prevCert, provider,
146
certStores, trustAnchors, validity, variant, anchor);
147
results.addAll(crls);
148
}
149
if (debug != null) {
150
debug.println("Returning " + results.size() + " CRLs");
151
}
152
return results;
153
} catch (CertificateException | IOException e) {
154
return Collections.emptySet();
155
}
156
}
157
158
/**
159
* Download CRLs from the given distribution point, verify and return them.
160
* See the top of the class for current limitations.
161
*
162
* @throws CertStoreException if there is an error retrieving the CRLs
163
* from one of the GeneralNames and no other CRLs are retrieved from
164
* the other GeneralNames. If more than one GeneralName throws an
165
* exception then the one from the last GeneralName is thrown.
166
*/
167
private static Collection<X509CRL> getCRLs(X509CRLSelector selector,
168
X509CertImpl certImpl, DistributionPoint point, boolean[] reasonsMask,
169
boolean signFlag, PublicKey prevKey, X509Certificate prevCert,
170
String provider, List<CertStore> certStores,
171
Set<TrustAnchor> trustAnchors, Date validity, String variant,
172
TrustAnchor anchor)
173
throws CertStoreException {
174
175
// check for full name
176
GeneralNames fullName = point.getFullName();
177
if (fullName == null) {
178
// check for relative name
179
RDN relativeName = point.getRelativeName();
180
if (relativeName == null) {
181
return Collections.emptySet();
182
}
183
try {
184
GeneralNames crlIssuers = point.getCRLIssuer();
185
if (crlIssuers == null) {
186
fullName = getFullNames
187
((X500Name) certImpl.getIssuerDN(), relativeName);
188
} else {
189
// should only be one CRL Issuer
190
if (crlIssuers.size() != 1) {
191
return Collections.emptySet();
192
} else {
193
fullName = getFullNames
194
((X500Name) crlIssuers.get(0).getName(), relativeName);
195
}
196
}
197
} catch (IOException ioe) {
198
return Collections.emptySet();
199
}
200
}
201
Collection<X509CRL> possibleCRLs = new ArrayList<>();
202
CertStoreException savedCSE = null;
203
for (Iterator<GeneralName> t = fullName.iterator(); t.hasNext(); ) {
204
try {
205
GeneralName name = t.next();
206
if (name.getType() == GeneralNameInterface.NAME_DIRECTORY) {
207
X500Name x500Name = (X500Name) name.getName();
208
possibleCRLs.addAll(
209
getCRLs(x500Name, certImpl.getIssuerX500Principal(),
210
certStores));
211
} else if (name.getType() == GeneralNameInterface.NAME_URI) {
212
URIName uriName = (URIName)name.getName();
213
X509CRL crl = getCRL(uriName);
214
if (crl != null) {
215
possibleCRLs.add(crl);
216
}
217
}
218
} catch (CertStoreException cse) {
219
savedCSE = cse;
220
}
221
}
222
// only throw CertStoreException if no CRLs are retrieved
223
if (possibleCRLs.isEmpty() && savedCSE != null) {
224
throw savedCSE;
225
}
226
227
Collection<X509CRL> crls = new ArrayList<>(2);
228
for (X509CRL crl : possibleCRLs) {
229
try {
230
// make sure issuer is not set
231
// we check the issuer in verifyCRLs method
232
selector.setIssuerNames(null);
233
if (selector.match(crl) && verifyCRL(certImpl, point, crl,
234
reasonsMask, signFlag, prevKey, prevCert, provider,
235
trustAnchors, certStores, validity, variant, anchor)) {
236
crls.add(crl);
237
}
238
} catch (IOException | CRLException e) {
239
// don't add the CRL
240
if (debug != null) {
241
debug.println("Exception verifying CRL: " + e.getMessage());
242
e.printStackTrace();
243
}
244
}
245
}
246
return crls;
247
}
248
249
/**
250
* Download CRL from given URI.
251
*/
252
private static X509CRL getCRL(URIName name) throws CertStoreException {
253
URI uri = name.getURI();
254
if (debug != null) {
255
debug.println("Trying to fetch CRL from DP " + uri);
256
}
257
CertStore ucs = null;
258
try {
259
ucs = URICertStore.getInstance
260
(new URICertStore.URICertStoreParameters(uri));
261
} catch (InvalidAlgorithmParameterException |
262
NoSuchAlgorithmException e) {
263
if (debug != null) {
264
debug.println("Can't create URICertStore: " + e.getMessage());
265
}
266
return null;
267
}
268
269
Collection<? extends CRL> crls = ucs.getCRLs(null);
270
if (crls.isEmpty()) {
271
return null;
272
} else {
273
return (X509CRL) crls.iterator().next();
274
}
275
}
276
277
/**
278
* Fetch CRLs from certStores.
279
*
280
* @throws CertStoreException if there is an error retrieving the CRLs from
281
* one of the CertStores and no other CRLs are retrieved from
282
* the other CertStores. If more than one CertStore throws an
283
* exception then the one from the last CertStore is thrown.
284
*/
285
private static Collection<X509CRL> getCRLs(X500Name name,
286
X500Principal certIssuer,
287
List<CertStore> certStores)
288
throws CertStoreException
289
{
290
if (debug != null) {
291
debug.println("Trying to fetch CRL from DP " + name);
292
}
293
X509CRLSelector xcs = new X509CRLSelector();
294
xcs.addIssuer(name.asX500Principal());
295
xcs.addIssuer(certIssuer);
296
Collection<X509CRL> crls = new ArrayList<>();
297
CertStoreException savedCSE = null;
298
for (CertStore store : certStores) {
299
try {
300
for (CRL crl : store.getCRLs(xcs)) {
301
crls.add((X509CRL)crl);
302
}
303
} catch (CertStoreException cse) {
304
if (debug != null) {
305
debug.println("Exception while retrieving " +
306
"CRLs: " + cse);
307
cse.printStackTrace();
308
}
309
savedCSE = new PKIX.CertStoreTypeException(store.getType(),cse);
310
}
311
}
312
// only throw CertStoreException if no CRLs are retrieved
313
if (crls.isEmpty() && savedCSE != null) {
314
throw savedCSE;
315
} else {
316
return crls;
317
}
318
}
319
320
/**
321
* Verifies a CRL for the given certificate's Distribution Point to
322
* ensure it is appropriate for checking the revocation status.
323
*
324
* @param certImpl the certificate whose revocation status is being checked
325
* @param point one of the distribution points of the certificate
326
* @param crl the CRL
327
* @param reasonsMask the interim reasons mask
328
* @param signFlag true if prevKey can be used to verify the CRL
329
* @param prevKey the public key that verifies the certificate's signature
330
* @param prevCert the certificate whose public key verifies
331
* {@code certImpl}'s signature
332
* @param provider the Signature provider to use
333
* @param trustAnchors a {@code Set} of {@code TrustAnchor}s
334
* @param certStores a {@code List} of {@code CertStore}s to be used in
335
* finding certificates and CRLs
336
* @param validity the time for which the validity of the CRL issuer's
337
* certification path should be determined
338
* @return true if ok, false if not
339
*/
340
static boolean verifyCRL(X509CertImpl certImpl, DistributionPoint point,
341
X509CRL crl, boolean[] reasonsMask, boolean signFlag,
342
PublicKey prevKey, X509Certificate prevCert, String provider,
343
Set<TrustAnchor> trustAnchors, List<CertStore> certStores,
344
Date validity, String variant, TrustAnchor anchor)
345
throws CRLException, IOException {
346
347
if (debug != null) {
348
debug.println("DistributionPointFetcher.verifyCRL: " +
349
"checking revocation status for" +
350
"\n SN: " + Debug.toHexString(certImpl.getSerialNumber()) +
351
"\n Subject: " + certImpl.getSubjectX500Principal() +
352
"\n Issuer: " + certImpl.getIssuerX500Principal());
353
}
354
355
boolean indirectCRL = false;
356
X509CRLImpl crlImpl = X509CRLImpl.toImpl(crl);
357
IssuingDistributionPointExtension idpExt =
358
crlImpl.getIssuingDistributionPointExtension();
359
X500Name certIssuer = (X500Name) certImpl.getIssuerDN();
360
X500Name crlIssuer = (X500Name) crlImpl.getIssuerDN();
361
362
// if crlIssuer is set, verify that it matches the issuer of the
363
// CRL and the CRL contains an IDP extension with the indirectCRL
364
// boolean asserted. Otherwise, verify that the CRL issuer matches the
365
// certificate issuer.
366
GeneralNames pointCrlIssuers = point.getCRLIssuer();
367
X500Name pointCrlIssuer = null;
368
if (pointCrlIssuers != null) {
369
if (idpExt == null ||
370
((Boolean) idpExt.get
371
(IssuingDistributionPointExtension.INDIRECT_CRL)).equals
372
(Boolean.FALSE)) {
373
return false;
374
}
375
boolean match = false;
376
for (Iterator<GeneralName> t = pointCrlIssuers.iterator();
377
!match && t.hasNext(); ) {
378
GeneralNameInterface name = t.next().getName();
379
if (crlIssuer.equals(name) == true) {
380
pointCrlIssuer = (X500Name) name;
381
match = true;
382
}
383
}
384
if (match == false) {
385
return false;
386
}
387
388
// we accept the case that a CRL issuer provide status
389
// information for itself.
390
if (issues(certImpl, crlImpl, provider)) {
391
// reset the public key used to verify the CRL's signature
392
prevKey = certImpl.getPublicKey();
393
} else {
394
indirectCRL = true;
395
}
396
} else if (crlIssuer.equals(certIssuer) == false) {
397
if (debug != null) {
398
debug.println("crl issuer does not equal cert issuer.\n" +
399
"crl issuer: " + crlIssuer + "\n" +
400
"cert issuer: " + certIssuer);
401
}
402
return false;
403
} else {
404
// in case of self-issued indirect CRL issuer.
405
KeyIdentifier certAKID = certImpl.getAuthKeyId();
406
KeyIdentifier crlAKID = crlImpl.getAuthKeyId();
407
408
if (certAKID == null || crlAKID == null) {
409
// cannot recognize indirect CRL without AKID
410
411
// we accept the case that a CRL issuer provide status
412
// information for itself.
413
if (issues(certImpl, crlImpl, provider)) {
414
// reset the public key used to verify the CRL's signature
415
prevKey = certImpl.getPublicKey();
416
}
417
} else if (!certAKID.equals(crlAKID)) {
418
// we accept the case that a CRL issuer provide status
419
// information for itself.
420
if (issues(certImpl, crlImpl, provider)) {
421
// reset the public key used to verify the CRL's signature
422
prevKey = certImpl.getPublicKey();
423
} else {
424
indirectCRL = true;
425
}
426
}
427
}
428
429
if (!indirectCRL && !signFlag) {
430
// cert's key cannot be used to verify the CRL
431
return false;
432
}
433
434
if (idpExt != null) {
435
DistributionPointName idpPoint = (DistributionPointName)
436
idpExt.get(IssuingDistributionPointExtension.POINT);
437
if (idpPoint != null) {
438
GeneralNames idpNames = idpPoint.getFullName();
439
if (idpNames == null) {
440
RDN relativeName = idpPoint.getRelativeName();
441
if (relativeName == null) {
442
if (debug != null) {
443
debug.println("IDP must be relative or full DN");
444
}
445
return false;
446
}
447
if (debug != null) {
448
debug.println("IDP relativeName:" + relativeName);
449
}
450
idpNames = getFullNames(crlIssuer, relativeName);
451
}
452
// if the DP name is present in the IDP CRL extension and the
453
// DP field is present in the DP, then verify that one of the
454
// names in the IDP matches one of the names in the DP
455
if (point.getFullName() != null ||
456
point.getRelativeName() != null) {
457
GeneralNames pointNames = point.getFullName();
458
if (pointNames == null) {
459
RDN relativeName = point.getRelativeName();
460
if (relativeName == null) {
461
if (debug != null) {
462
debug.println("DP must be relative or full DN");
463
}
464
return false;
465
}
466
if (debug != null) {
467
debug.println("DP relativeName:" + relativeName);
468
}
469
if (indirectCRL) {
470
if (pointCrlIssuers.size() != 1) {
471
// RFC 5280: there must be only 1 CRL issuer
472
// name when relativeName is present
473
if (debug != null) {
474
debug.println("must only be one CRL " +
475
"issuer when relative name present");
476
}
477
return false;
478
}
479
pointNames = getFullNames
480
(pointCrlIssuer, relativeName);
481
} else {
482
pointNames = getFullNames(certIssuer, relativeName);
483
}
484
}
485
boolean match = false;
486
for (Iterator<GeneralName> i = idpNames.iterator();
487
!match && i.hasNext(); ) {
488
GeneralNameInterface idpName = i.next().getName();
489
if (debug != null) {
490
debug.println("idpName: " + idpName);
491
}
492
for (Iterator<GeneralName> p = pointNames.iterator();
493
!match && p.hasNext(); ) {
494
GeneralNameInterface pointName = p.next().getName();
495
if (debug != null) {
496
debug.println("pointName: " + pointName);
497
}
498
match = idpName.equals(pointName);
499
}
500
}
501
if (!match) {
502
if (debug != null) {
503
debug.println("IDP name does not match DP name");
504
}
505
return false;
506
}
507
// if the DP name is present in the IDP CRL extension and the
508
// DP field is absent from the DP, then verify that one of the
509
// names in the IDP matches one of the names in the crlIssuer
510
// field of the DP
511
} else {
512
// verify that one of the names in the IDP matches one of
513
// the names in the cRLIssuer of the cert's DP
514
boolean match = false;
515
for (Iterator<GeneralName> t = pointCrlIssuers.iterator();
516
!match && t.hasNext(); ) {
517
GeneralNameInterface crlIssuerName = t.next().getName();
518
for (Iterator<GeneralName> i = idpNames.iterator();
519
!match && i.hasNext(); ) {
520
GeneralNameInterface idpName = i.next().getName();
521
match = crlIssuerName.equals(idpName);
522
}
523
}
524
if (!match) {
525
return false;
526
}
527
}
528
}
529
530
// if the onlyContainsUserCerts boolean is asserted, verify that the
531
// cert is not a CA cert
532
Boolean b = (Boolean)
533
idpExt.get(IssuingDistributionPointExtension.ONLY_USER_CERTS);
534
if (b.equals(Boolean.TRUE) && certImpl.getBasicConstraints() != -1) {
535
if (debug != null) {
536
debug.println("cert must be a EE cert");
537
}
538
return false;
539
}
540
541
// if the onlyContainsCACerts boolean is asserted, verify that the
542
// cert is a CA cert
543
b = (Boolean)
544
idpExt.get(IssuingDistributionPointExtension.ONLY_CA_CERTS);
545
if (b.equals(Boolean.TRUE) && certImpl.getBasicConstraints() == -1) {
546
if (debug != null) {
547
debug.println("cert must be a CA cert");
548
}
549
return false;
550
}
551
552
// verify that the onlyContainsAttributeCerts boolean is not
553
// asserted
554
b = (Boolean) idpExt.get
555
(IssuingDistributionPointExtension.ONLY_ATTRIBUTE_CERTS);
556
if (b.equals(Boolean.TRUE)) {
557
if (debug != null) {
558
debug.println("cert must not be an AA cert");
559
}
560
return false;
561
}
562
}
563
564
// compute interim reasons mask
565
boolean[] interimReasonsMask = new boolean[9];
566
ReasonFlags reasons = null;
567
if (idpExt != null) {
568
reasons = (ReasonFlags)
569
idpExt.get(IssuingDistributionPointExtension.REASONS);
570
}
571
572
boolean[] pointReasonFlags = point.getReasonFlags();
573
if (reasons != null) {
574
if (pointReasonFlags != null) {
575
// set interim reasons mask to the intersection of
576
// reasons in the DP and onlySomeReasons in the IDP
577
boolean[] idpReasonFlags = reasons.getFlags();
578
for (int i = 0; i < interimReasonsMask.length; i++) {
579
interimReasonsMask[i] =
580
(i < idpReasonFlags.length && idpReasonFlags[i]) &&
581
(i < pointReasonFlags.length && pointReasonFlags[i]);
582
}
583
} else {
584
// set interim reasons mask to the value of
585
// onlySomeReasons in the IDP (and clone it since we may
586
// modify it)
587
interimReasonsMask = reasons.getFlags().clone();
588
}
589
} else if (idpExt == null || reasons == null) {
590
if (pointReasonFlags != null) {
591
// set interim reasons mask to the value of DP reasons
592
interimReasonsMask = pointReasonFlags.clone();
593
} else {
594
// set interim reasons mask to the special value all-reasons
595
Arrays.fill(interimReasonsMask, true);
596
}
597
}
598
599
// verify that interim reasons mask includes one or more reasons
600
// not included in the reasons mask
601
boolean oneOrMore = false;
602
for (int i = 0; i < interimReasonsMask.length && !oneOrMore; i++) {
603
if (interimReasonsMask[i] &&
604
!(i < reasonsMask.length && reasonsMask[i]))
605
{
606
oneOrMore = true;
607
}
608
}
609
if (!oneOrMore) {
610
return false;
611
}
612
613
// Obtain and validate the certification path for the complete
614
// CRL issuer (if indirect CRL). If a key usage extension is present
615
// in the CRL issuer's certificate, verify that the cRLSign bit is set.
616
if (indirectCRL) {
617
X509CertSelector certSel = new X509CertSelector();
618
certSel.setSubject(crlIssuer.asX500Principal());
619
boolean[] crlSign = {false,false,false,false,false,false,true};
620
certSel.setKeyUsage(crlSign);
621
622
// Currently by default, forward builder does not enable
623
// subject/authority key identifier identifying for target
624
// certificate, instead, it only compares the CRL issuer and
625
// the target certificate subject. If the certificate of the
626
// delegated CRL issuer is a self-issued certificate, the
627
// builder is unable to find the proper CRL issuer by issuer
628
// name only, there is a potential dead loop on finding the
629
// proper issuer. It is of great help to narrow the target
630
// scope down to aware of authority key identifiers in the
631
// selector, for the purposes of breaking the dead loop.
632
AuthorityKeyIdentifierExtension akidext =
633
crlImpl.getAuthKeyIdExtension();
634
if (akidext != null) {
635
byte[] kid = akidext.getEncodedKeyIdentifier();
636
if (kid != null) {
637
certSel.setSubjectKeyIdentifier(kid);
638
}
639
640
SerialNumber asn = (SerialNumber)akidext.get(
641
AuthorityKeyIdentifierExtension.SERIAL_NUMBER);
642
if (asn != null) {
643
certSel.setSerialNumber(asn.getNumber());
644
}
645
// the subject criterion will be set by builder automatically.
646
}
647
648
// By now, we have validated the previous certificate, so we can
649
// trust it during the validation of the CRL issuer.
650
// In addition to the performance improvement, another benefit is to
651
// break the dead loop while looking for the issuer back and forth
652
// between the delegated self-issued certificate and its issuer.
653
Set<TrustAnchor> newTrustAnchors = new HashSet<>(trustAnchors);
654
655
if (prevKey != null) {
656
// Add the previous certificate as a trust anchor.
657
// If prevCert is not null, we want to construct a TrustAnchor
658
// using the cert object because when the certpath for the CRL
659
// is built later, the CertSelector will make comparisons with
660
// the TrustAnchor's trustedCert member rather than its pubKey.
661
TrustAnchor temporary;
662
if (prevCert != null) {
663
temporary = new TrustAnchor(prevCert, null);
664
} else {
665
X500Principal principal = certImpl.getIssuerX500Principal();
666
temporary = new TrustAnchor(principal, prevKey, null);
667
}
668
newTrustAnchors.add(temporary);
669
}
670
671
PKIXBuilderParameters params = null;
672
try {
673
params = new PKIXBuilderParameters(newTrustAnchors, certSel);
674
} catch (InvalidAlgorithmParameterException iape) {
675
throw new CRLException(iape);
676
}
677
params.setCertStores(certStores);
678
params.setSigProvider(provider);
679
params.setDate(validity);
680
try {
681
CertPathBuilder builder = CertPathBuilder.getInstance("PKIX");
682
PKIXCertPathBuilderResult result =
683
(PKIXCertPathBuilderResult) builder.build(params);
684
prevKey = result.getPublicKey();
685
} catch (GeneralSecurityException e) {
686
throw new CRLException(e);
687
}
688
}
689
690
// check the crl signature algorithm
691
try {
692
AlgorithmChecker.check(prevKey, crl, variant, anchor);
693
} catch (CertPathValidatorException cpve) {
694
if (debug != null) {
695
debug.println("CRL signature algorithm check failed: " + cpve);
696
}
697
return false;
698
}
699
700
// validate the signature on the CRL
701
try {
702
crl.verify(prevKey, provider);
703
} catch (GeneralSecurityException e) {
704
if (debug != null) {
705
debug.println("CRL signature failed to verify");
706
}
707
return false;
708
}
709
710
// reject CRL if any unresolved critical extensions remain in the CRL.
711
Set<String> unresCritExts = crl.getCriticalExtensionOIDs();
712
// remove any that we have processed
713
if (unresCritExts != null) {
714
unresCritExts.remove(IssuingDistributionPoint_Id.toString());
715
if (!unresCritExts.isEmpty()) {
716
if (debug != null) {
717
debug.println("Unrecognized critical extension(s) in CRL: "
718
+ unresCritExts);
719
for (String ext : unresCritExts) {
720
debug.println(ext);
721
}
722
}
723
return false;
724
}
725
}
726
727
// update reasonsMask
728
for (int i = 0; i < reasonsMask.length; i++) {
729
reasonsMask[i] = reasonsMask[i] ||
730
(i < interimReasonsMask.length && interimReasonsMask[i]);
731
}
732
733
return true;
734
}
735
736
/**
737
* Append relative name to the issuer name and return a new
738
* GeneralNames object.
739
*/
740
private static GeneralNames getFullNames(X500Name issuer, RDN rdn)
741
throws IOException
742
{
743
List<RDN> rdns = new ArrayList<>(issuer.rdns());
744
rdns.add(rdn);
745
X500Name fullName = new X500Name(rdns.toArray(new RDN[0]));
746
GeneralNames fullNames = new GeneralNames();
747
fullNames.add(new GeneralName(fullName));
748
return fullNames;
749
}
750
751
/**
752
* Verifies whether a CRL is issued by a certain certificate
753
*
754
* @param cert the certificate
755
* @param crl the CRL to be verified
756
* @param provider the name of the signature provider
757
*/
758
private static boolean issues(X509CertImpl cert, X509CRLImpl crl,
759
String provider) throws IOException
760
{
761
boolean matched = false;
762
763
AdaptableX509CertSelector issuerSelector =
764
new AdaptableX509CertSelector();
765
766
// check certificate's key usage
767
boolean[] usages = cert.getKeyUsage();
768
if (usages != null) {
769
usages[6] = true; // cRLSign
770
issuerSelector.setKeyUsage(usages);
771
}
772
773
// check certificate's subject
774
X500Principal crlIssuer = crl.getIssuerX500Principal();
775
issuerSelector.setSubject(crlIssuer);
776
777
/*
778
* Facilitate certification path construction with authority
779
* key identifier and subject key identifier.
780
*
781
* In practice, conforming CAs MUST use the key identifier method,
782
* and MUST include authority key identifier extension in all CRLs
783
* issued. [section 5.2.1, RFC 2459]
784
*/
785
AuthorityKeyIdentifierExtension crlAKID = crl.getAuthKeyIdExtension();
786
issuerSelector.setSkiAndSerialNumber(crlAKID);
787
788
matched = issuerSelector.match(cert);
789
790
// if AKID is unreliable, verify the CRL signature with the cert
791
if (matched && (crlAKID == null ||
792
cert.getAuthorityKeyIdentifierExtension() == null)) {
793
try {
794
crl.verify(cert.getPublicKey(), provider);
795
matched = true;
796
} catch (GeneralSecurityException e) {
797
matched = false;
798
}
799
}
800
801
return matched;
802
}
803
}
804
805