--- a/security/manager/ssl/nsCryptoHash.cpp
+++ b/security/manager/ssl/nsCryptoHash.cpp
@@ -1,28 +1,34 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 "nsCryptoHash.h"
+
#include <algorithm>
-#include "nsCryptoHash.h"
-
+#include "base64.h"
+#include "mozilla/ArrayUtils.h"
+#include "mozilla/Casting.h"
#include "nsIInputStream.h"
#include "nsIKeyModule.h"
-
#include "nsString.h"
-
+#include "pk11pub.h"
#include "sechash.h"
-#include "pk11pub.h"
-#include "base64.h"
+
+using namespace mozilla;
-#define NS_CRYPTO_HASH_BUFFER_SIZE 4096
+namespace {
+
+static const uint64_t STREAM_BUFFER_SIZE = 4096;
+
+} // namespace
//---------------------------------------------
// Implementing nsICryptoHash
//---------------------------------------------
nsCryptoHash::nsCryptoHash()
: mHashContext(nullptr)
, mInitialized(false)
@@ -56,17 +62,34 @@ NS_IMPL_ISUPPORTS(nsCryptoHash, nsICrypt
NS_IMETHODIMP
nsCryptoHash::Init(uint32_t algorithm)
{
nsNSSShutDownPreventionLock locker;
if (isAlreadyShutDown()) {
return NS_ERROR_NOT_AVAILABLE;
}
- HASH_HashType hashType = (HASH_HashType)algorithm;
+ HASH_HashType hashType;
+ switch (algorithm) {
+ case nsICryptoHash::MD2:
+ hashType = HASH_AlgMD2; break;
+ case nsICryptoHash::MD5:
+ hashType = HASH_AlgMD5; break;
+ case nsICryptoHash::SHA1:
+ hashType = HASH_AlgSHA1; break;
+ case nsICryptoHash::SHA256:
+ hashType = HASH_AlgSHA256; break;
+ case nsICryptoHash::SHA384:
+ hashType = HASH_AlgSHA384; break;
+ case nsICryptoHash::SHA512:
+ hashType = HASH_AlgSHA512; break;
+ default:
+ return NS_ERROR_INVALID_ARG;
+ }
+
if (mHashContext) {
if (!mInitialized && HASH_GetType(mHashContext.get()) == hashType) {
mInitialized = true;
HASH_Begin(mHashContext.get());
return NS_OK;
}
// Destroy current hash context if the type was different
@@ -83,21 +106,16 @@ nsCryptoHash::Init(uint32_t algorithm)
HASH_Begin(mHashContext.get());
mInitialized = true;
return NS_OK;
}
NS_IMETHODIMP
nsCryptoHash::InitWithString(const nsACString & aAlgorithm)
{
- nsNSSShutDownPreventionLock locker;
- if (isAlreadyShutDown()) {
- return NS_ERROR_NOT_AVAILABLE;
- }
-
if (aAlgorithm.LowerCaseEqualsLiteral("md2"))
return Init(nsICryptoHash::MD2);
if (aAlgorithm.LowerCaseEqualsLiteral("md5"))
return Init(nsICryptoHash::MD5);
if (aAlgorithm.LowerCaseEqualsLiteral("sha1"))
return Init(nsICryptoHash::SHA1);
@@ -158,53 +176,55 @@ nsCryptoHash::UpdateFromStream(nsIInputS
// So, if the stream has NO data available for the hash,
// or if the data available is less then what the caller
// requested, we can not fulfill the hash update. In this
// case, just return NS_ERROR_NOT_AVAILABLE indicating
// that there is not enough data in the stream to satisify
// the request.
- if (n == 0 || n < len)
+ if (n == 0 || n < len) {
return NS_ERROR_NOT_AVAILABLE;
-
- char buffer[NS_CRYPTO_HASH_BUFFER_SIZE];
- uint32_t read, readLimit;
-
- while(NS_SUCCEEDED(rv) && len>0)
- {
- readLimit = (uint32_t)std::min<uint64_t>(NS_CRYPTO_HASH_BUFFER_SIZE, len);
-
- rv = data->Read(buffer, readLimit, &read);
-
- if (NS_SUCCEEDED(rv))
- rv = Update((const uint8_t*)buffer, read);
-
+ }
+
+ char buffer[STREAM_BUFFER_SIZE];
+ while (len > 0) {
+ uint64_t readLimit = std::min<uint64_t>(STREAM_BUFFER_SIZE, len);
+ uint32_t read;
+ rv = data->Read(buffer, AssertedCast<uint32_t>(readLimit), &read);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ rv = Update(BitwiseCast<uint8_t*>(buffer), read);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
len -= read;
}
-
- return rv;
+
+ return NS_OK;
}
NS_IMETHODIMP
nsCryptoHash::Finish(bool ascii, nsACString & _retval)
{
nsNSSShutDownPreventionLock locker;
if (isAlreadyShutDown()) {
return NS_ERROR_NOT_AVAILABLE;
}
-
- if (!mInitialized)
+
+ if (!mInitialized) {
return NS_ERROR_NOT_INITIALIZED;
-
+ }
+
uint32_t hashLen = 0;
unsigned char buffer[HASH_LENGTH_MAX];
- unsigned char* pbuffer = buffer;
-
- HASH_End(mHashContext.get(), pbuffer, &hashLen, HASH_LENGTH_MAX);
+ HASH_End(mHashContext.get(), buffer, &hashLen, HASH_LENGTH_MAX);
mInitialized = false;
if (ascii)
{
UniquePORTString asciiData(BTOA_DataToAscii(buffer, hashLen));
NS_ENSURE_TRUE(asciiData, NS_ERROR_OUT_OF_MEMORY);
@@ -359,53 +379,60 @@ nsCryptoHMAC::UpdateFromStream(nsIInputS
// or if the data available is less then what the caller
// requested, we can not fulfill the HMAC update. In this
// case, just return NS_ERROR_NOT_AVAILABLE indicating
// that there is not enough data in the stream to satisify
// the request.
if (n == 0 || n < len)
return NS_ERROR_NOT_AVAILABLE;
-
- char buffer[NS_CRYPTO_HASH_BUFFER_SIZE];
- uint32_t read, readLimit;
-
- while(NS_SUCCEEDED(rv) && len > 0)
- {
- readLimit = (uint32_t)std::min<uint64_t>(NS_CRYPTO_HASH_BUFFER_SIZE, len);
-
- rv = aStream->Read(buffer, readLimit, &read);
- if (read == 0)
+
+ char buffer[STREAM_BUFFER_SIZE];
+ while (len > 0) {
+ uint64_t readLimit = std::min<uint64_t>(STREAM_BUFFER_SIZE, len);
+ uint32_t read;
+ rv = aStream->Read(buffer, AssertedCast<uint32_t>(readLimit), &read);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ if (read == 0) {
return NS_BASE_STREAM_CLOSED;
-
- if (NS_SUCCEEDED(rv))
- rv = Update((const uint8_t*)buffer, read);
-
+ }
+
+ rv = Update(BitwiseCast<uint8_t*>(buffer), read);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
len -= read;
}
-
- return rv;
+
+ return NS_OK;
}
NS_IMETHODIMP
nsCryptoHMAC::Finish(bool aASCII, nsACString & _retval)
{
nsNSSShutDownPreventionLock locker;
if (isAlreadyShutDown()) {
return NS_ERROR_NOT_AVAILABLE;
}
if (!mHMACContext)
return NS_ERROR_NOT_INITIALIZED;
uint32_t hashLen = 0;
unsigned char buffer[HASH_LENGTH_MAX];
- unsigned char* pbuffer = buffer;
+ SECStatus srv = PK11_DigestFinal(mHMACContext.get(), buffer, &hashLen,
+ HASH_LENGTH_MAX);
+ if (srv != SECSuccess) {
+ return NS_ERROR_FAILURE;
+ }
- PK11_DigestFinal(mHMACContext.get(), pbuffer, &hashLen, HASH_LENGTH_MAX);
if (aASCII)
{
UniquePORTString asciiData(BTOA_DataToAscii(buffer, hashLen));
NS_ENSURE_TRUE(asciiData, NS_ERROR_OUT_OF_MEMORY);
_retval.Assign(asciiData.get());
}
else