зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1272794 - Clean up Digest class API r=keeler,necko-reviewers,valentin
Differential Revision: https://phabricator.services.mozilla.com/D40983
This commit is contained in:
Родитель
96f7c5cf5c
Коммит
21cf959be5
|
@ -102,8 +102,7 @@ BackgroundFileSaver::BackgroundFileSaver()
|
|||
mSha256Enabled(false),
|
||||
mSignatureInfoEnabled(false),
|
||||
mActualTarget(nullptr),
|
||||
mActualTargetKeepPartial(false),
|
||||
mDigestContext(nullptr) {
|
||||
mActualTargetKeepPartial(false) {
|
||||
LOG(("Created BackgroundFileSaver [this = %p]", this));
|
||||
}
|
||||
|
||||
|
@ -518,16 +517,15 @@ nsresult BackgroundFileSaver::ProcessStateChange() {
|
|||
}
|
||||
}
|
||||
|
||||
// Create the digest context if requested and NSS hasn't been shut down.
|
||||
if (sha256Enabled && !mDigestContext) {
|
||||
mDigestContext =
|
||||
UniquePK11Context(PK11_CreateDigestContext(SEC_OID_SHA256));
|
||||
NS_ENSURE_TRUE(mDigestContext, NS_ERROR_OUT_OF_MEMORY);
|
||||
// Create the digest if requested and NSS hasn't been shut down.
|
||||
if (sha256Enabled && mDigest.isNothing()) {
|
||||
mDigest.emplace(Digest());
|
||||
mDigest->Begin(SEC_OID_SHA256);
|
||||
}
|
||||
|
||||
// When we are requested to append to an existing file, we should read the
|
||||
// existing data and ensure we include it as part of the final hash.
|
||||
if (mDigestContext && append && !isContinuation) {
|
||||
if (mDigest.isSome() && append && !isContinuation) {
|
||||
nsCOMPtr<nsIInputStream> inputStream;
|
||||
rv = NS_NewLocalFileInputStream(getter_AddRefs(inputStream), mActualTarget,
|
||||
PR_RDONLY | nsIFile::OS_READAHEAD);
|
||||
|
@ -545,9 +543,8 @@ nsresult BackgroundFileSaver::ProcessStateChange() {
|
|||
break;
|
||||
}
|
||||
|
||||
nsresult rv = MapSECStatus(
|
||||
PK11_DigestOp(mDigestContext.get(),
|
||||
BitwiseCast<unsigned char*, char*>(buffer), count));
|
||||
nsresult rv =
|
||||
mDigest->Update(BitwiseCast<unsigned char*, char*>(buffer), count);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
|
@ -582,14 +579,14 @@ nsresult BackgroundFileSaver::ProcessStateChange() {
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
outputStream = bufferedStream;
|
||||
|
||||
// Wrap the output stream so that it feeds the digest context if needed.
|
||||
if (mDigestContext) {
|
||||
// Constructing the DigestOutputStream cannot fail. Passing mDigestContext
|
||||
// Wrap the output stream so that it feeds the digest if needed.
|
||||
if (mDigest.isSome()) {
|
||||
// Constructing the DigestOutputStream cannot fail. Passing mDigest
|
||||
// to DigestOutputStream is safe, because BackgroundFileSaver always
|
||||
// outlives the outputStream. BackgroundFileSaver is reference-counted
|
||||
// before the call to AsyncCopy, and mDigestContext is never destroyed
|
||||
// before the call to AsyncCopy, and mDigest is never destroyed
|
||||
// before AsyncCopyCallback.
|
||||
outputStream = new DigestOutputStream(outputStream, mDigestContext.get());
|
||||
outputStream = new DigestOutputStream(outputStream, mDigest.ref());
|
||||
}
|
||||
|
||||
// Start copying our input to the target file. No errors can be raised past
|
||||
|
@ -675,13 +672,13 @@ bool BackgroundFileSaver::CheckCompletion() {
|
|||
}
|
||||
|
||||
// Finish computing the hash
|
||||
if (!failed && mDigestContext) {
|
||||
Digest d;
|
||||
rv = d.End(SEC_OID_SHA256, mDigestContext);
|
||||
if (!failed && mDigest.isSome()) {
|
||||
nsTArray<uint8_t> outArray;
|
||||
rv = mDigest->End(outArray);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
MutexAutoLock lock(mLock);
|
||||
mSha256 = nsDependentCSubstring(
|
||||
BitwiseCast<char*, unsigned char*>(d.get().data), d.get().len);
|
||||
BitwiseCast<char*, uint8_t*>(outArray.Elements()), outArray.Length());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1077,9 +1074,8 @@ nsresult BackgroundFileSaverStreamListener::NotifySuspendOrResume() {
|
|||
NS_IMPL_ISUPPORTS(DigestOutputStream, nsIOutputStream)
|
||||
|
||||
DigestOutputStream::DigestOutputStream(nsIOutputStream* aStream,
|
||||
PK11Context* aContext)
|
||||
: mOutputStream(aStream), mDigestContext(aContext) {
|
||||
MOZ_ASSERT(mDigestContext, "Can't have null digest context");
|
||||
Digest& aDigest)
|
||||
: mOutputStream(aStream), mDigest(aDigest) {
|
||||
MOZ_ASSERT(mOutputStream, "Can't have null output stream");
|
||||
}
|
||||
|
||||
|
@ -1091,9 +1087,8 @@ DigestOutputStream::Flush() { return mOutputStream->Flush(); }
|
|||
|
||||
NS_IMETHODIMP
|
||||
DigestOutputStream::Write(const char* aBuf, uint32_t aCount, uint32_t* retval) {
|
||||
nsresult rv = MapSECStatus(PK11_DigestOp(
|
||||
mDigestContext, BitwiseCast<const unsigned char*, const char*>(aBuf),
|
||||
aCount));
|
||||
nsresult rv = mDigest.Update(
|
||||
BitwiseCast<const unsigned char*, const char*>(aBuf), aCount);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return mOutputStream->Write(aBuf, aCount, retval);
|
||||
|
|
|
@ -228,7 +228,7 @@ class BackgroundFileSaver : public nsIBackgroundFileSaver {
|
|||
* Used to calculate the file hash. This keeps state across file renames and
|
||||
* is lazily initialized in ProcessStateChange.
|
||||
*/
|
||||
UniquePK11Context mDigestContext;
|
||||
Maybe<Digest> mDigest;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// Private methods
|
||||
|
@ -376,15 +376,15 @@ class DigestOutputStream : public nsIOutputStream {
|
|||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIOUTPUTSTREAM
|
||||
// Constructor. Neither parameter may be null. The caller owns both.
|
||||
DigestOutputStream(nsIOutputStream* outputStream, PK11Context* aContext);
|
||||
DigestOutputStream(nsIOutputStream* aStream, Digest& aDigest);
|
||||
|
||||
private:
|
||||
virtual ~DigestOutputStream() = default;
|
||||
|
||||
// Calls to write are passed to this stream.
|
||||
nsCOMPtr<nsIOutputStream> mOutputStream;
|
||||
// Digest context used to compute the hash, owned by the caller.
|
||||
PK11Context* mDigestContext;
|
||||
// Digest used to compute the hash, owned by the caller.
|
||||
Digest& mDigest;
|
||||
|
||||
// Don't accidentally copy construct.
|
||||
DigestOutputStream(const DigestOutputStream& d) = delete;
|
||||
|
|
|
@ -77,9 +77,10 @@ struct DigestWithAlgorithm {
|
|||
};
|
||||
|
||||
// The digest must have a lifetime greater than or equal to the returned string.
|
||||
inline nsDependentCSubstring DigestToDependentString(const Digest& digest) {
|
||||
return nsDependentCSubstring(
|
||||
BitwiseCast<char*, unsigned char*>(digest.get().data), digest.get().len);
|
||||
inline nsDependentCSubstring DigestToDependentString(
|
||||
nsTArray<uint8_t>& digest) {
|
||||
return nsDependentCSubstring(BitwiseCast<char*, uint8_t*>(digest.Elements()),
|
||||
digest.Length());
|
||||
}
|
||||
|
||||
// Reads a maximum of 8MB from a stream into the supplied buffer.
|
||||
|
@ -142,7 +143,7 @@ nsresult FindAndLoadOneEntry(
|
|||
/*out*/ nsACString& filename,
|
||||
/*out*/ SECItem& buf,
|
||||
/*optional, in*/ SECOidTag digestAlgorithm = SEC_OID_SHA1,
|
||||
/*optional, out*/ Digest* bufDigest = nullptr) {
|
||||
/*optional, out*/ nsTArray<uint8_t>* bufDigest = nullptr) {
|
||||
nsCOMPtr<nsIUTF8StringEnumerator> files;
|
||||
nsresult rv = zip->FindEntries(searchPattern, getter_AddRefs(files));
|
||||
if (NS_FAILED(rv) || !files) {
|
||||
|
@ -176,7 +177,8 @@ nsresult FindAndLoadOneEntry(
|
|||
}
|
||||
|
||||
if (bufDigest) {
|
||||
rv = bufDigest->DigestBuf(digestAlgorithm, buf.data, buf.len - 1);
|
||||
rv = Digest::DigestBuf(digestAlgorithm,
|
||||
Span<uint8_t>{buf.data, buf.len - 1}, *bufDigest);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
|
@ -210,13 +212,9 @@ nsresult VerifyStreamContentDigest(
|
|||
return NS_ERROR_SIGNED_JAR_ENTRY_TOO_LARGE;
|
||||
}
|
||||
|
||||
UniquePK11Context digestContext(
|
||||
PK11_CreateDigestContext(digestFromManifest.mAlgorithm));
|
||||
if (!digestContext) {
|
||||
return mozilla::psm::GetXPCOMFromNSSError(PR_GetError());
|
||||
}
|
||||
Digest digest;
|
||||
|
||||
rv = MapSECStatus(PK11_DigestBegin(digestContext.get()));
|
||||
rv = digest.Begin(digestFromManifest.mAlgorithm);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uint64_t totalBytesRead = 0;
|
||||
|
@ -235,7 +233,7 @@ nsresult VerifyStreamContentDigest(
|
|||
return NS_ERROR_SIGNED_JAR_ENTRY_TOO_LARGE;
|
||||
}
|
||||
|
||||
rv = MapSECStatus(PK11_DigestOp(digestContext.get(), buf.data, bytesRead));
|
||||
rv = digest.Update(buf.data, bytesRead);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
|
@ -246,11 +244,11 @@ nsresult VerifyStreamContentDigest(
|
|||
}
|
||||
|
||||
// Verify that the digests match.
|
||||
Digest digest;
|
||||
rv = digest.End(digestFromManifest.mAlgorithm, digestContext);
|
||||
nsTArray<uint8_t> outArray;
|
||||
rv = digest.End(outArray);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsDependentCSubstring digestStr(DigestToDependentString(digest));
|
||||
nsDependentCSubstring digestStr(DigestToDependentString(outArray));
|
||||
if (!digestStr.Equals(digestFromManifest.mDigest)) {
|
||||
return NS_ERROR_SIGNED_JAR_MODIFIED_ENTRY;
|
||||
}
|
||||
|
@ -749,13 +747,13 @@ Span<const uint8_t> GetPKCS7SignerCert(
|
|||
}
|
||||
|
||||
nsresult VerifySignature(AppTrustedRoot trustedRoot, const SECItem& buffer,
|
||||
const SECItem& detachedSHA1Digest,
|
||||
const SECItem& detachedSHA256Digest,
|
||||
nsTArray<uint8_t>& detachedSHA1Digest,
|
||||
nsTArray<uint8_t>& detachedSHA256Digest,
|
||||
/*out*/ SECOidTag& digestAlgorithm,
|
||||
/*out*/ nsTArray<uint8_t>& signerCert) {
|
||||
if (NS_WARN_IF(!buffer.data || buffer.len == 0 || !detachedSHA1Digest.data ||
|
||||
detachedSHA1Digest.len == 0 || !detachedSHA256Digest.data ||
|
||||
detachedSHA256Digest.len == 0)) {
|
||||
if (NS_WARN_IF(!buffer.data || buffer.len == 0 ||
|
||||
detachedSHA1Digest.Length() == 0 ||
|
||||
detachedSHA256Digest.Length() == 0)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
|
@ -799,17 +797,21 @@ nsresult VerifySignature(AppTrustedRoot trustedRoot, const SECItem& buffer,
|
|||
|
||||
NSSCMSSignerInfo* signerInfo =
|
||||
GetSignerInfoForDigestAlgorithm(signedData, SEC_OID_SHA256);
|
||||
const SECItem* detachedDigest = &detachedSHA256Digest;
|
||||
nsTArray<uint8_t>* tmpDetachedDigest = &detachedSHA256Digest;
|
||||
digestAlgorithm = SEC_OID_SHA256;
|
||||
if (!signerInfo) {
|
||||
signerInfo = GetSignerInfoForDigestAlgorithm(signedData, SEC_OID_SHA1);
|
||||
if (!signerInfo) {
|
||||
return NS_ERROR_CMS_VERIFY_NOT_SIGNED;
|
||||
}
|
||||
detachedDigest = &detachedSHA1Digest;
|
||||
tmpDetachedDigest = &detachedSHA1Digest;
|
||||
digestAlgorithm = SEC_OID_SHA1;
|
||||
}
|
||||
|
||||
const SECItem detachedDigest = {
|
||||
siBuffer, tmpDetachedDigest->Elements(),
|
||||
static_cast<unsigned int>(tmpDetachedDigest->Length())};
|
||||
|
||||
// Get the certificate that issued the PKCS7 signature.
|
||||
Span<const uint8_t> signerCertSpan =
|
||||
GetPKCS7SignerCert(signerInfo, collectedCerts);
|
||||
|
@ -853,7 +855,7 @@ nsresult VerifySignature(AppTrustedRoot trustedRoot, const SECItem& buffer,
|
|||
return mozilla::psm::GetXPCOMFromNSSError(SEC_ERROR_PKCS7_BAD_SIGNATURE);
|
||||
}
|
||||
return MapSECStatus(NSS_CMSSignerInfo_Verify(
|
||||
signerInfo, const_cast<SECItem*>(detachedDigest), &pkcs7DataOid));
|
||||
signerInfo, const_cast<SECItem*>(&detachedDigest), &pkcs7DataOid));
|
||||
}
|
||||
|
||||
class CoseVerificationContext {
|
||||
|
@ -1187,15 +1189,16 @@ nsresult VerifyPK7Signature(
|
|||
|
||||
// Calculate both the SHA-1 and SHA-256 hashes of the signature file - we
|
||||
// don't know what algorithm the PKCS#7 signature used.
|
||||
Digest sfCalculatedSHA1Digest;
|
||||
rv = sfCalculatedSHA1Digest.DigestBuf(SEC_OID_SHA1, sfBuffer.data,
|
||||
sfBuffer.len - 1);
|
||||
nsTArray<uint8_t> sfCalculatedSHA1Digest;
|
||||
rv = Digest::DigestBuf(SEC_OID_SHA1, sfBuffer.data, sfBuffer.len - 1,
|
||||
sfCalculatedSHA1Digest);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
Digest sfCalculatedSHA256Digest;
|
||||
rv = sfCalculatedSHA256Digest.DigestBuf(SEC_OID_SHA256, sfBuffer.data,
|
||||
sfBuffer.len - 1);
|
||||
|
||||
nsTArray<uint8_t> sfCalculatedSHA256Digest;
|
||||
rv = Digest::DigestBuf(SEC_OID_SHA256, sfBuffer.data, sfBuffer.len - 1,
|
||||
sfCalculatedSHA256Digest);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -1204,9 +1207,8 @@ nsresult VerifyPK7Signature(
|
|||
// If we get here, the signature has to verify even if PKCS#7 is not required.
|
||||
sigBuffer.type = siBuffer;
|
||||
SECOidTag digestToUse;
|
||||
rv =
|
||||
VerifySignature(aTrustedRoot, sigBuffer, sfCalculatedSHA1Digest.get(),
|
||||
sfCalculatedSHA256Digest.get(), digestToUse, aSignerCert);
|
||||
rv = VerifySignature(aTrustedRoot, sigBuffer, sfCalculatedSHA1Digest,
|
||||
sfCalculatedSHA256Digest, digestToUse, aSignerCert);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -1225,17 +1227,18 @@ nsresult VerifyPK7Signature(
|
|||
|
||||
// Read PK7 manifest (MF) file.
|
||||
ScopedAutoSECItem manifestBuffer;
|
||||
Digest mfCalculatedDigest;
|
||||
nsTArray<uint8_t> digestArray;
|
||||
nsAutoCString mfFilename;
|
||||
rv = FindAndLoadOneEntry(aZip, nsLiteralCString(JAR_MF_SEARCH_STRING),
|
||||
mfFilename, manifestBuffer, digestToUse,
|
||||
&mfCalculatedDigest);
|
||||
&digestArray);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsDependentCSubstring calculatedDigest(
|
||||
DigestToDependentString(mfCalculatedDigest));
|
||||
BitwiseCast<char*, uint8_t*>(digestArray.Elements()),
|
||||
digestArray.Length());
|
||||
if (!mfDigest.Equals(calculatedDigest)) {
|
||||
return NS_ERROR_SIGNED_JAR_MANIFEST_INVALID;
|
||||
}
|
||||
|
|
|
@ -36,15 +36,16 @@ static nsresult GetBase64HashSPKI(const BackCert& cert,
|
|||
Input derPublicKey = cert.GetSubjectPublicKeyInfo();
|
||||
|
||||
hashSPKIDigest.Truncate();
|
||||
Digest digest;
|
||||
nsresult nsrv = digest.DigestBuf(SEC_OID_SHA256, derPublicKey.UnsafeGetData(),
|
||||
derPublicKey.GetLength());
|
||||
nsTArray<uint8_t> digestArray;
|
||||
nsresult nsrv =
|
||||
Digest::DigestBuf(SEC_OID_SHA256, derPublicKey.UnsafeGetData(),
|
||||
derPublicKey.GetLength(), digestArray);
|
||||
if (NS_FAILED(nsrv)) {
|
||||
return nsrv;
|
||||
}
|
||||
return Base64Encode(nsDependentCSubstring(
|
||||
BitwiseCast<char*, unsigned char*>(digest.get().data),
|
||||
digest.get().len),
|
||||
BitwiseCast<char*, uint8_t*>(digestArray.Elements()),
|
||||
digestArray.Length()),
|
||||
hashSPKIDigest);
|
||||
}
|
||||
|
||||
|
|
|
@ -47,10 +47,10 @@ class BinaryHashSearchArrayComparator {
|
|||
// storage (Enterprise Root).
|
||||
// See also the constants in RootCertificateTelemetryUtils.h.
|
||||
int32_t RootCABinNumber(Span<const uint8_t> cert) {
|
||||
Digest digest;
|
||||
nsTArray<uint8_t> digestArray;
|
||||
|
||||
// Compute SHA256 hash of the certificate
|
||||
nsresult rv = digest.DigestBuf(SEC_OID_SHA256, cert.data(), cert.size());
|
||||
nsresult rv = Digest::DigestBuf(SEC_OID_SHA256, cert, digestArray);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return ROOT_CERTIFICATE_HASH_FAILURE;
|
||||
}
|
||||
|
@ -58,16 +58,15 @@ int32_t RootCABinNumber(Span<const uint8_t> cert) {
|
|||
// Compare against list of stored hashes
|
||||
size_t idx;
|
||||
|
||||
MOZ_LOG(
|
||||
gPublicKeyPinningTelemetryLog, LogLevel::Debug,
|
||||
("pkpinTelem: First bytes %02x %02x %02x %02x\n", digest.get().data[0],
|
||||
digest.get().data[1], digest.get().data[2], digest.get().data[3]));
|
||||
MOZ_LOG(gPublicKeyPinningTelemetryLog, LogLevel::Debug,
|
||||
("pkpinTelem: First bytes %02x %02x %02x %02x\n",
|
||||
digestArray.ElementAt(0), digestArray.ElementAt(1),
|
||||
digestArray.ElementAt(2), digestArray.ElementAt(3)));
|
||||
|
||||
if (mozilla::BinarySearchIf(
|
||||
ROOT_TABLE, 0, ArrayLength(ROOT_TABLE),
|
||||
BinaryHashSearchArrayComparator(
|
||||
static_cast<uint8_t*>(digest.get().data), digest.get().len),
|
||||
&idx)) {
|
||||
if (mozilla::BinarySearchIf(ROOT_TABLE, 0, ArrayLength(ROOT_TABLE),
|
||||
BinaryHashSearchArrayComparator(
|
||||
digestArray.Elements(), digestArray.Length()),
|
||||
&idx)) {
|
||||
MOZ_LOG(gPublicKeyPinningTelemetryLog, LogLevel::Debug,
|
||||
("pkpinTelem: Telemetry index was %zu, bin is %d\n", idx,
|
||||
ROOT_TABLE[idx].binNumber));
|
||||
|
|
|
@ -86,57 +86,96 @@ MOZ_TYPE_SPECIFIC_UNIQUE_PTR_TEMPLATE(UniquePK11Context, PK11Context,
|
|||
* Typical usage, for digesting a buffer in memory:
|
||||
*
|
||||
* nsCOMPtr<nsISupports> nssDummy = do_GetService("@mozilla.org/psm;1", &rv);
|
||||
* Digest digest;
|
||||
* nsresult rv = digest.DigestBuf(SEC_OID_SHA256, mybuffer, myBufferLen);
|
||||
* nsTArray<uint8_t> digestArray;
|
||||
* nsresult rv = Digest::DigestBuf(SEC_OID_SHA256, mybuffer, myBufferLen,
|
||||
* digestArray);
|
||||
* NS_ENSURE_SUCCESS(rv, rv);
|
||||
* rv = MapSECStatus(SomeNSSFunction(..., digest.get(), ...));
|
||||
*
|
||||
* Less typical usage, for digesting while doing streaming I/O and similar:
|
||||
*
|
||||
* Digest digest;
|
||||
* UniquePK11Context digestContext(PK11_CreateDigestContext(SEC_OID_SHA256));
|
||||
* NS_ENSURE_TRUE(digestContext, NS_ERROR_OUT_OF_MEMORY);
|
||||
* rv = MapSECStatus(PK11_DigestBegin(digestContext.get()));
|
||||
* nsresult rv = digest.Begin(SEC_OID_SHA256);
|
||||
* NS_ENSURE_SUCCESS(rv, rv);
|
||||
* for (...) {
|
||||
* rv = MapSECStatus(PK11_DigestOp(digestContext.get(), ...));
|
||||
* rv = digest.Update(buf, len);
|
||||
* NS_ENSURE_SUCCESS(rv, rv);
|
||||
* }
|
||||
* rv = digest.End(SEC_OID_SHA256, digestContext);
|
||||
* nsTArray<uint8_t> digestArray;
|
||||
* rv = digest.End(digestArray);
|
||||
* NS_ENSURE_SUCCESS(rv, rv)
|
||||
*/
|
||||
class Digest {
|
||||
public:
|
||||
Digest() : mItemBuf() {
|
||||
mItem.type = siBuffer;
|
||||
mItem.data = mItemBuf;
|
||||
mItem.len = 0;
|
||||
explicit Digest() : mLen(0), mDigestContext(nullptr) {}
|
||||
|
||||
static nsresult DigestBuf(SECOidTag hashAlg, Span<const uint8_t> buf,
|
||||
/*out*/ nsTArray<uint8_t>& out) {
|
||||
return Digest::DigestBuf(hashAlg, buf.Elements(), buf.Length(), out);
|
||||
}
|
||||
|
||||
nsresult DigestBuf(SECOidTag hashAlg, const uint8_t* buf, uint32_t len) {
|
||||
if (len > static_cast<uint32_t>(std::numeric_limits<int32_t>::max())) {
|
||||
static nsresult DigestBuf(SECOidTag hashAlg, const uint8_t* buf, uint32_t len,
|
||||
/*out*/ nsTArray<uint8_t>& out) {
|
||||
Digest digest;
|
||||
|
||||
nsresult rv = digest.Begin(hashAlg);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = digest.Update(buf, len);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = digest.End(out);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult Begin(SECOidTag hashAlg) {
|
||||
if (hashAlg != SEC_OID_SHA1 && hashAlg != SEC_OID_SHA256) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
mDigestContext = UniquePK11Context(PK11_CreateDigestContext(hashAlg));
|
||||
if (!mDigestContext) {
|
||||
return mozilla::psm::GetXPCOMFromNSSError(PR_GetError());
|
||||
}
|
||||
|
||||
nsresult rv = SetLength(hashAlg);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return MapSECStatus(
|
||||
PK11_HashBuf(hashAlg, mItem.data, buf, static_cast<int32_t>(len)));
|
||||
return MapSECStatus(PK11_DigestBegin(mDigestContext.get()));
|
||||
}
|
||||
|
||||
nsresult End(SECOidTag hashAlg, UniquePK11Context& context) {
|
||||
nsresult rv = SetLength(hashAlg);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsresult Update(Span<const uint8_t> in) {
|
||||
return Update(in.Elements(), in.Length());
|
||||
}
|
||||
|
||||
nsresult Update(const unsigned char* buf, const uint32_t len) {
|
||||
if (!mDigestContext) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
return MapSECStatus(PK11_DigestOp(mDigestContext.get(), buf, len));
|
||||
}
|
||||
|
||||
nsresult End(/*out*/ nsTArray<uint8_t>& out) {
|
||||
if (!mDigestContext) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
out.SetLength(mLen);
|
||||
uint32_t len;
|
||||
rv = MapSECStatus(
|
||||
PK11_DigestFinal(context.get(), mItem.data, &len, mItem.len));
|
||||
nsresult rv = MapSECStatus(
|
||||
PK11_DigestFinal(mDigestContext.get(), out.Elements(), &len, mLen));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
context = nullptr;
|
||||
NS_ENSURE_TRUE(len == mItem.len, NS_ERROR_UNEXPECTED);
|
||||
mDigestContext = nullptr;
|
||||
NS_ENSURE_TRUE(len == mLen, NS_ERROR_UNEXPECTED);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
const SECItem& get() const { return mItem; }
|
||||
|
||||
private:
|
||||
nsresult SetLength(SECOidTag hashType) {
|
||||
#ifdef _MSC_VER
|
||||
|
@ -147,16 +186,10 @@ class Digest {
|
|||
#endif
|
||||
switch (hashType) {
|
||||
case SEC_OID_SHA1:
|
||||
mItem.len = SHA1_LENGTH;
|
||||
mLen = SHA1_LENGTH;
|
||||
break;
|
||||
case SEC_OID_SHA256:
|
||||
mItem.len = SHA256_LENGTH;
|
||||
break;
|
||||
case SEC_OID_SHA384:
|
||||
mItem.len = SHA384_LENGTH;
|
||||
break;
|
||||
case SEC_OID_SHA512:
|
||||
mItem.len = SHA512_LENGTH;
|
||||
mLen = SHA256_LENGTH;
|
||||
break;
|
||||
default:
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
@ -168,8 +201,8 @@ class Digest {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
uint8_t mItemBuf[HASH_LENGTH_MAX];
|
||||
SECItem mItem;
|
||||
uint8_t mLen;
|
||||
UniquePK11Context mDigestContext;
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
|
|
@ -101,12 +101,15 @@ void LossyUTF8ToUTF16(const char* str, uint32_t len,
|
|||
|
||||
nsresult GetCertFingerprintByOidTag(CERTCertificate* nsscert, SECOidTag aOidTag,
|
||||
nsCString& fp) {
|
||||
Digest digest;
|
||||
nsresult rv =
|
||||
digest.DigestBuf(aOidTag, nsscert->derCert.data, nsscert->derCert.len);
|
||||
nsTArray<uint8_t> digestArray;
|
||||
nsresult rv = Digest::DigestBuf(aOidTag, nsscert->derCert.data,
|
||||
nsscert->derCert.len, digestArray);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
UniquePORTString tmpstr(CERT_Hexify(const_cast<SECItem*>(&digest.get()), 1));
|
||||
SECItem digestItem = {siBuffer, digestArray.Elements(),
|
||||
static_cast<unsigned int>(digestArray.Length())};
|
||||
|
||||
UniquePORTString tmpstr(CERT_Hexify(&digestItem, 1));
|
||||
NS_ENSURE_TRUE(tmpstr, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
fp.Assign(tmpstr.get());
|
||||
|
|
|
@ -581,15 +581,17 @@ nsNSSCertificate::GetSerialNumber(nsAString& _serialNumber) {
|
|||
nsresult nsNSSCertificate::GetCertificateHash(nsAString& aFingerprint,
|
||||
SECOidTag aHashAlg) {
|
||||
aFingerprint.Truncate();
|
||||
Digest digest;
|
||||
nsresult rv =
|
||||
digest.DigestBuf(aHashAlg, mCert->derCert.data, mCert->derCert.len);
|
||||
nsTArray<uint8_t> digestArray;
|
||||
nsresult rv = Digest::DigestBuf(aHashAlg, mCert->derCert.data,
|
||||
mCert->derCert.len, digestArray);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
SECItem digestItem = {siBuffer, digestArray.Elements(),
|
||||
static_cast<unsigned int>(digestArray.Length())};
|
||||
|
||||
UniquePORTString fpStr(CERT_Hexify(const_cast<SECItem*>(&digest.get()),
|
||||
true /* use colon delimiters */));
|
||||
UniquePORTString fpStr(
|
||||
CERT_Hexify(&digestItem, true /* use colon delimiters */));
|
||||
if (!fpStr) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -647,15 +649,15 @@ nsNSSCertificate::GetSha256SubjectPublicKeyInfoDigest(
|
|||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
pkix::Input derPublicKey = cert.GetSubjectPublicKeyInfo();
|
||||
Digest digest;
|
||||
nsresult rv = digest.DigestBuf(SEC_OID_SHA256, derPublicKey.UnsafeGetData(),
|
||||
derPublicKey.GetLength());
|
||||
nsTArray<uint8_t> digestArray;
|
||||
nsresult rv = Digest::DigestBuf(SEC_OID_SHA256, derPublicKey.UnsafeGetData(),
|
||||
derPublicKey.GetLength(), digestArray);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
rv = Base64Encode(nsDependentCSubstring(
|
||||
BitwiseCast<char*, unsigned char*>(digest.get().data),
|
||||
digest.get().len),
|
||||
BitwiseCast<char*, uint8_t*>(digestArray.Elements()),
|
||||
digestArray.Length()),
|
||||
aSha256SPKIDigest);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
|
|
|
@ -2563,18 +2563,20 @@ nsNSSComponent::IsCertContentSigningRoot(const nsTArray<uint8_t>& cert,
|
|||
bool* result) {
|
||||
NS_ENSURE_ARG_POINTER(result);
|
||||
*result = false;
|
||||
|
||||
if (cert.Length() > std::numeric_limits<uint32_t>::max()) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
Digest digest;
|
||||
nsresult rv =
|
||||
digest.DigestBuf(SEC_OID_SHA256, cert.Elements(), cert.Length());
|
||||
nsTArray<uint8_t> digestArray;
|
||||
nsresult rv = Digest::DigestBuf(SEC_OID_SHA256, cert.Elements(),
|
||||
cert.Length(), digestArray);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
UniquePORTString fingerprintCString(CERT_Hexify(
|
||||
const_cast<SECItem*>(&digest.get()), true /* use colon delimiters */));
|
||||
SECItem digestItem = {siBuffer, digestArray.Elements(),
|
||||
static_cast<unsigned int>(digestArray.Length())};
|
||||
|
||||
UniquePORTString fingerprintCString(
|
||||
CERT_Hexify(&digestItem, true /* use colon delimiters */));
|
||||
if (!fingerprintCString) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче