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/util/DisabledAlgorithmConstraints.java
38830 views
1
/*
2
* Copyright (c) 2010, 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.util;
27
28
import sun.security.validator.Validator;
29
30
import java.io.ByteArrayOutputStream;
31
import java.io.PrintStream;
32
import java.security.AlgorithmParameters;
33
import java.security.CryptoPrimitive;
34
import java.security.Key;
35
import java.security.cert.CertPathValidatorException;
36
import java.security.cert.CertPathValidatorException.BasicReason;
37
import java.security.interfaces.ECKey;
38
import java.security.spec.AlgorithmParameterSpec;
39
import java.security.spec.InvalidParameterSpecException;
40
import java.security.spec.MGF1ParameterSpec;
41
import java.security.spec.PSSParameterSpec;
42
import java.text.SimpleDateFormat;
43
import java.util.ArrayList;
44
import java.util.Arrays;
45
import java.util.Calendar;
46
import java.util.Date;
47
import java.util.HashMap;
48
import java.util.HashSet;
49
import java.util.List;
50
import java.util.Locale;
51
import java.util.Map;
52
import java.util.Set;
53
import java.util.Collection;
54
import java.util.Collections;
55
import java.util.StringTokenizer;
56
import java.util.TimeZone;
57
import java.util.regex.Pattern;
58
import java.util.regex.Matcher;
59
60
/**
61
* Algorithm constraints for disabled algorithms property
62
*
63
* See the "jdk.certpath.disabledAlgorithms" specification in java.security
64
* for the syntax of the disabled algorithm string.
65
*/
66
public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
67
private static final Debug debug = Debug.getInstance("certpath");
68
69
// Disabled algorithm security property for certificate path
70
public static final String PROPERTY_CERTPATH_DISABLED_ALGS =
71
"jdk.certpath.disabledAlgorithms";
72
73
// Legacy algorithm security property for certificate path and jar
74
public static final String PROPERTY_SECURITY_LEGACY_ALGS =
75
"jdk.security.legacyAlgorithms";
76
77
// Disabled algorithm security property for TLS
78
public static final String PROPERTY_TLS_DISABLED_ALGS =
79
"jdk.tls.disabledAlgorithms";
80
81
// Disabled algorithm security property for jar
82
public static final String PROPERTY_JAR_DISABLED_ALGS =
83
"jdk.jar.disabledAlgorithms";
84
85
// Property for disabled EC named curves
86
private static final String PROPERTY_DISABLED_EC_CURVES =
87
"jdk.disabled.namedCurves";
88
89
private static class CertPathHolder {
90
static final DisabledAlgorithmConstraints CONSTRAINTS =
91
new DisabledAlgorithmConstraints(PROPERTY_CERTPATH_DISABLED_ALGS);
92
}
93
94
private static class JarHolder {
95
static final DisabledAlgorithmConstraints CONSTRAINTS =
96
new DisabledAlgorithmConstraints(PROPERTY_JAR_DISABLED_ALGS);
97
}
98
99
private final List<String> disabledAlgorithms;
100
private final Constraints algorithmConstraints;
101
102
public static DisabledAlgorithmConstraints certPathConstraints() {
103
return CertPathHolder.CONSTRAINTS;
104
}
105
106
public static DisabledAlgorithmConstraints jarConstraints() {
107
return JarHolder.CONSTRAINTS;
108
}
109
110
/**
111
* Initialize algorithm constraints with the specified security property.
112
*
113
* @param propertyName the security property name that define the disabled
114
* algorithm constraints
115
*/
116
public DisabledAlgorithmConstraints(String propertyName) {
117
this(propertyName, new AlgorithmDecomposer());
118
}
119
120
/**
121
* Initialize algorithm constraints with the specified security property
122
* for a specific usage type.
123
*
124
* @param propertyName the security property name that define the disabled
125
* algorithm constraints
126
* @param decomposer an alternate AlgorithmDecomposer.
127
*/
128
public DisabledAlgorithmConstraints(String propertyName,
129
AlgorithmDecomposer decomposer) {
130
super(decomposer);
131
disabledAlgorithms = getAlgorithms(propertyName);
132
133
// Check for alias
134
int ecindex = -1, i = 0;
135
for (String s : disabledAlgorithms) {
136
if (s.regionMatches(true, 0,"include ", 0, 8)) {
137
if (s.regionMatches(true, 8, PROPERTY_DISABLED_EC_CURVES, 0,
138
PROPERTY_DISABLED_EC_CURVES.length())) {
139
ecindex = i;
140
break;
141
}
142
}
143
i++;
144
}
145
if (ecindex > -1) {
146
disabledAlgorithms.remove(ecindex);
147
disabledAlgorithms.addAll(ecindex,
148
getAlgorithms(PROPERTY_DISABLED_EC_CURVES));
149
}
150
algorithmConstraints = new Constraints(propertyName, disabledAlgorithms);
151
}
152
153
/*
154
* This only checks if the algorithm has been completely disabled. If
155
* there are keysize or other limit, this method allow the algorithm.
156
*/
157
@Override
158
public final boolean permits(Set<CryptoPrimitive> primitives,
159
String algorithm, AlgorithmParameters parameters) {
160
if (!checkAlgorithm(disabledAlgorithms, algorithm, decomposer)) {
161
return false;
162
}
163
164
if (parameters != null) {
165
return algorithmConstraints.permits(algorithm, parameters);
166
}
167
168
return true;
169
}
170
171
/*
172
* Checks if the key algorithm has been disabled or constraints have been
173
* placed on the key.
174
*/
175
@Override
176
public final boolean permits(Set<CryptoPrimitive> primitives, Key key) {
177
return checkConstraints(primitives, "", key, null);
178
}
179
180
/*
181
* Checks if the key algorithm has been disabled or if constraints have
182
* been placed on the key.
183
*/
184
@Override
185
public final boolean permits(Set<CryptoPrimitive> primitives,
186
String algorithm, Key key, AlgorithmParameters parameters) {
187
188
if (algorithm == null || algorithm.length() == 0) {
189
throw new IllegalArgumentException("No algorithm name specified");
190
}
191
192
return checkConstraints(primitives, algorithm, key, parameters);
193
}
194
195
public final void permits(String algorithm, AlgorithmParameters ap,
196
ConstraintsParameters cp) throws CertPathValidatorException {
197
198
permits(algorithm, cp);
199
if (ap != null) {
200
permits(ap, cp);
201
}
202
}
203
204
private void permits(AlgorithmParameters ap, ConstraintsParameters cp)
205
throws CertPathValidatorException {
206
207
switch (ap.getAlgorithm().toUpperCase(Locale.ENGLISH)) {
208
case "RSASSA-PSS":
209
permitsPSSParams(ap, cp);
210
break;
211
default:
212
// unknown algorithm, just ignore
213
}
214
}
215
216
private void permitsPSSParams(AlgorithmParameters ap,
217
ConstraintsParameters cp) throws CertPathValidatorException {
218
219
try {
220
PSSParameterSpec pssParams =
221
ap.getParameterSpec(PSSParameterSpec.class);
222
String digestAlg = pssParams.getDigestAlgorithm();
223
permits(digestAlg, cp);
224
AlgorithmParameterSpec mgfParams = pssParams.getMGFParameters();
225
if (mgfParams instanceof MGF1ParameterSpec) {
226
String mgfDigestAlg =
227
((MGF1ParameterSpec)mgfParams).getDigestAlgorithm();
228
if (!mgfDigestAlg.equalsIgnoreCase(digestAlg)) {
229
permits(mgfDigestAlg, cp);
230
}
231
}
232
} catch (InvalidParameterSpecException ipse) {
233
// ignore
234
}
235
}
236
237
public final void permits(String algorithm, ConstraintsParameters cp)
238
throws CertPathValidatorException {
239
240
// Check if named curves in the key are disabled.
241
for (Key key : cp.getKeys()) {
242
for (String curve : getNamedCurveFromKey(key)) {
243
if (!checkAlgorithm(disabledAlgorithms, curve, decomposer)) {
244
throw new CertPathValidatorException(
245
"Algorithm constraints check failed on disabled " +
246
"algorithm: " + curve,
247
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
248
}
249
}
250
}
251
252
algorithmConstraints.permits(algorithm, cp);
253
}
254
255
private static List<String> getNamedCurveFromKey(Key key) {
256
if (key instanceof ECKey) {
257
NamedCurve nc = CurveDB.lookup(((ECKey)key).getParams());
258
return (nc == null ? Collections.emptyList()
259
: Arrays.asList(CurveDB.getNamesByOID(nc.getObjectId())));
260
} else {
261
return Collections.emptyList();
262
}
263
}
264
265
// Check algorithm constraints with key and algorithm
266
private boolean checkConstraints(Set<CryptoPrimitive> primitives,
267
String algorithm, Key key, AlgorithmParameters parameters) {
268
269
// check the key parameter, it cannot be null.
270
if (key == null) {
271
throw new IllegalArgumentException("The key cannot be null");
272
}
273
274
// check the signature algorithm with parameters
275
if (algorithm != null && algorithm.length() != 0) {
276
if (!permits(primitives, algorithm, parameters)) {
277
return false;
278
}
279
}
280
281
// check the key algorithm
282
if (!permits(primitives, key.getAlgorithm(), null)) {
283
return false;
284
}
285
286
// If this is an elliptic curve, check if it is disabled
287
for (String curve : getNamedCurveFromKey(key)) {
288
if (!permits(primitives, curve, null)) {
289
return false;
290
}
291
}
292
293
// check the key constraints
294
return algorithmConstraints.permits(key);
295
}
296
297
298
/**
299
* Key and Certificate Constraints
300
*
301
* The complete disabling of an algorithm is not handled by Constraints or
302
* Constraint classes. That is addressed with
303
* permit(Set<CryptoPrimitive>, String, AlgorithmParameters)
304
*
305
* When passing a Key to permit(), the boolean return values follow the
306
* same as the interface class AlgorithmConstraints.permit(). This is to
307
* maintain compatibility:
308
* 'true' means the operation is allowed.
309
* 'false' means it failed the constraints and is disallowed.
310
*
311
* When passing ConstraintsParameters through permit(), an exception
312
* will be thrown on a failure to better identify why the operation was
313
* disallowed.
314
*/
315
316
private static class Constraints {
317
private Map<String, List<Constraint>> constraintsMap = new HashMap<>();
318
319
private static class Holder {
320
private static final Pattern DENY_AFTER_PATTERN = Pattern.compile(
321
"denyAfter\\s+(\\d{4})-(\\d{2})-(\\d{2})");
322
}
323
324
public Constraints(String propertyName, List<String> constraintArray) {
325
for (String constraintEntry : constraintArray) {
326
if (constraintEntry == null || constraintEntry.isEmpty()) {
327
continue;
328
}
329
330
constraintEntry = constraintEntry.trim();
331
if (debug != null) {
332
debug.println("Constraints: " + constraintEntry);
333
}
334
335
// Check if constraint is a complete disabling of an
336
// algorithm or has conditions.
337
int space = constraintEntry.indexOf(' ');
338
String algorithm = AlgorithmDecomposer.hashName(
339
((space > 0 ? constraintEntry.substring(0, space) :
340
constraintEntry)));
341
List<Constraint> constraintList =
342
constraintsMap.getOrDefault(
343
algorithm.toUpperCase(Locale.ENGLISH),
344
new ArrayList<>(1));
345
346
// Consider the impact of algorithm aliases.
347
for (String alias : AlgorithmDecomposer.getAliases(algorithm)) {
348
constraintsMap.putIfAbsent(
349
alias.toUpperCase(Locale.ENGLISH), constraintList);
350
}
351
352
// If there is no whitespace, it is a algorithm name; however,
353
// if there is a whitespace, could be a multi-word EC curve too.
354
if (space <= 0 || CurveDB.lookup(constraintEntry) != null) {
355
constraintList.add(new DisabledConstraint(algorithm));
356
continue;
357
}
358
359
String policy = constraintEntry.substring(space + 1);
360
361
// Convert constraint conditions into Constraint classes
362
Constraint c, lastConstraint = null;
363
// Allow only one jdkCA entry per constraint entry
364
boolean jdkCALimit = false;
365
// Allow only one denyAfter entry per constraint entry
366
boolean denyAfterLimit = false;
367
368
for (String entry : policy.split("&")) {
369
entry = entry.trim();
370
371
Matcher matcher;
372
if (entry.startsWith("keySize")) {
373
if (debug != null) {
374
debug.println("Constraints set to keySize: " +
375
entry);
376
}
377
StringTokenizer tokens = new StringTokenizer(entry);
378
if (!"keySize".equals(tokens.nextToken())) {
379
throw new IllegalArgumentException("Error in " +
380
"security property. Constraint unknown: " +
381
entry);
382
}
383
c = new KeySizeConstraint(algorithm,
384
KeySizeConstraint.Operator.of(tokens.nextToken()),
385
Integer.parseInt(tokens.nextToken()));
386
387
} else if (entry.equalsIgnoreCase("jdkCA")) {
388
if (debug != null) {
389
debug.println("Constraints set to jdkCA.");
390
}
391
if (jdkCALimit) {
392
throw new IllegalArgumentException("Only one " +
393
"jdkCA entry allowed in property. " +
394
"Constraint: " + constraintEntry);
395
}
396
c = new jdkCAConstraint(algorithm);
397
jdkCALimit = true;
398
399
} else if (entry.startsWith("denyAfter") &&
400
(matcher = Holder.DENY_AFTER_PATTERN.matcher(entry))
401
.matches()) {
402
if (debug != null) {
403
debug.println("Constraints set to denyAfter");
404
}
405
if (denyAfterLimit) {
406
throw new IllegalArgumentException("Only one " +
407
"denyAfter entry allowed in property. " +
408
"Constraint: " + constraintEntry);
409
}
410
int year = Integer.parseInt(matcher.group(1));
411
int month = Integer.parseInt(matcher.group(2));
412
int day = Integer.parseInt(matcher.group(3));
413
c = new DenyAfterConstraint(algorithm, year, month,
414
day);
415
denyAfterLimit = true;
416
} else if (entry.startsWith("usage")) {
417
String s[] = (entry.substring(5)).trim().split(" ");
418
c = new UsageConstraint(algorithm, s);
419
if (debug != null) {
420
debug.println("Constraints usage length is " + s.length);
421
}
422
} else {
423
throw new IllegalArgumentException("Error in security" +
424
" property. Constraint unknown: " + entry);
425
}
426
427
// Link multiple conditions for a single constraint
428
// into a linked list.
429
if (lastConstraint == null) {
430
constraintList.add(c);
431
} else {
432
lastConstraint.nextConstraint = c;
433
}
434
lastConstraint = c;
435
}
436
}
437
}
438
439
// Get applicable constraints based off the algorithm
440
private List<Constraint> getConstraints(String algorithm) {
441
return constraintsMap.get(algorithm.toUpperCase(Locale.ENGLISH));
442
}
443
444
// Check if KeySizeConstraints permit the specified key
445
public boolean permits(Key key) {
446
List<Constraint> list = getConstraints(key.getAlgorithm());
447
if (list == null) {
448
return true;
449
}
450
for (Constraint constraint : list) {
451
if (!constraint.permits(key)) {
452
if (debug != null) {
453
debug.println("Constraints: failed key size" +
454
"constraint check " + KeyUtil.getKeySize(key));
455
}
456
return false;
457
}
458
}
459
return true;
460
}
461
462
// Check if constraints permit this AlgorithmParameters.
463
public boolean permits(String algorithm, AlgorithmParameters aps) {
464
List<Constraint> list = getConstraints(algorithm);
465
if (list == null) {
466
return true;
467
}
468
469
for (Constraint constraint : list) {
470
if (!constraint.permits(aps)) {
471
if (debug != null) {
472
debug.println("Constraints: failed algorithm " +
473
"parameters constraint check " + aps);
474
}
475
476
return false;
477
}
478
}
479
480
return true;
481
}
482
483
public void permits(String algorithm, ConstraintsParameters cp)
484
throws CertPathValidatorException {
485
486
if (debug != null) {
487
debug.println("Constraints.permits(): " + algorithm + ", "
488
+ cp.toString());
489
}
490
491
// Get all signature algorithms to check for constraints
492
Set<String> algorithms = new HashSet<>();
493
if (algorithm != null) {
494
algorithms.addAll(AlgorithmDecomposer.decomposeOneHash(algorithm));
495
algorithms.add(algorithm);
496
}
497
498
for (Key key : cp.getKeys()) {
499
algorithms.add(key.getAlgorithm());
500
}
501
502
// Check all applicable constraints
503
for (String alg : algorithms) {
504
List<Constraint> list = getConstraints(alg);
505
if (list == null) {
506
continue;
507
}
508
for (Constraint constraint : list) {
509
constraint.permits(cp);
510
}
511
}
512
}
513
}
514
515
/**
516
* This abstract Constraint class for algorithm-based checking
517
* may contain one or more constraints. If the '&' on the {@Security}
518
* property is used, multiple constraints have been grouped together
519
* requiring all the constraints to fail for the check to be disallowed.
520
*
521
* If the class contains multiple constraints, the next constraint
522
* is stored in {@code nextConstraint} in linked-list fashion.
523
*/
524
private abstract static class Constraint {
525
String algorithm;
526
Constraint nextConstraint = null;
527
528
// operator
529
enum Operator {
530
EQ, // "=="
531
NE, // "!="
532
LT, // "<"
533
LE, // "<="
534
GT, // ">"
535
GE; // ">="
536
537
static Operator of(String s) {
538
switch (s) {
539
case "==":
540
return EQ;
541
case "!=":
542
return NE;
543
case "<":
544
return LT;
545
case "<=":
546
return LE;
547
case ">":
548
return GT;
549
case ">=":
550
return GE;
551
}
552
553
throw new IllegalArgumentException("Error in security " +
554
"property. " + s + " is not a legal Operator");
555
}
556
}
557
558
/**
559
* Check if an algorithm constraint is permitted with a given key.
560
*
561
* If the check inside of {@code permit()} fails, it must call
562
* {@code next()} with the same {@code Key} parameter passed if
563
* multiple constraints need to be checked.
564
*
565
* @param key Public key
566
* @return 'true' if constraint is allowed, 'false' if disallowed.
567
*/
568
public boolean permits(Key key) {
569
return true;
570
}
571
572
/**
573
* Check if the algorithm constraint permits a given cryptographic
574
* parameters.
575
*
576
* @param parameters the cryptographic parameters
577
* @return 'true' if the cryptographic parameters is allowed,
578
* 'false' ortherwise.
579
*/
580
public boolean permits(AlgorithmParameters parameters) {
581
return true;
582
}
583
584
/**
585
* Check if an algorithm constraint is permitted with a given
586
* ConstraintsParameters.
587
*
588
* If the check inside of {@code permits()} fails, it must call
589
* {@code next()} with the same {@code ConstraintsParameters}
590
* parameter passed if multiple constraints need to be checked.
591
*
592
* @param cp ConstraintsParameter containing certificate info
593
* @throws CertPathValidatorException if constraint disallows.
594
*
595
*/
596
public abstract void permits(ConstraintsParameters cp)
597
throws CertPathValidatorException;
598
599
/**
600
* Recursively check if the constraints are allowed.
601
*
602
* If {@code nextConstraint} is non-null, this method will
603
* call {@code nextConstraint}'s {@code permits()} to check if the
604
* constraint is allowed or denied. If the constraint's
605
* {@code permits()} is allowed, this method will exit this and any
606
* recursive next() calls, returning 'true'. If the constraints called
607
* were disallowed, the last constraint will throw
608
* {@code CertPathValidatorException}.
609
*
610
* @param cp ConstraintsParameters
611
* @return 'true' if constraint allows the operation, 'false' if
612
* we are at the end of the constraint list or,
613
* {@code nextConstraint} is null.
614
*/
615
boolean next(ConstraintsParameters cp)
616
throws CertPathValidatorException {
617
if (nextConstraint != null) {
618
nextConstraint.permits(cp);
619
return true;
620
}
621
return false;
622
}
623
624
/**
625
* Recursively check if this constraint is allowed,
626
*
627
* If {@code nextConstraint} is non-null, this method will
628
* call {@code nextConstraint}'s {@code permit()} to check if the
629
* constraint is allowed or denied. If the constraint's
630
* {@code permit()} is allowed, this method will exit this and any
631
* recursive next() calls, returning 'true'. If the constraints
632
* called were disallowed the check will exit with 'false'.
633
*
634
* @param key Public key
635
* @return 'true' if constraint allows the operation, 'false' if
636
* the constraint denies the operation.
637
*/
638
boolean next(Key key) {
639
return nextConstraint != null && nextConstraint.permits(key);
640
}
641
}
642
643
/*
644
* This class contains constraints dealing with the certificate chain
645
* of the certificate.
646
*/
647
private static class jdkCAConstraint extends Constraint {
648
jdkCAConstraint(String algo) {
649
algorithm = algo;
650
}
651
652
/*
653
* Check if ConstraintsParameters has a trusted match, if it does
654
* call next() for any following constraints. If it does not, exit
655
* as this constraint(s) does not restrict the operation.
656
*/
657
@Override
658
public void permits(ConstraintsParameters cp)
659
throws CertPathValidatorException {
660
if (debug != null) {
661
debug.println("jdkCAConstraints.permits(): " + algorithm);
662
}
663
664
// Check if any certs chain back to at least one trust anchor in
665
// cacerts
666
if (cp.anchorIsJdkCA()) {
667
if (next(cp)) {
668
return;
669
}
670
throw new CertPathValidatorException(
671
"Algorithm constraints check failed on certificate " +
672
"anchor limits. " + algorithm + cp.extendedExceptionMsg(),
673
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
674
}
675
}
676
}
677
678
/*
679
* This class handles the denyAfter constraint. The date is in the UTC/GMT
680
* timezone.
681
*/
682
private static class DenyAfterConstraint extends Constraint {
683
private Date denyAfterDate;
684
private static final SimpleDateFormat dateFormat =
685
new SimpleDateFormat("EEE, MMM d HH:mm:ss z yyyy");
686
687
DenyAfterConstraint(String algo, int year, int month, int day) {
688
Calendar c;
689
690
algorithm = algo;
691
692
if (debug != null) {
693
debug.println("DenyAfterConstraint read in as: year " +
694
year + ", month = " + month + ", day = " + day);
695
}
696
697
c = new Calendar.Builder().setTimeZone(TimeZone.getTimeZone("GMT"))
698
.setDate(year, month - 1, day).build();
699
700
if (year > c.getActualMaximum(Calendar.YEAR) ||
701
year < c.getActualMinimum(Calendar.YEAR)) {
702
throw new IllegalArgumentException(
703
"Invalid year given in constraint: " + year);
704
}
705
if ((month - 1) > c.getActualMaximum(Calendar.MONTH) ||
706
(month - 1) < c.getActualMinimum(Calendar.MONTH)) {
707
throw new IllegalArgumentException(
708
"Invalid month given in constraint: " + month);
709
}
710
if (day > c.getActualMaximum(Calendar.DAY_OF_MONTH) ||
711
day < c.getActualMinimum(Calendar.DAY_OF_MONTH)) {
712
throw new IllegalArgumentException(
713
"Invalid Day of Month given in constraint: " + day);
714
}
715
716
denyAfterDate = c.getTime();
717
if (debug != null) {
718
debug.println("DenyAfterConstraint date set to: " +
719
dateFormat.format(denyAfterDate));
720
}
721
}
722
723
/*
724
* Checking that the provided date is not beyond the constraint date.
725
* The provided date can be the PKIXParameter date if given,
726
* otherwise it is the current date.
727
*
728
* If the constraint disallows, call next() for any following
729
* constraints. Throw an exception if this is the last constraint.
730
*/
731
@Override
732
public void permits(ConstraintsParameters cp)
733
throws CertPathValidatorException {
734
Date currentDate;
735
String errmsg;
736
737
if (cp.getDate() != null) {
738
currentDate = cp.getDate();
739
} else {
740
currentDate = new Date();
741
}
742
743
if (!denyAfterDate.after(currentDate)) {
744
if (next(cp)) {
745
return;
746
}
747
throw new CertPathValidatorException(
748
"denyAfter constraint check failed: " + algorithm +
749
" used with Constraint date: " +
750
dateFormat.format(denyAfterDate) + "; params date: " +
751
dateFormat.format(currentDate) + cp.extendedExceptionMsg(),
752
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
753
}
754
}
755
756
/*
757
* Return result if the constraint's date is beyond the current date
758
* in UTC timezone.
759
*/
760
@Override
761
public boolean permits(Key key) {
762
if (next(key)) {
763
return true;
764
}
765
if (debug != null) {
766
debug.println("DenyAfterConstraints.permits(): " + algorithm);
767
}
768
769
return denyAfterDate.after(new Date());
770
}
771
}
772
773
/*
774
* The usage constraint is for the "usage" keyword. It checks against the
775
* variant value in ConstraintsParameters.
776
*/
777
private static class UsageConstraint extends Constraint {
778
String[] usages;
779
780
UsageConstraint(String algorithm, String[] usages) {
781
this.algorithm = algorithm;
782
this.usages = usages;
783
}
784
785
@Override
786
public void permits(ConstraintsParameters cp)
787
throws CertPathValidatorException {
788
String variant = cp.getVariant();
789
for (String usage : usages) {
790
791
boolean match = false;
792
switch (usage.toLowerCase()) {
793
case "tlsserver":
794
match = variant.equals(Validator.VAR_TLS_SERVER);
795
break;
796
case "tlsclient":
797
match = variant.equals(Validator.VAR_TLS_CLIENT);
798
break;
799
case "signedjar":
800
match =
801
variant.equals(Validator.VAR_PLUGIN_CODE_SIGNING) ||
802
variant.equals(Validator.VAR_CODE_SIGNING) ||
803
variant.equals(Validator.VAR_TSA_SERVER);
804
break;
805
}
806
807
if (debug != null) {
808
debug.println("Checking if usage constraint \"" + usage +
809
"\" matches \"" + cp.getVariant() + "\"");
810
// Because usage checking can come from many places
811
// a stack trace is very helpful.
812
ByteArrayOutputStream ba = new ByteArrayOutputStream();
813
PrintStream ps = new PrintStream(ba);
814
(new Exception()).printStackTrace(ps);
815
debug.println(ba.toString());
816
}
817
if (match) {
818
if (next(cp)) {
819
return;
820
}
821
throw new CertPathValidatorException("Usage constraint " +
822
usage + " check failed: " + algorithm +
823
cp.extendedExceptionMsg(),
824
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
825
}
826
}
827
}
828
}
829
830
/*
831
* This class contains constraints dealing with the key size
832
* support limits per algorithm. e.g. "keySize <= 1024"
833
*/
834
private static class KeySizeConstraint extends Constraint {
835
836
private int minSize; // the minimal available key size
837
private int maxSize; // the maximal available key size
838
private int prohibitedSize = -1; // unavailable key sizes
839
private int size;
840
841
public KeySizeConstraint(String algo, Operator operator, int length) {
842
algorithm = algo;
843
switch (operator) {
844
case EQ: // an unavailable key size
845
this.minSize = 0;
846
this.maxSize = Integer.MAX_VALUE;
847
prohibitedSize = length;
848
break;
849
case NE:
850
this.minSize = length;
851
this.maxSize = length;
852
break;
853
case LT:
854
this.minSize = length;
855
this.maxSize = Integer.MAX_VALUE;
856
break;
857
case LE:
858
this.minSize = length + 1;
859
this.maxSize = Integer.MAX_VALUE;
860
break;
861
case GT:
862
this.minSize = 0;
863
this.maxSize = length;
864
break;
865
case GE:
866
this.minSize = 0;
867
this.maxSize = length > 1 ? (length - 1) : 0;
868
break;
869
default:
870
// unlikely to happen
871
this.minSize = Integer.MAX_VALUE;
872
this.maxSize = -1;
873
}
874
}
875
876
/*
877
* For each key, check if each constraint fails and check if there is
878
* a linked constraint. Any permitted constraint will exit the linked
879
* list to allow the operation.
880
*/
881
@Override
882
public void permits(ConstraintsParameters cp)
883
throws CertPathValidatorException {
884
for (Key key : cp.getKeys()) {
885
if (!permitsImpl(key)) {
886
if (nextConstraint != null) {
887
nextConstraint.permits(cp);
888
continue;
889
}
890
throw new CertPathValidatorException(
891
"Algorithm constraints check failed on keysize limits: " +
892
algorithm + " " + KeyUtil.getKeySize(key) + " bit key" +
893
cp.extendedExceptionMsg(),
894
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
895
}
896
}
897
}
898
899
900
// Check if key constraint disable the specified key
901
// Uses old style permit()
902
@Override
903
public boolean permits(Key key) {
904
// If we recursively find a constraint that permits us to use
905
// this key, return true and skip any other constraint checks.
906
if (nextConstraint != null && nextConstraint.permits(key)) {
907
return true;
908
}
909
if (debug != null) {
910
debug.println("KeySizeConstraints.permits(): " + algorithm);
911
}
912
913
return permitsImpl(key);
914
}
915
916
@Override
917
public boolean permits(AlgorithmParameters parameters) {
918
String paramAlg = parameters.getAlgorithm();
919
if (!algorithm.equalsIgnoreCase(parameters.getAlgorithm())) {
920
// Consider the impact of the algorithm aliases.
921
Collection<String> aliases =
922
AlgorithmDecomposer.getAliases(algorithm);
923
if (!aliases.contains(paramAlg)) {
924
return true;
925
}
926
}
927
928
int keySize = KeyUtil.getKeySize(parameters);
929
if (keySize == 0) {
930
return false;
931
} else if (keySize > 0) {
932
return !((keySize < minSize) || (keySize > maxSize) ||
933
(prohibitedSize == keySize));
934
} // Otherwise, the key size is not accessible or determined.
935
// Conservatively, please don't disable such keys.
936
937
return true;
938
}
939
940
private boolean permitsImpl(Key key) {
941
// Verify this constraint is for this public key algorithm
942
if (algorithm.compareToIgnoreCase(key.getAlgorithm()) != 0) {
943
return true;
944
}
945
946
size = KeyUtil.getKeySize(key);
947
if (size == 0) {
948
return false; // we don't allow any key of size 0.
949
} else if (size > 0) {
950
return !((size < minSize) || (size > maxSize) ||
951
(prohibitedSize == size));
952
} // Otherwise, the key size is not accessible. Conservatively,
953
// please don't disable such keys.
954
955
return true;
956
}
957
}
958
959
/*
960
* This constraint is used for the complete disabling of the algorithm.
961
*/
962
private static class DisabledConstraint extends Constraint {
963
DisabledConstraint(String algo) {
964
algorithm = algo;
965
}
966
967
@Override
968
public void permits(ConstraintsParameters cp)
969
throws CertPathValidatorException {
970
throw new CertPathValidatorException(
971
"Algorithm constraints check failed on disabled " +
972
"algorithm: " + algorithm + cp.extendedExceptionMsg(),
973
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
974
}
975
976
@Override
977
public boolean permits(Key key) {
978
return false;
979
}
980
}
981
}
982
983