|
9 | 9 |
|
10 | 10 | #include "shared/crypto/Certificate.hxx" |
11 | 11 | #include "shared/crypto/EllipticCurveUtils.hxx" |
| 12 | +#include "shared/tsl/OcspHelper.hxx" |
12 | 13 | #include "shared/tsl/OcspService.hxx" |
13 | 14 | #include "shared/tsl/TrustStore.hxx" |
14 | 15 | #include "shared/tsl/TslService.hxx" |
@@ -178,3 +179,59 @@ TEST_F(TslServiceTest, verifyCertificatePolicyFailing)//NOLINT(readability-funct |
178 | 179 | {TslErrorCode::CERT_TYPE_MISMATCH}, |
179 | 180 | HttpStatus::BadRequest); |
180 | 181 | } |
| 182 | + |
| 183 | + |
| 184 | +TEST_F(TslServiceTest, doNotCacheProvidedOcspResponse) |
| 185 | +{ |
| 186 | + UrlRequestSenderMock requestSender({}); |
| 187 | + X509Certificate x509Certificate = X509Certificate::createFromAsnBytes( |
| 188 | + {reinterpret_cast<const unsigned char*>(userCertificate.data()), userCertificate.size()}); |
| 189 | + |
| 190 | + auto iterator = mTrustStore->mServiceInformationMap.find( |
| 191 | + {x509Certificate.getIssuer(), x509Certificate.getAuthorityKeyIdentifier()}); |
| 192 | + ASSERT_NE(mTrustStore->mServiceInformationMap.end(), iterator); |
| 193 | + |
| 194 | + auto cert = Certificate::fromBinaryDer(userCertificate); |
| 195 | + auto certCa = Certificate::fromBase64Der(iterator->second.certificate.toBase64()); |
| 196 | + |
| 197 | + auto checkDescriptor = TslTestHelper::getDefaultTestOcspCheckDescriptor(); |
| 198 | + OcspCertidPtr certId(OCSP_cert_to_id(nullptr, cert.toX509(), certCa.toX509())); |
| 199 | + |
| 200 | + const auto certPairValid = MockOcsp::CertificatePair{.certificate = cert, |
| 201 | + .issuer = certCa, |
| 202 | + .testMode = MockOcsp::CertificateOcspTestMode::SUCCESS}; |
| 203 | + |
| 204 | + auto ocspCert = TslTestHelper::getDefaultOcspCertificate(); |
| 205 | + auto ocspKey = TslTestHelper::getDefaultOcspPrivateKey(); |
| 206 | + |
| 207 | + auto response = MockOcsp::create(certId.get(), {certPairValid}, ocspCert, ocspKey).toDer(); |
| 208 | + checkDescriptor.providedOcspResponse = OcspHelper::stringToOcspResponse(response); |
| 209 | + |
| 210 | + |
| 211 | + const auto fingerprint = x509Certificate.getSha256FingerprintHex(); |
| 212 | + |
| 213 | + // if we dont make a request, do not cache the ocsp response |
| 214 | + using enum OcspCheckDescriptor::OcspCheckMode; |
| 215 | + for (auto mode : {PROVIDED_OR_CACHE_REQUEST_IF_OUTDATED, PROVIDED_OR_CACHE, PROVIDED_OR_CACHE_REQUEST_IF_OUTDATED, |
| 216 | + PROVIDED_ONLY}) |
| 217 | + { |
| 218 | + checkDescriptor.mode = mode; |
| 219 | + mTrustStore->cleanCachedOcspData(fingerprint); |
| 220 | + EXPECT_NO_THROW(TslService::checkCertificate(x509Certificate, {CertificateType::C_HCI_OSIG}, requestSender, |
| 221 | + *mTrustStore, checkDescriptor)); |
| 222 | + ASSERT_FALSE(mTrustStore->getCachedOcspData(fingerprint).has_value()); |
| 223 | + } |
| 224 | + |
| 225 | + // if we have to make a request, allow caching of the ocsp response |
| 226 | + TslTestHelper::setOcspUrlRequestHandler(requestSender, "http://ocsp-testref.tsl.telematik-test/ocsp", |
| 227 | + {{cert, certCa, MockOcsp::CertificateOcspTestMode::SUCCESS}}); |
| 228 | + |
| 229 | + for (auto mode : {FORCE_OCSP_REQUEST_STRICT, FORCE_OCSP_REQUEST_ALLOW_CACHE}) |
| 230 | + { |
| 231 | + checkDescriptor.mode = mode; |
| 232 | + mTrustStore->cleanCachedOcspData(fingerprint); |
| 233 | + EXPECT_NO_THROW(TslService::checkCertificate(x509Certificate, {CertificateType::C_HCI_OSIG}, requestSender, |
| 234 | + *mTrustStore, checkDescriptor)); |
| 235 | + ASSERT_TRUE(mTrustStore->getCachedOcspData(fingerprint).has_value()); |
| 236 | + } |
| 237 | +} |
0 commit comments