Skip to content

Commit 86facbc

Browse files
author
Eugene Bochilo
committed
Fix BasicConstraints extension validation
DEVSIX-8420 Autoported commit. Original commit hash: [57a1bc81a] Manual files: sign/src/main/java/com/itextpdf/signatures/validation/v1/SignatureValidationProperties.java
1 parent acbd2cb commit 86facbc

File tree

10 files changed

+287
-8
lines changed

10 files changed

+287
-8
lines changed

itext.tests/itext.sign.tests/itext/signatures/validation/v1/CertificateChainValidatorTest.cs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,47 @@ public virtual void ValidChainTest() {
7878
GetSubjectDN()).WithCertificate(rootCert)));
7979
}
8080

81+
[NUnit.Framework.Test]
82+
public virtual void ValidNumericBasicConstraintsTest() {
83+
String chainName = CERTS_SRC + "signChainWithValidNumericBasicConstraints.pem";
84+
IX509Certificate[] certificateChain = PemFileHelper.ReadFirstChain(chainName);
85+
IX509Certificate signingCert = (IX509Certificate)certificateChain[0];
86+
IX509Certificate intermediateCert = (IX509Certificate)certificateChain[1];
87+
IX509Certificate rootCert = (IX509Certificate)certificateChain[2];
88+
CertificateChainValidator validator = validatorChainBuilder.BuildCertificateChainValidator();
89+
certificateRetriever.AddKnownCertificates(JavaCollectionsUtil.SingletonList<IX509Certificate>(intermediateCert
90+
));
91+
certificateRetriever.SetTrustedCertificates(JavaCollectionsUtil.SingletonList<IX509Certificate>(rootCert));
92+
ValidationReport report = validator.ValidateCertificate(baseContext, signingCert, TimeTestUtil.TEST_DATE_TIME
93+
);
94+
AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID).HasNumberOfFailures
95+
(0).HasNumberOfLogs(1).HasLogItem((la) => la.WithCheckName(CertificateChainValidator.CERTIFICATE_CHECK
96+
).WithMessage("Certificate {0} is trusted, revocation data checks are not required.", (l) => rootCert.
97+
GetSubjectDN()).WithCertificate(rootCert)));
98+
}
99+
100+
[NUnit.Framework.Test]
101+
public virtual void InvalidNumericBasicConstraintsTest() {
102+
String chainName = CERTS_SRC + "signChainWithInvalidNumericBasicConstraints.pem";
103+
IX509Certificate[] certificateChain = PemFileHelper.ReadFirstChain(chainName);
104+
IX509Certificate signingCert = (IX509Certificate)certificateChain[0];
105+
IX509Certificate intermediateCert = (IX509Certificate)certificateChain[1];
106+
IX509Certificate rootCert = (IX509Certificate)certificateChain[2];
107+
CertificateChainValidator validator = validatorChainBuilder.BuildCertificateChainValidator();
108+
certificateRetriever.AddKnownCertificates(JavaCollectionsUtil.SingletonList<IX509Certificate>(intermediateCert
109+
));
110+
certificateRetriever.SetTrustedCertificates(JavaCollectionsUtil.SingletonList<IX509Certificate>(rootCert));
111+
ValidationReport report = validator.ValidateCertificate(baseContext, signingCert, TimeTestUtil.TEST_DATE_TIME
112+
);
113+
AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID).HasNumberOfFailures
114+
(2).HasNumberOfLogs(3).HasLogItem((la) => la.WithCheckName(CertificateChainValidator.CERTIFICATE_CHECK
115+
).WithMessage("Certificate {0} is trusted, revocation data checks are not required.", (l) => rootCert.
116+
GetSubjectDN()).WithCertificate(rootCert)).HasLogItem((la) => la.WithCheckName(CertificateChainValidator
117+
.EXTENSIONS_CHECK).WithMessage(CertificateChainValidator.EXTENSION_MISSING, (l) => "2.5.29.19").WithCertificate
118+
(rootCert)).HasLogItem((la) => la.WithCheckName(CertificateChainValidator.EXTENSIONS_CHECK).WithMessage
119+
(CertificateChainValidator.EXTENSION_MISSING, (l) => "2.5.29.19").WithCertificate(intermediateCert)));
120+
}
121+
81122
[NUnit.Framework.Test]
82123
public virtual void RevocationValidationCallTest() {
83124
String chainName = CERTS_SRC + "chain.pem";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIDczCCAlugAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwVDELMAkGA1UEBhMCQkUx
3+
DjAMBgNVBAoMBWlUZXh0MTUwMwYDVQQDDCxpVGV4dFRlc3RJbnZhbGlkQmFzaWND
4+
b25zdHJhaW50c0ludGVybWVkaWF0ZTAgFw0wMDAxMDEwMDAwMDBaGA8yNTAwMDEw
5+
MTAwMDAwMFowTzELMAkGA1UEBhMCQkUxDjAMBgNVBAoMBWlUZXh0MTAwLgYDVQQD
6+
DCdpVGV4dFRlc3RJbnZhbGlkQmFzaWNDb25zdHJhaW50c1NpZ25pbmcwggEiMA0G
7+
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDk0UKW8iOW/YPocIBpaICH96wbdhwd
8+
9O1spY/7LA6JHLVZgSRIB3if5sU3tNclN3uO2NPiQhZXCMDJP+ISdQGCCSeRCo0n
9+
OXu46984qB4+YrlT3ScpAQ0uZY943PYTcBVnUYMYA+nFRZhtJ8aLJpBl5ND08ye0
10+
TlEWTU0RmXNXhUbhAuwWdAHaDTDYGyJ+Bmr3ob/ktILtHwzS8rkGw+FRY+bty4BD
11+
mJTGiSNR/c2MdUikXOVzoybRX7BqvvHlU78XZTtGxwIJ17oorZBgk/8AUMSCe+xN
12+
2Zr13ucerbTnRLNBo1lbHIb4jWH5aq7BLdah9qEPOMTTc2aGow3yR9U1AgMBAAGj
13+
UjBQMB0GA1UdDgQWBBQkLmgOAQOWlcnrtVUv57Rj05TsRTAfBgNVHSMEGDAWgBQ3
14+
AGQi1plfpKj08MVTNx54NFkCczAOBgNVHQ8BAf8EBAMCBkAwDQYJKoZIhvcNAQEL
15+
BQADggEBADHWfy2/K8cd1P1ijelp/KOj92ESC1i1seo4tGfRreM5+VskkIbix2Dl
16+
8/Gpy1/Igw9jMoOdPyyqj72mBO2aiEikNL8+PQgKjK7WVF7MLdWPtE2h77fiQN3o
17+
J1ybtlrasOSmlSKxixyFHL2caBjLC/YiYU28wuAGkDqSb3bug6JKz0U+KP5bQr1Y
18+
+irR91kcpiIAfdeDmN1NLa+IHcwAHzZNtc334map1vXy4AVbox1oee+pICkgyAgM
19+
XGuUMqts5sfBVCeZ4YXmtFEFhypo9sZgQ82yj8D/n53oyOfGok9sZtQO5d/KL523
20+
6UISiCz3koNIaqnFJejITnmHrE7SgvE=
21+
-----END CERTIFICATE-----
22+
-----BEGIN CERTIFICATE-----
23+
MIIDhDCCAmygAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwTDELMAkGA1UEBhMCQkUx
24+
DjAMBgNVBAoMBWlUZXh0MS0wKwYDVQQDDCRpVGV4dFRlc3RJbnZhbGlkQmFzaWND
25+
b25zdHJhaW50c1Jvb3QwIBcNMDAwMTAxMDAwMDAwWhgPMjUwMDAxMDEwMDAwMDBa
26+
MFQxCzAJBgNVBAYTAkJFMQ4wDAYDVQQKDAVpVGV4dDE1MDMGA1UEAwwsaVRleHRU
27+
ZXN0SW52YWxpZEJhc2ljQ29uc3RyYWludHNJbnRlcm1lZGlhdGUwggEiMA0GCSqG
28+
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCf1b92W/Yeitn6iwuZHmfF7cw740VaqHGO
29+
AavE6DhwVCrfVlWDvamF+Sewnf2KuIxeWaYciy5TQ/nIa8CcD3qDJsYjYUK6L+Ro
30+
E+Lb5YMKOEUpc2p4XZvLXmOIOl3AEe2AnIDxREk1gfu6BYFyzmju8rHLSy7ua/I5
31+
672qude/EPGG+jyb+ajIbyNSsL65hkOrJUcJtlRIhJQVCZ39hcNdA8lRBrVzq1NW
32+
gnExyFsqlIYpAuD1IsnS/r1kMOzjPai/AhPOqpnB6ogZp+Dr99wYY57Dv9BdfvKt
33+
guX608D5m0Rp3yrEQ/X5m9frTvp09MCHKMU+X9+14LZiaod3AtQVAgMBAAGjZjBk
34+
MB0GA1UdDgQWBBQ3AGQi1plfpKj08MVTNx54NFkCczAfBgNVHSMEGDAWgBTvssgF
35+
UYUg7luFw9zAr9tZuQouvDASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQE
36+
AwICBDANBgkqhkiG9w0BAQsFAAOCAQEANzdFjm4iasZpvPwPEeoulmGr33Ofp0L+
37+
IQ03ZYjgUDSx3xuUhfpZHgmEcoovQz6IGw0wlp4W7HJ8rqaj3aLEte7ZXF2mpaTQ
38+
vGU3suY3SXTLTZq2TinA0KEToaObX9XLVTJTe6GNMcNf1uAQnQVzOgm3kNpnqcLp
39+
QyNZrUH+q4q6gO9EcdMAq4oFXvqPkxYy01B9eHChrASWV3/CsbuyLUDnY1ZduGGZ
40+
yXF8/NiAgsYQk12cryo5sbkHzpbH62zSwdvzf4s/dp95Tub9bxdta7NYVJL0eOe7
41+
nTMcY6TMT7FXFIkpZ3nr2zEonGMf+zM5qG2crqtteHGbWqmp3f8R/Q==
42+
-----END CERTIFICATE-----
43+
-----BEGIN CERTIFICATE-----
44+
MIIDfDCCAmSgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwTDELMAkGA1UEBhMCQkUx
45+
DjAMBgNVBAoMBWlUZXh0MS0wKwYDVQQDDCRpVGV4dFRlc3RJbnZhbGlkQmFzaWND
46+
b25zdHJhaW50c1Jvb3QwIBcNMDAwMTAxMDAwMDAwWhgPMjUwMDAxMDEwMDAwMDBa
47+
MEwxCzAJBgNVBAYTAkJFMQ4wDAYDVQQKDAVpVGV4dDEtMCsGA1UEAwwkaVRleHRU
48+
ZXN0SW52YWxpZEJhc2ljQ29uc3RyYWludHNSb290MIIBIjANBgkqhkiG9w0BAQEF
49+
AAOCAQ8AMIIBCgKCAQEA3ktft1LujBsmfphuvEC2LpRfz41pleSyi2NRQKK6wQZE
50+
SDMAn94fVS43+sJkiSGrJuc+5VGe0Cy17RU8SVVnXy4/AVBvr/YrLjGfNTuCW+A/
51+
pBJEyLJ/8dSkmT2jBX8KpcUyrjHi8Q7OIUae3Hu5WBz4hcmTYoXfcEQwamoiuqx4
52+
nKtH+CEOZ4rtG2zxDSRhw7HishUYc0U886txYVtZJ+PfCzblntecsNNaucJCCHZB
53+
H0aF9yHsleumVL2i24ELHY5izNHH75rM4kpWFPUXD9dMwU7UUDpL9RoW92HpG7X/
54+
CTDPZGzHRt8srUtFH4S2b0cI0lCW0eW7dkmIYleWQwIDAQABo2YwZDAdBgNVHQ4E
55+
FgQU77LIBVGFIO5bhcPcwK/bWbkKLrwwHwYDVR0jBBgwFoAU77LIBVGFIO5bhcPc
56+
wK/bWbkKLrwwEgYDVR0TAQH/BAgwBgEB/wIBATAOBgNVHQ8BAf8EBAMCAQYwDQYJ
57+
KoZIhvcNAQELBQADggEBAA3Nyit5cNUHE9hVpEZ4mkpYoHDiw7NfHqmuhRC4Gnsy
58+
oVaVgQmDJH52EwWLqpZkQCSr3gwJv+OZZ1oR+LW1qRSyXqIcoLzyuxj3sBclbwzE
59+
XCknvNT1D2Kbd2mubz37GwwdzN4T59lWO371aIT4uoYWaTIdkYFCiONydfsKzBsS
60+
uEGb1z94pZ71Kt00jwrG8CP841Cdw5RRsb39AAI9k8Gy4+g24HZeLI+Z4/ZlmsFG
61+
XNgx5PDZpNZ5W+xlEc5W7ksL675AoD51yoW9d/J7DXg7NI5ur5MxOUf+T0wQh/W5
62+
9uwx924xwDeeHdLBxdZHsN9v4eVIxELr9huFrN9SbRQ=
63+
-----END CERTIFICATE-----
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIDbzCCAlegAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwUjELMAkGA1UEBhMCQkUx
3+
DjAMBgNVBAoMBWlUZXh0MTMwMQYDVQQDDCppVGV4dFRlc3RWYWxpZEJhc2ljQ29u
4+
c3RyYWludHNJbnRlcm1lZGlhdGUwIBcNMDAwMTAxMDAwMDAwWhgPMjUwMDAxMDEw
5+
MDAwMDBaME0xCzAJBgNVBAYTAkJFMQ4wDAYDVQQKDAVpVGV4dDEuMCwGA1UEAwwl
6+
aVRleHRUZXN0VmFsaWRCYXNpY0NvbnN0cmFpbnRzU2lnbmluZzCCASIwDQYJKoZI
7+
hvcNAQEBBQADggEPADCCAQoCggEBAOTRQpbyI5b9g+hwgGlogIf3rBt2HB307Wyl
8+
j/ssDokctVmBJEgHeJ/mxTe01yU3e47Y0+JCFlcIwMk/4hJ1AYIJJ5EKjSc5e7jr
9+
3zioHj5iuVPdJykBDS5lj3jc9hNwFWdRgxgD6cVFmG0nxosmkGXk0PTzJ7ROURZN
10+
TRGZc1eFRuEC7BZ0AdoNMNgbIn4Gavehv+S0gu0fDNLyuQbD4VFj5u3LgEOYlMaJ
11+
I1H9zYx1SKRc5XOjJtFfsGq+8eVTvxdlO0bHAgnXuiitkGCT/wBQxIJ77E3ZmvXe
12+
5x6ttOdEs0GjWVschviNYflqrsEt1qH2oQ84xNNzZoajDfJH1TUCAwEAAaNSMFAw
13+
HQYDVR0OBBYEFCQuaA4BA5aVyeu1VS/ntGPTlOxFMB8GA1UdIwQYMBaAFDcAZCLW
14+
mV+kqPTwxVM3Hng0WQJzMA4GA1UdDwEB/wQEAwIGQDANBgkqhkiG9w0BAQsFAAOC
15+
AQEAjRQhDitwg17vfnX+px6XnyebR15xYVNUEBIzY8r+ZSb6yGOQNQhBBikqGLYW
16+
iOAWcPoCGYdJh/yxg/dUpDYDXl5BEfRTnL/93NrdOaYJPv7WE4Vp0V+rasmthYwz
17+
e66gMXmFZdQ3OPkLQJg5asqTpus9/1XSts3eyawiuNfCvQDNmJJggaj0eog8iIj5
18+
KuSPDrapqUC7BCy8wm0riu/ExvkXOFYI66FVGy7NQoU+/C/rkEAKaMqNBklNm8nO
19+
gsr/IRaJkWOWgsK6HNq6bnxeQz4rEvSiVr65T2isdp0MSTHgmQ0g/VcPh7am70Vr
20+
cF08cI/+5FsNk9lxnu8u4GTZxA==
21+
-----END CERTIFICATE-----
22+
-----BEGIN CERTIFICATE-----
23+
MIIDgDCCAmigAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwSjELMAkGA1UEBhMCQkUx
24+
DjAMBgNVBAoMBWlUZXh0MSswKQYDVQQDDCJpVGV4dFRlc3RWYWxpZEJhc2ljQ29u
25+
c3RyYWludHNSb290MCAXDTAwMDEwMTAwMDAwMFoYDzI1MDAwMTAxMDAwMDAwWjBS
26+
MQswCQYDVQQGEwJCRTEOMAwGA1UECgwFaVRleHQxMzAxBgNVBAMMKmlUZXh0VGVz
27+
dFZhbGlkQmFzaWNDb25zdHJhaW50c0ludGVybWVkaWF0ZTCCASIwDQYJKoZIhvcN
28+
AQEBBQADggEPADCCAQoCggEBAJ/Vv3Zb9h6K2fqLC5keZ8XtzDvjRVqocY4Bq8To
29+
OHBUKt9WVYO9qYX5J7Cd/Yq4jF5ZphyLLlND+chrwJwPeoMmxiNhQrov5GgT4tvl
30+
gwo4RSlzanhdm8teY4g6XcAR7YCcgPFESTWB+7oFgXLOaO7ysctLLu5r8jnrvaq5
31+
178Q8Yb6PJv5qMhvI1KwvrmGQ6slRwm2VEiElBUJnf2Fw10DyVEGtXOrU1aCcTHI
32+
WyqUhikC4PUiydL+vWQw7OM9qL8CE86qmcHqiBmn4Ov33BhjnsO/0F1+8q2C5frT
33+
wPmbRGnfKsRD9fmb1+tO+nT0wIcoxT5f37XgtmJqh3cC1BUCAwEAAaNmMGQwHQYD
34+
VR0OBBYEFDcAZCLWmV+kqPTwxVM3Hng0WQJzMB8GA1UdIwQYMBaAFO+yyAVRhSDu
35+
W4XD3MCv21m5Ci68MBIGA1UdEwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgIE
36+
MA0GCSqGSIb3DQEBCwUAA4IBAQB0CFElE09ge6LUM+odJMLzAvMg2ZbeuyM0tbe1
37+
QyivtRVDVQXyJRL55dGUtRSMCxx5Iv3wwoH6W+2k4IsXKFQH/vmPv9mnCXtThoaw
38+
iTYUR7TmZnMj9cGBKekAsAmm8cI5qMkKzz0nUAerGvPoF1Pe+7yZeqpafe9ltjF6
39+
RCGxJFhQL0bL9o6Z52qzZJdOrHRh7Xqz7ikGaPGFvsKk3J8evWNX/4fVoN6VHZ4w
40+
MLqCmNtBzTXOO/pdFsMrYZ5JKUQGBDbXJ8xFTMZwNO+oRarKmTExVLSVdAIq2Tmv
41+
Xn5u7+WWu1FXQa6rIxeRgfKvGrMuQAM21GYKB4owSNIZWEju
42+
-----END CERTIFICATE-----
43+
-----BEGIN CERTIFICATE-----
44+
MIIDeDCCAmCgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwSjELMAkGA1UEBhMCQkUx
45+
DjAMBgNVBAoMBWlUZXh0MSswKQYDVQQDDCJpVGV4dFRlc3RWYWxpZEJhc2ljQ29u
46+
c3RyYWludHNSb290MCAXDTAwMDEwMTAwMDAwMFoYDzI1MDAwMTAxMDAwMDAwWjBK
47+
MQswCQYDVQQGEwJCRTEOMAwGA1UECgwFaVRleHQxKzApBgNVBAMMImlUZXh0VGVz
48+
dFZhbGlkQmFzaWNDb25zdHJhaW50c1Jvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IB
49+
DwAwggEKAoIBAQDeS1+3Uu6MGyZ+mG68QLYulF/PjWmV5LKLY1FAorrBBkRIMwCf
50+
3h9VLjf6wmSJIasm5z7lUZ7QLLXtFTxJVWdfLj8BUG+v9isuMZ81O4Jb4D+kEkTI
51+
sn/x1KSZPaMFfwqlxTKuMeLxDs4hRp7ce7lYHPiFyZNihd9wRDBqaiK6rHicq0f4
52+
IQ5niu0bbPENJGHDseKyFRhzRTzzq3FhW1kn498LNuWe15yw01q5wkIIdkEfRoX3
53+
IeyV66ZUvaLbgQsdjmLM0cfvmsziSlYU9RcP10zBTtRQOkv1Ghb3Yekbtf8JMM9k
54+
bMdG3yytS0UfhLZvRwjSUJbR5bt2SYhiV5ZDAgMBAAGjZjBkMB0GA1UdDgQWBBTv
55+
ssgFUYUg7luFw9zAr9tZuQouvDAfBgNVHSMEGDAWgBTvssgFUYUg7luFw9zAr9tZ
56+
uQouvDASBgNVHRMBAf8ECDAGAQH/AgECMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG
57+
9w0BAQsFAAOCAQEAcJsUExWQAKX6VZc1yVorL3mf2/keswI9RdSb7s+CU6WMKvga
58+
Bb0wOANC46oetD0e2QWmi396sxTmC/X/wiG0OhA2TnuuMi9EISQFXTDjfUUxUF1i
59+
k6T+EyGq1f7SFzrhCsSVAmAgSVUDp2IeERtNZbGP0uPPIqII767oLKkHzhh21LlN
60+
3zZKwvUrsk+E6quAVWFSiRoEzH2drV0fcOFLrw+NCH6Rh31QBk1wEDJocJ4U9zsD
61+
6w/EU0oyNuKTaQXSh75G5MZMUdmHGj1elVF8tRWWpZzuKgfnVDKb3GxdEf3FEg6y
62+
usswWis9kk/09DZU5AuyvBJTvdq58p4+U4kYtg==
63+
-----END CERTIFICATE-----

itext/itext.sign/itext/signatures/validation/v1/CRLValidator.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,8 @@ public virtual void Validate(ValidationReport report, ValidationContext context,
186186
IDistributionPoint distributionPoint = null;
187187
if (!issuingDistPoint.IsNull()) {
188188
// Verify that certificate is in the CRL scope using IDP extension.
189-
bool basicConstraintsCaAsserted = new BasicConstraintsExtension(true).ExistsInCertificate(certificate);
189+
bool basicConstraintsCaAsserted = new DynamicBasicConstraintsExtension().WithCertificateChainSize(1).ExistsInCertificate
190+
(certificate);
190191
if ((issuingDistPoint.OnlyContainsUserCerts() && basicConstraintsCaAsserted) || (issuingDistPoint.OnlyContainsCACerts
191192
() && !basicConstraintsCaAsserted)) {
192193
report.AddReportItem(new CertificateReportItem(certificate, CRL_CHECK, CERTIFICATE_IS_NOT_IN_THE_CRL_SCOPE

itext/itext.sign/itext/signatures/validation/v1/CertificateChainValidator.cs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -210,9 +210,14 @@ public virtual ValidationReport ValidateCertificate(ValidationContext context, I
210210
/// </returns>
211211
public virtual ValidationReport Validate(ValidationReport result, ValidationContext context, IX509Certificate
212212
certificate, DateTime validationDate) {
213+
return Validate(result, context, certificate, validationDate, 0);
214+
}
215+
216+
private ValidationReport Validate(ValidationReport result, ValidationContext context, IX509Certificate certificate
217+
, DateTime validationDate, int certificateChainSize) {
213218
ValidationContext localContext = context.SetValidatorContext(ValidatorContext.CERTIFICATE_CHAIN_VALIDATOR);
214219
ValidateValidityPeriod(result, certificate, validationDate);
215-
ValidateRequiredExtensions(result, localContext, certificate);
220+
ValidateRequiredExtensions(result, localContext, certificate, certificateChainSize);
216221
if (StopValidation(result, localContext)) {
217222
return result;
218223
}
@@ -225,7 +230,7 @@ public virtual ValidationReport Validate(ValidationReport result, ValidationCont
225230
if (StopValidation(result, localContext)) {
226231
return result;
227232
}
228-
ValidateChain(result, localContext, certificate, validationDate);
233+
ValidateChain(result, localContext, certificate, validationDate, certificateChainSize);
229234
return result;
230235
}
231236

@@ -319,10 +324,13 @@ private void ValidateValidityPeriod(ValidationReport result, IX509Certificate ce
319324
}
320325

321326
private void ValidateRequiredExtensions(ValidationReport result, ValidationContext context, IX509Certificate
322-
certificate) {
327+
certificate, int certificateChainSize) {
323328
IList<CertificateExtension> requiredExtensions = properties.GetRequiredExtensions(context);
324329
if (requiredExtensions != null) {
325330
foreach (CertificateExtension requiredExtension in requiredExtensions) {
331+
if (requiredExtension is DynamicCertificateExtension) {
332+
((DynamicCertificateExtension)requiredExtension).WithCertificateChainSize(certificateChainSize);
333+
}
326334
if (!requiredExtension.ExistsInCertificate(certificate)) {
327335
result.AddReportItem(new CertificateReportItem(certificate, EXTENSIONS_CHECK, MessageFormatUtil.Format(EXTENSION_MISSING
328336
, requiredExtension.GetExtensionOid()), ReportItem.ReportItemStatus.INVALID));
@@ -339,7 +347,7 @@ private void ValidateRevocationData(ValidationReport report, ValidationContext c
339347
}
340348

341349
private void ValidateChain(ValidationReport result, ValidationContext context, IX509Certificate certificate
342-
, DateTime validationDate) {
350+
, DateTime validationDate, int certificateChainSize) {
343351
IX509Certificate issuerCertificate = null;
344352
try {
345353
issuerCertificate = (IX509Certificate)certificateRetriever.RetrieveIssuerCertificate(certificate);
@@ -370,7 +378,7 @@ private void ValidateChain(ValidationReport result, ValidationContext context, I
370378
return;
371379
}
372380
this.Validate(result, context.SetCertificateSource(CertificateSource.CERT_ISSUER), issuerCertificate, validationDate
373-
);
381+
, certificateChainSize + 1);
374382
}
375383
}
376384
}

itext/itext.sign/itext/signatures/validation/v1/SignatureValidationProperties.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public SignatureValidationProperties() {
7070
<CertificateExtension>(new KeyUsageExtension(KeyUsage.NON_REPUDIATION)));
7171
IList<CertificateExtension> certIssuerRequiredExtensions = new List<CertificateExtension>();
7272
certIssuerRequiredExtensions.Add(new KeyUsageExtension(KeyUsage.KEY_CERT_SIGN));
73-
certIssuerRequiredExtensions.Add(new BasicConstraintsExtension(true));
73+
certIssuerRequiredExtensions.Add(new DynamicBasicConstraintsExtension());
7474
SetRequiredExtensions(CertificateSources.Of(CertificateSource.CERT_ISSUER), certIssuerRequiredExtensions);
7575
SetRequiredExtensions(CertificateSources.Of(CertificateSource.TIMESTAMP), JavaCollectionsUtil.SingletonList
7676
<CertificateExtension>(new ExtendedKeyUsageExtension(JavaCollectionsUtil.SingletonList<String>(ExtendedKeyUsageExtension

itext/itext.sign/itext/signatures/validation/v1/extensions/BasicConstraintsExtension.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ You should have received a copy of the GNU Affero General Public License
2828

2929
namespace iText.Signatures.Validation.V1.Extensions {
3030
/// <summary>Class representing "Basic Constraints" certificate extension.</summary>
31+
[System.ObsoleteAttribute(@"since 8.0.5. To be removed.")]
3132
public class BasicConstraintsExtension : CertificateExtension {
3233
private static readonly IBouncyCastleFactory FACTORY = BouncyCastleFactoryCreator.GetFactory();
3334

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
using iText.Bouncycastleconnector;
2+
using iText.Commons.Bouncycastle;
3+
using iText.Commons.Bouncycastle.Cert;
4+
using iText.Signatures;
5+
6+
namespace iText.Signatures.Validation.V1.Extensions {
7+
/// <summary>
8+
/// Class representing "Basic Constraints" certificate extension,
9+
/// which uses provided amount of certificates in chain during the comparison.
10+
/// </summary>
11+
public class DynamicBasicConstraintsExtension : DynamicCertificateExtension {
12+
private static readonly IBouncyCastleFactory FACTORY = BouncyCastleFactoryCreator.GetFactory();
13+
14+
/// <summary>
15+
/// Create new instance of
16+
/// <see cref="DynamicBasicConstraintsExtension"/>.
17+
/// </summary>
18+
public DynamicBasicConstraintsExtension()
19+
: base(OID.X509Extensions.BASIC_CONSTRAINTS, FACTORY.CreateBasicConstraints(true).ToASN1Primitive()) {
20+
}
21+
22+
/// <summary>Check if this extension is present in the provided certificate.</summary>
23+
/// <remarks>
24+
/// Check if this extension is present in the provided certificate.
25+
/// In case of
26+
/// <see cref="DynamicBasicConstraintsExtension"/>
27+
/// , check if path length for this extension is less or equal
28+
/// to the path length, specified in the certificate.
29+
/// </remarks>
30+
/// <param name="certificate">
31+
///
32+
/// <see cref="iText.Commons.Bouncycastle.Cert.IX509Certificate"/>
33+
/// in which this extension shall be present
34+
/// </param>
35+
/// <returns>
36+
///
37+
/// <see langword="true"/>
38+
/// if this path length is less or equal to a one from the certificate,
39+
/// <see langword="false"/>
40+
/// otherwise
41+
/// </returns>
42+
public override bool ExistsInCertificate(IX509Certificate certificate) {
43+
try {
44+
if (CertificateUtil.GetExtensionValue(certificate, OID.X509Extensions.BASIC_CONSTRAINTS) == null) {
45+
return false;
46+
}
47+
}
48+
catch (System.IO.IOException) {
49+
return false;
50+
}
51+
return certificate.GetBasicConstraints() >= GetCertificateChainSize();
52+
}
53+
}
54+
}

0 commit comments

Comments
 (0)