Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/GAP/pkg/fining/examples/include/   (Algebra von RWTH Aachen Version 4.15.1©)  Datei vom 27.6.2023 mit Größe 699 B image not shown  

Quelle  CTLogVerifier.cpp   Sprache: unbekannt

 
/* -*- 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/. */


#include "CTLogVerifier.h"

#include <stdint.h>

#include "CTSerialization.h"
#include "CertVerifier.h"
#include "hasht.h"
#include "mozpkix/Result.h"
#include "mozpkix/pkixnss.h"
#include "mozpkix/pkixutil.h"
#include "mozilla/glean/SecurityCtMetrics.h"

using namespace mozilla::pkix;

namespace mozilla {
namespace ct {

// A TrustDomain used to extract the SCT log signature parameters
// given its subjectPublicKeyInfo.
// Only RSASSA-PKCS1v15 with SHA-256 and ECDSA (using the NIST P-256 curve)
// with SHA-256 are allowed.
// RSA keys must be at least 2048 bits.
// See See RFC 6962, Section 2.1.4.
class SignatureParamsTrustDomain final : public TrustDomain {
 public:
  SignatureParamsTrustDomain()
      : mSignatureAlgorithm(DigitallySigned::SignatureAlgorithm::Anonymous) {}

  pkix::Result GetCertTrust(EndEntityOrCA, const CertPolicyId&, Input,
                            TrustLevel&) override {
    return pkix::Result::FATAL_ERROR_LIBRARY_FAILURE;
  }

  pkix::Result FindIssuer(Input, IssuerChecker&, Time) override {
    return pkix::Result::FATAL_ERROR_LIBRARY_FAILURE;
  }

  pkix::Result CheckRevocation(EndEntityOrCA, const CertID&, Time, Duration,
                               const Input*, const Input*,
                               const Input*) override {
    return pkix::Result::FATAL_ERROR_LIBRARY_FAILURE;
  }

  pkix::Result IsChainValid(const DERArray&, Time,
                            const CertPolicyId&) override {
    return pkix::Result::FATAL_ERROR_LIBRARY_FAILURE;
  }

  pkix::Result DigestBuf(Input, DigestAlgorithm, uint8_t*, size_t) override {
    return pkix::Result::FATAL_ERROR_LIBRARY_FAILURE;
  }

  pkix::Result CheckSignatureDigestAlgorithm(DigestAlgorithm, EndEntityOrCA,
                                             Time) override {
    return pkix::Result::FATAL_ERROR_LIBRARY_FAILURE;
  }

  pkix::Result CheckECDSACurveIsAcceptable(EndEntityOrCA,
                                           NamedCurve curve) override {
    assert(mSignatureAlgorithm ==
           DigitallySigned::SignatureAlgorithm::Anonymous);
    if (curve != NamedCurve::secp256r1) {
      return pkix::Result::ERROR_UNSUPPORTED_ELLIPTIC_CURVE;
    }
    mSignatureAlgorithm = DigitallySigned::SignatureAlgorithm::ECDSA;
    return Success;
  }

  pkix::Result VerifyECDSASignedData(Input, DigestAlgorithm, Input,
                                     Input) override {
    return pkix::Result::FATAL_ERROR_LIBRARY_FAILURE;
  }

  pkix::Result CheckRSAPublicKeyModulusSizeInBits(
      EndEntityOrCA, unsigned int modulusSizeInBits) override {
    assert(mSignatureAlgorithm ==
           DigitallySigned::SignatureAlgorithm::Anonymous);
    // Require RSA keys of at least 2048 bits. See RFC 6962, Section 2.1.4.
    if (modulusSizeInBits < 2048) {
      return pkix::Result::ERROR_INADEQUATE_KEY_SIZE;
    }
    mSignatureAlgorithm = DigitallySigned::SignatureAlgorithm::RSA;
    return Success;
  }

  pkix::Result VerifyRSAPKCS1SignedData(Input, DigestAlgorithm, Input,
                                        Input) override {
    return pkix::Result::FATAL_ERROR_LIBRARY_FAILURE;
  }

  pkix::Result VerifyRSAPSSSignedData(Input, DigestAlgorithm, Input,
                                      Input) override {
    return pkix::Result::FATAL_ERROR_LIBRARY_FAILURE;
  }

  pkix::Result CheckValidityIsAcceptable(Time, Time, EndEntityOrCA,
                                         KeyPurposeId) override {
    return pkix::Result::FATAL_ERROR_LIBRARY_FAILURE;
  }

  pkix::Result NetscapeStepUpMatchesServerAuth(Time, bool&) override {
    return pkix::Result::FATAL_ERROR_LIBRARY_FAILURE;
  }

  void NoteAuxiliaryExtension(AuxiliaryExtension, Input) override {}

  DigitallySigned::SignatureAlgorithm mSignatureAlgorithm;
};

CTLogVerifier::CTLogVerifier(CTLogOperatorId operatorId, CTLogState state,
                             uint64_t timestamp)
    : mSignatureAlgorithm(DigitallySigned::SignatureAlgorithm::Anonymous),
      mOperatorId(operatorId),
      mState(state),
      mTimestamp(timestamp) {}

pkix::Result CTLogVerifier::Init(Input subjectPublicKeyInfo) {
  SignatureParamsTrustDomain trustDomain;
  pkix::Result rv = CheckSubjectPublicKeyInfo(subjectPublicKeyInfo, trustDomain,
                                              EndEntityOrCA::MustBeEndEntity);
  if (rv != Success) {
    return rv;
  }
  mSignatureAlgorithm = trustDomain.mSignatureAlgorithm;

  InputToBuffer(subjectPublicKeyInfo, mSubjectPublicKeyInfo);

  mKeyId.resize(SHA256_LENGTH);
  rv = DigestBufNSS(subjectPublicKeyInfo, DigestAlgorithm::sha256,
                    mKeyId.data(), mKeyId.size());
  if (rv != Success) {
    return rv;
  }

  return Success;
}

pkix::Result CTLogVerifier::Verify(const LogEntry& entry,
                                   const SignedCertificateTimestamp& sct,
                                   SignatureCache* signatureCache) {
  if (mKeyId.empty() || sct.logId != mKeyId || !signatureCache) {
    return pkix::Result::FATAL_ERROR_INVALID_ARGS;
  }
  if (!SignatureParametersMatch(sct.signature)) {
    return pkix::Result::FATAL_ERROR_INVALID_ARGS;
  }

  Buffer serializedLogEntry;
  pkix::Result rv = EncodeLogEntry(entry, serializedLogEntry);
  if (rv != Success) {
    return rv;
  }

  Input logEntryInput;
  rv = BufferToInput(serializedLogEntry, logEntryInput);
  if (rv != Success) {
    return rv;
  }

  // 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.empty()) {
    rv = sctExtensionsInput.Init(sct.extensions.data(), sct.extensions.size());
    if (rv != Success) {
      return rv;
    }
  }

  Buffer serializedData;
  rv = EncodeV1SCTSignedData(sct.timestamp, logEntryInput, sctExtensionsInput,
                             serializedData);
  if (rv != Success) {
    return rv;
  }
  return VerifySignature(serializedData, sct.signature.signatureData,
                         signatureCache);
}

bool CTLogVerifier::SignatureParametersMatch(const DigitallySigned& signature) {
  return signature.SignatureParametersMatch(
      DigitallySigned::HashAlgorithm::SHA256, mSignatureAlgorithm);
}

pkix::Result CTLogVerifier::VerifySignature(Input data, Input signature,
                                            SignatureCache* signatureCache) {
  Input spki;
  pkix::Result rv = BufferToInput(mSubjectPublicKeyInfo, spki);
  if (rv != Success) {
    return rv;
  }

  switch (mSignatureAlgorithm) {
    case DigitallySigned::SignatureAlgorithm::RSA:
      rv = psm::VerifySignedDataWithCache(
          der::PublicKeyAlgorithm::RSA_PKCS1,
          mozilla::glean::sct_signature_cache::total,
          mozilla::glean::sct_signature_cache::hits, data,
          DigestAlgorithm::sha256, signature, spki, signatureCache, nullptr);
      break;
    case DigitallySigned::SignatureAlgorithm::ECDSA:
      rv = psm::VerifySignedDataWithCache(
          der::PublicKeyAlgorithm::ECDSA,
          mozilla::glean::sct_signature_cache::total,
          mozilla::glean::sct_signature_cache::hits, data,
          DigestAlgorithm::sha256, signature, spki, signatureCache, nullptr);
      break;
    // We do not expect new values added to this enum any time soon,
    // so just listing all the available ones seems to be the easiest way
    // to suppress warning C4061 on MSVC (which expects all values of the
    // enum to be explicitly handled).
    case DigitallySigned::SignatureAlgorithm::Anonymous:
    case DigitallySigned::SignatureAlgorithm::DSA:
    default:
      assert(false);
      return pkix::Result::FATAL_ERROR_INVALID_ARGS;
  }
  if (rv != Success) {
    if (IsFatalError(rv)) {
      return rv;
    }
    // If the error is non-fatal, we assume the signature was invalid.
    return pkix::Result::ERROR_BAD_SIGNATURE;
  }
  return Success;
}

pkix::Result CTLogVerifier::VerifySignature(const Buffer& data,
                                            const Buffer& signature,
                                            SignatureCache* signatureCache) {
  Input dataInput;
  pkix::Result rv = BufferToInput(data, dataInput);
  if (rv != Success) {
    return rv;
  }
  Input signatureInput;
  rv = BufferToInput(signature, signatureInput);
  if (rv != Success) {
    return rv;
  }
  return VerifySignature(dataInput, signatureInput, signatureCache);
}

}  // namespace ct
}  // namespace mozilla

100%


[ Dauer der Verarbeitung: 0.33 Sekunden  (vorverarbeitet)  ]