mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-05 07:18:39 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
562
security/manager/ssl/ContentSignatureVerifier.cpp
Normal file
562
security/manager/ssl/ContentSignatureVerifier.cpp
Normal file
|
|
@ -0,0 +1,562 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=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 "ContentSignatureVerifier.h"
|
||||
|
||||
#include "BRNameMatchingPolicy.h"
|
||||
#include "SharedCertVerifier.h"
|
||||
#include "cryptohi.h"
|
||||
#include "keyhi.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Casting.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsISupportsPriority.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsNSSComponent.h"
|
||||
#include "nsSecurityHeaderParser.h"
|
||||
#include "nsStreamUtils.h"
|
||||
#include "nsWhitespaceTokenizer.h"
|
||||
#include "nsXPCOMStrings.h"
|
||||
#include "nssb64.h"
|
||||
#include "pkix/pkix.h"
|
||||
#include "pkix/pkixtypes.h"
|
||||
#include "secerr.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(ContentSignatureVerifier,
|
||||
nsIContentSignatureVerifier,
|
||||
nsIInterfaceRequestor,
|
||||
nsIStreamListener)
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::pkix;
|
||||
using namespace mozilla::psm;
|
||||
|
||||
static LazyLogModule gCSVerifierPRLog("ContentSignatureVerifier");
|
||||
#define CSVerifier_LOG(args) MOZ_LOG(gCSVerifierPRLog, LogLevel::Debug, args)
|
||||
|
||||
// Content-Signature prefix
|
||||
const nsLiteralCString kPREFIX = NS_LITERAL_CSTRING("Content-Signature:\x00");
|
||||
|
||||
ContentSignatureVerifier::~ContentSignatureVerifier()
|
||||
{
|
||||
nsNSSShutDownPreventionLock locker;
|
||||
if (isAlreadyShutDown()) {
|
||||
return;
|
||||
}
|
||||
destructorSafeDestroyNSSReference();
|
||||
shutdown(ShutdownCalledFrom::Object);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ContentSignatureVerifier::VerifyContentSignature(
|
||||
const nsACString& aData, const nsACString& aCSHeader,
|
||||
const nsACString& aCertChain, const nsACString& aName, bool* _retval)
|
||||
{
|
||||
NS_ENSURE_ARG(_retval);
|
||||
nsresult rv = CreateContext(aData, aCSHeader, aCertChain, aName);
|
||||
if (NS_FAILED(rv)) {
|
||||
*_retval = false;
|
||||
CSVerifier_LOG(("CSVerifier: Signature verification failed\n"));
|
||||
if (rv == NS_ERROR_INVALID_SIGNATURE) {
|
||||
return NS_OK;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
return End(_retval);
|
||||
}
|
||||
|
||||
bool
|
||||
IsNewLine(char16_t c)
|
||||
{
|
||||
return c == '\n' || c == '\r';
|
||||
}
|
||||
|
||||
nsresult
|
||||
ReadChainIntoCertList(const nsACString& aCertChain, CERTCertList* aCertList,
|
||||
const nsNSSShutDownPreventionLock& /*proofOfLock*/)
|
||||
{
|
||||
bool inBlock = false;
|
||||
bool certFound = false;
|
||||
|
||||
const nsCString header = NS_LITERAL_CSTRING("-----BEGIN CERTIFICATE-----");
|
||||
const nsCString footer = NS_LITERAL_CSTRING("-----END CERTIFICATE-----");
|
||||
|
||||
nsCWhitespaceTokenizerTemplate<IsNewLine> tokenizer(aCertChain);
|
||||
|
||||
nsAutoCString blockData;
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
nsDependentCSubstring token = tokenizer.nextToken();
|
||||
if (token.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
if (inBlock) {
|
||||
if (token.Equals(footer)) {
|
||||
inBlock = false;
|
||||
certFound = true;
|
||||
// base64 decode data, make certs, append to chain
|
||||
ScopedAutoSECItem der;
|
||||
if (!NSSBase64_DecodeBuffer(nullptr, &der, blockData.BeginReading(),
|
||||
blockData.Length())) {
|
||||
CSVerifier_LOG(("CSVerifier: decoding the signature failed\n"));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
UniqueCERTCertificate tmpCert(
|
||||
CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &der, nullptr, false,
|
||||
true));
|
||||
if (!tmpCert) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
// if adding tmpCert succeeds, tmpCert will now be owned by aCertList
|
||||
SECStatus res = CERT_AddCertToListTail(aCertList, tmpCert.get());
|
||||
if (res != SECSuccess) {
|
||||
return MapSECStatus(res);
|
||||
}
|
||||
Unused << tmpCert.release();
|
||||
} else {
|
||||
blockData.Append(token);
|
||||
}
|
||||
} else if (token.Equals(header)) {
|
||||
inBlock = true;
|
||||
blockData = "";
|
||||
}
|
||||
}
|
||||
if (inBlock || !certFound) {
|
||||
// the PEM data did not end; bad data.
|
||||
CSVerifier_LOG(("CSVerifier: supplied chain contains bad data\n"));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
ContentSignatureVerifier::CreateContextInternal(const nsACString& aData,
|
||||
const nsACString& aCertChain,
|
||||
const nsACString& aName)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
nsNSSShutDownPreventionLock locker;
|
||||
if (isAlreadyShutDown()) {
|
||||
CSVerifier_LOG(("CSVerifier: nss is already shutdown\n"));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
UniqueCERTCertList certCertList(CERT_NewCertList());
|
||||
if (!certCertList) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
nsresult rv = ReadChainIntoCertList(aCertChain, certCertList.get(), locker);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
CERTCertListNode* node = CERT_LIST_HEAD(certCertList.get());
|
||||
if (!node || CERT_LIST_END(node, certCertList.get()) || !node->cert) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
SECItem* certSecItem = &node->cert->derCert;
|
||||
|
||||
Input certDER;
|
||||
mozilla::pkix::Result result =
|
||||
certDER.Init(BitwiseCast<uint8_t*, unsigned char*>(certSecItem->data),
|
||||
certSecItem->len);
|
||||
if (result != Success) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
// Check the signerCert chain is good
|
||||
CSTrustDomain trustDomain(certCertList);
|
||||
result = BuildCertChain(trustDomain, certDER, Now(),
|
||||
EndEntityOrCA::MustBeEndEntity,
|
||||
KeyUsage::noParticularKeyUsageRequired,
|
||||
KeyPurposeId::id_kp_codeSigning,
|
||||
CertPolicyId::anyPolicy,
|
||||
nullptr/*stapledOCSPResponse*/);
|
||||
if (result != Success) {
|
||||
// if there was a library error, return an appropriate error
|
||||
if (IsFatalError(result)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
// otherwise, assume the signature was invalid
|
||||
CSVerifier_LOG(("CSVerifier: The supplied chain is bad\n"));
|
||||
return NS_ERROR_INVALID_SIGNATURE;
|
||||
}
|
||||
|
||||
// Check the SAN
|
||||
Input hostnameInput;
|
||||
|
||||
result = hostnameInput.Init(
|
||||
BitwiseCast<const uint8_t*, const char*>(aName.BeginReading()),
|
||||
aName.Length());
|
||||
if (result != Success) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
BRNameMatchingPolicy nameMatchingPolicy(BRNameMatchingPolicy::Mode::Enforce);
|
||||
result = CheckCertHostname(certDER, hostnameInput, nameMatchingPolicy);
|
||||
if (result != Success) {
|
||||
return NS_ERROR_INVALID_SIGNATURE;
|
||||
}
|
||||
|
||||
mKey.reset(CERT_ExtractPublicKey(node->cert));
|
||||
|
||||
// in case we were not able to extract a key
|
||||
if (!mKey) {
|
||||
CSVerifier_LOG(("CSVerifier: unable to extract a key\n"));
|
||||
return NS_ERROR_INVALID_SIGNATURE;
|
||||
}
|
||||
|
||||
// Base 64 decode the signature
|
||||
ScopedAutoSECItem rawSignatureItem;
|
||||
if (!NSSBase64_DecodeBuffer(nullptr, &rawSignatureItem, mSignature.get(),
|
||||
mSignature.Length())) {
|
||||
CSVerifier_LOG(("CSVerifier: decoding the signature failed\n"));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// get signature object
|
||||
ScopedAutoSECItem signatureItem;
|
||||
// We have a raw ecdsa signature r||s so we have to DER-encode it first
|
||||
// Note that we have to check rawSignatureItem->len % 2 here as
|
||||
// DSAU_EncodeDerSigWithLen asserts this
|
||||
if (rawSignatureItem.len == 0 || rawSignatureItem.len % 2 != 0) {
|
||||
CSVerifier_LOG(("CSVerifier: signature length is bad\n"));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (DSAU_EncodeDerSigWithLen(&signatureItem, &rawSignatureItem,
|
||||
rawSignatureItem.len) != SECSuccess) {
|
||||
CSVerifier_LOG(("CSVerifier: encoding the signature failed\n"));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// this is the only OID we support for now
|
||||
SECOidTag oid = SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE;
|
||||
|
||||
mCx = UniqueVFYContext(
|
||||
VFY_CreateContext(mKey.get(), &signatureItem, oid, nullptr));
|
||||
if (!mCx) {
|
||||
return NS_ERROR_INVALID_SIGNATURE;
|
||||
}
|
||||
|
||||
if (VFY_Begin(mCx.get()) != SECSuccess) {
|
||||
return NS_ERROR_INVALID_SIGNATURE;
|
||||
}
|
||||
|
||||
rv = UpdateInternal(kPREFIX, locker);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
// add data if we got any
|
||||
return UpdateInternal(aData, locker);
|
||||
}
|
||||
|
||||
nsresult
|
||||
ContentSignatureVerifier::DownloadCertChain()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mCertChainURL.IsEmpty()) {
|
||||
return NS_ERROR_INVALID_SIGNATURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> certChainURI;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(certChainURI), mCertChainURL);
|
||||
if (NS_FAILED(rv) || !certChainURI) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// If the address is not https, fail.
|
||||
bool isHttps = false;
|
||||
rv = certChainURI->SchemeIs("https", &isHttps);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
if (!isHttps) {
|
||||
return NS_ERROR_INVALID_SIGNATURE;
|
||||
}
|
||||
|
||||
rv = NS_NewChannel(getter_AddRefs(mChannel), certChainURI,
|
||||
nsContentUtils::GetSystemPrincipal(),
|
||||
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
|
||||
nsIContentPolicy::TYPE_OTHER);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// we need this chain soon
|
||||
nsCOMPtr<nsISupportsPriority> priorityChannel = do_QueryInterface(mChannel);
|
||||
if (priorityChannel) {
|
||||
priorityChannel->AdjustPriority(nsISupportsPriority::PRIORITY_HIGHEST);
|
||||
}
|
||||
|
||||
rv = mChannel->AsyncOpen2(this);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Create a context for content signature verification using CreateContext below.
|
||||
// This function doesn't require a cert chain to be passed, but instead aCSHeader
|
||||
// must contain an x5u value that is then used to download the cert chain.
|
||||
NS_IMETHODIMP
|
||||
ContentSignatureVerifier::CreateContextWithoutCertChain(
|
||||
nsIContentSignatureReceiverCallback *aCallback, const nsACString& aCSHeader,
|
||||
const nsACString& aName)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aCallback);
|
||||
if (mInitialised) {
|
||||
return NS_ERROR_ALREADY_INITIALIZED;
|
||||
}
|
||||
mInitialised = true;
|
||||
|
||||
// we get the raw content-signature header here, so first parse aCSHeader
|
||||
nsresult rv = ParseContentSignatureHeader(aCSHeader);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mCallback = aCallback;
|
||||
mName.Assign(aName);
|
||||
|
||||
// We must download the cert chain now.
|
||||
// This is async and blocks createContextInternal calls.
|
||||
return DownloadCertChain();
|
||||
}
|
||||
|
||||
// Create a context for a content signature verification.
|
||||
// It sets signature, certificate chain and name that should be used to verify
|
||||
// the data. The data parameter is the first part of the data to verify (this
|
||||
// can be the empty string).
|
||||
NS_IMETHODIMP
|
||||
ContentSignatureVerifier::CreateContext(const nsACString& aData,
|
||||
const nsACString& aCSHeader,
|
||||
const nsACString& aCertChain,
|
||||
const nsACString& aName)
|
||||
{
|
||||
if (mInitialised) {
|
||||
return NS_ERROR_ALREADY_INITIALIZED;
|
||||
}
|
||||
mInitialised = true;
|
||||
// The cert chain is given in aCertChain so we don't have to download anything.
|
||||
mHasCertChain = true;
|
||||
|
||||
// we get the raw content-signature header here, so first parse aCSHeader
|
||||
nsresult rv = ParseContentSignatureHeader(aCSHeader);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return CreateContextInternal(aData, aCertChain, aName);
|
||||
}
|
||||
|
||||
nsresult
|
||||
ContentSignatureVerifier::UpdateInternal(
|
||||
const nsACString& aData, const nsNSSShutDownPreventionLock& /*proofOfLock*/)
|
||||
{
|
||||
if (!aData.IsEmpty()) {
|
||||
if (VFY_Update(mCx.get(), (const unsigned char*)nsPromiseFlatCString(aData).get(),
|
||||
aData.Length()) != SECSuccess){
|
||||
return NS_ERROR_INVALID_SIGNATURE;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add data to the context that shold be verified.
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
ContentSignatureVerifier::Update(const nsACString& aData)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
nsNSSShutDownPreventionLock locker;
|
||||
if (isAlreadyShutDown()) {
|
||||
CSVerifier_LOG(("CSVerifier: nss is already shutdown\n"));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// If we didn't create the context yet, bail!
|
||||
if (!mHasCertChain) {
|
||||
MOZ_ASSERT_UNREACHABLE(
|
||||
"Someone called ContentSignatureVerifier::Update before "
|
||||
"downloading the cert chain.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return UpdateInternal(aData, locker);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish signature verification and return the result in _retval.
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
ContentSignatureVerifier::End(bool* _retval)
|
||||
{
|
||||
NS_ENSURE_ARG(_retval);
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
nsNSSShutDownPreventionLock locker;
|
||||
if (isAlreadyShutDown()) {
|
||||
CSVerifier_LOG(("CSVerifier: nss is already shutdown\n"));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// If we didn't create the context yet, bail!
|
||||
if (!mHasCertChain) {
|
||||
MOZ_ASSERT_UNREACHABLE(
|
||||
"Someone called ContentSignatureVerifier::End before "
|
||||
"downloading the cert chain.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*_retval = (VFY_End(mCx.get()) == SECSuccess);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
ContentSignatureVerifier::ParseContentSignatureHeader(
|
||||
const nsACString& aContentSignatureHeader)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
// We only support p384 ecdsa according to spec
|
||||
NS_NAMED_LITERAL_CSTRING(signature_var, "p384ecdsa");
|
||||
NS_NAMED_LITERAL_CSTRING(certChainURL_var, "x5u");
|
||||
|
||||
nsSecurityHeaderParser parser(aContentSignatureHeader.BeginReading());
|
||||
nsresult rv = parser.Parse();
|
||||
if (NS_FAILED(rv)) {
|
||||
CSVerifier_LOG(("CSVerifier: could not parse ContentSignature header\n"));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
LinkedList<nsSecurityHeaderDirective>* directives = parser.GetDirectives();
|
||||
|
||||
for (nsSecurityHeaderDirective* directive = directives->getFirst();
|
||||
directive != nullptr; directive = directive->getNext()) {
|
||||
CSVerifier_LOG(("CSVerifier: found directive %s\n", directive->mName.get()));
|
||||
if (directive->mName.Length() == signature_var.Length() &&
|
||||
directive->mName.EqualsIgnoreCase(signature_var.get(),
|
||||
signature_var.Length())) {
|
||||
if (!mSignature.IsEmpty()) {
|
||||
CSVerifier_LOG(("CSVerifier: found two ContentSignatures\n"));
|
||||
return NS_ERROR_INVALID_SIGNATURE;
|
||||
}
|
||||
|
||||
CSVerifier_LOG(("CSVerifier: found a ContentSignature directive\n"));
|
||||
mSignature = directive->mValue;
|
||||
}
|
||||
if (directive->mName.Length() == certChainURL_var.Length() &&
|
||||
directive->mName.EqualsIgnoreCase(certChainURL_var.get(),
|
||||
certChainURL_var.Length())) {
|
||||
if (!mCertChainURL.IsEmpty()) {
|
||||
CSVerifier_LOG(("CSVerifier: found two x5u values\n"));
|
||||
return NS_ERROR_INVALID_SIGNATURE;
|
||||
}
|
||||
|
||||
CSVerifier_LOG(("CSVerifier: found an x5u directive\n"));
|
||||
mCertChainURL = directive->mValue;
|
||||
}
|
||||
}
|
||||
|
||||
// we have to ensure that we found a signature at this point
|
||||
if (mSignature.IsEmpty()) {
|
||||
CSVerifier_LOG(("CSVerifier: got a Content-Signature header but didn't find a signature.\n"));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Bug 769521: We have to change b64 url to regular encoding as long as we
|
||||
// don't have a b64 url decoder. This should change soon, but in the meantime
|
||||
// we have to live with this.
|
||||
mSignature.ReplaceChar('-', '+');
|
||||
mSignature.ReplaceChar('_', '/');
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* nsIStreamListener implementation */
|
||||
|
||||
NS_IMETHODIMP
|
||||
ContentSignatureVerifier::OnStartRequest(nsIRequest* aRequest,
|
||||
nsISupports* aContext)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ContentSignatureVerifier::OnStopRequest(nsIRequest* aRequest,
|
||||
nsISupports* aContext, nsresult aStatus)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
nsCOMPtr<nsIContentSignatureReceiverCallback> callback;
|
||||
callback.swap(mCallback);
|
||||
nsresult rv;
|
||||
|
||||
// Check HTTP status code and return if it's not 200.
|
||||
nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(aRequest, &rv);
|
||||
uint32_t httpResponseCode;
|
||||
if (NS_FAILED(rv) || NS_FAILED(http->GetResponseStatus(&httpResponseCode)) ||
|
||||
httpResponseCode != 200) {
|
||||
callback->ContextCreated(false);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (NS_FAILED(aStatus)) {
|
||||
callback->ContextCreated(false);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAutoCString certChain;
|
||||
for (uint32_t i = 0; i < mCertChain.Length(); ++i) {
|
||||
certChain.Append(mCertChain[i]);
|
||||
}
|
||||
|
||||
// We got the cert chain now. Let's create the context.
|
||||
rv = CreateContextInternal(NS_LITERAL_CSTRING(""), certChain, mName);
|
||||
if (NS_FAILED(rv)) {
|
||||
callback->ContextCreated(false);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mHasCertChain = true;
|
||||
callback->ContextCreated(true);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ContentSignatureVerifier::OnDataAvailable(nsIRequest* aRequest,
|
||||
nsISupports* aContext,
|
||||
nsIInputStream* aInputStream,
|
||||
uint64_t aOffset, uint32_t aCount)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
nsAutoCString buffer;
|
||||
|
||||
nsresult rv = NS_ConsumeStream(aInputStream, aCount, buffer);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!mCertChain.AppendElement(buffer, fallible)) {
|
||||
mCertChain.TruncateLength(0);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ContentSignatureVerifier::GetInterface(const nsIID& uuid, void** result)
|
||||
{
|
||||
return QueryInterface(uuid, result);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue