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