gecko-dev/security/certverifier/CTLogVerifier.h
David Keeler af0ce9fbd6 bug 1357226 - work around a library inefficiency with EC keys when verifying ECDSA signatures r=fkiefer,jcj
Calling VFY_VerifyDigestDirect causes the provided SECKEYPublicKey to be
reimported to the softoken regardless of if it already exists on it. EC keys
must be verified upon import (to see if the point is on the curve to avoid some
small subgroup attacks), and so repeatedly doing this with a static key (say,
for example, a key corresponding to a built-in certificate transparency log) is
inefficient. This patch alters the certificate transparency implementation to
import these keys each once and then use PK11_Verify for ECDSA signature
verification, which doesn't have the same drawback.

Since this change causes CertVerifier to hold an NSS resource (via its
MultiLogCTVerifier having a list of CTLogVerifier, each of which now has a
SECKEYPublicKey), nsNSSComponent has to make sure it goes away before shutting
down NSS. This patch ensures this happens in nsNSSComponent::ShutdownNSS().

MozReview-Commit-ID: 6VSmz7S53y2

--HG--
extra : rebase_source : 4994db9de80a6c1aec3d7e322ff30d040140ce92
2017-04-11 14:11:28 -07:00

92 lines
3.7 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef CTLogVerifier_h
#define CTLogVerifier_h
#include "CTLog.h"
#include "pkix/Input.h"
#include "pkix/pkix.h"
#include "pkix/Result.h"
#include "ScopedNSSTypes.h"
#include "SignedCertificateTimestamp.h"
#include "SignedTreeHead.h"
namespace mozilla { namespace ct {
// Verifies Signed Certificate Timestamps (SCTs) provided by a specific log
// using the public key of that log. Assumes the SCT being verified
// matches the log by log key ID and signature parameters (an error is returned
// otherwise).
// The verification functions return Success if the provided SCT has passed
// verification, ERROR_BAD_SIGNATURE if failed verification, or other result
// on error.
class CTLogVerifier
{
public:
CTLogVerifier();
// Initializes the verifier with log-specific information. Only the public
// key is used for verification, other parameters are purely informational.
// |subjectPublicKeyInfo| is a DER-encoded SubjectPublicKeyInfo.
// |operatorId| The numeric ID of the log operator as assigned at
// https://www.certificate-transparency.org/known-logs .
// |logStatus| Either "Included" or "Disqualified".
// |disqualificationTime| Disqualification timestamp (for disqualified logs).
// An error is returned if |subjectPublicKeyInfo| refers to an unsupported
// public key.
pkix::Result Init(pkix::Input subjectPublicKeyInfo,
CTLogOperatorId operatorId,
CTLogStatus logStatus,
uint64_t disqualificationTime);
// Returns the log's key ID, which is a SHA256 hash of its public key.
// See RFC 6962, Section 3.2.
const Buffer& keyId() const { return mKeyId; }
CTLogOperatorId operatorId() const { return mOperatorId; }
bool isDisqualified() const { return mDisqualified; }
uint64_t disqualificationTime() const { return mDisqualificationTime; }
// Verifies that |sct| contains a valid signature for |entry|.
// |sct| must be signed by the verifier's log.
pkix::Result Verify(const LogEntry& entry,
const SignedCertificateTimestamp& sct);
// Verifies the signature in |sth|.
// |sth| must be signed by the verifier's log.
pkix::Result VerifySignedTreeHead(const SignedTreeHead& sth);
// Returns true if the signature and hash algorithms in |signature|
// match those of the log.
bool SignatureParametersMatch(const DigitallySigned& signature);
private:
// Performs the underlying verification using the log's public key. Note
// that |signature| contains the raw signature data (i.e. without any
// DigitallySigned struct encoding).
// Returns Success if passed verification, ERROR_BAD_SIGNATURE if failed
// verification, or other result on error.
pkix::Result VerifySignature(pkix::Input data, pkix::Input signature);
pkix::Result VerifySignature(const Buffer& data, const Buffer& signature);
// mPublicECKey works around an architectural deficiency in NSS. In the case
// of EC, if we don't create, import, and cache this key, NSS will import and
// verify it every signature verification, which is slow. For RSA, this is
// unused and will be null.
UniqueSECKEYPublicKey mPublicECKey;
Buffer mSubjectPublicKeyInfo;
Buffer mKeyId;
DigitallySigned::SignatureAlgorithm mSignatureAlgorithm;
CTLogOperatorId mOperatorId;
bool mDisqualified;
uint64_t mDisqualificationTime;
};
} } // namespace mozilla::ct
#endif // CTLogVerifier_h