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