aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2019-05-28 09:12:55 -0400
committerJack Lloyd <[email protected]>2019-05-28 09:12:55 -0400
commite6775cf25394e2c3333facd060d3951ee30389b5 (patch)
treeaaba84d95d3306289fcd8d146db444819b36578a /src
parent021f84110ab3ec1f6916b69a1894b1ac2f144ee6 (diff)
parente292cf26fc66727b964cde84492ad179980ad2d6 (diff)
Merge GH #1974 Add ability to set max allowed age for an OCSP response
Diffstat (limited to 'src')
-rw-r--r--src/lib/x509/cert_status.cpp2
-rw-r--r--src/lib/x509/cert_status.h1
-rw-r--r--src/lib/x509/ocsp.cpp26
-rw-r--r--src/lib/x509/ocsp.h6
-rw-r--r--src/lib/x509/x509path.cpp5
-rw-r--r--src/lib/x509/x509path.h3
-rw-r--r--src/tests/data/x509/ocsp/bdrive_encryption.pem43
-rw-r--r--src/tests/data/x509/ocsp/bdrive_root.pem31
-rw-r--r--src/tests/data/x509/ocsp/patrickschmidt.pem46
-rw-r--r--src/tests/data/x509/ocsp/patrickschmidt_ocsp.derbin0 -> 4235 bytes
-rw-r--r--src/tests/test_ocsp.cpp149
11 files changed, 287 insertions, 25 deletions
diff --git a/src/lib/x509/cert_status.cpp b/src/lib/x509/cert_status.cpp
index 79bcd1b07..4efd49edf 100644
--- a/src/lib/x509/cert_status.cpp
+++ b/src/lib/x509/cert_status.cpp
@@ -46,6 +46,8 @@ const char* to_string(Certificate_Status_Code code)
return "OCSP is not yet valid";
case Certificate_Status_Code::OCSP_HAS_EXPIRED:
return "OCSP response has expired";
+ case Certificate_Status_Code::OCSP_IS_TOO_OLD:
+ return "OCSP response is too old";
case Certificate_Status_Code::CRL_NOT_YET_VALID:
return "CRL response is not yet valid";
case Certificate_Status_Code::CRL_HAS_EXPIRED:
diff --git a/src/lib/x509/cert_status.h b/src/lib/x509/cert_status.h
index fc1174df3..b682746f8 100644
--- a/src/lib/x509/cert_status.h
+++ b/src/lib/x509/cert_status.h
@@ -48,6 +48,7 @@ enum class Certificate_Status_Code {
OCSP_HAS_EXPIRED = 2003,
CRL_NOT_YET_VALID = 2004,
CRL_HAS_EXPIRED = 2005,
+ OCSP_IS_TOO_OLD = 2006,
// Chain generation problems
CERT_ISSUER_NOT_FOUND = 3000,
diff --git a/src/lib/x509/ocsp.cpp b/src/lib/x509/ocsp.cpp
index de229d412..7907d08e2 100644
--- a/src/lib/x509/ocsp.cpp
+++ b/src/lib/x509/ocsp.cpp
@@ -269,11 +269,12 @@ Certificate_Status_Code Response::check_signature(const std::vector<Certificate_
}
Certificate_Status_Code Response::status_for(const X509_Certificate& issuer,
- const X509_Certificate& subject,
- std::chrono::system_clock::time_point ref_time) const
+ const X509_Certificate& subject,
+ std::chrono::system_clock::time_point ref_time,
+ std::chrono::seconds max_age) const
{
- if (m_responses.empty())
- return m_dummy_response_status;
+ if(m_responses.empty())
+ { return m_dummy_response_status; }
for(const auto& response : m_responses)
{
@@ -282,18 +283,23 @@ Certificate_Status_Code Response::status_for(const X509_Certificate& issuer,
X509_Time x509_ref_time(ref_time);
if(response.cert_status() == 1)
- return Certificate_Status_Code::CERT_IS_REVOKED;
+ { return Certificate_Status_Code::CERT_IS_REVOKED; }
if(response.this_update() > x509_ref_time)
- return Certificate_Status_Code::OCSP_NOT_YET_VALID;
+ { return Certificate_Status_Code::OCSP_NOT_YET_VALID; }
- if(response.next_update().time_is_set() && x509_ref_time > response.next_update())
- return Certificate_Status_Code::OCSP_HAS_EXPIRED;
+ if(response.next_update().time_is_set())
+ {
+ if(x509_ref_time > response.next_update())
+ { return Certificate_Status_Code::OCSP_HAS_EXPIRED; }
+ }
+ else if(max_age > std::chrono::seconds::zero() && ref_time - response.this_update().to_std_timepoint() > max_age)
+ { return Certificate_Status_Code::OCSP_IS_TOO_OLD; }
if(response.cert_status() == 0)
- return Certificate_Status_Code::OCSP_RESPONSE_GOOD;
+ { return Certificate_Status_Code::OCSP_RESPONSE_GOOD; }
else
- return Certificate_Status_Code::OCSP_BAD_STATUS;
+ { return Certificate_Status_Code::OCSP_BAD_STATUS; }
}
}
diff --git a/src/lib/x509/ocsp.h b/src/lib/x509/ocsp.h
index 884b1c5b3..e9d09850f 100644
--- a/src/lib/x509/ocsp.h
+++ b/src/lib/x509/ocsp.h
@@ -139,17 +139,21 @@ class BOTAN_PUBLIC_API(2,0) Response final
* @param issuer issuer certificate
* @param subject subject certificate
* @param ref_time the reference time
+ * @param max_age the maximum age the response should be considered valid
+ * if next_update is not set
* @return OCSP status code, possible values:
* CERT_IS_REVOKED,
* OCSP_NOT_YET_VALID,
* OCSP_HAS_EXPIRED,
+ * OCSP_IS_TOO_OLD,
* OCSP_RESPONSE_GOOD,
* OCSP_BAD_STATUS,
* OCSP_CERT_NOT_LISTED
*/
Certificate_Status_Code status_for(const X509_Certificate& issuer,
const X509_Certificate& subject,
- std::chrono::system_clock::time_point ref_time = std::chrono::system_clock::now()) const;
+ std::chrono::system_clock::time_point ref_time = std::chrono::system_clock::now(),
+ std::chrono::seconds max_age = std::chrono::seconds::zero()) const;
/**
* @return the certificate chain, if provided in response
diff --git a/src/lib/x509/x509path.cpp b/src/lib/x509/x509path.cpp
index 9d886ca7a..a889aa4d4 100644
--- a/src/lib/x509/x509path.cpp
+++ b/src/lib/x509/x509path.cpp
@@ -204,7 +204,8 @@ CertificatePathStatusCodes
PKIX::check_ocsp(const std::vector<std::shared_ptr<const X509_Certificate>>& cert_path,
const std::vector<std::shared_ptr<const OCSP::Response>>& ocsp_responses,
const std::vector<Certificate_Store*>& trusted_certstores,
- std::chrono::system_clock::time_point ref_time)
+ std::chrono::system_clock::time_point ref_time,
+ std::chrono::seconds max_age)
{
if(cert_path.empty())
throw Invalid_Argument("PKIX::check_ocsp cert_path empty");
@@ -227,7 +228,7 @@ PKIX::check_ocsp(const std::vector<std::shared_ptr<const X509_Certificate>>& cer
if(ocsp_signature_status == Certificate_Status_Code::OCSP_SIGNATURE_OK)
{
// Signature ok, so check the claimed status
- Certificate_Status_Code ocsp_status = ocsp_responses.at(i)->status_for(*ca, *subject, ref_time);
+ Certificate_Status_Code ocsp_status = ocsp_responses.at(i)->status_for(*ca, *subject, ref_time, max_age);
status.insert(ocsp_status);
}
else
diff --git a/src/lib/x509/x509path.h b/src/lib/x509/x509path.h
index 841f1a8ef..3e457b970 100644
--- a/src/lib/x509/x509path.h
+++ b/src/lib/x509/x509path.h
@@ -352,7 +352,8 @@ CertificatePathStatusCodes
BOTAN_PUBLIC_API(2,0) check_ocsp(const std::vector<std::shared_ptr<const X509_Certificate>>& cert_path,
const std::vector<std::shared_ptr<const OCSP::Response>>& ocsp_responses,
const std::vector<Certificate_Store*>& certstores,
- std::chrono::system_clock::time_point ref_time);
+ std::chrono::system_clock::time_point ref_time,
+ std::chrono::seconds max_age = std::chrono::seconds::zero());
/**
* Check CRLs for revocation information
diff --git a/src/tests/data/x509/ocsp/bdrive_encryption.pem b/src/tests/data/x509/ocsp/bdrive_encryption.pem
new file mode 100644
index 000000000..395027a3a
--- /dev/null
+++ b/src/tests/data/x509/ocsp/bdrive_encryption.pem
@@ -0,0 +1,43 @@
+-----BEGIN CERTIFICATE-----
+MIIHiDCCBXCgAwIBAgIDD+SyMA0GCSqGSIb3DQEBDQUAMEwxCzAJBgNVBAYTAkRF
+MR0wGwYDVQQKExRCdW5kZXNkcnVja2VyZWkgR21iSDEeMBwGA1UEAxMVQmRyaXZl
+IFJvb3QgQ0EgMSAyMDE3MB4XDTE3MDYyOTE2MTAzNVoXDTMyMDYyOTEyMzAxNlow
+ZTELMAkGA1UEBhMCREUxHTAbBgNVBAoTFEJ1bmRlc2RydWNrZXJlaSBHbWJIMRow
+GAYDVQQLExFCZHJpdmUgRW5jcnlwdGlvbjEbMBkGA1UEAxMSQmRyaXZlIENBIDEt
+MSAyMDE3MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAuRNrAhqeS6J9
+v1LKzWsbKFt2HpfL4DsL5LGlc7AsDtYUsR117waFIsHQ0au+fRwY6FdBgDNntr1u
+IGX26OUcHuVWDVyGQfEOlW4/OBg6vF2HkX7qds0BIaJqUwBhpFV+MZB8n7/njMRU
+i0dKO0JAydIkr2cbtb6CPRnv6Hq3irEGv6GuXAAr77ja+CTuAEnH2W/XSwfj/nwe
+U87LrVx5XMV7K7kkjd69TaSsowJk3wJ8XVGiT0TdontqqKH5uYu9qNFdjlEB6HXE
+go3ookMyCIRF77lxAIznS/kHlsW/qwvvHWOJCBsktNbwAIYAGSohXQFhj7aAp6Qd
+VB9B7A/lJ5O6IjdqpgmK+PRblfcmpvmo5TgNmVN3mAkBt+dI5kgRAuq7Opo8ZWyg
+6/AQueeRrcBO2Cglxo4RMKsFht8CNcfbpdoqo+rQmcfmDqTEPa9VgqKBdmmZPc5W
+1CCHlzASRJq95zLN9E6jIa9jUctWDrlcTTvLsF7cefGJGrq1t4KlzMVvxZ1MojWt
+BxFyywLyiQJUSH+NZtmrAv1lA9398Sh/HP+wJ7mVXkGXGiqWbeMy1MQGvD/nWn6L
+hJFR6q1Dk4z+Y69yGAZ3/kJ3KUduOft8uvfpp3bE6pWc8c2U+qt89r1VB9uCWJ6s
+8Lq/0AQsMGpyQCDpBNSN9ZXt4BvNNskCAwEAAaOCAlgwggJUMB8GA1UdIwQYMBaA
+FHKvqBQDb73a+QPjH7s39hTffforMIIBDwYIKwYBBQUHAQEEggEBMIH+MDkGCCsG
+AQUFBzABhi1odHRwOi8vYmRyaXZlLXJvb3QtY2EtMS0yMDE3Lm9jc3AuZC10cnVz
+dC5uZXQwRAYIKwYBBQUHMAKGOGh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY2dpLWJp
+bi9CZHJpdmVfUm9vdF9DQV8xXzIwMTcuY3J0MHsGCCsGAQUFBzAChm9sZGFwOi8v
+ZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUJkcml2ZSUyMFJvb3QlMjBDQSUyMDEl
+MjAyMDE3LE89QnVuZGVzZHJ1Y2tlcmVpJTIwR21iSCxDPURFP2NBQ2VydGlmaWNh
+dGU/YmFzZT8wFwYDVR0gBBAwDjAMBgoqghQAUIU9g3QBMIHBBgNVHR8EgbkwgbYw
+gbOggbCgga2GdWxkYXA6Ly9kaXJlY3RvcnkuZC10cnVzdC5uZXQvQ049QmRyaXZl
+JTIwUm9vdCUyMENBJTIwMSUyMDIwMTcsTz1CdW5kZXNkcnVja2VyZWklMjBHbWJI
+LEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdIY0aHR0cDovL2NybC5kLXRy
+dXN0Lm5ldC9jcmwvYmRyaXZlX3Jvb3RfY2FfMV8yMDE3LmNybDAdBgNVHQ4EFgQU
+3PghhQ8DCnR3GLZtlmKvvrwca5YwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQI
+MAYBAf8CAQAwDQYJKoZIhvcNAQENBQADggIBAClBw10/yUy4lN+VdvT71l22aMoC
+LvrdyArq+XN5p2NTji0hGBVNLicGT8/GJ9Pssf8E4RbH3QCwhb68T7Kg5Atcn0e3
+5q7jws4ZuWOlpT2sgYkilWOi+Okp6Ty+QStgdpRsQ2U4RKpO0/h/0V0fv6VRaYVk
+j6IRyd2pgAkrrutQh7F20D29j0emLmc0SF2hn++AACY7V021drKIJsEmbiQ7h68t
+cFLZl660LYwJ+1ZrQDmcJTghROFi6DLb4dk/xPYlb2PoonBaGThCbyCNa+SpqbfS
+6zoaBNMaYaA11zXoV/2fReYBtj5NZTu1KyqKfYcm/yAxws1a/lbf1moGdNwsxcxV
+M3EcyZMkgB/XkPtjLCxCfKDonp0T4rt+pDgt+wfvyE8BUEXm8A6v+HD7rn8xmiLB
+h/vhFIDqNaA9DlfjQFGU+d+JN/Iv92IZk63cqDn6kMJPiewscrrws4oc/V2yKi6v
+Iicq3VRFsyrzdlcTWodQCIO4uKUBDJIqXfCs4wr6aW/JH4iGKDGYn4dcc9lLJ5sq
+m2rTQyWJMa7+M6ZT4UrYX/rISr/i4KT/fHPR3HR9Oxv0mM6hGl2ihClegEhMEIeQ
+vb/GhyisXfCxPNzDJawna+wm+rYZ4vcJq0/C3XVpv2vnraYTfqgASBevElDhmSZa
+nsfsTJkA8VidAuBl
+-----END CERTIFICATE-----
diff --git a/src/tests/data/x509/ocsp/bdrive_root.pem b/src/tests/data/x509/ocsp/bdrive_root.pem
new file mode 100644
index 000000000..21a29974a
--- /dev/null
+++ b/src/tests/data/x509/ocsp/bdrive_root.pem
@@ -0,0 +1,31 @@
+-----BEGIN CERTIFICATE-----
+MIIFVzCCAz+gAwIBAgIDD+SxMA0GCSqGSIb3DQEBDQUAMEwxCzAJBgNVBAYTAkRF
+MR0wGwYDVQQKExRCdW5kZXNkcnVja2VyZWkgR21iSDEeMBwGA1UEAxMVQmRyaXZl
+IFJvb3QgQ0EgMSAyMDE3MB4XDTE3MDYyOTEyMzAxNloXDTMyMDYyOTEyMzAxNlow
+TDELMAkGA1UEBhMCREUxHTAbBgNVBAoTFEJ1bmRlc2RydWNrZXJlaSBHbWJIMR4w
+HAYDVQQDExVCZHJpdmUgUm9vdCBDQSAxIDIwMTcwggIiMA0GCSqGSIb3DQEBAQUA
+A4ICDwAwggIKAoICAQDSEdramwmqOL/lpQE3nEejFYIneJv8ruPMAhnjBeavcPWL
+WUMaDP3jyU1S5PDF+QXJYszZhNPwED0NBv7fnQ4qbpbYLYWkfncBpzrBorwo6yub
++rlurRRsSd0rQjUuRNS9/iaJhriISWyakktj6+POyGDH/dCNjz3z+nwPzclJvIo0
+1R5vJbt24H6ScIINmJVMGiZ/rCYpzhzsY+rwyso+wmqoJ/jzJPt5J2FQ7vsA3GAM
+ekVUtYc6xgIEsIBD4Jvm0Pq1neHr2WqADh4POT922kaki65MUsPOmd7eaE2bBeSR
+/cTmbk5Qm2S6YpIRlQWW642gx4foQLaMSr+g7pRGpuQRhDk6tWIzcTkVQ0eyQz8s
+qLSzGq5FZGtlRmDGgZBo37pD8aLqI12qqecAg46QTDoAn68KsDwhQUefZqJO7g5j
+nD6sPBDuiSIHb97j5MQhu5/Qs5za8UT/x38wP57cpCEhtAegqBfdqg/1ZifD+xma
+x282uympWgXxbRAfjEy59g9RwcK8jaP+r1E0qPcNiD+WG4f7DRhc4C7VF9ekSyH5
+MnIIipDyw094CXSoNBvoU5xISTkOOGm8q+plWun6wRTq6jZdExgTHzBQeTos664k
+SS8ibVhUbIiNPEmYKvNY+4kZs9oZxNE2KXitKEIXxgZIm0VgK7/a3XAU01b5CQID
+AQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRyr6gUA2+92vkD4x+7
+N/YU3336KzAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQENBQADggIBAD34vu6J
+ZsC7UrXA5pwlOo1VKhIU5e8o6OjgbJ8FDmOP0YakwAe9B4TSIFhRjohXGM7Rj3mx
+8zolPucMH95hNpeG/23af6tgy6a8+xeL/TTy0LMTYNcHaeRhyOIi6Hp3Om6+LhCG
+/R/JRO0ilMEDHbZ4d3vAQ9x+QLiVuz2d4yw6eR3ucOVoXImlsO63O8n8QlI+SW6o
+n8+L5EpMK7EcHlnqJKFqA1yPmZz/6sTUTaFVw/JeAEbACnP7+8EDT9yuE5H4IvTh
+3Y0BHB6+nh/2koqZsuF+/hhjSP8Sp7LUH5Eu7plwsdLeUY7JXDTl5R8eCycwiMi3
+prpQacDKzdUb42zNkBcGdBQ99DG+emNjd2/Nwsp7r7nZltOx3C+emqLXIWoSkWvv
+vdzukpJrhdkt4GPpGUv2I87yuxkqrRwSychrE+jVERyI8O7QjqWdsRSOAk6N7svm
+zTKIwP6Rmj3LCu8UD4kiSOhdwAzuMTv8AKywZAYQ9eEEuuIoDTfWMIk2AYnklPVP
+s00mKMlkjMt2EZZCKnNzQyZHn1jVRweqotKmZPCgtwUxvYscaz9PaEPsIC5DQc73
+6fpC5oGp4yXQBrw8dVzX65/sYy7GDCDzCxk8yM5lVXSdeufPOMCxIVDXXTbWBDDU
+7mRl/EOq5wivzBx6bFGIRkSCPqi2T7oWPfoA
+-----END CERTIFICATE-----
diff --git a/src/tests/data/x509/ocsp/patrickschmidt.pem b/src/tests/data/x509/ocsp/patrickschmidt.pem
new file mode 100644
index 000000000..0455f4b71
--- /dev/null
+++ b/src/tests/data/x509/ocsp/patrickschmidt.pem
@@ -0,0 +1,46 @@
+-----BEGIN CERTIFICATE-----
+MIIINDCCBhygAwIBAgIDJF8VMA0GCSqGSIb3DQEBDQUAMGUxCzAJBgNVBAYTAkRF
+MR0wGwYDVQQKExRCdW5kZXNkcnVja2VyZWkgR21iSDEaMBgGA1UECxMRQmRyaXZl
+IEVuY3J5cHRpb24xGzAZBgNVBAMTEkJkcml2ZSBDQSAxLTEgMjAxNzAeFw0xOTAx
+MTQxODU0MDhaFw0yMjAxMTQxODU0MDhaMIHiMQswCQYDVQQGEwJERTEQMA4GA1UE
+ChMHTmV4ZW5pbzEtMCsGA1UECxMkMzcyZTc0NmItZTQ3NS00NWMyLWI4MmMtMzM0
+MTM4YTY2NDA3MRgwFgYDVQQDEw9QYXRyaWNrIFNjaG1pZHQxFTATBgNVBAUTDENT
+TTAxNDgwMTMwOTEPMA0GA1UEBxMGQmVybGluMT8wPQYJKoZIhvcNAQkBFjAzNzJl
+NzQ2Yi1lNDc1LTQ1YzItYjgyYy0zMzQxMzhhNjY0MDdAYmRyLW1haWwuZGUxDzAN
+BgNVBAgTBkJlcmxpbjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANoU
+hK4HbAr3pRT0U62M9shiq1JK3209oZtFAyXbUdN5SFE7MXRefn2gE/x0W2Eq/PAr
+dCbM8I7DovtXfnWpiJGYlM/WU8oGoWpayn7rkYfDicDuTFK0VwISXeRsvSf2DFv0
+eSdhVscyYle8sgNn9wBH2/nhOuSeeXBWOg/h9sGgiKkOVXZkNgZxNKdcet5kbVNW
+lGfxa7LRJQMbTZL6WjgrrNKCJFEih7gRaEQsaPcCiaBOwDv8G89c2V4Cd45XmhAr
+1YF7t42iMdW6aEDkohD5UW/eqvrb0VXWB02WrcQn/6X17hQzVRKol90DU/8LZ+9G
+qSrb/x6byd9M4NGWHqr+dpskY2PW/eJdpyQd0pluCXbTPVkrebntsn1z0md95Rdq
+HiOz3AZ6TN1noS7gmCHX4o/HBiAHc7SU8FziY1iDKofah17isAP7JD5L8TfBGiie
+pcDTTn1tSSfzvgoI5mDUl10yyJ/fPXvlp4pKhIMCwwDKQOaAcKLYsRmi4cp+OsX6
+hGX4qcS3FiOF3u+pB/tggZ6Se1GkR6zJiAqeW7neRFuiU3+zVmrtLaAb1qm6vaUj
+ZBfAWgUg2p1ug2FG+17K6NMf4ST2wgiTi64UmMQES6UBDxX2PkRfd+ooQE7JS8wU
+jhmikglhOMwM+pb77NTOn0Dr3wmKinbBO3ngH00hAgMBAAGjggJtMIICaTAfBgNV
+HSMEGDAWgBTc+CGFDwMKdHcYtm2WYq++vBxrljCCAQMGCCsGAQUFBwEBBIH2MIHz
+MDYGCCsGAQUFBzABhipodHRwOi8vYmRyaXZlLWNhLTEtMS0yMDE3Lm9jc3AuZC10
+cnVzdC5uZXQwQQYIKwYBBQUHMAKGNWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY2dp
+LWJpbi9CZHJpdmVfQ0FfMS0xXzIwMTcuY3J0MHYGCCsGAQUFBzAChmpsZGFwOi8v
+ZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUJkcml2ZSUyMENBJTIwMS0xJTIwMjAx
+NyxPPUJ1bmRlc2RydWNrZXJlaSUyMEdtYkgsQz1ERT9jQUNlcnRpZmljYXRlP2Jh
+c2U/MBcGA1UdIAQQMA4wDAYKKoIUAFCFPYN0ATCBuQYDVR0fBIGxMIGuMIGroIGo
+oIGlhnBsZGFwOi8vZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUJkcml2ZSUyMENB
+JTIwMS0xJTIwMjAxNyxPPUJ1bmRlc2RydWNrZXJlaSUyMEdtYkgsQz1ERT9jZXJ0
+aWZpY2F0ZXJldm9jYXRpb25saXN0hjFodHRwOi8vY3JsLmQtdHJ1c3QubmV0L2Ny
+bC9iZHJpdmVfY2FfMS0xXzIwMTcuY3JsMB0GA1UdDgQWBBRhGyV3lS9YNFG5FcWR
+Ic5WTHPJJTAOBgNVHQ8BAf8EBAMCBDAwOwYDVR0RBDQwMoEwMzcyZTc0NmItZTQ3
+NS00NWMyLWI4MmMtMzM0MTM4YTY2NDA3QGJkci1tYWlsLmRlMA0GCSqGSIb3DQEB
+DQUAA4ICAQAWD20kwhIJxYK6Ma3y/dV2lPsZqGb5z2JYoLzgsEp9INTeqwqxwFer
+aSJmEkYxuR2z+g17lzeVCbu5ijHi0P1a6uKf6sB7goNorVC9ipU5gCTwt5LcZ66d
+ZuXVTEc3XUsu6CJ4r1e1kAJckKugWkWvM/UqnhCYQMnm6GgoJA0PlwVLDpy4myQL
+DEQvUqhDD+iPm0tttzLeoJ5g+gtsEMFqq96EFfkv8mHQLDvqDqT91QjoNBUNc7hQ
+s7qlvQjCS15ntTCOV6ruvwAFDacCcFuFSyRN9wnf3TxgJ36q4JKAIiC1VrjqJWTD
+yGO+2gIFkuCwRjSgsTy0bjtsTTe2rJVf5GXqDcrQQqaJdrv21XFlhwRuhjulkseU
+ocWjvByMG/2rBhOQRXNHGkxsrUrlaVMaA+erdUgU4vGBQq1OfGtnDzLzB+XSYVH1
+8+Mc8DdS2TyhcnYTpA7ZLUOcXRxen68m+0QmNY5uKo0OqSbH1vU8/upme3BKL702
+08jtRbYLGMy+E0gVcIttZbQU2FGlmWXz4uTopgSeCvl1VVs9U+J+65UZlHi2gUVr
+fNdGaRoMg9nYcDnxYCDaauAgeulHawquH8Ir3XBXmEkje4c56h7cnjPiCp1Yxg0a
+ox1cE2ofXhF7Alk31z971RbA3dhfPPxGZ9AU3CAQA+leUkdjfCvtmw==
+-----END CERTIFICATE-----
diff --git a/src/tests/data/x509/ocsp/patrickschmidt_ocsp.der b/src/tests/data/x509/ocsp/patrickschmidt_ocsp.der
new file mode 100644
index 000000000..39a7b20a5
--- /dev/null
+++ b/src/tests/data/x509/ocsp/patrickschmidt_ocsp.der
Binary files differ
diff --git a/src/tests/test_ocsp.cpp b/src/tests/test_ocsp.cpp
index 753e4455b..5c28c128d 100644
--- a/src/tests/test_ocsp.cpp
+++ b/src/tests/test_ocsp.cpp
@@ -124,9 +124,47 @@ class OCSP_Tests final : public Test
return result;
}
- Test::Result test_response_verification()
+ Test::Result test_response_verification_with_next_update_without_max_age()
{
- Test::Result result("OCSP request check");
+ Test::Result result("OCSP request check with next_update w/o max_age");
+
+ std::shared_ptr<const Botan::X509_Certificate> ee = load_test_X509_cert("x509/ocsp/randombit.pem");
+ std::shared_ptr<const Botan::X509_Certificate> ca = load_test_X509_cert("x509/ocsp/letsencrypt.pem");
+ std::shared_ptr<const Botan::X509_Certificate> trust_root = load_test_X509_cert("x509/ocsp/geotrust.pem");
+
+ const std::vector<std::shared_ptr<const Botan::X509_Certificate>> cert_path = { ee, ca, trust_root };
+
+ std::shared_ptr<const Botan::OCSP::Response> ocsp = load_test_OCSP_resp("x509/ocsp/randombit_ocsp.der");
+
+ Botan::Certificate_Store_In_Memory certstore;
+ certstore.add_certificate(trust_root);
+
+ auto check_ocsp = [&](const std::chrono::system_clock::time_point valid_time,
+ const Botan::Certificate_Status_Code expected)
+ {
+ const auto ocsp_status = Botan::PKIX::check_ocsp(cert_path, { ocsp }, { &certstore }, valid_time);
+
+ return result.test_eq("Expected size of ocsp_status", ocsp_status.size(), 1) &&
+ result.test_eq("Expected size of ocsp_status[0]", ocsp_status[0].size(), 1) &&
+ result.confirm(std::string("Status: '") + Botan::to_string(expected) + "'",
+ ocsp_status[0].count(expected));
+ };
+
+ check_ocsp(Botan::calendar_point(2016, 11, 11, 12, 30, 0).to_std_timepoint(),
+ Botan::Certificate_Status_Code::OCSP_NOT_YET_VALID);
+ check_ocsp(Botan::calendar_point(2016, 11, 18, 12, 30, 0).to_std_timepoint(),
+ Botan::Certificate_Status_Code::OCSP_RESPONSE_GOOD);
+ check_ocsp(Botan::calendar_point(2016, 11, 20, 8, 30, 0).to_std_timepoint(),
+ Botan::Certificate_Status_Code::OCSP_RESPONSE_GOOD);
+ check_ocsp(Botan::calendar_point(2016, 11, 28, 8, 30, 0).to_std_timepoint(),
+ Botan::Certificate_Status_Code::OCSP_HAS_EXPIRED);
+
+ return result;
+ }
+
+ Test::Result test_response_verification_with_next_update_with_max_age()
+ {
+ Test::Result result("OCSP request check with next_update with max_age");
std::shared_ptr<const Botan::X509_Certificate> ee = load_test_X509_cert("x509/ocsp/randombit.pem");
std::shared_ptr<const Botan::X509_Certificate> ca = load_test_X509_cert("x509/ocsp/letsencrypt.pem");
@@ -140,16 +178,102 @@ class OCSP_Tests final : public Test
certstore.add_certificate(trust_root);
// Some arbitrary time within the validity period of the test certs
- const auto valid_time = Botan::calendar_point(2016, 11, 20, 8, 30, 0).to_std_timepoint();
- const auto ocsp_status = Botan::PKIX::check_ocsp(cert_path, { ocsp }, { &certstore }, valid_time);
+ const auto max_age = std::chrono::minutes(59);
- if(result.test_eq("Expected size of ocsp_status", ocsp_status.size(), 1))
+ auto check_ocsp = [&](const std::chrono::system_clock::time_point valid_time,
+ const Botan::Certificate_Status_Code expected)
{
- if(result.test_eq("Expected size of ocsp_status[0]", ocsp_status[0].size(), 1))
- {
- result.confirm("Status good", ocsp_status[0].count(Botan::Certificate_Status_Code::OCSP_RESPONSE_GOOD));
- }
- }
+ const auto ocsp_status = Botan::PKIX::check_ocsp(cert_path, { ocsp }, { &certstore }, valid_time, max_age);
+
+ return result.test_eq("Expected size of ocsp_status", ocsp_status.size(), 1) &&
+ result.test_eq("Expected size of ocsp_status[0]", ocsp_status[0].size(), 1) &&
+ result.confirm(std::string("Status: '") + Botan::to_string(expected) + "'",
+ ocsp_status[0].count(expected));
+ };
+
+ check_ocsp(Botan::calendar_point(2016, 11, 11, 12, 30, 0).to_std_timepoint(),
+ Botan::Certificate_Status_Code::OCSP_NOT_YET_VALID);
+ check_ocsp(Botan::calendar_point(2016, 11, 18, 12, 30, 0).to_std_timepoint(),
+ Botan::Certificate_Status_Code::OCSP_RESPONSE_GOOD);
+ check_ocsp(Botan::calendar_point(2016, 11, 20, 8, 30, 0).to_std_timepoint(),
+ Botan::Certificate_Status_Code::OCSP_RESPONSE_GOOD);
+ check_ocsp(Botan::calendar_point(2016, 11, 28, 8, 30, 0).to_std_timepoint(),
+ Botan::Certificate_Status_Code::OCSP_HAS_EXPIRED);
+
+ return result;
+ }
+
+ Test::Result test_response_verification_without_next_update_with_max_age()
+ {
+ Test::Result result("OCSP request check w/o next_update with max_age");
+
+ std::shared_ptr<const Botan::X509_Certificate> ee = load_test_X509_cert("x509/ocsp/patrickschmidt.pem");
+ std::shared_ptr<const Botan::X509_Certificate> ca = load_test_X509_cert("x509/ocsp/bdrive_encryption.pem");
+ std::shared_ptr<const Botan::X509_Certificate> trust_root = load_test_X509_cert("x509/ocsp/bdrive_root.pem");
+
+ const std::vector<std::shared_ptr<const Botan::X509_Certificate>> cert_path = { ee, ca, trust_root };
+
+ std::shared_ptr<const Botan::OCSP::Response> ocsp = load_test_OCSP_resp("x509/ocsp/patrickschmidt_ocsp.der");
+
+ Botan::Certificate_Store_In_Memory certstore;
+ certstore.add_certificate(trust_root);
+
+ // Some arbitrary time within the validity period of the test certs
+ const auto max_age = std::chrono::minutes(59);
+
+ auto check_ocsp = [&](const std::chrono::system_clock::time_point valid_time,
+ const Botan::Certificate_Status_Code expected)
+ {
+ const auto ocsp_status = Botan::PKIX::check_ocsp(cert_path, { ocsp }, { &certstore }, valid_time, max_age);
+
+ return result.test_eq("Expected size of ocsp_status", ocsp_status.size(), 1) &&
+ result.test_eq("Expected size of ocsp_status[0]", ocsp_status[0].size(), 1) &&
+ result.confirm(std::string("Status: '") + Botan::to_string(expected) + "'",
+ ocsp_status[0].count(expected));
+ };
+
+ check_ocsp(Botan::calendar_point(2019, 5, 28, 7, 0, 0).to_std_timepoint(),
+ Botan::Certificate_Status_Code::OCSP_NOT_YET_VALID);
+ check_ocsp(Botan::calendar_point(2019, 5, 28, 7, 30, 0).to_std_timepoint(),
+ Botan::Certificate_Status_Code::OCSP_RESPONSE_GOOD);
+ check_ocsp(Botan::calendar_point(2019, 5, 28, 8, 0, 0).to_std_timepoint(),
+ Botan::Certificate_Status_Code::OCSP_IS_TOO_OLD);
+
+ return result;
+ }
+
+ Test::Result test_response_verification_without_next_update_without_max_age()
+ {
+ Test::Result result("OCSP request check w/o next_update w/o max_age");
+
+ std::shared_ptr<const Botan::X509_Certificate> ee = load_test_X509_cert("x509/ocsp/patrickschmidt.pem");
+ std::shared_ptr<const Botan::X509_Certificate> ca = load_test_X509_cert("x509/ocsp/bdrive_encryption.pem");
+ std::shared_ptr<const Botan::X509_Certificate> trust_root = load_test_X509_cert("x509/ocsp/bdrive_root.pem");
+
+ const std::vector<std::shared_ptr<const Botan::X509_Certificate>> cert_path = { ee, ca, trust_root };
+
+ std::shared_ptr<const Botan::OCSP::Response> ocsp = load_test_OCSP_resp("x509/ocsp/patrickschmidt_ocsp.der");
+
+ Botan::Certificate_Store_In_Memory certstore;
+ certstore.add_certificate(trust_root);
+
+ auto check_ocsp = [&](const std::chrono::system_clock::time_point valid_time,
+ const Botan::Certificate_Status_Code expected)
+ {
+ const auto ocsp_status = Botan::PKIX::check_ocsp(cert_path, { ocsp }, { &certstore }, valid_time);
+
+ return result.test_eq("Expected size of ocsp_status", ocsp_status.size(), 1) &&
+ result.test_eq("Expected size of ocsp_status[0]", ocsp_status[0].size(), 1) &&
+ result.confirm(std::string("Status: '") + Botan::to_string(expected) + "'",
+ ocsp_status[0].count(expected));
+ };
+
+ check_ocsp(Botan::calendar_point(2019, 5, 28, 7, 0, 0).to_std_timepoint(),
+ Botan::Certificate_Status_Code::OCSP_NOT_YET_VALID);
+ check_ocsp(Botan::calendar_point(2019, 5, 28, 7, 30, 0).to_std_timepoint(),
+ Botan::Certificate_Status_Code::OCSP_RESPONSE_GOOD);
+ check_ocsp(Botan::calendar_point(2019, 5, 28, 8, 0, 0).to_std_timepoint(),
+ Botan::Certificate_Status_Code::OCSP_RESPONSE_GOOD);
return result;
}
@@ -224,7 +348,10 @@ class OCSP_Tests final : public Test
results.push_back(test_request_encoding());
results.push_back(test_response_parsing());
results.push_back(test_response_certificate_access());
- results.push_back(test_response_verification());
+ results.push_back(test_response_verification_with_next_update_without_max_age());
+ results.push_back(test_response_verification_with_next_update_with_max_age());
+ results.push_back(test_response_verification_without_next_update_with_max_age());
+ results.push_back(test_response_verification_without_next_update_without_max_age());
results.push_back(test_response_verification_softfail());
#if defined(BOTAN_HAS_ONLINE_REVOCATION_CHECKS)