mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-04 13:07:52 +00:00
Bug 1493788 - convert mozilla::Vector to std::vector in certificate transparency implementation r=jcj
In order to make our certificate transparency implementation standalone, we have to remove mozilla-specific dependencies such as mozilla::Vector. Depends on D6844 Differential Revision: https://phabricator.services.mozilla.com/D6845 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
24a8ad1851
commit
1661adeb86
@ -245,11 +245,7 @@ CertVerifier::LoadKnownCTLogs()
|
||||
continue;
|
||||
}
|
||||
|
||||
rv = mCTVerifier->AddLog(std::move(logVerifier));
|
||||
if (rv != Success) {
|
||||
MOZ_ASSERT_UNREACHABLE("Failed activating a known CT Log");
|
||||
continue;
|
||||
}
|
||||
mCTVerifier->AddLog(std::move(logVerifier));
|
||||
}
|
||||
// TBD: Initialize mCTDiversityPolicy with the CA dependency map
|
||||
// of the known CT logs operators.
|
||||
@ -391,11 +387,7 @@ CertVerifier::VerifyCertificateTransparencyPolicy(
|
||||
}
|
||||
|
||||
CTLogOperatorList allOperators;
|
||||
rv = GetCTLogOperatorsFromVerifiedSCTList(result.verifiedScts,
|
||||
allOperators);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
GetCTLogOperatorsFromVerifiedSCTList(result.verifiedScts, allOperators);
|
||||
|
||||
CTLogOperatorList dependentOperators;
|
||||
rv = mCTDiversityPolicy->GetDependentOperators(builtChain, allOperators,
|
||||
@ -406,14 +398,8 @@ CertVerifier::VerifyCertificateTransparencyPolicy(
|
||||
|
||||
CTPolicyEnforcer ctPolicyEnforcer;
|
||||
CTPolicyCompliance ctPolicyCompliance;
|
||||
rv = ctPolicyEnforcer.CheckCompliance(result.verifiedScts, lifetimeInMonths,
|
||||
dependentOperators, ctPolicyCompliance);
|
||||
if (rv != Success) {
|
||||
MOZ_LOG(gCertVerifierLog, LogLevel::Debug,
|
||||
("CT policy check failed with fatal error %" PRIu32 "\n",
|
||||
static_cast<uint32_t>(rv)));
|
||||
return rv;
|
||||
}
|
||||
ctPolicyEnforcer.CheckCompliance(result.verifiedScts, lifetimeInMonths,
|
||||
dependentOperators, ctPolicyCompliance);
|
||||
|
||||
if (ctInfo) {
|
||||
ctInfo->verifyResult = std::move(result);
|
||||
|
@ -7,8 +7,9 @@
|
||||
#ifndef BTInclusionProof_h
|
||||
#define BTInclusionProof_h
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "Buffer.h"
|
||||
#include "mozilla/Vector.h"
|
||||
|
||||
namespace mozilla { namespace ct {
|
||||
|
||||
@ -26,14 +27,12 @@ namespace mozilla { namespace ct {
|
||||
// NodeHash inclusion_path<1..2^16-1>;
|
||||
// } InclusionProofDataV2;
|
||||
|
||||
const uint64_t kInitialPathLengthCapacity = 32;
|
||||
|
||||
struct InclusionProofDataV2
|
||||
{
|
||||
Buffer logId;
|
||||
uint64_t treeSize;
|
||||
uint64_t leafIndex;
|
||||
Vector<Buffer, kInitialPathLengthCapacity> inclusionPath;
|
||||
std::vector<Buffer> inclusionPath;
|
||||
};
|
||||
|
||||
} } // namespace mozilla:ct
|
||||
|
@ -67,7 +67,7 @@ DecodeInclusionProof(pkix::Reader& reader, InclusionProofDataV2& output)
|
||||
}
|
||||
|
||||
Reader pathReader(pathInput);
|
||||
Vector<Buffer, kInitialPathLengthCapacity> inclusionPath;
|
||||
std::vector<Buffer> inclusionPath;
|
||||
|
||||
while (!pathReader.AtEnd()) {
|
||||
Input hash;
|
||||
@ -77,24 +77,16 @@ DecodeInclusionProof(pkix::Reader& reader, InclusionProofDataV2& output)
|
||||
}
|
||||
|
||||
Buffer hashBuffer;
|
||||
rv = InputToBuffer(hash, hashBuffer);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
InputToBuffer(hash, hashBuffer);
|
||||
|
||||
if (!inclusionPath.append(std::move(hashBuffer))) {
|
||||
return pkix::Result::FATAL_ERROR_NO_MEMORY;
|
||||
}
|
||||
inclusionPath.push_back(std::move(hashBuffer));
|
||||
}
|
||||
|
||||
if (!reader.AtEnd()){
|
||||
return pkix::Result::ERROR_BAD_DER;
|
||||
}
|
||||
|
||||
rv = InputToBuffer(logId, result.logId);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
InputToBuffer(logId, result.logId);
|
||||
|
||||
result.inclusionPath = std::move(inclusionPath);
|
||||
|
||||
|
@ -12,7 +12,7 @@ bool
|
||||
operator==(const ct::Buffer& a, const ct::Buffer& b)
|
||||
{
|
||||
return (a.empty() && b.empty()) ||
|
||||
(a.length() == b.length() && memcmp(a.begin(), b.begin(), a.length()) == 0);
|
||||
(a.size() == b.size() && memcmp(a.data(), b.data(), a.size()) == 0);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -7,22 +7,12 @@
|
||||
#ifndef Buffer_h
|
||||
#define Buffer_h
|
||||
|
||||
#include "mozilla/Vector.h"
|
||||
#include <vector>
|
||||
|
||||
namespace mozilla { namespace ct {
|
||||
|
||||
typedef Vector<uint8_t> Buffer;
|
||||
typedef std::vector<uint8_t> Buffer;
|
||||
|
||||
} } // namespace mozilla::ct
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// Comparison operators are placed under mozilla namespace since
|
||||
// mozilla::ct::Buffer is actually mozilla::Vector.
|
||||
bool operator==(const ct::Buffer& a, const ct::Buffer& b);
|
||||
bool operator!=(const ct::Buffer& a, const ct::Buffer& b);
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
#endif // Buffer_h
|
||||
|
@ -10,7 +10,7 @@ namespace mozilla { namespace ct {
|
||||
|
||||
typedef mozilla::pkix::Result Result;
|
||||
|
||||
Result
|
||||
void
|
||||
GetCTLogOperatorsFromVerifiedSCTList(const VerifiedSCTList& list,
|
||||
CTLogOperatorList& operators)
|
||||
{
|
||||
@ -25,12 +25,9 @@ GetCTLogOperatorsFromVerifiedSCTList(const VerifiedSCTList& list,
|
||||
}
|
||||
}
|
||||
if (!alreadyAdded) {
|
||||
if (!operators.append(sctLogOperatorId)) {
|
||||
return Result::FATAL_ERROR_NO_MEMORY;
|
||||
}
|
||||
operators.push_back(sctLogOperatorId);
|
||||
}
|
||||
}
|
||||
return Success;
|
||||
}
|
||||
|
||||
Result
|
||||
|
@ -9,7 +9,6 @@
|
||||
|
||||
#include "CTLog.h"
|
||||
#include "CTVerifyResult.h"
|
||||
#include "mozilla/Vector.h"
|
||||
#include "pkix/Result.h"
|
||||
#include "ScopedNSSTypes.h"
|
||||
|
||||
@ -17,8 +16,8 @@ namespace mozilla { namespace ct {
|
||||
|
||||
// Retuns the list of unique CT log operator IDs appearing in the provided
|
||||
// list of verified SCTs.
|
||||
pkix::Result GetCTLogOperatorsFromVerifiedSCTList(const VerifiedSCTList& list,
|
||||
CTLogOperatorList& operators);
|
||||
void GetCTLogOperatorsFromVerifiedSCTList(const VerifiedSCTList& list,
|
||||
CTLogOperatorList& operators);
|
||||
|
||||
// Helper class used by CTPolicyEnforcer to check the CT log operators
|
||||
// diversity requirements of the CT Policy.
|
||||
|
@ -8,8 +8,7 @@
|
||||
#define CTLog_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mozilla/Vector.h"
|
||||
#include <vector>
|
||||
|
||||
namespace mozilla { namespace ct {
|
||||
|
||||
@ -19,7 +18,7 @@ namespace mozilla { namespace ct {
|
||||
// values (such as -1) to indicate a "null" or unknown log ID.
|
||||
typedef int16_t CTLogOperatorId;
|
||||
|
||||
typedef Vector<CTLogOperatorId, 8> CTLogOperatorList;
|
||||
typedef std::vector<CTLogOperatorId> CTLogOperatorList;
|
||||
|
||||
// Current status of a CT log in regard to its inclusion in the
|
||||
// Known Logs List such as https://www.certificate-transparency.org/known-logs
|
||||
|
@ -157,16 +157,13 @@ CTLogVerifier::Init(Input subjectPublicKeyInfo,
|
||||
}
|
||||
mSignatureAlgorithm = trustDomain.mSignatureAlgorithm;
|
||||
|
||||
rv = InputToBuffer(subjectPublicKeyInfo, mSubjectPublicKeyInfo);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
InputToBuffer(subjectPublicKeyInfo, mSubjectPublicKeyInfo);
|
||||
|
||||
if (mSignatureAlgorithm == DigitallySigned::SignatureAlgorithm::ECDSA) {
|
||||
SECItem spkiSECItem = {
|
||||
siBuffer,
|
||||
mSubjectPublicKeyInfo.begin(),
|
||||
static_cast<unsigned int>(mSubjectPublicKeyInfo.length())
|
||||
mSubjectPublicKeyInfo.data(),
|
||||
static_cast<unsigned int>(mSubjectPublicKeyInfo.size())
|
||||
};
|
||||
UniqueCERTSubjectPublicKeyInfo spki(
|
||||
SECKEY_DecodeDERSubjectPublicKeyInfo(&spkiSECItem));
|
||||
@ -190,11 +187,9 @@ CTLogVerifier::Init(Input subjectPublicKeyInfo,
|
||||
mPublicECKey.reset(nullptr);
|
||||
}
|
||||
|
||||
if (!mKeyId.resizeUninitialized(SHA256_LENGTH)) {
|
||||
return Result::FATAL_ERROR_NO_MEMORY;
|
||||
}
|
||||
mKeyId.resize(SHA256_LENGTH);
|
||||
rv = DigestBufNSS(subjectPublicKeyInfo, DigestAlgorithm::sha256,
|
||||
mKeyId.begin(), mKeyId.length());
|
||||
mKeyId.data(), mKeyId.size());
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
@ -229,9 +224,8 @@ CTLogVerifier::Verify(const LogEntry& entry,
|
||||
// sct.extensions may be empty. If it is, sctExtensionsInput will remain in
|
||||
// its default state, which is valid but of length 0.
|
||||
Input sctExtensionsInput;
|
||||
if (sct.extensions.length() > 0) {
|
||||
rv = sctExtensionsInput.Init(sct.extensions.begin(),
|
||||
sct.extensions.length());
|
||||
if (!sct.extensions.empty()) {
|
||||
rv = sctExtensionsInput.Init(sct.extensions.data(), sct.extensions.size());
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -6,13 +6,14 @@
|
||||
|
||||
#include "CTObjectsExtractor.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "hasht.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Casting.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/PodOperations.h"
|
||||
#include "mozilla/RangedPtr.h"
|
||||
#include "mozilla/Vector.h"
|
||||
#include "pkix/pkixnss.h"
|
||||
#include "pkixutil.h"
|
||||
|
||||
@ -238,9 +239,7 @@ private:
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
if (!mExtensionTLVs.append(std::move(extensionTLV))) {
|
||||
return Result::FATAL_ERROR_NO_MEMORY;
|
||||
}
|
||||
mExtensionTLVs.push_back(std::move(extensionTLV));
|
||||
}
|
||||
}
|
||||
return Success;
|
||||
@ -257,7 +256,7 @@ private:
|
||||
// dump of |mExtensionTLVs|
|
||||
|
||||
Result rv;
|
||||
if (mExtensionTLVs.length() > 0) {
|
||||
if (!mExtensionTLVs.empty()) {
|
||||
uint8_t tbsHeaderBuffer[MAX_TLV_HEADER_LENGTH];
|
||||
uint8_t extensionsContextHeaderBuffer[MAX_TLV_HEADER_LENGTH];
|
||||
uint8_t extensionsHeaderBuffer[MAX_TLV_HEADER_LENGTH];
|
||||
@ -344,7 +343,7 @@ private:
|
||||
|
||||
Input mDER;
|
||||
Input mTLVsBeforeExtensions;
|
||||
Vector<Input, 16> mExtensionTLVs;
|
||||
std::vector<Input> mExtensionTLVs;
|
||||
Output mOutput;
|
||||
Input mPrecertTBS;
|
||||
};
|
||||
@ -358,39 +357,36 @@ GetPrecertLogEntry(Input leafCertificate, Input issuerSubjectPublicKeyInfo,
|
||||
output.Reset();
|
||||
|
||||
Buffer precertTBSBuffer;
|
||||
if (!precertTBSBuffer.resize(leafCertificate.GetLength())) {
|
||||
return Result::FATAL_ERROR_NO_MEMORY;
|
||||
}
|
||||
precertTBSBuffer.resize(leafCertificate.GetLength());
|
||||
|
||||
PrecertTBSExtractor extractor(leafCertificate,
|
||||
precertTBSBuffer.begin(),
|
||||
precertTBSBuffer.length());
|
||||
precertTBSBuffer.data(),
|
||||
precertTBSBuffer.size());
|
||||
Result rv = extractor.Init();
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
Input precertTBS(extractor.GetPrecertTBS());
|
||||
MOZ_ASSERT(precertTBS.UnsafeGetData() == precertTBSBuffer.begin());
|
||||
precertTBSBuffer.shrinkTo(precertTBS.GetLength());
|
||||
MOZ_ASSERT(precertTBS.UnsafeGetData() == precertTBSBuffer.data());
|
||||
MOZ_ASSERT(precertTBS.GetLength() <= precertTBSBuffer.size());
|
||||
precertTBSBuffer.resize(precertTBS.GetLength());
|
||||
|
||||
output.type = LogEntry::Type::Precert;
|
||||
output.tbsCertificate = std::move(precertTBSBuffer);
|
||||
|
||||
if (!output.issuerKeyHash.resizeUninitialized(SHA256_LENGTH)) {
|
||||
return Result::FATAL_ERROR_NO_MEMORY;
|
||||
}
|
||||
output.issuerKeyHash.resize(SHA256_LENGTH);
|
||||
return DigestBufNSS(issuerSubjectPublicKeyInfo, DigestAlgorithm::sha256,
|
||||
output.issuerKeyHash.begin(),
|
||||
output.issuerKeyHash.length());
|
||||
output.issuerKeyHash.data(),
|
||||
output.issuerKeyHash.size());
|
||||
}
|
||||
|
||||
Result
|
||||
void
|
||||
GetX509LogEntry(Input leafCertificate, LogEntry& output)
|
||||
{
|
||||
MOZ_ASSERT(leafCertificate.GetLength() > 0);
|
||||
output.Reset();
|
||||
output.type = LogEntry::Type::X509;
|
||||
return InputToBuffer(leafCertificate, output.leafCertificate);
|
||||
InputToBuffer(leafCertificate, output.leafCertificate);
|
||||
}
|
||||
|
||||
} } // namespace mozilla::ct
|
||||
|
@ -32,11 +32,11 @@ pkix::Result GetPrecertLogEntry(pkix::Input leafCertificate,
|
||||
// X.509v3 certificate that is not expected to contain an X.509v3 extension
|
||||
// with the OID 1.3.6.1.4.1.11129.2.4.2 (meaning a certificate without
|
||||
// an embedded SCT).
|
||||
// On success, fills |output| with the data for an X509Chain log entry.
|
||||
// Fills |output| with the data for an X509Chain log entry.
|
||||
// The returned |output| is intended to be verified by CTLogVerifier::Verify.
|
||||
// Note that |leafCertificate| is not checked for validity or well-formedness.
|
||||
// You might want to validate it first using pkix::BuildCertChain or similar.
|
||||
pkix::Result GetX509LogEntry(pkix::Input leafCertificate, LogEntry& output);
|
||||
void GetX509LogEntry(pkix::Input leafCertificate, LogEntry& output);
|
||||
|
||||
} } // namespace mozilla::ct
|
||||
|
||||
|
@ -8,11 +8,11 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/Vector.h"
|
||||
|
||||
extern mozilla::LazyLogModule gCertVerifierLog;
|
||||
|
||||
@ -63,7 +63,7 @@ HasValidNonEmbeddedSct(const VerifiedSCTList& verifiedScts)
|
||||
// log operators running the CT logs that issued the SCTs which satisfy
|
||||
// the provided boolean predicate.
|
||||
template <typename SelectFunc>
|
||||
static Result
|
||||
void
|
||||
CountIndependentLogOperatorsForSelectedScts(const VerifiedSCTList& verifiedScts,
|
||||
const CTLogOperatorList& dependentOperators,
|
||||
size_t& count,
|
||||
@ -93,26 +93,23 @@ CountIndependentLogOperatorsForSelectedScts(const VerifiedSCTList& verifiedScts,
|
||||
}
|
||||
// ...and if not, add it.
|
||||
if (!alreadyAdded) {
|
||||
if (!operatorIds.append(sctLogOperatorId)) {
|
||||
return Result::FATAL_ERROR_NO_MEMORY;
|
||||
}
|
||||
operatorIds.push_back(sctLogOperatorId);
|
||||
}
|
||||
}
|
||||
count = operatorIds.length();
|
||||
return Success;
|
||||
count = operatorIds.size();
|
||||
}
|
||||
|
||||
// Given a list of verified SCTs, counts the number of distinct CT logs
|
||||
// that issued the SCTs that satisfy the |selected| predicate.
|
||||
template <typename SelectFunc>
|
||||
static Result
|
||||
static void
|
||||
CountLogsForSelectedScts(const VerifiedSCTList& verifiedScts,
|
||||
size_t& count,
|
||||
SelectFunc selected)
|
||||
{
|
||||
// Keep pointers to log ids (of type Buffer) from |verifiedScts| to save on
|
||||
// memory allocations.
|
||||
Vector<const Buffer*, 8> logIds;
|
||||
std::vector<const Buffer*> logIds;
|
||||
for (const VerifiedSCT& verifiedSct : verifiedScts) {
|
||||
if (!selected(verifiedSct)) {
|
||||
continue;
|
||||
@ -129,13 +126,10 @@ CountLogsForSelectedScts(const VerifiedSCTList& verifiedScts,
|
||||
}
|
||||
// ...and if not, add it.
|
||||
if (!alreadyAdded) {
|
||||
if (!logIds.append(sctLogId)) {
|
||||
return Result::FATAL_ERROR_NO_MEMORY;
|
||||
}
|
||||
logIds.push_back(sctLogId);
|
||||
}
|
||||
}
|
||||
count = logIds.length();
|
||||
return Success;
|
||||
count = logIds.size();
|
||||
}
|
||||
|
||||
// Calculates the effective issuance time of connection's certificate using
|
||||
@ -186,30 +180,26 @@ LogWasQualifiedForSct(const VerifiedSCT& verifiedSct, uint64_t certIssuanceTime)
|
||||
// "are CT Qualified if they are presented with SCTs from once or
|
||||
// currently qualified logs run by a minimum of one entity independent
|
||||
// of the CA."
|
||||
static Result
|
||||
static void
|
||||
CheckOperatorDiversityCompliance(const VerifiedSCTList& verifiedScts,
|
||||
uint64_t certIssuanceTime,
|
||||
const CTLogOperatorList& dependentOperators,
|
||||
bool& compliant)
|
||||
{
|
||||
size_t independentOperatorsCount;
|
||||
Result rv = CountIndependentLogOperatorsForSelectedScts(verifiedScts,
|
||||
CountIndependentLogOperatorsForSelectedScts(verifiedScts,
|
||||
dependentOperators, independentOperatorsCount,
|
||||
[certIssuanceTime](const VerifiedSCT& verifiedSct)->bool {
|
||||
return LogWasQualifiedForSct(verifiedSct, certIssuanceTime);
|
||||
});
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
// Having at least 2 operators implies we have at least 2 SCTs.
|
||||
// For the grandfathering provision (1 operator) we will need to include
|
||||
// an additional SCTs count check using
|
||||
// rv = CountLogsForSelectedScts(verifiedScts, sctsCount,
|
||||
// CountLogsForSelectedScts(verifiedScts, sctsCount,
|
||||
// [certIssuanceTime](const VerifiedSCT& verifiedSct)->bool {
|
||||
// return LogWasQualifiedForSct(verifiedSct, certIssuanceTime);
|
||||
// });
|
||||
compliant = independentOperatorsCount >= 2;
|
||||
return Success;
|
||||
}
|
||||
|
||||
// Qualification Case #1 (non-embedded SCTs) - the following must hold:
|
||||
@ -218,28 +208,24 @@ CheckOperatorDiversityCompliance(const VerifiedSCTList& verifiedScts,
|
||||
// AND
|
||||
// b. There are at least two SCTs from logs qualified at the time of check,
|
||||
// presented via any method.
|
||||
static Result
|
||||
static void
|
||||
CheckNonEmbeddedCompliance(const VerifiedSCTList& verifiedScts, bool& compliant)
|
||||
{
|
||||
if (!HasValidNonEmbeddedSct(verifiedScts)) {
|
||||
compliant = false;
|
||||
return Success;
|
||||
return;
|
||||
}
|
||||
|
||||
size_t validSctsCount;
|
||||
Result rv = CountLogsForSelectedScts(verifiedScts, validSctsCount,
|
||||
CountLogsForSelectedScts(verifiedScts, validSctsCount,
|
||||
[](const VerifiedSCT& verifiedSct)->bool {
|
||||
return verifiedSct.status == VerifiedSCT::Status::Valid;
|
||||
});
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
MOZ_LOG(gCertVerifierLog, LogLevel::Debug,
|
||||
("CT Policy non-embedded case status: validSCTs=%zu\n",
|
||||
validSctsCount));
|
||||
compliant = validSctsCount >= 2;
|
||||
return Success;
|
||||
}
|
||||
|
||||
// Qualification Case #2 (embedded SCTs) - the following must hold:
|
||||
@ -249,7 +235,7 @@ CheckNonEmbeddedCompliance(const VerifiedSCTList& verifiedScts, bool& compliant)
|
||||
// logs, where N is the lifetime of the certificate in years (normally
|
||||
// rounding up, but rounding down when up to 3 months over), and must be
|
||||
// at least 1.
|
||||
static Result
|
||||
static void
|
||||
CheckEmbeddedCompliance(const VerifiedSCTList& verifiedScts,
|
||||
size_t certLifetimeInCalendarMonths,
|
||||
uint64_t certIssuanceTime,
|
||||
@ -257,21 +243,18 @@ CheckEmbeddedCompliance(const VerifiedSCTList& verifiedScts,
|
||||
{
|
||||
if (!HasValidEmbeddedSct(verifiedScts)) {
|
||||
compliant = false;
|
||||
return Success;
|
||||
return;
|
||||
}
|
||||
|
||||
// Count the compliant embedded SCTs. Only a single SCT from each log
|
||||
// is accepted. Note that a given log might return several different SCTs
|
||||
// for the same precertificate (it is permitted, but advised against).
|
||||
size_t embeddedSctsCount;
|
||||
Result rv = CountLogsForSelectedScts(verifiedScts, embeddedSctsCount,
|
||||
CountLogsForSelectedScts(verifiedScts, embeddedSctsCount,
|
||||
[certIssuanceTime](const VerifiedSCT& verifiedSct)->bool {
|
||||
return verifiedSct.origin == VerifiedSCT::Origin::Embedded &&
|
||||
LogWasQualifiedForSct(verifiedSct, certIssuanceTime);
|
||||
});
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
size_t requiredSctsCount =
|
||||
GetRequiredEmbeddedSctsCount(certLifetimeInCalendarMonths);
|
||||
@ -282,10 +265,9 @@ CheckEmbeddedCompliance(const VerifiedSCTList& verifiedScts,
|
||||
requiredSctsCount, embeddedSctsCount));
|
||||
|
||||
compliant = embeddedSctsCount >= requiredSctsCount;
|
||||
return Success;
|
||||
}
|
||||
|
||||
Result
|
||||
void
|
||||
CTPolicyEnforcer::CheckCompliance(const VerifiedSCTList& verifiedScts,
|
||||
size_t certLifetimeInCalendarMonths,
|
||||
const CTLogOperatorList& dependentOperators,
|
||||
@ -294,33 +276,23 @@ CTPolicyEnforcer::CheckCompliance(const VerifiedSCTList& verifiedScts,
|
||||
uint64_t certIssuanceTime = GetEffectiveCertIssuanceTime(verifiedScts);
|
||||
|
||||
bool diversityOK;
|
||||
Result rv = CheckOperatorDiversityCompliance(verifiedScts, certIssuanceTime,
|
||||
dependentOperators,
|
||||
diversityOK);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
CheckOperatorDiversityCompliance(verifiedScts, certIssuanceTime,
|
||||
dependentOperators, diversityOK);
|
||||
if (diversityOK) {
|
||||
MOZ_LOG(gCertVerifierLog, LogLevel::Debug,
|
||||
("CT Policy: diversity satisfied\n"));
|
||||
}
|
||||
|
||||
bool nonEmbeddedCaseOK;
|
||||
rv = CheckNonEmbeddedCompliance(verifiedScts, nonEmbeddedCaseOK);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
CheckNonEmbeddedCompliance(verifiedScts, nonEmbeddedCaseOK);
|
||||
if (nonEmbeddedCaseOK) {
|
||||
MOZ_LOG(gCertVerifierLog, LogLevel::Debug,
|
||||
("CT Policy: non-embedded case satisfied)\n"));
|
||||
}
|
||||
|
||||
bool embeddedCaseOK;
|
||||
rv = CheckEmbeddedCompliance(verifiedScts, certLifetimeInCalendarMonths,
|
||||
certIssuanceTime, embeddedCaseOK);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
CheckEmbeddedCompliance(verifiedScts, certLifetimeInCalendarMonths,
|
||||
certIssuanceTime, embeddedCaseOK);
|
||||
if (embeddedCaseOK) {
|
||||
MOZ_LOG(gCertVerifierLog, LogLevel::Debug,
|
||||
("CT Policy: embedded case satisfied\n"));
|
||||
@ -351,7 +323,6 @@ CTPolicyEnforcer::CheckCompliance(const VerifiedSCTList& verifiedScts,
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Unexpected CTPolicyCompliance type");
|
||||
}
|
||||
return Success;
|
||||
}
|
||||
|
||||
} } // namespace mozilla::ct
|
||||
|
@ -54,10 +54,10 @@ public:
|
||||
// operators are treated differenly when evaluating the policy.
|
||||
// See CTDiversityPolicy class.
|
||||
// |compliance| - the result of the compliance check.
|
||||
pkix::Result CheckCompliance(const VerifiedSCTList& verifiedScts,
|
||||
size_t certLifetimeInCalendarMonths,
|
||||
const CTLogOperatorList& dependentOperators,
|
||||
CTPolicyCompliance& compliance);
|
||||
void CheckCompliance(const VerifiedSCTList& verifiedScts,
|
||||
size_t certLifetimeInCalendarMonths,
|
||||
const CTLogOperatorList& dependentOperators,
|
||||
CTPolicyCompliance& compliance);
|
||||
};
|
||||
|
||||
} } // namespace mozilla::ct
|
||||
|
@ -183,12 +183,10 @@ ReadVersion(Reader& in, SignedCertificateTimestamp::Version& out)
|
||||
static Result
|
||||
UncheckedWriteUint(size_t length, uint64_t value, Buffer& output)
|
||||
{
|
||||
if (!output.reserve(length + output.length())) {
|
||||
return Result::FATAL_ERROR_NO_MEMORY;
|
||||
}
|
||||
output.reserve(length + output.size());
|
||||
for (; length > 0; --length) {
|
||||
uint8_t nextByte = (value >> ((length - 1) * 8)) & 0xFF;
|
||||
output.infallibleAppend(nextByte);
|
||||
output.push_back(nextByte);
|
||||
}
|
||||
return Success;
|
||||
}
|
||||
@ -226,23 +224,18 @@ WriteUint(T value, Buffer& output)
|
||||
// length when reading.
|
||||
// If the length of |input| is dynamic and data is expected to follow it,
|
||||
// WriteVariableBytes must be used.
|
||||
static Result
|
||||
static void
|
||||
WriteEncodedBytes(Input input, Buffer& output)
|
||||
{
|
||||
if (!output.append(input.UnsafeGetData(), input.GetLength())) {
|
||||
return Result::FATAL_ERROR_NO_MEMORY;
|
||||
}
|
||||
return Success;
|
||||
output.insert(output.end(), input.UnsafeGetData(),
|
||||
input.UnsafeGetData() + input.GetLength());
|
||||
}
|
||||
|
||||
// Same as above, but the source data is in a Buffer.
|
||||
static Result
|
||||
static void
|
||||
WriteEncodedBytes(const Buffer& source, Buffer& output)
|
||||
{
|
||||
if (!output.appendAll(source)) {
|
||||
return Result::FATAL_ERROR_NO_MEMORY;
|
||||
}
|
||||
return Success;
|
||||
output.insert(output.end(), source.begin(), source.end());
|
||||
}
|
||||
|
||||
// A variable-length byte array is prefixed by its length when serialized.
|
||||
@ -275,7 +268,8 @@ WriteVariableBytes(Input input, Buffer& output)
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
return WriteEncodedBytes(input, output);
|
||||
WriteEncodedBytes(input, output);
|
||||
return Success;
|
||||
}
|
||||
|
||||
// Same as above, but the source data is in a Buffer.
|
||||
@ -305,13 +299,10 @@ EncodeAsn1CertLogEntry(const LogEntry& entry, Buffer& output)
|
||||
static Result
|
||||
EncodePrecertLogEntry(const LogEntry& entry, Buffer& output)
|
||||
{
|
||||
if (entry.issuerKeyHash.length() != kLogIdLength) {
|
||||
if (entry.issuerKeyHash.size() != kLogIdLength) {
|
||||
return Result::FATAL_ERROR_INVALID_ARGS;
|
||||
}
|
||||
Result rv = WriteEncodedBytes(entry.issuerKeyHash, output);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
WriteEncodedBytes(entry.issuerKeyHash, output);
|
||||
return WriteVariableBytes<kTbsCertificateLengthBytes>(entry.tbsCertificate,
|
||||
output);
|
||||
}
|
||||
@ -352,10 +343,7 @@ DecodeDigitallySigned(Reader& reader, DigitallySigned& output)
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
rv = InputToBuffer(signatureData, result.signatureData);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
InputToBuffer(signatureData, result.signatureData);
|
||||
|
||||
output = std::move(result);
|
||||
return Success;
|
||||
@ -406,10 +394,7 @@ EncodeV1SCTSignedData(uint64_t timestamp, Input serializedLogEntry,
|
||||
}
|
||||
// NOTE: serializedLogEntry must already be serialized and contain the
|
||||
// length as the prefix.
|
||||
rv = WriteEncodedBytes(serializedLogEntry, output);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
WriteEncodedBytes(serializedLogEntry, output);
|
||||
return WriteVariableBytes<kExtensionsLengthBytes>(extensions, output);
|
||||
}
|
||||
|
||||
@ -435,10 +420,11 @@ EncodeTreeHeadSignature(const SignedTreeHead& signedTreeHead,
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
if (signedTreeHead.sha256RootHash.length() != kSthRootHashLength) {
|
||||
if (signedTreeHead.sha256RootHash.size() != kSthRootHashLength) {
|
||||
return Result::FATAL_ERROR_INVALID_ARGS;
|
||||
}
|
||||
return WriteEncodedBytes(signedTreeHead.sha256RootHash, output);
|
||||
WriteEncodedBytes(signedTreeHead.sha256RootHash, output);
|
||||
return Success;
|
||||
}
|
||||
|
||||
Result
|
||||
@ -502,14 +488,8 @@ DecodeSignedCertificateTimestamp(Reader& reader,
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = InputToBuffer(logId, result.logId);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
rv = InputToBuffer(extensions, result.extensions);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
InputToBuffer(logId, result.logId);
|
||||
InputToBuffer(extensions, result.extensions);
|
||||
result.timestamp = timestamp;
|
||||
|
||||
output = std::move(result);
|
||||
@ -517,7 +497,7 @@ DecodeSignedCertificateTimestamp(Reader& reader,
|
||||
}
|
||||
|
||||
Result
|
||||
EncodeSCTList(const Vector<pkix::Input>& scts, Buffer& output)
|
||||
EncodeSCTList(const std::vector<pkix::Input>& scts, Buffer& output)
|
||||
{
|
||||
// Find out the total size of the SCT list to be written so we can
|
||||
// write the prefix for the list before writing its contents.
|
||||
@ -528,9 +508,7 @@ EncodeSCTList(const Vector<pkix::Input>& scts, Buffer& output)
|
||||
/* length prefix size */ kSerializedSCTLengthBytes;
|
||||
}
|
||||
|
||||
if (!output.reserve(kSCTListLengthBytes + sctListLength)) {
|
||||
return Result::FATAL_ERROR_NO_MEMORY;
|
||||
}
|
||||
output.reserve(kSCTListLengthBytes + sctListLength);
|
||||
|
||||
// Write the prefix for the SCT list.
|
||||
Result rv = WriteVariableBytesPrefix<kSCTListLengthBytes>(sctListLength,
|
||||
|
@ -7,7 +7,8 @@
|
||||
#ifndef CTSerialization_h
|
||||
#define CTSerialization_h
|
||||
|
||||
#include "mozilla/Vector.h"
|
||||
#include <vector>
|
||||
|
||||
#include "pkix/Input.h"
|
||||
#include "pkix/Result.h"
|
||||
#include "SignedCertificateTimestamp.h"
|
||||
@ -63,7 +64,8 @@ pkix::Result DecodeSignedCertificateTimestamp(pkix::Reader& input,
|
||||
SignedCertificateTimestamp& output);
|
||||
|
||||
// Encodes a list of SCTs (|scts|) to |output|.
|
||||
pkix::Result EncodeSCTList(const Vector<pkix::Input>& scts, Buffer& output);
|
||||
pkix::Result EncodeSCTList(const std::vector<pkix::Input>& scts,
|
||||
Buffer& output);
|
||||
|
||||
} } // namespace mozilla::ct
|
||||
|
||||
|
@ -7,8 +7,9 @@
|
||||
#ifndef CTVerifyResult_h
|
||||
#define CTVerifyResult_h
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "CTLog.h"
|
||||
#include "mozilla/Vector.h"
|
||||
#include "SignedCertificateTimestamp.h"
|
||||
|
||||
namespace mozilla { namespace ct {
|
||||
@ -54,7 +55,7 @@ struct VerifiedSCT
|
||||
uint64_t logDisqualificationTime;
|
||||
};
|
||||
|
||||
typedef Vector<VerifiedSCT> VerifiedSCTList;
|
||||
typedef std::vector<VerifiedSCT> VerifiedSCTList;
|
||||
|
||||
// Holds Signed Certificate Timestamps verification results.
|
||||
class CTVerifyResult
|
||||
|
@ -16,25 +16,19 @@ namespace mozilla { namespace ct {
|
||||
using namespace mozilla::pkix;
|
||||
|
||||
// Note: this moves |verifiedSct| to the target list in |result|.
|
||||
static Result
|
||||
static void
|
||||
StoreVerifiedSct(CTVerifyResult& result,
|
||||
VerifiedSCT&& verifiedSct,
|
||||
VerifiedSCT::Status status)
|
||||
{
|
||||
verifiedSct.status = status;
|
||||
if (!result.verifiedScts.append(std::move(verifiedSct))) {
|
||||
return Result::FATAL_ERROR_NO_MEMORY;
|
||||
}
|
||||
return Success;
|
||||
result.verifiedScts.push_back(std::move(verifiedSct));
|
||||
}
|
||||
|
||||
Result
|
||||
void
|
||||
MultiLogCTVerifier::AddLog(CTLogVerifier&& log)
|
||||
{
|
||||
if (!mLogs.append(std::move(log))) {
|
||||
return Result::FATAL_ERROR_NO_MEMORY;
|
||||
}
|
||||
return Success;
|
||||
mLogs.push_back(std::move(log));
|
||||
}
|
||||
|
||||
Result
|
||||
@ -67,10 +61,7 @@ MultiLogCTVerifier::Verify(Input cert,
|
||||
}
|
||||
|
||||
LogEntry x509Entry;
|
||||
rv = GetX509LogEntry(cert, x509Entry);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
GetX509LogEntry(cert, x509Entry);
|
||||
|
||||
// Verify SCTs from a stapled OCSP response
|
||||
if (sctListFromOCSPResponse.GetLength() > 0) {
|
||||
@ -151,23 +142,26 @@ MultiLogCTVerifier::VerifySingleSCT(SignedCertificateTimestamp&& sct,
|
||||
|
||||
if (!matchingLog) {
|
||||
// SCT does not match any known log.
|
||||
return StoreVerifiedSct(result, std::move(verifiedSct),
|
||||
VerifiedSCT::Status::UnknownLog);
|
||||
StoreVerifiedSct(result, std::move(verifiedSct),
|
||||
VerifiedSCT::Status::UnknownLog);
|
||||
return Success;
|
||||
}
|
||||
|
||||
verifiedSct.logOperatorId = matchingLog->operatorId();
|
||||
|
||||
if (!matchingLog->SignatureParametersMatch(verifiedSct.sct.signature)) {
|
||||
// SCT signature parameters do not match the log's.
|
||||
return StoreVerifiedSct(result, std::move(verifiedSct),
|
||||
VerifiedSCT::Status::InvalidSignature);
|
||||
StoreVerifiedSct(result, std::move(verifiedSct),
|
||||
VerifiedSCT::Status::InvalidSignature);
|
||||
return Success;
|
||||
}
|
||||
|
||||
Result rv = matchingLog->Verify(expectedEntry, verifiedSct.sct);
|
||||
if (rv != Success) {
|
||||
if (rv == Result::ERROR_BAD_SIGNATURE) {
|
||||
return StoreVerifiedSct(result, std::move(verifiedSct),
|
||||
VerifiedSCT::Status::InvalidSignature);
|
||||
StoreVerifiedSct(result, std::move(verifiedSct),
|
||||
VerifiedSCT::Status::InvalidSignature);
|
||||
return Success;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
@ -181,8 +175,9 @@ MultiLogCTVerifier::VerifySingleSCT(SignedCertificateTimestamp&& sct,
|
||||
Time sctTime =
|
||||
TimeFromEpochInSeconds((verifiedSct.sct.timestamp + 999u) / 1000u);
|
||||
if (sctTime > time) {
|
||||
return StoreVerifiedSct(result, std::move(verifiedSct),
|
||||
VerifiedSCT::Status::InvalidTimestamp);
|
||||
StoreVerifiedSct(result, std::move(verifiedSct),
|
||||
VerifiedSCT::Status::InvalidTimestamp);
|
||||
return Success;
|
||||
}
|
||||
|
||||
// SCT verified ok, see if the log is qualified. Since SCTs from
|
||||
@ -190,12 +185,13 @@ MultiLogCTVerifier::VerifySingleSCT(SignedCertificateTimestamp&& sct,
|
||||
// the CT Policy), the log qualification check must be the last one we do.
|
||||
if (matchingLog->isDisqualified()) {
|
||||
verifiedSct.logDisqualificationTime = matchingLog->disqualificationTime();
|
||||
return StoreVerifiedSct(result, std::move(verifiedSct),
|
||||
VerifiedSCT::Status::ValidFromDisqualifiedLog);
|
||||
StoreVerifiedSct(result, std::move(verifiedSct),
|
||||
VerifiedSCT::Status::ValidFromDisqualifiedLog);
|
||||
return Success;
|
||||
}
|
||||
|
||||
return StoreVerifiedSct(result, std::move(verifiedSct),
|
||||
VerifiedSCT::Status::Valid);
|
||||
StoreVerifiedSct(result, std::move(verifiedSct), VerifiedSCT::Status::Valid);
|
||||
return Success;
|
||||
}
|
||||
|
||||
} } // namespace mozilla::ct
|
||||
|
@ -7,9 +7,10 @@
|
||||
#ifndef MultiLogCTVerifier_h
|
||||
#define MultiLogCTVerifier_h
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "CTLogVerifier.h"
|
||||
#include "CTVerifyResult.h"
|
||||
#include "mozilla/Vector.h"
|
||||
#include "pkix/Input.h"
|
||||
#include "pkix/Result.h"
|
||||
#include "pkix/Time.h"
|
||||
@ -23,7 +24,7 @@ class MultiLogCTVerifier
|
||||
{
|
||||
public:
|
||||
// Adds a new log to the list of known logs to verify against.
|
||||
pkix::Result AddLog(CTLogVerifier&& log);
|
||||
void AddLog(CTLogVerifier&& log);
|
||||
|
||||
// Verifies SCTs embedded in the certificate itself, SCTs embedded in a
|
||||
// stapled OCSP response, and SCTs obtained via the
|
||||
@ -79,7 +80,7 @@ private:
|
||||
CTVerifyResult& result);
|
||||
|
||||
// The list of known logs.
|
||||
Vector<CTLogVerifier> mLogs;
|
||||
std::vector<CTLogVerifier> mLogs;
|
||||
};
|
||||
|
||||
} } // namespace mozilla::ct
|
||||
|
@ -8,7 +8,6 @@
|
||||
#define SignedCertificateTimestamp_h
|
||||
|
||||
#include "Buffer.h"
|
||||
#include "mozilla/Vector.h"
|
||||
#include "pkix/Input.h"
|
||||
#include "pkix/Result.h"
|
||||
|
||||
@ -88,19 +87,16 @@ struct SignedCertificateTimestamp
|
||||
|
||||
inline pkix::Result BufferToInput(const Buffer& buffer, pkix::Input& input)
|
||||
{
|
||||
if (buffer.length() == 0) {
|
||||
if (buffer.empty()) {
|
||||
return pkix::Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
}
|
||||
return input.Init(buffer.begin(), buffer.length());
|
||||
return input.Init(buffer.data(), buffer.size());
|
||||
}
|
||||
|
||||
inline pkix::Result InputToBuffer(pkix::Input input, Buffer& buffer)
|
||||
inline void InputToBuffer(pkix::Input input, Buffer& buffer)
|
||||
{
|
||||
buffer.clear();
|
||||
if (!buffer.append(input.UnsafeGetData(), input.GetLength())) {
|
||||
return pkix::Result::FATAL_ERROR_NO_MEMORY;
|
||||
}
|
||||
return pkix::Success;
|
||||
buffer.assign(input.UnsafeGetData(),
|
||||
input.UnsafeGetData() + input.GetLength());
|
||||
}
|
||||
|
||||
} } // namespace mozilla::ct
|
||||
|
@ -50,10 +50,7 @@ TEST_F(BTSerializationTest, DecodesInclusionProof)
|
||||
const uint64_t expectedLeafIndex = 2;
|
||||
const uint64_t expectedInclusionPathElements = 2;
|
||||
|
||||
const uint8_t EXPECTED_LOGID[] = { 0x01, 0x00 };
|
||||
Buffer expectedLogId;
|
||||
MOZ_RELEASE_ASSERT(expectedLogId.append(EXPECTED_LOGID, 2));
|
||||
|
||||
Buffer expectedLogId = { 0x01, 0x00 };
|
||||
|
||||
Input encodedProofInput = InputForBuffer(mTestInclusionProof);
|
||||
Reader encodedProofReader(encodedProofInput);
|
||||
@ -63,7 +60,7 @@ TEST_F(BTSerializationTest, DecodesInclusionProof)
|
||||
EXPECT_EQ(expectedLogId, ipr.logId);
|
||||
EXPECT_EQ(expectedTreeSize, ipr.treeSize);
|
||||
EXPECT_EQ(expectedLeafIndex, ipr.leafIndex);
|
||||
EXPECT_EQ(expectedInclusionPathElements, ipr.inclusionPath.length());
|
||||
EXPECT_EQ(expectedInclusionPathElements, ipr.inclusionPath.size());
|
||||
EXPECT_EQ(GetTestNodeHash0(), ipr.inclusionPath[0]);
|
||||
EXPECT_EQ(GetTestNodeHash1(), ipr.inclusionPath[1]);
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ TEST_F(CTLogVerifierTest, FailsInvalidLogID)
|
||||
|
||||
// Mangle the log ID, which should cause it to match a different log before
|
||||
// attempting signature validation.
|
||||
MOZ_RELEASE_ASSERT(certSct.logId.append('\x0'));
|
||||
certSct.logId.push_back('\x0');
|
||||
|
||||
EXPECT_EQ(pkix::Result::FATAL_ERROR_INVALID_ARGS, mLog.Verify(certEntry,
|
||||
certSct));
|
||||
@ -126,7 +126,8 @@ TEST_F(CTLogVerifierTest, DoesNotVerifyInvalidSTH)
|
||||
TEST_F(CTLogVerifierTest, ExcessDataInPublicKey)
|
||||
{
|
||||
Buffer key = GetTestPublicKey();
|
||||
MOZ_RELEASE_ASSERT(key.append("extra", 5));
|
||||
std::string extra = "extra";
|
||||
key.insert(key.end(), extra.begin(), extra.end());
|
||||
|
||||
CTLogVerifier log;
|
||||
EXPECT_NE(Success, log.Init(InputForBuffer(key),
|
||||
|
@ -61,14 +61,14 @@ TEST_F(CTObjectsExtractorTest, ExtractPrecert)
|
||||
TEST_F(CTObjectsExtractorTest, ExtractOrdinaryX509Cert)
|
||||
{
|
||||
LogEntry entry;
|
||||
ASSERT_EQ(Success, GetX509LogEntry(InputForBuffer(mTestCert), entry));
|
||||
GetX509LogEntry(InputForBuffer(mTestCert), entry);
|
||||
|
||||
EXPECT_EQ(LogEntry::Type::X509, entry.type);
|
||||
// Should have empty tbsCertificate / issuerKeyHash for this log entry type.
|
||||
EXPECT_TRUE(entry.tbsCertificate.empty());
|
||||
EXPECT_TRUE(entry.issuerKeyHash.empty());
|
||||
// Length of leafCertificate should be 718, see the CT Serialization tests.
|
||||
EXPECT_EQ(718U, entry.leafCertificate.length());
|
||||
EXPECT_EQ(718U, entry.leafCertificate.size());
|
||||
}
|
||||
|
||||
// Test that an externally-provided SCT verifies over the LogEntry
|
||||
@ -79,7 +79,7 @@ TEST_F(CTObjectsExtractorTest, ComplementarySCTVerifies)
|
||||
GetX509CertSCT(sct);
|
||||
|
||||
LogEntry entry;
|
||||
ASSERT_EQ(Success, GetX509LogEntry(InputForBuffer(mTestCert), entry));
|
||||
GetX509LogEntry(InputForBuffer(mTestCert), entry);
|
||||
EXPECT_EQ(Success, mLog.Verify(entry, sct));
|
||||
}
|
||||
|
||||
|
@ -33,17 +33,17 @@ class CTPolicyEnforcerTest : public ::testing::Test
|
||||
public:
|
||||
void SetUp() override
|
||||
{
|
||||
MOZ_ALWAYS_TRUE(OPERATORS_1_AND_2.append(OPERATOR_1));
|
||||
MOZ_ALWAYS_TRUE(OPERATORS_1_AND_2.append(OPERATOR_2));
|
||||
OPERATORS_1_AND_2.push_back(OPERATOR_1);
|
||||
OPERATORS_1_AND_2.push_back(OPERATOR_2);
|
||||
}
|
||||
|
||||
void GetLogId(Buffer& logId, size_t logNo)
|
||||
{
|
||||
ASSERT_TRUE(logId.resize(SHA256_LENGTH));
|
||||
logId.resize(SHA256_LENGTH);
|
||||
std::fill(logId.begin(), logId.end(), 0);
|
||||
// Just raw-copy |logId| into the output buffer.
|
||||
MOZ_ASSERT(sizeof(logNo) <= logId.length());
|
||||
memcpy(logId.begin(), &logNo, sizeof(logNo));
|
||||
MOZ_ASSERT(sizeof(logNo) <= logId.size());
|
||||
memcpy(logId.data(), &logNo, sizeof(logNo));
|
||||
}
|
||||
|
||||
void AddSct(VerifiedSCTList& verifiedScts,
|
||||
@ -65,7 +65,7 @@ public:
|
||||
Buffer logId;
|
||||
GetLogId(logId, logNo);
|
||||
verifiedSct.sct.logId = std::move(logId);
|
||||
ASSERT_TRUE(verifiedScts.append(std::move(verifiedSct)));
|
||||
verifiedScts.push_back(std::move(verifiedSct));
|
||||
}
|
||||
|
||||
void AddMultipleScts(VerifiedSCTList& verifiedScts,
|
||||
@ -87,11 +87,10 @@ public:
|
||||
CTPolicyCompliance expectedCompliance)
|
||||
{
|
||||
CTPolicyCompliance compliance;
|
||||
ASSERT_EQ(Success,
|
||||
mPolicyEnforcer.CheckCompliance(verifiedSct,
|
||||
certLifetimeInCalendarMonths,
|
||||
dependentLogOperators,
|
||||
compliance));
|
||||
mPolicyEnforcer.CheckCompliance(verifiedSct,
|
||||
certLifetimeInCalendarMonths,
|
||||
dependentLogOperators,
|
||||
compliance);
|
||||
EXPECT_EQ(expectedCompliance, compliance);
|
||||
}
|
||||
|
||||
@ -355,12 +354,7 @@ TEST_F(CTPolicyEnforcerTest,
|
||||
AddMultipleScts(scts, sctsAvailable, 1, ORIGIN_EMBEDDED, TIMESTAMP_1);
|
||||
|
||||
CTPolicyCompliance compliance;
|
||||
ASSERT_EQ(Success,
|
||||
mPolicyEnforcer.CheckCompliance(scts, months, NO_OPERATORS,
|
||||
compliance))
|
||||
<< "i=" << i
|
||||
<< " sctsRequired=" << sctsRequired
|
||||
<< " sctsAvailable=" << sctsAvailable;
|
||||
mPolicyEnforcer.CheckCompliance(scts, months, NO_OPERATORS, compliance);
|
||||
EXPECT_EQ(CTPolicyCompliance::NotEnoughScts, compliance)
|
||||
<< "i=" << i
|
||||
<< " sctsRequired=" << sctsRequired
|
||||
@ -372,10 +366,7 @@ TEST_F(CTPolicyEnforcerTest,
|
||||
AddMultipleScts(scts, sctsRequired, 2, ORIGIN_EMBEDDED, TIMESTAMP_1);
|
||||
|
||||
CTPolicyCompliance compliance;
|
||||
ASSERT_EQ(Success,
|
||||
mPolicyEnforcer.CheckCompliance(scts, months, NO_OPERATORS,
|
||||
compliance))
|
||||
<< "i=" << i;
|
||||
mPolicyEnforcer.CheckCompliance(scts, months, NO_OPERATORS, compliance);
|
||||
EXPECT_EQ(CTPolicyCompliance::Compliant, compliance)
|
||||
<< "i=" << i;
|
||||
}
|
||||
|
@ -48,8 +48,7 @@ TEST_F(CTSerializationTest, FailsToDecodePartialDigitallySigned)
|
||||
{
|
||||
Input partial;
|
||||
ASSERT_EQ(Success,
|
||||
partial.Init(mTestDigitallySigned.begin(),
|
||||
mTestDigitallySigned.length() - 5));
|
||||
partial.Init(mTestDigitallySigned.data(), mTestDigitallySigned.size() - 5));
|
||||
Reader partialReader(partial);
|
||||
|
||||
DigitallySigned parsed;
|
||||
@ -64,7 +63,7 @@ TEST_F(CTSerializationTest, EncodesDigitallySigned)
|
||||
DigitallySigned::HashAlgorithm::SHA256;
|
||||
digitallySigned.signatureAlgorithm =
|
||||
DigitallySigned::SignatureAlgorithm::ECDSA;
|
||||
digitallySigned.signatureData = cloneBuffer(mTestSignatureData);
|
||||
digitallySigned.signatureData = mTestSignatureData;
|
||||
|
||||
Buffer encoded;
|
||||
|
||||
@ -79,14 +78,12 @@ TEST_F(CTSerializationTest, EncodesLogEntryForX509Cert)
|
||||
|
||||
Buffer encoded;
|
||||
ASSERT_EQ(Success, EncodeLogEntry(entry, encoded));
|
||||
EXPECT_EQ((718U + 5U), encoded.length());
|
||||
EXPECT_EQ((718U + 5U), encoded.size());
|
||||
// First two bytes are log entry type. Next, length:
|
||||
// Length is 718 which is 512 + 206, which is 0x2ce
|
||||
Buffer expectedPrefix;
|
||||
MOZ_RELEASE_ASSERT(expectedPrefix.append("\0\0\0\x2\xCE", 5));
|
||||
// Length is 718 which is 512 + 206, which is { 0, ..., 2, 206 }.
|
||||
Buffer expectedPrefix = { 0, 0, 0, 2, 206 };
|
||||
Buffer encodedPrefix;
|
||||
MOZ_RELEASE_ASSERT(encodedPrefix.
|
||||
append(encoded.begin(), encoded.begin() + 5));
|
||||
encodedPrefix.assign(encoded.begin(), encoded.begin() + 5);
|
||||
EXPECT_EQ(expectedPrefix, encodedPrefix);
|
||||
}
|
||||
|
||||
@ -98,20 +95,17 @@ TEST_F(CTSerializationTest, EncodesLogEntryForPrecert)
|
||||
Buffer encoded;
|
||||
ASSERT_EQ(Success, EncodeLogEntry(entry, encoded));
|
||||
// log entry type + issuer key + length + tbsCertificate
|
||||
EXPECT_EQ((2U + 32U + 3U + entry.tbsCertificate.length()), encoded.length());
|
||||
EXPECT_EQ((2U + 32U + 3U + entry.tbsCertificate.size()), encoded.size());
|
||||
|
||||
// First two bytes are log entry type.
|
||||
Buffer expectedPrefix;
|
||||
MOZ_RELEASE_ASSERT(expectedPrefix.append("\0\x1", 2));
|
||||
Buffer expectedPrefix = { 0, 1 };
|
||||
Buffer encodedPrefix;
|
||||
MOZ_RELEASE_ASSERT(encodedPrefix.
|
||||
append(encoded.begin(), encoded.begin() + 2));
|
||||
encodedPrefix.assign(encoded.begin(), encoded.begin() + 2);
|
||||
EXPECT_EQ(expectedPrefix, encodedPrefix);
|
||||
|
||||
// Next is the issuer key (32 bytes).
|
||||
Buffer encodedKeyHash;
|
||||
MOZ_RELEASE_ASSERT(encodedKeyHash.
|
||||
append(encoded.begin() + 2, encoded.begin() + 2 + 32));
|
||||
encodedKeyHash.assign(encoded.begin() + 2, encoded.begin() + 2 + 32);
|
||||
EXPECT_EQ(GetDefaultIssuerKeyHash(), encodedKeyHash);
|
||||
}
|
||||
|
||||
@ -124,18 +118,15 @@ TEST_F(CTSerializationTest, EncodesV1SCTSignedData)
|
||||
Buffer encoded;
|
||||
ASSERT_EQ(Success, EncodeV1SCTSignedData(
|
||||
timestamp, dummyEntry, emptyExtensions, encoded));
|
||||
EXPECT_EQ((size_t) 15, encoded.length());
|
||||
EXPECT_EQ((size_t) 15, encoded.size());
|
||||
|
||||
const uint8_t EXPECTED_BYTES[] = {
|
||||
Buffer expectedBuffer = {
|
||||
0x00, // version
|
||||
0x00, // signature type
|
||||
0x00, 0x00, 0x01, 0x39, 0xFE, 0x35, 0x3C, 0xF5, // timestamp
|
||||
0x61, 0x62, 0x63, // log signature
|
||||
0x00, 0x00 // extensions (empty)
|
||||
};
|
||||
Buffer expectedBuffer;
|
||||
MOZ_RELEASE_ASSERT(
|
||||
expectedBuffer.append(EXPECTED_BYTES, sizeof(EXPECTED_BYTES)));
|
||||
EXPECT_EQ(expectedBuffer, encoded);
|
||||
}
|
||||
|
||||
@ -182,9 +173,9 @@ TEST_F(CTSerializationTest, EncodesSCTList)
|
||||
const uint8_t SCT_1[] = { 0x61, 0x62, 0x63 };
|
||||
const uint8_t SCT_2[] = { 0x64, 0x65, 0x66 };
|
||||
|
||||
Vector<Input> list;
|
||||
ASSERT_TRUE(list.append(Input(SCT_1)));
|
||||
ASSERT_TRUE(list.append(Input(SCT_2)));
|
||||
std::vector<Input> list;
|
||||
list.push_back(Input(SCT_1));
|
||||
list.push_back(Input(SCT_2));
|
||||
|
||||
Buffer encodedList;
|
||||
ASSERT_EQ(Success, EncodeSCTList(list, encodedList));
|
||||
@ -217,7 +208,7 @@ TEST_F(CTSerializationTest, DecodesSignedCertificateTimestamp)
|
||||
const uint64_t expectedTime = 1365181456089;
|
||||
EXPECT_EQ(expectedTime, sct.timestamp);
|
||||
const size_t expectedSignatureLength = 71;
|
||||
EXPECT_EQ(expectedSignatureLength, sct.signature.signatureData.length());
|
||||
EXPECT_EQ(expectedSignatureLength, sct.signature.signatureData.size());
|
||||
EXPECT_TRUE(sct.extensions.empty());
|
||||
}
|
||||
|
||||
@ -253,18 +244,17 @@ TEST_F(CTSerializationTest, EncodesValidSignedTreeHead)
|
||||
// Bytes 2-9 are timestamp
|
||||
// Bytes 10-17 are tree size
|
||||
// Bytes 18-49 are sha256 root hash
|
||||
ASSERT_EQ(50u, encoded.length());
|
||||
const uint8_t EXPECTED_BYTES_PREFIX[] = {
|
||||
ASSERT_EQ(50u, encoded.size());
|
||||
Buffer expectedBuffer = {
|
||||
0x00, // version
|
||||
0x01, // signature type
|
||||
0x00, 0x00, 0x01, 0x45, 0x3c, 0x5f, 0xb8, 0x35, // timestamp
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15 // tree size
|
||||
// sha256 root hash should follow
|
||||
};
|
||||
Buffer expectedBuffer;
|
||||
MOZ_RELEASE_ASSERT(expectedBuffer.append(EXPECTED_BYTES_PREFIX, 18));
|
||||
Buffer hash = GetSampleSTHSHA256RootHash();
|
||||
MOZ_RELEASE_ASSERT(expectedBuffer.append(hash.begin(), hash.length()));
|
||||
expectedBuffer.insert(expectedBuffer.end(), hash.begin(),
|
||||
hash.begin() + hash.size());
|
||||
EXPECT_EQ(expectedBuffer, encoded);
|
||||
}
|
||||
} } // namespace mozilla::ct
|
||||
|
@ -446,11 +446,11 @@ HexToBytes(const char* hexData)
|
||||
MOZ_RELEASE_ASSERT(hexLen > 0 && (hexLen % 2 == 0));
|
||||
size_t resultLen = hexLen / 2;
|
||||
Buffer result;
|
||||
MOZ_RELEASE_ASSERT(result.reserve(resultLen));
|
||||
result.reserve(resultLen);
|
||||
for (size_t i = 0; i < resultLen; ++i) {
|
||||
uint8_t hi = CharToByte(hexData[i*2]);
|
||||
uint8_t lo = CharToByte(hexData[i*2 + 1]);
|
||||
result.infallibleAppend((hi << 4) | lo);
|
||||
result.push_back((hi << 4) | lo);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -495,7 +495,7 @@ GetTestDigitallySignedData()
|
||||
// 1 byte of signature algorithm
|
||||
// 2 bytes - prefix containing length of the signature data.
|
||||
Buffer result;
|
||||
MOZ_RELEASE_ASSERT(result.append(encoded.begin() + 4, encoded.end()));
|
||||
result.assign(encoded.begin() + 4, encoded.end());
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -663,7 +663,7 @@ GetSampleSTHTreeHeadDecodedSignature(DigitallySigned& signature)
|
||||
{
|
||||
Buffer ths = HexToBytes(kSampleSTHTreeHeadSignature);
|
||||
Input thsInput;
|
||||
ASSERT_EQ(Success, thsInput.Init(ths.begin(), ths.length()));
|
||||
ASSERT_EQ(Success, thsInput.Init(ths.data(), ths.size()));
|
||||
Reader thsReader(thsInput);
|
||||
ASSERT_EQ(Success, DecodeDigitallySigned(thsReader, signature));
|
||||
ASSERT_TRUE(thsReader.AtEnd());
|
||||
@ -719,7 +719,7 @@ ExtractCertSPKI(Input cert)
|
||||
|
||||
Input spkiInput = backCert.GetSubjectPublicKeyInfo();
|
||||
Buffer spki;
|
||||
MOZ_RELEASE_ASSERT(InputToBuffer(spkiInput, spki) == Success);
|
||||
InputToBuffer(spkiInput, spki);
|
||||
return spki;
|
||||
}
|
||||
|
||||
@ -741,7 +741,7 @@ ExtractEmbeddedSCTList(Input cert, Buffer& result)
|
||||
ASSERT_EQ(Success,
|
||||
ExtractSignedCertificateTimestampListFromExtension(*scts,
|
||||
sctList));
|
||||
ASSERT_EQ(Success, InputToBuffer(sctList, result));
|
||||
InputToBuffer(sctList, result);
|
||||
}
|
||||
}
|
||||
|
||||
@ -839,10 +839,7 @@ public:
|
||||
ADD_FAILURE();
|
||||
return;
|
||||
}
|
||||
if (InputToBuffer(data, signedCertificateTimestamps) != Success) {
|
||||
ADD_FAILURE();
|
||||
return;
|
||||
}
|
||||
InputToBuffer(data, signedCertificateTimestamps);
|
||||
}
|
||||
|
||||
Buffer signedCertificateTimestamps;
|
||||
@ -873,20 +870,11 @@ ExtractSCTListFromOCSPResponse(Input cert,
|
||||
result = std::move(trustDomain.signedCertificateTimestamps);
|
||||
}
|
||||
|
||||
Buffer
|
||||
cloneBuffer(const Buffer& buffer)
|
||||
{
|
||||
Buffer cloned;
|
||||
MOZ_RELEASE_ASSERT(cloned.appendAll(buffer));
|
||||
return cloned;
|
||||
}
|
||||
|
||||
Input
|
||||
InputForBuffer(const Buffer& buffer)
|
||||
{
|
||||
Input input;
|
||||
MOZ_RELEASE_ASSERT(Success ==
|
||||
input.Init(buffer.begin(), buffer.length()));
|
||||
MOZ_RELEASE_ASSERT(Success == input.Init(buffer.data(), buffer.size()));
|
||||
return input;
|
||||
}
|
||||
|
||||
@ -908,7 +896,7 @@ operator<<(std::ostream& stream, const ct::Buffer& buffer)
|
||||
if (buffer.empty()) {
|
||||
stream << "EMPTY";
|
||||
} else {
|
||||
for (size_t i = 0; i < buffer.length(); ++i) {
|
||||
for (size_t i = 0; i < buffer.size(); ++i) {
|
||||
if (i >= 1000) {
|
||||
stream << "...";
|
||||
break;
|
||||
|
@ -128,9 +128,6 @@ void ExtractSCTListFromOCSPResponse(pkix::Input cert,
|
||||
pkix::Time time,
|
||||
Buffer& result);
|
||||
|
||||
// We need this in tests code since mozilla::Vector only allows move assignment.
|
||||
Buffer cloneBuffer(const Buffer& buffer);
|
||||
|
||||
// Returns Input for the data stored in the buffer, failing assertion on error.
|
||||
pkix::Input InputForBuffer(const Buffer& buffer);
|
||||
|
||||
@ -139,12 +136,4 @@ pkix::Input InputForSECItem(const SECItem& item);
|
||||
|
||||
} } // namespace mozilla::ct
|
||||
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// GTest needs this to be in Buffer's namespace (i.e. in mozilla::Vector's).
|
||||
std::ostream& operator<<(std::ostream& stream, const ct::Buffer& buf);
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // CTTestUtils_h
|
||||
|
@ -39,7 +39,7 @@ public:
|
||||
mLogOperatorID,
|
||||
CTLogStatus::Included,
|
||||
0 /*disqualification time*/));
|
||||
ASSERT_EQ(Success, mVerifier.AddLog(std::move(log)));
|
||||
mVerifier.AddLog(std::move(log));
|
||||
|
||||
mTestCert = GetDEREncodedX509Cert();
|
||||
mEmbeddedCert = GetDEREncodedTestEmbeddedCert();
|
||||
@ -56,7 +56,7 @@ public:
|
||||
VerifiedSCT::Origin origin)
|
||||
{
|
||||
EXPECT_EQ(0U, result.decodingErrors);
|
||||
ASSERT_EQ(1U, result.verifiedScts.length());
|
||||
ASSERT_EQ(1U, result.verifiedScts.size());
|
||||
EXPECT_EQ(VerifiedSCT::Status::Valid, result.verifiedScts[0].status);
|
||||
EXPECT_EQ(origin, result.verifiedScts[0].origin);
|
||||
EXPECT_EQ(mLogOperatorID, result.verifiedScts[0].logOperatorId);
|
||||
@ -65,8 +65,8 @@ public:
|
||||
// Writes an SCTList containing a single |sct| into |output|.
|
||||
void EncodeSCTListForTesting(Input sct, Buffer& output)
|
||||
{
|
||||
Vector<Input> list;
|
||||
ASSERT_TRUE(list.append(std::move(sct)));
|
||||
std::vector<Input> list;
|
||||
list.push_back(std::move(sct));
|
||||
ASSERT_EQ(Success, EncodeSCTList(list, output));
|
||||
}
|
||||
|
||||
@ -225,7 +225,7 @@ TEST_F(MultiLogCTVerifierTest, IdentifiesSCTFromUnknownLog)
|
||||
mNow, result));
|
||||
|
||||
EXPECT_EQ(0U, result.decodingErrors);
|
||||
ASSERT_EQ(1U, result.verifiedScts.length());
|
||||
ASSERT_EQ(1U, result.verifiedScts.size());
|
||||
EXPECT_EQ(VerifiedSCT::Status::UnknownLog, result.verifiedScts[0].status);
|
||||
}
|
||||
|
||||
@ -236,7 +236,7 @@ TEST_F(MultiLogCTVerifierTest, IdentifiesSCTFromDisqualifiedLog)
|
||||
const uint64_t disqualificationTime = 12345u;
|
||||
ASSERT_EQ(Success, log.Init(InputForBuffer(GetTestPublicKey()),
|
||||
mLogOperatorID, CTLogStatus::Disqualified, disqualificationTime));
|
||||
ASSERT_EQ(Success, verifier.AddLog(std::move(log)));
|
||||
verifier.AddLog(std::move(log));
|
||||
|
||||
Buffer sct(GetTestSignedCertificateTimestamp());
|
||||
Buffer sctList;
|
||||
@ -249,7 +249,7 @@ TEST_F(MultiLogCTVerifierTest, IdentifiesSCTFromDisqualifiedLog)
|
||||
mNow, result));
|
||||
|
||||
EXPECT_EQ(0U, result.decodingErrors);
|
||||
ASSERT_EQ(1U, result.verifiedScts.length());
|
||||
ASSERT_EQ(1U, result.verifiedScts.size());
|
||||
EXPECT_EQ(VerifiedSCT::Status::ValidFromDisqualifiedLog,
|
||||
result.verifiedScts[0].status);
|
||||
EXPECT_EQ(disqualificationTime,
|
||||
|
@ -1294,7 +1294,7 @@ GatherCertificateTransparencyTelemetry(const UniqueCERTCertList& certList,
|
||||
|
||||
// Handle the histogram of SCTs counts.
|
||||
uint32_t sctsCount =
|
||||
static_cast<uint32_t>(info.verifyResult.verifiedScts.length());
|
||||
static_cast<uint32_t>(info.verifyResult.verifiedScts.size());
|
||||
// Note that sctsCount can also be 0 in case we've received SCT binary data,
|
||||
// but it failed to parse (e.g. due to unsupported CT protocol version).
|
||||
Telemetry::Accumulate(Telemetry::SSL_SCTS_PER_CONNECTION, sctsCount);
|
||||
|
Loading…
x
Reference in New Issue
Block a user