aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/build-data/oids.txt1
-rw-r--r--src/lib/asn1/oids.cpp4
-rw-r--r--src/lib/x509/x509_ext.cpp11
-rw-r--r--src/lib/x509/x509_ext.h11
-rw-r--r--src/lib/x509/x509cert.cpp16
-rw-r--r--src/lib/x509/x509cert.h5
-rw-r--r--src/tests/data/x509/misc/contains_authority_info_access.pem31
-rw-r--r--src/tests/data/x509/misc/contains_authority_info_access_with_two_ca_issuers.pem46
-rw-r--r--src/tests/unit_x509.cpp39
9 files changed, 160 insertions, 4 deletions
diff --git a/src/build-data/oids.txt b/src/build-data/oids.txt
index 089523e69..321439e5b 100644
--- a/src/build-data/oids.txt
+++ b/src/build-data/oids.txt
@@ -235,6 +235,7 @@
1.3.6.1.5.5.7.48.1 = PKIX.OCSP
1.3.6.1.5.5.7.48.1.1 = PKIX.OCSP.BasicResponse
+1.3.6.1.5.5.7.48.2 = PKIX.CertificateAuthorityIssuers
1.3.6.1.4.1.311.20.2.2 = Microsoft SmartcardLogon
diff --git a/src/lib/asn1/oids.cpp b/src/lib/asn1/oids.cpp
index 2c97f1d29..b60ec24d2 100644
--- a/src/lib/asn1/oids.cpp
+++ b/src/lib/asn1/oids.cpp
@@ -1,7 +1,7 @@
/*
* OID maps
*
-* This file was automatically generated by ./src/scripts/oids.py on 2017-12-05
+* This file was automatically generated by ./src/scripts/oids.py on 2018-01-03
*
* All manual edits to this file will be lost. Edit the script
* then regenerate this source file.
@@ -143,6 +143,7 @@ std::string lookup(const OID& oid)
if(oid_str == "1.3.6.1.5.5.7.3.9") return "PKIX.OCSPSigning";
if(oid_str == "1.3.6.1.5.5.7.48.1") return "PKIX.OCSP";
if(oid_str == "1.3.6.1.5.5.7.48.1.1") return "PKIX.OCSP.BasicResponse";
+ if(oid_str == "1.3.6.1.5.5.7.48.2") return "PKIX.CertificateAuthorityIssuers";
if(oid_str == "1.3.6.1.5.5.7.8.5") return "PKIX.XMPPAddr";
if(oid_str == "2.16.840.1.101.3.4.1.2") return "AES-128/CBC";
if(oid_str == "2.16.840.1.101.3.4.1.22") return "AES-192/CBC";
@@ -303,6 +304,7 @@ OID lookup(const std::string& name)
if(name == "PKCS9.MessageDigest") return OID("1.2.840.113549.1.9.4");
if(name == "PKCS9.UnstructuredName") return OID("1.2.840.113549.1.9.2");
if(name == "PKIX.AuthorityInformationAccess") return OID("1.3.6.1.5.5.7.1.1");
+ if(name == "PKIX.CertificateAuthorityIssuers") return OID("1.3.6.1.5.5.7.48.2");
if(name == "PKIX.ClientAuth") return OID("1.3.6.1.5.5.7.3.2");
if(name == "PKIX.CodeSigning") return OID("1.3.6.1.5.5.7.3.3");
if(name == "PKIX.EmailProtection") return OID("1.3.6.1.5.5.7.3.4");
diff --git a/src/lib/x509/x509_ext.cpp b/src/lib/x509/x509_ext.cpp
index afb79f6bf..c3b58236a 100644
--- a/src/lib/x509/x509_ext.cpp
+++ b/src/lib/x509/x509_ext.cpp
@@ -777,6 +777,15 @@ void Authority_Information_Access::decode_inner(const std::vector<uint8_t>& in)
}
}
+ if(oid == OIDS::lookup("PKIX.CertificateAuthorityIssuers"))
+ {
+ BER_Object name = info.get_next_object();
+
+ if(name.type_tag == 6 && name.class_tag == CONTEXT_SPECIFIC)
+ {
+ m_ca_issuers.push_back(ASN1::to_string(name));
+ }
+ }
}
}
@@ -784,6 +793,8 @@ void Authority_Information_Access::contents_to(Data_Store& subject, Data_Store&)
{
if(!m_ocsp_responder.empty())
subject.add("OCSP.responder", m_ocsp_responder);
+ for(const std::string& ca_issuer : m_ca_issuers)
+ subject.add("PKIX.CertificateAuthorityIssuers", ca_issuer);
}
/*
diff --git a/src/lib/x509/x509_ext.h b/src/lib/x509/x509_ext.h
index 235496cbd..8e702daf1 100644
--- a/src/lib/x509/x509_ext.h
+++ b/src/lib/x509/x509_ext.h
@@ -544,21 +544,25 @@ class BOTAN_PUBLIC_API(2,0) Certificate_Policies final : public Certificate_Exte
std::vector<OID> m_oids;
};
+/**
+* Authority Information Access Extension
+*/
class BOTAN_PUBLIC_API(2,0) Authority_Information_Access final : public Certificate_Extension
{
public:
Authority_Information_Access* copy() const override
- { return new Authority_Information_Access(m_ocsp_responder); }
+ { return new Authority_Information_Access(m_ocsp_responder, m_ca_issuers); }
Authority_Information_Access() = default;
- explicit Authority_Information_Access(const std::string& ocsp) :
- m_ocsp_responder(ocsp) {}
+ explicit Authority_Information_Access(const std::string& ocsp, const std::vector<std::string>& ca_issuers = std::vector<std::string>()) :
+ m_ocsp_responder(ocsp), m_ca_issuers(ca_issuers) {}
std::string ocsp_responder() const { return m_ocsp_responder; }
static OID static_oid() { return OID("1.3.6.1.5.5.7.1.1"); }
OID oid_of() const override { return static_oid(); }
+ const std::vector<std::string> ca_issuers() const { return m_ca_issuers; }
private:
std::string oid_name() const override
@@ -572,6 +576,7 @@ class BOTAN_PUBLIC_API(2,0) Authority_Information_Access final : public Certific
void contents_to(Data_Store&, Data_Store&) const override;
std::string m_ocsp_responder;
+ std::vector<std::string> m_ca_issuers;
};
/**
diff --git a/src/lib/x509/x509cert.cpp b/src/lib/x509/x509cert.cpp
index dd0514dfb..f298006c0 100644
--- a/src/lib/x509/x509cert.cpp
+++ b/src/lib/x509/x509cert.cpp
@@ -47,6 +47,7 @@ struct X509_Certificate_Data
std::vector<std::string> m_crl_distribution_points;
std::string m_ocsp_responder;
+ std::vector<std::string> m_ca_issuers;
AlternativeName m_subject_alt_name;
AlternativeName m_issuer_alt_name;
@@ -262,6 +263,7 @@ std::unique_ptr<X509_Certificate_Data> parse_x509_cert_body(const X509_Object& o
if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Authority_Information_Access>())
{
data->m_ocsp_responder = ext->ocsp_responder();
+ data->m_ca_issuers = ext->ca_issuers();
}
if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::CRL_Distribution_Points>())
@@ -543,6 +545,11 @@ std::string X509_Certificate::ocsp_responder() const
return data().m_ocsp_responder;
}
+std::vector<std::string> X509_Certificate::ca_issuers() const
+ {
+ return data().m_ca_issuers;
+ }
+
std::string X509_Certificate::crl_distribution_point() const
{
// just returns the first (arbitrarily)
@@ -815,6 +822,15 @@ std::string X509_Certificate::to_string() const
if(!ocsp_responder().empty())
out << "OCSP responder " << ocsp_responder() << "\n";
+
+ std::vector<std::string> ca_issuers = this->ca_issuers();
+ if(!ca_issuers.empty())
+ {
+ out << "CA Issuers:\n";
+ for(size_t i = 0; i != ca_issuers.size(); i++)
+ out << " URI: " << ca_issuers[i] << "\n";
+ }
+
if(!crl_distribution_point().empty())
out << "CRL " << crl_distribution_point() << "\n";
diff --git a/src/lib/x509/x509cert.h b/src/lib/x509/x509cert.h
index e87e5e436..a1448637d 100644
--- a/src/lib/x509/x509cert.h
+++ b/src/lib/x509/x509cert.h
@@ -346,6 +346,11 @@ class BOTAN_PUBLIC_API(2,0) X509_Certificate : public X509_Object
std::string ocsp_responder() const;
/**
+ * Return the listed addresses of ca issuers, or empty if not set
+ */
+ std::vector<std::string> ca_issuers() const;
+
+ /**
* Return the CRL distribution point, or empty if not set
*/
std::string crl_distribution_point() const;
diff --git a/src/tests/data/x509/misc/contains_authority_info_access.pem b/src/tests/data/x509/misc/contains_authority_info_access.pem
new file mode 100644
index 000000000..5a0d780c7
--- /dev/null
+++ b/src/tests/data/x509/misc/contains_authority_info_access.pem
@@ -0,0 +1,31 @@
+-----BEGIN CERTIFICATE-----
+MIIFazCCBFOgAwIBAgIQA9OHVX59Hl5rTdrLvK1+iDANBgkqhkiG9w0BAQsFADBC
+MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMS
+UmFwaWRTU0wgU0hBMjU2IENBMB4XDTE3MDIwOTAwMDAwMFoXDTE4MDIxMTIzNTk1
+OVowGDEWMBQGA1UEAwwNKi5uZXhlbmlvLmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAPgFzshLD9g4UDCzD64Qt+ZMC6EfTfIRrTprIL32Bq94eu+l
+qEsuVgoXd9inV/52+mqzQXAa//zIY32XkW+kZVlD3zjC7jVZwV9gJJterrCpqLR0
+B4OECsciARJkasJwo82gt40OCgsUMWAwigl+geo93yuL403vB3wVOBD73e8I+W4D
+49sWSzfepyFMzg+JwTrs6GafNOG8S4ZlC/js4eUJl5MllMXUzzYa/flBqZ/U2nZ3
+MtbvgPiW7NPblrAaIUSTs2rJgXIT5zZnfbZWRcpY8uSuXLywMqf5mXIoUNrn1Xc5
+oVnva9PIUpnFG47aOQ39P6Q3u4R3FosREgdW2oUCAwEAAaOCAoUwggKBMCUGA1Ud
+EQQeMByCDSoubmV4ZW5pby5jb22CC25leGVuaW8uY29tMAkGA1UdEwQCMAAwKwYD
+VR0fBCQwIjAgoB6gHIYaaHR0cDovL2dwLnN5bWNiLmNvbS9ncC5jcmwwbwYDVR0g
+BGgwZjBkBgZngQwBAgEwWjAqBggrBgEFBQcCARYeaHR0cHM6Ly93d3cucmFwaWRz
+c2wuY29tL2xlZ2FsMCwGCCsGAQUFBwICMCAMHmh0dHBzOi8vd3d3LnJhcGlkc3Ns
+LmNvbS9sZWdhbDAfBgNVHSMEGDAWgBSXwidQnsLJ7AyIMsh8reKmAU/abzAOBgNV
+HQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMFcGCCsG
+AQUFBwEBBEswSTAfBggrBgEFBQcwAYYTaHR0cDovL2dwLnN5bWNkLmNvbTAmBggr
+BgEFBQcwAoYaaHR0cDovL2dwLnN5bWNiLmNvbS9ncC5jcnQwggEEBgorBgEEAdZ5
+AgQCBIH1BIHyAPAAdwDd6x0reg1PpiCLga2BaHB+Lo6dAdVciI09EcTNtuy+zAAA
+AVojuwb7AAAEAwBIMEYCIQD65jDGmWRhjXeXt3sTexf+KOHsQ0McBEFJI21J6RYy
+rgIhALScDzJaJBFnwPVz7lMnQye4O1gBbQc2qRtbCjhkwoxpAHUApLkJkLQYWBSH
+uxOizGdwCjw1mAT5G9+443fNDsgN3BAAAAFaI7sHMQAABAMARjBEAiByzWJV1ewW
+SugasxG6UGIolrRcueMDiYNcgvv98+ImIQIgN3jXAtnZRSjRIOggvSo59KUGuWvO
+HXb9zZR7FGubm04wDQYJKoZIhvcNAQELBQADggEBAGbFsNFcunndr71N646kTmpu
+UDr/bZcL5GCbsd0mV9LcVHeqxjL1d6jRUZKp4QVAyEVSL8KaAv1IAbQmFEO74mqf
+MpH1qzoMqtoOnPCVCO4LP9yLSqDSc+oBQQ1yocGVEnHEiJD3kJrzd47dC5zY0e/D
+/k8VFn8ln88g6lyzfjUtvs6kMBgj9xbOEUzVb3zVawqDUgzOuwYuFEMG85ff6a5F
+6MIlMiQxIXxH23z2Smcffu1I9HLIb0sJfbNDRSsbfL8/+GYWqnF9aOuCeFPX/Eav
+mbV6s/+dy90v7DB67ykcmWIiDHZypV9+7c+I5jUXNqA0rQNYs6eyMo/LnDvIIkU=
+-----END CERTIFICATE-----
diff --git a/src/tests/data/x509/misc/contains_authority_info_access_with_two_ca_issuers.pem b/src/tests/data/x509/misc/contains_authority_info_access_with_two_ca_issuers.pem
new file mode 100644
index 000000000..f7a2923e1
--- /dev/null
+++ b/src/tests/data/x509/misc/contains_authority_info_access_with_two_ca_issuers.pem
@@ -0,0 +1,46 @@
+-----BEGIN CERTIFICATE-----
+MIIINTCCBh2gAwIBAgIDAOudMA0GCSqGSIb3DQEBDQUAMG4xCzAJBgNVBAYTAkRF
+MR0wGwYDVQQKExRCdW5kZXNkcnVja2VyZWkgR21iSDEeMBwGA1UECxMVQmRyaXZl
+IEF1dGhlbnRpY2F0aW9uMSAwHgYDVQQDExdCZHJpdmUgVGVzdCBDQSAxLTIgMjAx
+NzAeFw0xNzA3MDQxNjQ2MTJaFw0yMDA3MDQxNjQ2MTJaMIG9MQswCQYDVQQGEwJE
+RTEVMBMGA1UEChMMbmVYZW5pbyBHbWJIMRUwEwYDVQQDDAxSZW7DqSBNZXVzZWwx
+DjAMBgNVBCoMBVJlbsOpMQ8wDQYDVQQEEwZNZXVzZWwxFTATBgNVBAUTDENTTTAw
+MTg3MDI4NDEPMA0GA1UEBxMGQmVybGluMSYwJAYJKoZIhvcNAQkBFhdyZW5lLm1l
+dXNlbEBuZXhlbmlvLmNvbTEPMA0GA1UECBMGQmVybGluMIICIjANBgkqhkiG9w0B
+AQEFAAOCAg8AMIICCgKCAgEA0DoJbM6jwZOgNU5BWheLWKB04ycd7BajeMyQ7GNd
+c13U5Br+61VUP7V8r72a/eDoZxlLPzDhlgZp0U5kDKfsrQfulx3SFJ4cfh9Zk1Jn
+XpAj+iVKJRfJCM7yH7D+pAyeMqkujsAgS2PNbek9ftSn4bMDz8BfJulH6ttM+82h
+hn2L7F5jVXJVOlhDgVk9lONm17FxtgrJLQ3Pyq+K7SAJsBHCWbDQ+jA3ftE+MEzC
+kWZgSpqY5S0PSPq1886doMTfCmoBBvlFJqmIwxDLue1rVrtcoDaDmu8ubpiGNMyV
+9MS+8SRtt83N7uC1AWjaaNo0F0YkHI7pu3ezBzEDixDQENFo6dQEjwwVZ1U8+sGx
+XyyZCZ59Q0qA4lgO9rKW7STPET7lYWxRWKAjTJqbcSrfSlF/aISeIYExzWlzNc/x
+j77oUTXFSJUet77saQ8Q2fDFZrY186ILwdsSfoJTyq4rHVaUTTsXSZWM/3JAuyto
+BCiB3JAFjT3VIL+J2CAfHA0tbo/S/3rTTeL9FDtjZqFxLSIGlonUkC37h7X2kJz8
+NDNzRZivce16suHJvcCug5BLv8YR6L4ltJb+5R4Oap6sj0ucdyRHfxFhOGm6KuQZ
+UdPKg702iVI1MSFfogehaaSuLdzQf9JZhUBcrHD3hnFB43dM9P1gjtHdlKTTmn5r
+xu0CAwEAAaOCAoowggKGMCcGA1UdJQQgMB4GCCsGAQUFBwMCBggrBgEFBQcDBQYI
+KwYBBQUHAwcwHwYDVR0jBBgwFoAUTLjqt54mTOqT9hq3Dlk+Eyxshh4wggEEBggr
+BgEFBQcBAQSB9zCB9DArBggrBgEFBQcwAYYfaHR0cDovL3N0YWdpbmcub2NzcC5k
+LXRydXN0Lm5ldDBGBggrBgEFBQcwAoY6aHR0cDovL3d3dy5kLXRydXN0Lm5ldC9j
+Z2ktYmluL0Jkcml2ZV9UZXN0X0NBXzEtMl8yMDE3LmNydDB9BggrBgEFBQcwAoZx
+bGRhcDovL2RpcmVjdG9yeS5kLXRydXN0Lm5ldC9DTj1CZHJpdmUlMjBUZXN0JTIw
+Q0ElMjAxLTIlMjAyMDE3LE89QnVuZGVzZHJ1Y2tlcmVpJTIwR21iSCxDPURFP2NB
+Q2VydGlmaWNhdGU/YmFzZT8wFwYDVR0gBBAwDjAMBgorBgEEAaU0AgICMIHFBgNV
+HR8Egb0wgbowgbeggbSggbGGd2xkYXA6Ly9kaXJlY3RvcnkuZC10cnVzdC5uZXQv
+Q049QmRyaXZlJTIwVGVzdCUyMENBJTIwMS0yJTIwMjAxNyxPPUJ1bmRlc2RydWNr
+ZXJlaSUyMEdtYkgsQz1ERT9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0hjZodHRw
+Oi8vY3JsLmQtdHJ1c3QubmV0L2NybC9iZHJpdmVfdGVzdF9jYV8xLTJfMjAxNy5j
+cmwwHQYDVR0OBBYEFOvOhR43QAFq7O7B8Ju7PuL6BaXPMA4GA1UdDwEB/wQEAwIH
+gDAiBgNVHREEGzAZgRdyZW5lLm1ldXNlbEBuZXhlbmlvLmNvbTANBgkqhkiG9w0B
+AQ0FAAOCAgEADLWieLjuNv4VxrYLbfPoP5U0BTlvpvnxAwC8//l91b+KO3J+Pvz5
+ina+xTErIT9c+jg2QtC5oXqNihzN3RxQUs/7NA22td8tWfBld0138BASNckuP595
+LH4Ka7FY6pWwhRHty0GLqmRg8fR8LbnyOUqBLgs6DYI4RmhaSDUPCVMrh3OIwbSc
+fKL/88Z8UHD8sxdww3GNybv8FbcRo5g0udtm0MMeemSt7E1B7nlMItLjqspLI9Ay
+GnnkNmn95LxCDLXRIyViuHr3877yMmE9ibv+y41Xz+MLEFvmxe2rFOc+uWVrjFfK
+HMtV7Q34xJYqBY4uVFF+Kmg4OyYFgNjOInwc8Bu09SqGsla/fyMBJwd2IG7xwobm
+cwnf8+En8aavwlYG4lzfdNVo9CGpft6/86x7OoGbDSeH5JIjYI6xLqa/Cw1F64mR
+Maye+cdGg+t4RE1Xri3e65lZM0Z11MT4NtIS5owBBMsmqILIHTaWStD9XfM7FTdQ
+GnLD8AQBqMADxrEwIu8uUtZFxO9ZaYkBDtEVqo671ErwjCNtzx0EtE9bh6Vfat6s
+qk4CFqKlfCWmAAUXlIQXm5DgKsnC4wE6XTa0HVSDLzh+WBeOdrX7gmhcPSmWkJ8Z
+/blH36mCwiQ+Mx+Z1InIfSS9FoOhxsmmpX0QXnfBgjUWE8aq6yiXInA=
+-----END CERTIFICATE----- \ No newline at end of file
diff --git a/src/tests/unit_x509.cpp b/src/tests/unit_x509.cpp
index 1fd4dc239..0aa9d0209 100644
--- a/src/tests/unit_x509.cpp
+++ b/src/tests/unit_x509.cpp
@@ -465,6 +465,44 @@ Test::Result test_x509_bmpstring()
return result;
}
+Test::Result test_x509_authority_info_access_extension()
+ {
+ Test::Result result("X509 with PKIX.AuthorityInformationAccess extension");
+
+ // contains no AIA extension
+ Botan::X509_Certificate no_aia_cert(Test::data_file("x509/misc/contains_utf8string.pem"));
+
+ result.test_eq("number of ca_issuers URLs", no_aia_cert.ca_issuers().size(), 0);
+ result.test_eq("CA issuer URL matches", no_aia_cert.ocsp_responder(), "");
+
+ // contains AIA extension with 1 CA issuer URL and 1 OCSP responder
+ Botan::X509_Certificate aia_cert(Test::data_file("x509/misc/contains_authority_info_access.pem"));
+
+ const auto ca_issuers = aia_cert.ca_issuers();
+
+ result.test_eq("number of ca_issuers URLs", ca_issuers.size(), 1);
+ if (result.tests_failed())
+ return result;
+
+ result.test_eq("CA issuer URL matches", ca_issuers[0], "http://gp.symcb.com/gp.crt");
+ result.test_eq("OCSP responder URL matches", aia_cert.ocsp_responder(), "http://gp.symcd.com");
+
+ // contains AIA extension with 2 CA issuer URL and 1 OCSP responder
+ Botan::X509_Certificate aia_cert_2ca(Test::data_file("x509/misc/contains_authority_info_access_with_two_ca_issuers.pem"));
+
+ const auto ca_issuers2 = aia_cert_2ca.ca_issuers();
+
+ result.test_eq("number of ca_issuers URLs", ca_issuers2.size(), 2);
+ if (result.tests_failed())
+ return result;
+
+ result.test_eq("CA issuer URL matches", ca_issuers2[0], "http://www.d-trust.net/cgi-bin/Bdrive_Test_CA_1-2_2017.crt");
+ result.test_eq("CA issuer URL matches", ca_issuers2[1], "ldap://directory.d-trust.net/CN=Bdrive%20Test%20CA%201-2%202017,O=Bundesdruckerei%20GmbH,C=DE?cACertificate?base?");
+ result.test_eq("OCSP responder URL matches", aia_cert_2ca.ocsp_responder(), "http://staging.ocsp.d-trust.net");
+
+ return result;
+ }
+
Test::Result test_x509_cert(const std::string& sig_algo, const std::string& sig_padding = "", const std::string& hash_fn = "SHA-256")
{
Test::Result result("X509 Unit");
@@ -1424,6 +1462,7 @@ class X509_Cert_Unit_Tests final : public Test
results.push_back(test_crl_dn_name());
results.push_back(test_x509_uninit());
results.push_back(test_x509_decode_list());
+ results.push_back(test_x509_authority_info_access_extension());
return results;
}