aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Neus <[email protected]>2017-05-19 12:21:30 +0200
committerDaniel Neus <[email protected]>2017-05-19 12:33:03 +0200
commit9618c63002b2c620affea5f4475d275ce7c46643 (patch)
tree2fd1356654aa64d08ff2927edb6da7974ff95ab1
parent2f53dc937f33816445c7646b88e0ad826d197482 (diff)
fix pathLenConstraint validation
Fixes GH #991 The problem with the current implementation of the chain validation code is that is runs from the end certificate to the trust cert. @securitykernel and me tried to fix the pathLenConstraint validation within this reverse loop but we were not sure if we missed some edge cases. So we felt safer to use the algorithm listed in RFC 5280 which executes from the top to the bottom. It's probably best to rewrite the code to use the whole algorithm from RFC 5280, i.e. validating the chain from the trust to the end cert. Additionally, we wrote some tests including the one that raised this issue initially.
-rw-r--r--src/lib/x509/x509cert.cpp2
-rw-r--r--src/lib/x509/x509path.cpp37
-rw-r--r--src/tests/data/extended_x509/01/end.crt19
-rw-r--r--src/tests/data/extended_x509/01/int.crt18
-rw-r--r--src/tests/data/extended_x509/01/root.crt18
-rw-r--r--src/tests/data/extended_x509/02/end.crt20
-rw-r--r--src/tests/data/extended_x509/02/int1-2.crt20
-rw-r--r--src/tests/data/extended_x509/02/int1.crt20
-rw-r--r--src/tests/data/extended_x509/02/root.crt20
-rw-r--r--src/tests/data/extended_x509/03/end.crt20
-rw-r--r--src/tests/data/extended_x509/03/int1.crt20
-rw-r--r--src/tests/data/extended_x509/03/root.crt20
-rw-r--r--src/tests/data/extended_x509/expected.txt3
-rw-r--r--src/tests/test_x509_path.cpp78
14 files changed, 310 insertions, 5 deletions
diff --git a/src/lib/x509/x509cert.cpp b/src/lib/x509/x509cert.cpp
index 512e4aa63..40bdbf477 100644
--- a/src/lib/x509/x509cert.cpp
+++ b/src/lib/x509/x509cert.cpp
@@ -334,7 +334,7 @@ bool X509_Certificate::has_ex_constraint(const std::string& ex_constraint) const
*/
uint32_t X509_Certificate::path_limit() const
{
- return m_subject.get1_uint32("X509v3.BasicConstraints.path_constraint", 0);
+ return m_subject.get1_uint32("X509v3.BasicConstraints.path_constraint", Cert_Extension::NO_CERT_PATH_LIMIT);
}
/*
diff --git a/src/lib/x509/x509path.cpp b/src/lib/x509/x509path.cpp
index 8521e51a7..a06df2460 100644
--- a/src/lib/x509/x509path.cpp
+++ b/src/lib/x509/x509path.cpp
@@ -76,13 +76,9 @@ PKIX::check_chain(const std::vector<std::shared_ptr<const X509_Certificate>>& ce
status.insert(Certificate_Status_Code::CERT_HAS_EXPIRED);
// Check issuer constraints
-
if(!issuer->is_CA_cert() && !self_signed_ee_cert)
status.insert(Certificate_Status_Code::CA_CERT_NOT_FOR_CERT_ISSUER);
- if(issuer->path_limit() < i)
- status.insert(Certificate_Status_Code::CERT_CHAIN_TOO_LONG);
-
std::unique_ptr<Public_Key> issuer_key(issuer->subject_public_key());
if(!issuer_key)
@@ -115,6 +111,39 @@ PKIX::check_chain(const std::vector<std::shared_ptr<const X509_Certificate>>& ce
}
}
+ // path len check
+ size_t max_path_length = cert_path.size();
+ for(size_t i = cert_path.size() - 1; i > 0 ; --i)
+ {
+ std::set<Certificate_Status_Code>& status = cert_status.at(i);
+ const std::shared_ptr<const X509_Certificate>& subject = cert_path[i];
+
+ /*
+ * If the certificate was not self-issued, verify that max_path_length is
+ * greater than zero and decrement max_path_length by 1.
+ */
+ if(subject->subject_dn() != subject->issuer_dn())
+ {
+ if(max_path_length > 0)
+ {
+ --max_path_length;
+ }
+ else
+ {
+ status.insert(Certificate_Status_Code::CERT_CHAIN_TOO_LONG);
+ }
+ }
+
+ /*
+ * If pathLenConstraint is present in the certificate and is less than max_path_length,
+ * set max_path_length to the value of pathLenConstraint.
+ */
+ if(subject->path_limit() != Cert_Extension::NO_CERT_PATH_LIMIT && subject->path_limit() < max_path_length)
+ {
+ max_path_length = subject->path_limit();
+ }
+ }
+
return cert_status;
}
diff --git a/src/tests/data/extended_x509/01/end.crt b/src/tests/data/extended_x509/01/end.crt
new file mode 100644
index 000000000..5d05a8e5e
--- /dev/null
+++ b/src/tests/data/extended_x509/01/end.crt
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDDDCCAfSgAwIBAgIBAzANBgkqhkiG9w0BAQsFADAbMQswCQYDVQQGEwJERTEM
+MAoGA1UEAxMDSW50MB4XDTE3MDMzMTIwMzYwMFoXDTE4MDMzMTIwMzYwMFowGjEL
+MAkGA1UEBhMCREUxCzAJBgNVBAMTAkVFMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAt3ZPYYEIMIAViK68jKugGUMIISV4X7JjUz3/k44E2E2ovPem7mhq
+JPOzKpaS9+AOzEIJQIT+a6Re4+DmUNvW9Zm6P2J4Lrc8ixoCejMSwrtyqCCTJ+ef
+i6o82d0Tgge4ZnudiIzozUJy1rAS5T+rV6re3SUdKdjgLkva735Bve67/gS9eh5L
+AIQpN8ZPa4+qzbwfGZe3PGgOV2701LzQCrVRe7KWpm1ZjOi5WTRh0xAHiC6WpM2F
+eF0aRkC18Sat3FTi0ba2cqikttPnghFhShLUyUvn/LrLsk/ajGaArbV88Hk+p8l/
+pXhNh1X0zftxS/Fa1QCFbb4OxQMSmGZgMwIDAQABo1wwWjAMBgNVHRMBAf8EAjAA
+MB0GA1UdDgQWBBRH3e2M6wVjMMj76gDRe1/q5KkFwDALBgNVHQ8EBAMCBLAwHgYJ
+YIZIAYb4QgENBBEWD3hjYSBjZXJ0aWZpY2F0ZTANBgkqhkiG9w0BAQsFAAOCAQEA
+TF2AdhF57cBnjmeiv+HKKgjybWvA2X14k+rdRasNg87oJ/v2Kf/llJkUu2vs44tQ
+8HrmET6nq+0dPdJL4SsgyYqCW82hGh0W1saSFyCq+Wbk4DSFbHopOxlbbgX4GUJ/
+wfRY6BVRhz3IdPR4TM0zJ4o3nk+OTfBi+3ckfaK5DYNsnYbZwoG92ISMSRHGmg6g
+UYXOVmHmzIFK0ESl8+om2VsbWPRUCBOtU1BJLYwpx4RyIBBYPHR4npu+OpNrcBzR
+MaZuHuoKbqvZlvCclbd37YffyWryOGEf+YcjQPy8BqFMUQBBRH9gW4Ph819UYFpb
+IozFU/jYzXzXoxG4hMqtHA==
+-----END CERTIFICATE-----
diff --git a/src/tests/data/extended_x509/01/int.crt b/src/tests/data/extended_x509/01/int.crt
new file mode 100644
index 000000000..b6708f169
--- /dev/null
+++ b/src/tests/data/extended_x509/01/int.crt
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC8TCCAdmgAwIBAgIBAjANBgkqhkiG9w0BAQsFADAcMQswCQYDVQQGEwJERTEN
+MAsGA1UEAxMEUm9vdDAeFw0xNzAzMzEyMDM1MDBaFw0yNzAzMzEyMDM1MDBaMBsx
+CzAJBgNVBAYTAkRFMQwwCgYDVQQDEwNJbnQwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQC7vyhLG+LWNHi/7MdX971HRqc8TD0aSG4nbclEeV+mGPRhdbVD
+A+ZQn8Bj26iqRMJ8WT6+/M1rycOaAcEsfGSjPCSqrBuyo973nqMgiTfCgucFYtj/
+jkUArJQ8yuNJkLXkQK+4S0iSA1h7nPLwC967qPKcJnQgeHJDjKU9AefXoda66zxO
+kbaX4y5oY346tWP/0pjDeo2zix15jajPrAvCtDFJrYni71ixFNHZRI159cscSvfR
+I2lNnkUJ/M/6UnwflYgin7N/DHk/oad96bXatuKmdCWA/5R4FAnAhwdL7sbTy4LL
+jV8amewEhSn51iSFqVIm6wO7NiZw8D3/603TAgMBAAGjPzA9MA8GA1UdEwEB/wQF
+MAMBAf8wHQYDVR0OBBYEFHs9prehJUV7V9rn0KlYPmZqzRXXMAsGA1UdDwQEAwIB
+BjANBgkqhkiG9w0BAQsFAAOCAQEADsKaZEuxy9upg0HTxWy2RfY8im+Xg5qkU2IW
++vSFr1QoZWVn59y3WzeoBqi9dFquQyUjTvPUHJoplh9CvHWZbL0ih/NUt70uy/Jz
+kyacpcFEbiAZD6sPCe6JwOSrEAEnTRDpP2Gn6gRxVOXGptMFpX54yxf4shZJnyy/
+r1iY11WQGy4qJS+20eUj4CxqletBzKfMiar9oX9sJl/Go1KzZexnIqli2v1/KevX
+6PRc+ubmz4aZzkRzP9v0Ie8YxJmjY5LLnhjY/G2GV8I6p8y5UqYkYRPvGJXB5WAi
+1b6uvuEhgatAelk1mn95Pv7W8ASLWbbV4OippdZUdOCkxs/D+w==
+-----END CERTIFICATE-----
diff --git a/src/tests/data/extended_x509/01/root.crt b/src/tests/data/extended_x509/01/root.crt
new file mode 100644
index 000000000..f83c6c516
--- /dev/null
+++ b/src/tests/data/extended_x509/01/root.crt
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC9TCCAd2gAwIBAgIBATANBgkqhkiG9w0BAQsFADAcMQswCQYDVQQGEwJERTEN
+MAsGA1UEAxMEUm9vdDAeFw0xNzAzMzEyMDMzMDBaFw0yNzAzMzEyMDMzMDBaMBwx
+CzAJBgNVBAYTAkRFMQ0wCwYDVQQDEwRSb290MIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEA86tiSCsS6wRGe/iylnLS3WnxcWM/x8qrQZQ5JAaB7LMR6Dfp
+DSBk9vU4/h0CbYVr9+7an3dEDA6Raoh+qLDklspqDQ5cXlYee8GMutQbSTxtKA+4
+fgIrT18JyBu993IBszwj01BVD+Ibun+Bw/pg7dYD3w+T60njMb4EirU5/0e1CKxB
+iv5UEY7R6DkIU4QXHzvj0Dstls5XTsIAODuh4IEwsnMq9ZQi7Cl4AflUABAY0w6B
+nEhbb3wMmg1ndDnv9RcOP3IQzIFuQG3i8SdH1Rik/00N9Mom7sRCulrPhZoNFbTV
+tQ9PZ8iQPUNzJNrIkWZ/O9uN023wtbiGlgSytQIDAQABo0IwQDASBgNVHRMBAf8E
+CDAGAQH/AgEBMB0GA1UdDgQWBBRfG0Pzn9XuCESFgLCJOWpwAC/XFDALBgNVHQ8E
+BAMCAQYwDQYJKoZIhvcNAQELBQADggEBAH2RqhCbx3SjljbbqPq8dxUccLvtIf/S
+oxPn7ogdG3WuwfCQzXJ7v0HwcLTytF+/zYYgPTip9RmQdVqym9YjlDAG5NlFQm3b
+jYZQ0gUrG56tb57K1YjQcrUU15ewbILZU0N0gfs+p1PMUkFsVVsPienO7j0aRKmB
+U6Ecgma8kS/++QvlFlgXE+shdzXjN92nuqHeJ8aNaPb7ueD6b82+LK8ZuCPPtHUN
+EdCzKWYlHzMKklLVbfzXbHG5yiiim9OaFqsY+7ljWJiT//s5bbGRJjBb2GCSwVvI
+wOubEvVrJ02l7U69LxaHsXXRlKw3vq1Z3HbKAIJlWMIPvaFQKnY9RdI=
+-----END CERTIFICATE-----
diff --git a/src/tests/data/extended_x509/02/end.crt b/src/tests/data/extended_x509/02/end.crt
new file mode 100644
index 000000000..b0dc343b6
--- /dev/null
+++ b/src/tests/data/extended_x509/02/end.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDOzCCAiOgAwIBAgIBBDANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDExRQYXRo
+TGVuIFRlc3QgSW50MSBDQTAeFw0xNzA1MTcxMjQyMDBaFw0xODA1MTcxMjQyMDBa
+MBoxGDAWBgNVBAMTD1BhdGhMZW4gVGVzdCBFRTCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAMrhTUs/sAT4S2JMYFh8Z7bSzgQLqt3l+cAW1mgiw3ydh0+L
+aytLRmyJrX0K6B2zEZKilbPXPJW2O1fY5lIvrYz0HGJRcQWRhZ9IaAqkWNSrIGR6
+bCodpDH/Lr3nUuvsaLobFs+e+YLdXu1TwQMBieIi5eXuwaPIpcGi8Byl2iBsS9UT
+CYDj08rwOwF8f/zgWJK/2to2TraHTHw+rjlOL5MEXxjLC50ZnKaAzw4K49mnRv8U
+exzs67250Sa0ZONB3nh1/Z+FBNIsdXcNDoMtn04/sk1F/TF3f8jA3h+HOvfGrE6O
+dqJ6DJK4UD/RqfRiD0+6Spcx+eu2rR2ss9ISKJ8CAwEAAaOBhjCBgzAMBgNVHRMB
+Af8EAjAAMB0GA1UdDgQWBBTrUJdF9MaI2YaBus2Teo09rq/YEDBHBgNVHSMEQDA+
+gBRBtmp9tx8Q7LqmvCh8n9jxgmLcsqEjpCEwHzEdMBsGA1UEAxMUUGF0aExlbiBU
+ZXN0IEludDEgQ0GCAQMwCwYDVR0PBAQDAgXgMA0GCSqGSIb3DQEBCwUAA4IBAQBA
+q9bK4nMz0H2vLmSfiqbNB7chjKztAzQkD1YZTDmyuDVFXNu6ooClWOIOAPj0/XrL
+s2LHz0KodS4QkEStoK8lsFDmo6lNCKVkGsSNUUwmWa2P43EpmzZdVSd0tk/BSA0O
+dPifwTncW9hsseHoe5G29ddLdnRE9MH/5rrLOMFPSa0wHOXNqbt6wAANTwrBY+QV
+xFQSmkBiICqJqCpcqe7gH/x9lgNYdQxBCnR6pitj6uxmOLl40qzfVfzKQe8hovyA
+piOjaYJ4i4j7xl3nlsw4CjaRitpDwLXjL8LQfdoOD/FWj18+DFcH59azqBjoyr6x
+OtnVSv2VDcvcvhNHiqCy
+-----END CERTIFICATE-----
diff --git a/src/tests/data/extended_x509/02/int1-2.crt b/src/tests/data/extended_x509/02/int1-2.crt
new file mode 100644
index 000000000..6c93d0492
--- /dev/null
+++ b/src/tests/data/extended_x509/02/int1-2.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDRjCCAi6gAwIBAgIBAzANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDExRQYXRo
+TGVuIFRlc3QgSW50MSBDQTAeFw0xNzA1MTcxMjQxMDBaFw0yNzA1MTcxMjQxMDBa
+MB8xHTAbBgNVBAMTFFBhdGhMZW4gVGVzdCBJbnQxIENBMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEAoQGuLP6gafHVnoyFbtTVBV+Svc6TwG6nBLWMj5oI
+csWF5815WuDKJCIef0FzT81ew2PqxJKqvwu68+IW6v5EmIMO99fig80/o/IVWwuv
+/ycRIth4UJsEpg25QUiFwBcmeJ3Hhjrf+2cPqKLT7dCiz+FJY6fXQdpo8vtJVMSa
+8u5oA0NoSYnVnRrT8mDP2io1egWkwdFjn4JLZ99UYVBCEi/Pp3DNhtkn3rwaIm6v
+SGxKxtgHWqTmldeCB+k7YVOPOYLbAlhNknpXFiU4Op0hEFMtgnUXGH5s2bJNM0sS
+VOBG78UIfRPxumkPYelzPCUsYbRJ7PulybtNdtWFPtlDewIDAQABo4GMMIGJMBIG
+A1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFEG2an23HxDsuqa8KHyf2PGCYtyy
+MEcGA1UdIwRAMD6AFNtU+/YoX0TQdnd50WtkXsyilRoGoSOkITAfMR0wGwYDVQQD
+ExRQYXRoTGVuIFRlc3QgUm9vdCBDQYIBAjALBgNVHQ8EBAMCAQYwDQYJKoZIhvcN
+AQELBQADggEBAKWTS0/h4bDNbBQaELSMbYyyNw+WQKRJKRawoC9d89JywD/1xjM2
+byCySAOdsuWX5t8PuDIHjLu4vykF792Cpx3ToWztHTPYkpg/Ci25H4Vvhbdlb62X
+h712cQ0hEdrNC5Uahl3jUpYfdktF8un3fp33yazlF2PHswWtgFBpU3u0GZi4R7ft
+CsY1XzzxaEjBwfu8vDLf/kkdJBpXh97rkGhfogNSJ4+EAlqbJ+rTj1ucW7ou9M9d
+vvIHAx1lJWERoSDUDOIigpJaHSs2kIvF1/+pCW7pJiZ2EwD5S0Kj0m+6Evic/Vo0
+6Ff9EE6WPEMY4p3ykFc6+TIOj8Xbw03VFWI=
+-----END CERTIFICATE-----
diff --git a/src/tests/data/extended_x509/02/int1.crt b/src/tests/data/extended_x509/02/int1.crt
new file mode 100644
index 000000000..66a5d9a8c
--- /dev/null
+++ b/src/tests/data/extended_x509/02/int1.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDRjCCAi6gAwIBAgIBAjANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDExRQYXRo
+TGVuIFRlc3QgUm9vdCBDQTAeFw0xNzA1MTcxMjQxMDBaFw0yNzA1MTcxMjQxMDBa
+MB8xHTAbBgNVBAMTFFBhdGhMZW4gVGVzdCBJbnQxIENBMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEAvcX2nM3+B9OTzmVbl80c6rBnoCCINvrsRNEqPET5
+zF5NSGZzJJo3GF9iZCov4rLSWIgyHqekWIbs5JximdIc5JaNkEeic6RYU4u+5GFI
+ki2qXfNiqIPgxAO2F8/7W0nXa5B+2kH8d62m2um8ONY6f1NkBM+bTLgMb78K3js4
+eftYjRVd3EFzBEiIVKj3VyGRtbiNWZCRbT7/X4tCjYVwjFZejbyZkQJv5qhbWv0X
+Il/6gNbvN5P1Iumy5yBfKwonJiYyLv3DZME5sexzAJa7OxNEwJApuY+93soA0iLd
+1WyzNpeL4hzNvpYUi5YuiLjA5oHLPmFYN96wKUAP9yWhfwIDAQABo4GMMIGJMBIG
+A1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFNtU+/YoX0TQdnd50WtkXsyilRoG
+MEcGA1UdIwRAMD6AFOphOYxY6kM+m0UT5FTvNLzki+2HoSOkITAfMR0wGwYDVQQD
+ExRQYXRoTGVuIFRlc3QgUm9vdCBDQYIBATALBgNVHQ8EBAMCAQYwDQYJKoZIhvcN
+AQELBQADggEBAHyi1KRBgrpu/bxiioRchfZN9AtVS2qeohA0WkDZbdbgI5j/sqgy
+IfVVQizBJVeTfFuv6C2davHnnpoDUTYwY4tiQz4ZJtTm2zLmUw3ennujlLJeBP5O
+ykjcU7lxAmf6vAdMvqRuIHvx/nYgE2G3T6sx7Doa5kdruCHosLvuUU6sP0cQjxsH
+x0gbDTvE+DjIjrSlCAVBwNB0zcOHG0A/fV2SEHy4Pi/JthEvXExngXnNMFlPEA58
+1FL8M0bpxW3M2tchFoGhTrSDt4hkYqsV1kGK8zXgqT9PxyaSE9lvNjBVtGNbt+9Q
+jMbhRokpXaUALVxpHN5gC2YOO9yYD40EPUU=
+-----END CERTIFICATE-----
diff --git a/src/tests/data/extended_x509/02/root.crt b/src/tests/data/extended_x509/02/root.crt
new file mode 100644
index 000000000..c66ac1c00
--- /dev/null
+++ b/src/tests/data/extended_x509/02/root.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDRjCCAi6gAwIBAgIBATANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDExRQYXRo
+TGVuIFRlc3QgUm9vdCBDQTAeFw0xNzA1MTcxMjM5MDBaFw0yNzA1MTcxMjM5MDBa
+MB8xHTAbBgNVBAMTFFBhdGhMZW4gVGVzdCBSb290IENBMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEAwGl+aRGnJVyfSZlnoD+r9R8KjsJE6aduNtmDrTxE
+XkKceCfcqDyCVyF7jufmxrLnSEHEz4cx3hMGkG3SrsWmpzoIrSbvLliJs8uopBHv
+yojTRoCMHP6BQeRIFl/Z9g0NMpP+wC2a2pLL6Notsc2WCMbZOelx8JpyZDgHMmgg
+JiHydtTf5jw6U8O/KRoAJcd8cNMnWHb+ibwZ621WpFk38C9RA95lNhF3GoAKRAxb
+4VV0b1UXDfWEo2ame7PHJv2COv4ufWfMVn011nrUYU8AuzJX+mZj3dFqbvri9rB1
+KVzYkZkhf+ih3BMbH/ZZn18LU3IDwkLubYpE9Vnd75DxsQIDAQABo4GMMIGJMBIG
+A1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYEFOphOYxY6kM+m0UT5FTvNLzki+2H
+MEcGA1UdIwRAMD6AFOphOYxY6kM+m0UT5FTvNLzki+2HoSOkITAfMR0wGwYDVQQD
+ExRQYXRoTGVuIFRlc3QgUm9vdCBDQYIBATALBgNVHQ8EBAMCAQYwDQYJKoZIhvcN
+AQELBQADggEBAHAIh/0/urh5Z5uY0D5XtGQ5ZVHSGb23i15mVFDQafMy1G5wsKRx
+/cO/Gg7U0TuAl8mxvOlJtLCIC/1RybRegmhkzsxWZVaavxlZvRW+mpquJBA32+Qn
+Tc8tdYftICzgowdCl0m2RlZJXDOc6//8LUqcIsz85XOeBjMMRSrkGIJU/Iq4xSyd
+zIqH+iilsP5r9MzBWCtwWFzy/noZAtl9aaHFtCPVTAE6L4rXxPEKFJ65nQdSl2pN
+4KqR6JImoGLoat87sVDjs4GJdbcyx6GSo8Qgj7cbxGkkD87jfPeqFMCJlf0bkTxX
+xgbGs+HNsuzjl5bfZtCFLDYVGrJ+TlFTn/s=
+-----END CERTIFICATE-----
diff --git a/src/tests/data/extended_x509/03/end.crt b/src/tests/data/extended_x509/03/end.crt
new file mode 100644
index 000000000..d4ef54dcf
--- /dev/null
+++ b/src/tests/data/extended_x509/03/end.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDQzCCAiugAwIBAgIBBDANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDExRQYXRo
+TGVuIFRlc3QgSW50MSBDQTAeFw0xNzA1MTcxMjQ2MDBaFw0yNzA1MTcxMjQ2MDBa
+MB8xHTAbBgNVBAMTFFBhdGhMZW4gVGVzdCBJbnQyIENBMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEAoQGuLP6gafHVnoyFbtTVBV+Svc6TwG6nBLWMj5oI
+csWF5815WuDKJCIef0FzT81ew2PqxJKqvwu68+IW6v5EmIMO99fig80/o/IVWwuv
+/ycRIth4UJsEpg25QUiFwBcmeJ3Hhjrf+2cPqKLT7dCiz+FJY6fXQdpo8vtJVMSa
+8u5oA0NoSYnVnRrT8mDP2io1egWkwdFjn4JLZ99UYVBCEi/Pp3DNhtkn3rwaIm6v
+SGxKxtgHWqTmldeCB+k7YVOPOYLbAlhNknpXFiU4Op0hEFMtgnUXGH5s2bJNM0sS
+VOBG78UIfRPxumkPYelzPCUsYbRJ7PulybtNdtWFPtlDewIDAQABo4GJMIGGMA8G
+A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFEG2an23HxDsuqa8KHyf2PGCYtyyMEcG
+A1UdIwRAMD6AFNtU+/YoX0TQdnd50WtkXsyilRoGoSOkITAfMR0wGwYDVQQDExRQ
+YXRoTGVuIFRlc3QgUm9vdCBDQYIBAzALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEL
+BQADggEBAJMJUlCtT9OCt6G/jNRcZrsxprlVvGBpLItHF6Kol+gs/Pz93c3rLxj6
+czp2OqjZFsm6k0Fl6kSrBQHRH/dZdKZlsNtMnrF0RXonuJVBaSONKC6SFOc4E9qa
+nNfx/AB40IGdhKbgHNS/92Q4kIwV2JfbQPXTmOvFTtFH/saUoTmlMWaBIeEEjQX2
+/NjyCvSUvKVwAgTF/HWspzjuEVukiCszVOQV8UuhEnLSdvztuguf0CkM93W17x7t
+//R04hz+TOLCAp5OzeZB4y4UE+oroo1ynzdTnQ7PHMxh67+mX2piawc00zyHqqTf
+09z9uN4HmyJNQ4FXUvhC0Q+tISCaB68=
+-----END CERTIFICATE-----
diff --git a/src/tests/data/extended_x509/03/int1.crt b/src/tests/data/extended_x509/03/int1.crt
new file mode 100644
index 000000000..1e4ec713e
--- /dev/null
+++ b/src/tests/data/extended_x509/03/int1.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDQzCCAiugAwIBAgIBAzANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDExRQYXRo
+TGVuIFRlc3QgUm9vdCBDQTAeFw0xNzA1MTcxMjQ1MDBaFw0yNzA1MTcxMjQ1MDBa
+MB8xHTAbBgNVBAMTFFBhdGhMZW4gVGVzdCBJbnQxIENBMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEAvcX2nM3+B9OTzmVbl80c6rBnoCCINvrsRNEqPET5
+zF5NSGZzJJo3GF9iZCov4rLSWIgyHqekWIbs5JximdIc5JaNkEeic6RYU4u+5GFI
+ki2qXfNiqIPgxAO2F8/7W0nXa5B+2kH8d62m2um8ONY6f1NkBM+bTLgMb78K3js4
+eftYjRVd3EFzBEiIVKj3VyGRtbiNWZCRbT7/X4tCjYVwjFZejbyZkQJv5qhbWv0X
+Il/6gNbvN5P1Iumy5yBfKwonJiYyLv3DZME5sexzAJa7OxNEwJApuY+93soA0iLd
+1WyzNpeL4hzNvpYUi5YuiLjA5oHLPmFYN96wKUAP9yWhfwIDAQABo4GJMIGGMA8G
+A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNtU+/YoX0TQdnd50WtkXsyilRoGMEcG
+A1UdIwRAMD6AFOphOYxY6kM+m0UT5FTvNLzki+2HoSOkITAfMR0wGwYDVQQDExRQ
+YXRoTGVuIFRlc3QgUm9vdCBDQYIBATALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEL
+BQADggEBAK+euvQn4INuV1Dy12Vf8MYQQgFptU+ysBI8pXHxVjrR3VSk+LlNNwQ3
+50bKF/fNOb9YjosBYnPf/oL1O6yUEN+lNfsDwDK7P42poiUy4x+1oRua9AVYFKdP
+LTDhyfK/LQNMG3UizZLU7UwHZDTGpzeozUQB8yRIIJpnBw3hkD3ZK1GUGHiGPCN7
+A3f/D6sCRU3K9JIGrPjx8Nfuh9OEMsVDMCE2rGyhNz24EajFZoX+4C6lxzwDHMqR
+l7dW7TeplPalUHlpp1o+rJiJVxXTuL1cJr6jqmM1Uzbm/d/b2kwDyyX5xmTQBJ2g
+MqKPmIPvcEEsfuzOZCDb2HhSiaUI39M=
+-----END CERTIFICATE-----
diff --git a/src/tests/data/extended_x509/03/root.crt b/src/tests/data/extended_x509/03/root.crt
new file mode 100644
index 000000000..c66ac1c00
--- /dev/null
+++ b/src/tests/data/extended_x509/03/root.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDRjCCAi6gAwIBAgIBATANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDExRQYXRo
+TGVuIFRlc3QgUm9vdCBDQTAeFw0xNzA1MTcxMjM5MDBaFw0yNzA1MTcxMjM5MDBa
+MB8xHTAbBgNVBAMTFFBhdGhMZW4gVGVzdCBSb290IENBMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEAwGl+aRGnJVyfSZlnoD+r9R8KjsJE6aduNtmDrTxE
+XkKceCfcqDyCVyF7jufmxrLnSEHEz4cx3hMGkG3SrsWmpzoIrSbvLliJs8uopBHv
+yojTRoCMHP6BQeRIFl/Z9g0NMpP+wC2a2pLL6Notsc2WCMbZOelx8JpyZDgHMmgg
+JiHydtTf5jw6U8O/KRoAJcd8cNMnWHb+ibwZ621WpFk38C9RA95lNhF3GoAKRAxb
+4VV0b1UXDfWEo2ame7PHJv2COv4ufWfMVn011nrUYU8AuzJX+mZj3dFqbvri9rB1
+KVzYkZkhf+ih3BMbH/ZZn18LU3IDwkLubYpE9Vnd75DxsQIDAQABo4GMMIGJMBIG
+A1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYEFOphOYxY6kM+m0UT5FTvNLzki+2H
+MEcGA1UdIwRAMD6AFOphOYxY6kM+m0UT5FTvNLzki+2HoSOkITAfMR0wGwYDVQQD
+ExRQYXRoTGVuIFRlc3QgUm9vdCBDQYIBATALBgNVHQ8EBAMCAQYwDQYJKoZIhvcN
+AQELBQADggEBAHAIh/0/urh5Z5uY0D5XtGQ5ZVHSGb23i15mVFDQafMy1G5wsKRx
+/cO/Gg7U0TuAl8mxvOlJtLCIC/1RybRegmhkzsxWZVaavxlZvRW+mpquJBA32+Qn
+Tc8tdYftICzgowdCl0m2RlZJXDOc6//8LUqcIsz85XOeBjMMRSrkGIJU/Iq4xSyd
+zIqH+iilsP5r9MzBWCtwWFzy/noZAtl9aaHFtCPVTAE6L4rXxPEKFJ65nQdSl2pN
+4KqR6JImoGLoat87sVDjs4GJdbcyx6GSo8Qgj7cbxGkkD87jfPeqFMCJlf0bkTxX
+xgbGs+HNsuzjl5bfZtCFLDYVGrJ+TlFTn/s=
+-----END CERTIFICATE-----
diff --git a/src/tests/data/extended_x509/expected.txt b/src/tests/data/extended_x509/expected.txt
new file mode 100644
index 000000000..ee6fc5943
--- /dev/null
+++ b/src/tests/data/extended_x509/expected.txt
@@ -0,0 +1,3 @@
+01:Verified
+02:Verified
+03:Verified \ No newline at end of file
diff --git a/src/tests/test_x509_path.cpp b/src/tests/test_x509_path.cpp
index 5fc20e3d7..e7cd9c18c 100644
--- a/src/tests/test_x509_path.cpp
+++ b/src/tests/test_x509_path.cpp
@@ -240,6 +240,84 @@ std::vector<Test::Result> NIST_Path_Validation_Tests::run()
BOTAN_REGISTER_TEST("x509_path_nist", NIST_Path_Validation_Tests);
+class Extended_Path_Validation_Tests : public Test
+ {
+ public:
+ std::vector<Test::Result> run() override;
+ };
+
+std::vector<Test::Result> Extended_Path_Validation_Tests::run()
+ {
+ std::vector<Test::Result> results;
+
+ const std::string extended_x509_test_dir = Test::data_dir() + "/extended_x509";
+
+ try
+ {
+ // Do nothing, just test filesystem access
+ Botan::get_files_recursive(extended_x509_test_dir);
+ }
+ catch(Botan::No_Filesystem_Access&)
+ {
+ Test::Result result("Extended x509 path validation");
+ result.test_note("Skipping due to missing filesystem access");
+ results.push_back(result);
+ return results;
+ }
+
+ std::map<std::string, std::string> expected =
+ read_results(Test::data_file("extended_x509/expected.txt"));
+
+ for(auto i = expected.begin(); i != expected.end(); ++i)
+ {
+ const std::string test_name = i->first;
+ const std::string expected_result = i->second;
+
+ const std::string test_dir = extended_x509_test_dir + "/" + test_name;
+
+ Test::Result result("Extended X509 path validation");
+ result.start_timer();
+
+ const std::vector<std::string> all_files = Botan::get_files_recursive(test_dir);
+
+ if(all_files.empty())
+ {
+ result.test_failure("No test files found in " + test_dir);
+ results.push_back(result);
+ continue;
+ }
+
+ Botan::Certificate_Store_In_Memory store;
+
+ for(auto const& file : all_files)
+ {
+ if(file.find(".crt") != std::string::npos && file != "end.crt")
+ {
+ store.add_certificate(Botan::X509_Certificate(file));
+ }
+ }
+
+ Botan::X509_Certificate end_user(test_dir + "/end.crt");
+
+ Botan::Path_Validation_Restrictions restrictions;
+ Botan::Path_Validation_Result validation_result =
+ Botan::x509_path_validate(end_user,
+ restrictions,
+ store);
+
+ result.test_eq(test_name + " path validation result",
+ validation_result.result_string(),
+ expected_result);
+
+ result.end_timer();
+ results.push_back(result);
+ }
+
+ return results;
+ }
+
+BOTAN_REGISTER_TEST("x509_path_extended", Extended_Path_Validation_Tests);
+
#endif
}