new file mode 100644
--- /dev/null
+++ b/security/pkix/test/gtest/pkixcert_signature_algorithm_tests.cpp
@@ -0,0 +1,266 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+#include "pkix/pkix.h"
+#include "pkix/pkixnss.h"
+#include "pkixgtest.h"
+#include "pkixtestutil.h"
+
+using namespace mozilla::pkix;
+using namespace mozilla::pkix::test;
+
+static ByteString
+CreateCert(const char* issuerCN,
+ const char* subjectCN,
+ EndEntityOrCA endEntityOrCA,
+ const ByteString& signatureAlgorithm,
+ /*optional*/ TestKeyPair* issuerKey,
+ /*out*/ ScopedTestKeyPair& subjectKey,
+ /*out*/ ByteString& subjectDER)
+{
+ static long serialNumberValue = 0;
+ ++serialNumberValue;
+ ByteString serialNumber(CreateEncodedSerialNumber(serialNumberValue));
+ EXPECT_FALSE(ENCODING_FAILED(serialNumber));
+
+ ByteString issuerDER(CNToDERName(issuerCN));
+ EXPECT_FALSE(ENCODING_FAILED(issuerDER));
+ subjectDER = CNToDERName(subjectCN);
+ EXPECT_FALSE(ENCODING_FAILED(subjectDER));
+
+ ByteString extensions[2];
+ if (endEntityOrCA == EndEntityOrCA::MustBeCA) {
+ extensions[0] =
+ CreateEncodedBasicConstraints(true, nullptr,
+ ExtensionCriticality::Critical);
+ EXPECT_FALSE(ENCODING_FAILED(extensions[0]));
+ }
+
+ ByteString certDER(CreateEncodedCertificate(v3, signatureAlgorithm,
+ serialNumber,
+ issuerDER, oneDayBeforeNow,
+ oneDayAfterNow, subjectDER,
+ extensions, issuerKey,
+ signatureAlgorithm, subjectKey));
+ EXPECT_FALSE(ENCODING_FAILED(certDER));
+ return certDER;
+}
+
+class AlgorithmTestsTrustDomain : public TrustDomain
+{
+public:
+ AlgorithmTestsTrustDomain(const ByteString& rootDER,
+ const ByteString& rootSubjectDER,
+ /*optional*/ const ByteString& intDER,
+ /*optional*/ const ByteString& intSubjectDER)
+ : rootDER(rootDER)
+ , rootSubjectDER(rootSubjectDER)
+ , intDER(intDER)
+ , intSubjectDER(intSubjectDER)
+ {
+ }
+
+private:
+ virtual Result GetCertTrust(EndEntityOrCA, const CertPolicyId&,
+ Input candidateCert,
+ /*out*/ TrustLevel& trustLevel)
+ {
+ if (InputEqualsByteString(candidateCert, rootDER)) {
+ trustLevel = TrustLevel::TrustAnchor;
+ } else {
+ trustLevel = TrustLevel::InheritsTrust;
+ }
+ return Success;
+ }
+
+ virtual Result FindIssuer(Input encodedIssuerName, IssuerChecker& checker,
+ Time)
+ {
+ ByteString* issuerDER = nullptr;
+ if (InputEqualsByteString(encodedIssuerName, rootSubjectDER)) {
+ issuerDER = &rootDER;
+ } else if (InputEqualsByteString(encodedIssuerName, intSubjectDER)) {
+ issuerDER = &intDER;
+ } else {
+ // FindIssuer just returns success if it can't find a potential issuer.
+ return Success;
+ }
+ Input issuerCert;
+ Result rv = issuerCert.Init(issuerDER->data(), issuerDER->length());
+ if (rv != Success) {
+ return rv;
+ }
+ bool keepGoing;
+ return checker.Check(issuerCert, nullptr, keepGoing);
+ }
+
+ virtual Result CheckRevocation(EndEntityOrCA, const CertID&, Time,
+ const Input*, const Input*)
+ {
+ return Success;
+ }
+
+ virtual Result IsChainValid(const DERArray&, Time)
+ {
+ return Success;
+ }
+
+ virtual Result VerifySignedData(const SignedDataWithSignature& signedData,
+ Input subjectPublicKeyInfo)
+ {
+ EXPECT_NE(SignatureAlgorithm::unsupported_algorithm, signedData.algorithm);
+ return ::mozilla::pkix::VerifySignedData(signedData, subjectPublicKeyInfo,
+ nullptr);
+ }
+
+ virtual Result DigestBuf(Input, uint8_t*, size_t)
+ {
+ ADD_FAILURE();
+ return Result::FATAL_ERROR_LIBRARY_FAILURE;
+ }
+
+ virtual Result CheckPublicKey(Input subjectPublicKeyInfo)
+ {
+ return TestCheckPublicKey(subjectPublicKeyInfo);
+ }
+
+ ByteString rootDER;
+ ByteString rootSubjectDER;
+ ByteString intDER;
+ ByteString intSubjectDER;
+};
+
+static const ByteString NO_INTERMEDIATE; // empty
+
+struct ChainValidity
+{
+ // In general, a certificate is generated for each of these. However, if
+ // optionalIntermediateSignatureAlgorithm is NO_INTERMEDIATE, then only 2
+ // certificates are generated.
+ // The certificate generated for the given rootSignatureAlgorithm is the
+ // trust anchor.
+ ByteString endEntitySignatureAlgorithm;
+ ByteString optionalIntermediateSignatureAlgorithm;
+ ByteString rootSignatureAlgorithm;
+ bool isValid;
+};
+
+static const ChainValidity CHAIN_VALIDITY[] =
+{
+ // The trust anchor may have a signature with an unsupported signature
+ // algorithm.
+ { sha256WithRSAEncryption,
+ NO_INTERMEDIATE,
+ md5WithRSAEncryption,
+ true
+ },
+ { sha256WithRSAEncryption,
+ NO_INTERMEDIATE,
+ md2WithRSAEncryption,
+ true
+ },
+
+ // Certificates that are not trust anchors must not have a signature with an
+ // unsupported signature algorithm.
+ { md5WithRSAEncryption,
+ NO_INTERMEDIATE,
+ sha256WithRSAEncryption,
+ false
+ },
+ { md2WithRSAEncryption,
+ NO_INTERMEDIATE,
+ sha256WithRSAEncryption,
+ false
+ },
+ { md2WithRSAEncryption,
+ NO_INTERMEDIATE,
+ md5WithRSAEncryption,
+ false
+ },
+ { sha256WithRSAEncryption,
+ md5WithRSAEncryption,
+ sha256WithRSAEncryption,
+ false
+ },
+ { sha256WithRSAEncryption,
+ md2WithRSAEncryption,
+ sha256WithRSAEncryption,
+ false
+ },
+ { sha256WithRSAEncryption,
+ md2WithRSAEncryption,
+ md5WithRSAEncryption,
+ false
+ },
+};
+
+class pkixcert_IsValidChainForAlgorithm
+ : public ::testing::Test
+ , public ::testing::WithParamInterface<ChainValidity>
+{
+};
+
+TEST_P(pkixcert_IsValidChainForAlgorithm, IsValidChainForAlgorithm)
+{
+ const ChainValidity& chainValidity(GetParam());
+ const char* rootCN = "CN=Root";
+ ScopedTestKeyPair rootKey;
+ ByteString rootSubjectDER;
+ ByteString rootEncoded(
+ CreateCert(rootCN, rootCN, EndEntityOrCA::MustBeCA,
+ chainValidity.rootSignatureAlgorithm,
+ nullptr, rootKey, rootSubjectDER));
+ EXPECT_FALSE(ENCODING_FAILED(rootEncoded));
+ EXPECT_FALSE(ENCODING_FAILED(rootSubjectDER));
+
+ const char* issuerCN = rootCN;
+ TestKeyPair* issuerKey = rootKey.get();
+
+ const char* intermediateCN = "CN=Intermediate";
+ ScopedTestKeyPair intermediateKey;
+ ByteString intermediateSubjectDER;
+ ByteString intermediateEncoded;
+ if (chainValidity.optionalIntermediateSignatureAlgorithm != NO_INTERMEDIATE) {
+ intermediateEncoded =
+ CreateCert(rootCN, intermediateCN, EndEntityOrCA::MustBeCA,
+ chainValidity.optionalIntermediateSignatureAlgorithm,
+ rootKey.get(), intermediateKey, intermediateSubjectDER);
+ EXPECT_FALSE(ENCODING_FAILED(intermediateEncoded));
+ EXPECT_FALSE(ENCODING_FAILED(intermediateSubjectDER));
+ issuerCN = intermediateCN;
+ issuerKey = intermediateKey.get();
+ }
+
+ AlgorithmTestsTrustDomain trustDomain(rootEncoded, rootSubjectDER,
+ intermediateEncoded,
+ intermediateSubjectDER);
+
+ const char* endEntityCN = "CN=End Entity";
+ ScopedTestKeyPair endEntityKey;
+ ByteString endEntitySubjectDER;
+ ByteString endEntityEncoded(
+ CreateCert(issuerCN, endEntityCN, EndEntityOrCA::MustBeEndEntity,
+ chainValidity.endEntitySignatureAlgorithm,
+ issuerKey, endEntityKey, endEntitySubjectDER));
+ EXPECT_FALSE(ENCODING_FAILED(endEntityEncoded));
+ EXPECT_FALSE(ENCODING_FAILED(endEntitySubjectDER));
+
+ Input endEntity;
+ ASSERT_EQ(Success, endEntity.Init(endEntityEncoded.data(),
+ endEntityEncoded.length()));
+ Result expectedResult = chainValidity.isValid
+ ? Success
+ : Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED;
+ ASSERT_EQ(expectedResult,
+ BuildCertChain(trustDomain, endEntity, Now(),
+ EndEntityOrCA::MustBeEndEntity,
+ KeyUsage::noParticularKeyUsageRequired,
+ KeyPurposeId::id_kp_serverAuth,
+ CertPolicyId::anyPolicy, nullptr));
+}
+
+INSTANTIATE_TEST_CASE_P(pkixcert_IsValidChainForAlgorithm,
+ pkixcert_IsValidChainForAlgorithm,
+ testing::ValuesIn(CHAIN_VALIDITY));
--- a/security/pkix/test/gtest/pkixocsp_VerifyEncodedOCSPResponse.cpp
+++ b/security/pkix/test/gtest/pkixocsp_VerifyEncodedOCSPResponse.cpp
@@ -234,31 +234,33 @@ public:
static void SetUpTestCase()
{
pkixocsp_VerifyEncodedResponse::SetUpTestCase();
}
ByteString CreateEncodedOCSPSuccessfulResponse(
OCSPResponseContext::CertStatus certStatus,
const CertID& certID,
- /*optional*/ const char* signerName,
+ /*optional*/ const char* signerName,
const TestKeyPair& signerKeyPair,
time_t producedAt, time_t thisUpdate,
- /*optional*/ const time_t* nextUpdate,
- /*optional*/ const ByteString* certs = nullptr)
+ /*optional*/ const time_t* nextUpdate,
+ const ByteString& signatureAlgorithm,
+ /*optional*/ const ByteString* certs = nullptr)
{
OCSPResponseContext context(certID, producedAt);
if (signerName) {
context.signerNameDER = CNToDERName(signerName);
EXPECT_FALSE(ENCODING_FAILED(context.signerNameDER));
}
context.signerKeyPair = signerKeyPair.Clone();
EXPECT_TRUE(context.signerKeyPair);
context.responseStatus = OCSPResponseContext::successful;
context.producedAt = producedAt;
+ context.signatureAlgorithm = signatureAlgorithm;
context.certs = certs;
context.certStatus = certStatus;
context.thisUpdate = thisUpdate;
context.nextUpdate = nextUpdate ? *nextUpdate : 0;
context.includeNextUpdate = nextUpdate != nullptr;
return CreateEncodedOCSPResponse(context);
@@ -266,17 +268,18 @@ public:
};
TEST_F(pkixocsp_VerifyEncodedResponse_successful, good_byKey)
{
ByteString responseString(
CreateEncodedOCSPSuccessfulResponse(
OCSPResponseContext::good, *endEntityCertID, byKey,
*rootKeyPair, oneDayBeforeNow,
- oneDayBeforeNow, &oneDayAfterNow));
+ oneDayBeforeNow, &oneDayAfterNow,
+ sha256WithRSAEncryption));
Input response;
ASSERT_EQ(Success,
response.Init(responseString.data(), responseString.length()));
bool expired;
ASSERT_EQ(Success,
VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID,
Now(), END_ENTITY_MAX_LIFETIME_IN_DAYS,
response, expired));
@@ -284,17 +287,18 @@ TEST_F(pkixocsp_VerifyEncodedResponse_su
}
TEST_F(pkixocsp_VerifyEncodedResponse_successful, good_byName)
{
ByteString responseString(
CreateEncodedOCSPSuccessfulResponse(
OCSPResponseContext::good, *endEntityCertID, rootName,
*rootKeyPair, oneDayBeforeNow,
- oneDayBeforeNow, &oneDayAfterNow));
+ oneDayBeforeNow, &oneDayAfterNow,
+ sha256WithRSAEncryption));
Input response;
ASSERT_EQ(Success,
response.Init(responseString.data(), responseString.length()));
bool expired;
ASSERT_EQ(Success,
VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
END_ENTITY_MAX_LIFETIME_IN_DAYS,
response, expired));
@@ -302,17 +306,18 @@ TEST_F(pkixocsp_VerifyEncodedResponse_su
}
TEST_F(pkixocsp_VerifyEncodedResponse_successful, good_byKey_without_nextUpdate)
{
ByteString responseString(
CreateEncodedOCSPSuccessfulResponse(
OCSPResponseContext::good, *endEntityCertID, byKey,
*rootKeyPair, oneDayBeforeNow,
- oneDayBeforeNow, nullptr));
+ oneDayBeforeNow, nullptr,
+ sha256WithRSAEncryption));
Input response;
ASSERT_EQ(Success,
response.Init(responseString.data(), responseString.length()));
bool expired;
ASSERT_EQ(Success,
VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
END_ENTITY_MAX_LIFETIME_IN_DAYS,
response, expired));
@@ -320,17 +325,18 @@ TEST_F(pkixocsp_VerifyEncodedResponse_su
}
TEST_F(pkixocsp_VerifyEncodedResponse_successful, revoked)
{
ByteString responseString(
CreateEncodedOCSPSuccessfulResponse(
OCSPResponseContext::revoked, *endEntityCertID, byKey,
*rootKeyPair, oneDayBeforeNow,
- oneDayBeforeNow, &oneDayAfterNow));
+ oneDayBeforeNow, &oneDayAfterNow,
+ sha256WithRSAEncryption));
Input response;
ASSERT_EQ(Success,
response.Init(responseString.data(), responseString.length()));
bool expired;
ASSERT_EQ(Result::ERROR_REVOKED_CERTIFICATE,
VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
END_ENTITY_MAX_LIFETIME_IN_DAYS,
response, expired));
@@ -338,28 +344,49 @@ TEST_F(pkixocsp_VerifyEncodedResponse_su
}
TEST_F(pkixocsp_VerifyEncodedResponse_successful, unknown)
{
ByteString responseString(
CreateEncodedOCSPSuccessfulResponse(
OCSPResponseContext::unknown, *endEntityCertID, byKey,
*rootKeyPair, oneDayBeforeNow,
- oneDayBeforeNow, &oneDayAfterNow));
+ oneDayBeforeNow, &oneDayAfterNow,
+ sha256WithRSAEncryption));
Input response;
ASSERT_EQ(Success,
response.Init(responseString.data(), responseString.length()));
bool expired;
ASSERT_EQ(Result::ERROR_OCSP_UNKNOWN_CERT,
VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
END_ENTITY_MAX_LIFETIME_IN_DAYS,
response, expired));
ASSERT_FALSE(expired);
}
+TEST_F(pkixocsp_VerifyEncodedResponse_successful,
+ good_unsupportedSignatureAlgorithm)
+{
+ ByteString responseString(
+ CreateEncodedOCSPSuccessfulResponse(
+ OCSPResponseContext::good, *endEntityCertID, byKey,
+ *rootKeyPair, oneDayBeforeNow,
+ oneDayBeforeNow, &oneDayAfterNow,
+ md5WithRSAEncryption));
+ Input response;
+ ASSERT_EQ(Success,
+ response.Init(responseString.data(), responseString.length()));
+ bool expired;
+ ASSERT_EQ(Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED,
+ VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID,
+ Now(), END_ENTITY_MAX_LIFETIME_IN_DAYS,
+ response, expired));
+ ASSERT_FALSE(expired);
+}
+
///////////////////////////////////////////////////////////////////////////////
// indirect responses (signed by a delegated OCSP responder cert)
class pkixocsp_VerifyEncodedResponse_DelegatedResponder
: public pkixocsp_VerifyEncodedResponse_successful
{
protected:
// certSubjectName should be unique for each call. This way, we avoid any
@@ -367,40 +394,45 @@ protected:
// we generate a new keypair on each call. Either one of these should be
// sufficient to avoid issues with the NSS cache, but we do both to be
// cautious.
//
// signerName should be byKey to use the byKey ResponderID construction, or
// another value (usually equal to certSubjectName) to use the byName
// ResponderID construction.
//
+ // certSignatureAlgorithm specifies the signature algorithm that the
+ // certificate will be signed with, not the OCSP response.
+ //
// If signerEKU is omitted, then the certificate will have the
// id-kp-OCSPSigning EKU. If signerEKU is SEC_OID_UNKNOWN then it will not
// have any EKU extension. Otherwise, the certificate will have the given
// EKU.
ByteString CreateEncodedIndirectOCSPSuccessfulResponse(
const char* certSubjectName,
OCSPResponseContext::CertStatus certStatus,
const char* signerName,
+ const ByteString& certSignatureAlgorithm,
/*optional*/ const Input* signerEKUDER = &OCSPSigningEKUDER,
/*optional, out*/ ByteString* signerDEROut = nullptr)
{
assert(certSubjectName);
const ByteString extensions[] = {
signerEKUDER
? CreateEncodedEKUExtension(*signerEKUDER,
ExtensionCriticality::NotCritical)
: ByteString(),
ByteString()
};
ScopedTestKeyPair signerKeyPair;
ByteString signerDER(CreateEncodedCertificate(
++rootIssuedCount, rootName,
oneDayBeforeNow, oneDayAfterNow, certSubjectName,
+ certSignatureAlgorithm,
signerEKUDER ? extensions : nullptr,
rootKeyPair.get(), signerKeyPair));
EXPECT_FALSE(ENCODING_FAILED(signerDER));
if (signerDEROut) {
*signerDEROut = signerDER;
}
ByteString signerNameDER;
@@ -408,24 +440,27 @@ protected:
signerNameDER = CNToDERName(signerName);
EXPECT_FALSE(ENCODING_FAILED(signerNameDER));
}
ByteString certs[] = { signerDER, ByteString() };
return CreateEncodedOCSPSuccessfulResponse(certStatus, *endEntityCertID,
signerName, *signerKeyPair,
oneDayBeforeNow,
oneDayBeforeNow,
- &oneDayAfterNow, certs);
+ &oneDayAfterNow,
+ sha256WithRSAEncryption,
+ certs);
}
static ByteString CreateEncodedCertificate(uint32_t serialNumber,
const char* issuer,
time_t notBefore,
time_t notAfter,
const char* subject,
+ const ByteString& signatureAlg,
/*optional*/ const ByteString* extensions,
/*optional*/ TestKeyPair* signerKeyPair,
/*out*/ ScopedTestKeyPair& keyPair)
{
ByteString serialNumberDER(CreateEncodedSerialNumber(serialNumber));
if (ENCODING_FAILED(serialNumberDER)) {
return ByteString();
}
@@ -434,53 +469,53 @@ protected:
return ByteString();
}
ByteString subjectDER(CNToDERName(subject));
if (ENCODING_FAILED(subjectDER)) {
return ByteString();
}
return ::mozilla::pkix::test::CreateEncodedCertificate(
v3,
- sha256WithRSAEncryption,
+ signatureAlg,
serialNumberDER, issuerDER, notBefore,
notAfter, subjectDER, extensions,
signerKeyPair,
- sha256WithRSAEncryption,
+ signatureAlg,
keyPair);
}
static const Input OCSPSigningEKUDER;
};
/*static*/ const Input pkixocsp_VerifyEncodedResponse_DelegatedResponder::
OCSPSigningEKUDER(tlv_id_kp_OCSPSigning);
TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, good_byKey)
{
ByteString responseString(
CreateEncodedIndirectOCSPSuccessfulResponse(
"good_indirect_byKey", OCSPResponseContext::good,
- byKey));
+ byKey, sha256WithRSAEncryption));
Input response;
ASSERT_EQ(Success,
response.Init(responseString.data(), responseString.length()));
bool expired;
ASSERT_EQ(Success,
VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
END_ENTITY_MAX_LIFETIME_IN_DAYS,
response, expired));
ASSERT_FALSE(expired);
}
TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, good_byName)
{
ByteString responseString(
CreateEncodedIndirectOCSPSuccessfulResponse(
"good_indirect_byName", OCSPResponseContext::good,
- "good_indirect_byName"));
+ "good_indirect_byName", sha256WithRSAEncryption));
Input response;
ASSERT_EQ(Success,
response.Init(responseString.data(), responseString.length()));
bool expired;
ASSERT_EQ(Success,
VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
END_ENTITY_MAX_LIFETIME_IN_DAYS,
response, expired));
@@ -492,17 +527,18 @@ TEST_F(pkixocsp_VerifyEncodedResponse_De
{
ScopedTestKeyPair missingSignerKeyPair(GenerateKeyPair());
ASSERT_TRUE(missingSignerKeyPair);
ByteString responseString(
CreateEncodedOCSPSuccessfulResponse(
OCSPResponseContext::good, *endEntityCertID, byKey,
*missingSignerKeyPair, oneDayBeforeNow,
- oneDayBeforeNow, nullptr));
+ oneDayBeforeNow, nullptr,
+ sha256WithRSAEncryption));
Input response;
ASSERT_EQ(Success,
response.Init(responseString.data(), responseString.length()));
bool expired;
ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT,
VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
END_ENTITY_MAX_LIFETIME_IN_DAYS,
response, expired));
@@ -513,17 +549,18 @@ TEST_F(pkixocsp_VerifyEncodedResponse_De
good_byName_missing_signer)
{
ScopedTestKeyPair missingSignerKeyPair(GenerateKeyPair());
ASSERT_TRUE(missingSignerKeyPair);
ByteString responseString(
CreateEncodedOCSPSuccessfulResponse(
OCSPResponseContext::good, *endEntityCertID,
"missing", *missingSignerKeyPair,
- oneDayBeforeNow, oneDayBeforeNow, nullptr));
+ oneDayBeforeNow, oneDayBeforeNow, nullptr,
+ sha256WithRSAEncryption));
Input response;
ASSERT_EQ(Success,
response.Init(responseString.data(), responseString.length()));
bool expired;
ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT,
VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
END_ENTITY_MAX_LIFETIME_IN_DAYS,
response, expired));
@@ -540,26 +577,27 @@ TEST_F(pkixocsp_VerifyEncodedResponse_De
ByteString()
};
ScopedTestKeyPair signerKeyPair;
ByteString signerDER(CreateEncodedCertificate(
++rootIssuedCount, rootName,
now - (10 * Time::ONE_DAY_IN_SECONDS),
now - (2 * Time::ONE_DAY_IN_SECONDS),
- signerName, extensions, rootKeyPair.get(),
- signerKeyPair));
+ signerName, sha256WithRSAEncryption, extensions,
+ rootKeyPair.get(), signerKeyPair));
ASSERT_FALSE(ENCODING_FAILED(signerDER));
ByteString certs[] = { signerDER, ByteString() };
ByteString responseString(
CreateEncodedOCSPSuccessfulResponse(
OCSPResponseContext::good, *endEntityCertID,
signerName, *signerKeyPair, oneDayBeforeNow,
- oneDayBeforeNow, &oneDayAfterNow, certs));
+ oneDayBeforeNow, &oneDayAfterNow,
+ sha256WithRSAEncryption, certs));
Input response;
ASSERT_EQ(Success,
response.Init(responseString.data(), responseString.length()));
bool expired;
ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT,
VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
END_ENTITY_MAX_LIFETIME_IN_DAYS,
response, expired));
@@ -575,43 +613,45 @@ TEST_F(pkixocsp_VerifyEncodedResponse_De
ByteString()
};
ScopedTestKeyPair signerKeyPair;
ByteString signerDER(CreateEncodedCertificate(
++rootIssuedCount, rootName,
now + (2 * Time::ONE_DAY_IN_SECONDS),
now + (10 * Time::ONE_DAY_IN_SECONDS),
- signerName, extensions, rootKeyPair.get(),
- signerKeyPair));
+ signerName, sha256WithRSAEncryption, extensions,
+ rootKeyPair.get(), signerKeyPair));
ASSERT_FALSE(ENCODING_FAILED(signerDER));
ByteString certs[] = { signerDER, ByteString() };
ByteString responseString(
CreateEncodedOCSPSuccessfulResponse(
OCSPResponseContext::good, *endEntityCertID,
signerName, *signerKeyPair, oneDayBeforeNow,
- oneDayBeforeNow, &oneDayAfterNow, certs));
+ oneDayBeforeNow, &oneDayAfterNow,
+ sha256WithRSAEncryption, certs));
Input response;
ASSERT_EQ(Success,
response.Init(responseString.data(), responseString.length()));
bool expired;
ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT,
VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
END_ENTITY_MAX_LIFETIME_IN_DAYS,
response, expired));
ASSERT_FALSE(expired);
}
TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, good_no_eku)
{
ByteString responseString(
CreateEncodedIndirectOCSPSuccessfulResponse(
"good_indirect_wrong_eku",
- OCSPResponseContext::good, byKey, nullptr));
+ OCSPResponseContext::good, byKey,
+ sha256WithRSAEncryption, nullptr));
Input response;
ASSERT_EQ(Success,
response.Init(responseString.data(), responseString.length()));
bool expired;
ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT,
VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
END_ENTITY_MAX_LIFETIME_IN_DAYS,
response, expired));
@@ -621,17 +661,18 @@ TEST_F(pkixocsp_VerifyEncodedResponse_De
static const Input serverAuthEKUDER(tlv_id_kp_serverAuth);
TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,
good_indirect_wrong_eku)
{
ByteString responseString(
CreateEncodedIndirectOCSPSuccessfulResponse(
"good_indirect_wrong_eku",
- OCSPResponseContext::good, byKey, &serverAuthEKUDER));
+ OCSPResponseContext::good, byKey,
+ sha256WithRSAEncryption, &serverAuthEKUDER));
Input response;
ASSERT_EQ(Success,
response.Init(responseString.data(), responseString.length()));
bool expired;
ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT,
VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
END_ENTITY_MAX_LIFETIME_IN_DAYS,
response, expired));
@@ -639,17 +680,18 @@ TEST_F(pkixocsp_VerifyEncodedResponse_De
}
// Test that signature of OCSP response signer cert is verified
TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, good_tampered_eku)
{
ByteString tamperedResponse(
CreateEncodedIndirectOCSPSuccessfulResponse(
"good_indirect_tampered_eku",
- OCSPResponseContext::good, byKey, &serverAuthEKUDER));
+ OCSPResponseContext::good, byKey,
+ sha256WithRSAEncryption, &serverAuthEKUDER));
ASSERT_EQ(Success,
TamperOnce(tamperedResponse,
ByteString(tlv_id_kp_serverAuth,
sizeof(tlv_id_kp_serverAuth)),
ByteString(tlv_id_kp_OCSPSigning,
sizeof(tlv_id_kp_OCSPSigning))));
Input tamperedResponseInput;
ASSERT_EQ(Success, tamperedResponseInput.Init(tamperedResponse.data(),
@@ -675,27 +717,28 @@ TEST_F(pkixocsp_VerifyEncodedResponse_De
const ByteString extensions[] = {
CreateEncodedEKUExtension(OCSPSigningEKUDER,
ExtensionCriticality::NotCritical),
ByteString()
};
ScopedTestKeyPair signerKeyPair;
ByteString signerDER(CreateEncodedCertificate(
1, subCAName, oneDayBeforeNow, oneDayAfterNow,
- signerName, extensions, unknownKeyPair.get(),
- signerKeyPair));
+ signerName, sha256WithRSAEncryption, extensions,
+ unknownKeyPair.get(), signerKeyPair));
ASSERT_FALSE(ENCODING_FAILED(signerDER));
// OCSP response signed by that delegated responder
ByteString certs[] = { signerDER, ByteString() };
ByteString responseString(
CreateEncodedOCSPSuccessfulResponse(
OCSPResponseContext::good, *endEntityCertID,
signerName, *signerKeyPair, oneDayBeforeNow,
- oneDayBeforeNow, &oneDayAfterNow, certs));
+ oneDayBeforeNow, &oneDayAfterNow,
+ sha256WithRSAEncryption, certs));
Input response;
ASSERT_EQ(Success,
response.Init(responseString.data(), responseString.length()));
bool expired;
ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT,
VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
END_ENTITY_MAX_LIFETIME_IN_DAYS,
response, expired));
@@ -715,41 +758,42 @@ TEST_F(pkixocsp_VerifyEncodedResponse_De
const ByteString subCAExtensions[] = {
CreateEncodedBasicConstraints(true, 0, ExtensionCriticality::NotCritical),
ByteString()
};
ScopedTestKeyPair subCAKeyPair;
ByteString subCADER(CreateEncodedCertificate(
++rootIssuedCount, rootName,
oneDayBeforeNow, oneDayAfterNow,
- subCAName, subCAExtensions, rootKeyPair.get(),
- subCAKeyPair));
+ subCAName, sha256WithRSAEncryption,
+ subCAExtensions, rootKeyPair.get(), subCAKeyPair));
ASSERT_FALSE(ENCODING_FAILED(subCADER));
// Delegated responder cert signed by that sub-CA
const ByteString extensions[] = {
CreateEncodedEKUExtension(OCSPSigningEKUDER,
ExtensionCriticality::NotCritical),
ByteString(),
};
ScopedTestKeyPair signerKeyPair;
ByteString signerDER(CreateEncodedCertificate(
1, subCAName, oneDayBeforeNow, oneDayAfterNow,
- signerName, extensions, subCAKeyPair.get(),
- signerKeyPair));
+ signerName, sha256WithRSAEncryption, extensions,
+ subCAKeyPair.get(), signerKeyPair));
ASSERT_FALSE(ENCODING_FAILED(signerDER));
// OCSP response signed by the delegated responder issued by the sub-CA
// that is trying to impersonate the root.
ByteString certs[] = { subCADER, signerDER, ByteString() };
ByteString responseString(
CreateEncodedOCSPSuccessfulResponse(
OCSPResponseContext::good, *endEntityCertID,
signerName, *signerKeyPair, oneDayBeforeNow,
- oneDayBeforeNow, &oneDayAfterNow, certs));
+ oneDayBeforeNow, &oneDayAfterNow,
+ sha256WithRSAEncryption, certs));
Input response;
ASSERT_EQ(Success,
response.Init(responseString.data(), responseString.length()));
bool expired;
ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT,
VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
END_ENTITY_MAX_LIFETIME_IN_DAYS,
response, expired));
@@ -768,64 +812,89 @@ TEST_F(pkixocsp_VerifyEncodedResponse_De
// sub-CA of root (root is the direct issuer of endEntity)
const ByteString subCAExtensions[] = {
CreateEncodedBasicConstraints(true, 0, ExtensionCriticality::NotCritical),
ByteString()
};
ScopedTestKeyPair subCAKeyPair;
ByteString subCADER(CreateEncodedCertificate(++rootIssuedCount, rootName,
oneDayBeforeNow, oneDayAfterNow,
- subCAName, subCAExtensions,
+ subCAName,
+ sha256WithRSAEncryption,
+ subCAExtensions,
rootKeyPair.get(),
subCAKeyPair));
ASSERT_FALSE(ENCODING_FAILED(subCADER));
// Delegated responder cert signed by that sub-CA
const ByteString extensions[] = {
CreateEncodedEKUExtension(OCSPSigningEKUDER,
ExtensionCriticality::NotCritical),
ByteString()
};
ScopedTestKeyPair signerKeyPair;
ByteString signerDER(CreateEncodedCertificate(
1, subCAName, oneDayBeforeNow, oneDayAfterNow,
- signerName, extensions, subCAKeyPair.get(),
- signerKeyPair));
+ signerName, sha256WithRSAEncryption, extensions,
+ subCAKeyPair.get(), signerKeyPair));
ASSERT_FALSE(ENCODING_FAILED(signerDER));
// OCSP response signed by the delegated responder issued by the sub-CA
// that is trying to impersonate the root.
ByteString certs[] = { signerDER, subCADER, ByteString() };
ByteString responseString(
CreateEncodedOCSPSuccessfulResponse(
OCSPResponseContext::good, *endEntityCertID,
signerName, *signerKeyPair, oneDayBeforeNow,
- oneDayBeforeNow, &oneDayAfterNow, certs));
+ oneDayBeforeNow, &oneDayAfterNow,
+ sha256WithRSAEncryption, certs));
Input response;
ASSERT_EQ(Success,
response.Init(responseString.data(), responseString.length()));
bool expired;
ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT,
VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
END_ENTITY_MAX_LIFETIME_IN_DAYS,
response, expired));
ASSERT_FALSE(expired);
}
+TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,
+ good_unsupportedSignatureAlgorithmOnResponder)
+{
+ // Note that the algorithm ID (md5WithRSAEncryption) identifies the signature
+ // algorithm that will be used to sign the certificate that issues the OCSP
+ // responses, not the responses themselves.
+ ByteString responseString(
+ CreateEncodedIndirectOCSPSuccessfulResponse(
+ "good_indirect_unsupportedSignatureAlgorithm",
+ OCSPResponseContext::good, byKey,
+ md5WithRSAEncryption));
+ Input response;
+ ASSERT_EQ(Success,
+ response.Init(responseString.data(), responseString.length()));
+ bool expired;
+ ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT,
+ VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
+ END_ENTITY_MAX_LIFETIME_IN_DAYS,
+ response, expired));
+}
+
class pkixocsp_VerifyEncodedResponse_GetCertTrust
: public pkixocsp_VerifyEncodedResponse_DelegatedResponder {
public:
void SetUp()
{
pkixocsp_VerifyEncodedResponse_DelegatedResponder::SetUp();
responseString =
CreateEncodedIndirectOCSPSuccessfulResponse(
"OCSPGetCertTrustTest Signer", OCSPResponseContext::good,
- byKey, &OCSPSigningEKUDER, &signerCertDER);
+ byKey, sha256WithRSAEncryption, &OCSPSigningEKUDER,
+ &signerCertDER);
if (ENCODING_FAILED(responseString)) {
abort();
}
if (response.Init(responseString.data(), responseString.length())
!= Success) {
abort();
}
if (signerCertDER.length() == 0) {