Index: content/child/webcrypto/platform_crypto_nss.cc |
diff --git a/content/child/webcrypto/platform_crypto_nss.cc b/content/child/webcrypto/platform_crypto_nss.cc |
index 75a73d8b3d06d086e9dc3726f2598e6a1aa4af2c..8799376582813efa6ddad6ffeb7482cf53fdf23b 100644 |
--- a/content/child/webcrypto/platform_crypto_nss.cc |
+++ b/content/child/webcrypto/platform_crypto_nss.cc |
@@ -13,6 +13,7 @@ |
#include "base/lazy_instance.h" |
#include "base/logging.h" |
+#include "base/memory/scoped_ptr.h" |
#include "content/child/webcrypto/crypto_data.h" |
#include "content/child/webcrypto/status.h" |
#include "content/child/webcrypto/webcrypto_util.h" |
@@ -663,6 +664,94 @@ struct FreeRsaPrivateKey { |
} // namespace |
+class DigestorNSS : public blink::WebCryptoDigestor { |
+ public: |
+ explicit DigestorNSS(blink::WebCryptoAlgorithmId algorithm_id) |
+ : hash_context_(NULL), algorithm_id_(algorithm_id) {} |
+ |
+ virtual ~DigestorNSS() { |
+ if (!hash_context_) |
+ return; |
+ |
+ HASH_Destroy(hash_context_); |
+ hash_context_ = NULL; |
+ } |
+ |
+ virtual bool consume(const unsigned char* data, unsigned int size) { |
+ return ConsumeWithStatus(data, size).IsSuccess(); |
+ } |
+ |
+ Status ConsumeWithStatus(const unsigned char* data, unsigned int size) { |
+ // Initialize everything if the object hasn't been initialized yet. |
+ if (!hash_context_) { |
+ Status error = Init(); |
+ if (!error.IsSuccess()) |
+ return error; |
+ } |
+ |
+ HASH_Update(hash_context_, data, size); |
+ |
+ return Status::Success(); |
+ } |
+ |
+ virtual bool finish(unsigned char*& result_data, |
+ unsigned int& result_data_size) { |
+ Status error = FinishInternal(result_, &result_data_size); |
+ if (!error.IsSuccess()) |
+ return false; |
+ result_data = result_; |
+ return true; |
+ } |
+ |
+ Status FinishWithWebArrayAndStatus(blink::WebArrayBuffer* result) { |
+ if (!hash_context_) |
+ return Status::ErrorUnexpected(); |
+ |
+ unsigned int result_length = HASH_ResultLenContext(hash_context_); |
+ *result = blink::WebArrayBuffer::create(result_length, 1); |
+ unsigned char* digest = reinterpret_cast<unsigned char*>(result->data()); |
+ unsigned int digest_size; // ignored |
+ return FinishInternal(digest, &digest_size); |
+ } |
+ |
+ private: |
+ Status Init() { |
+ HASH_HashType hash_type = WebCryptoAlgorithmToNSSHashType(algorithm_id_); |
+ |
+ if (hash_type == HASH_AlgNULL) |
+ return Status::ErrorUnsupported(); |
+ |
+ hash_context_ = HASH_Create(hash_type); |
+ if (!hash_context_) |
+ return Status::Error(); |
+ |
+ HASH_Begin(hash_context_); |
+ |
+ return Status::Success(); |
+ } |
+ |
+ Status FinishInternal(unsigned char* result, unsigned int* result_size) { |
+ if (!hash_context_) { |
+ Status error = Init(); |
+ if (!error.IsSuccess()) |
+ return error; |
+ } |
+ |
+ unsigned int hash_result_length = HASH_ResultLenContext(hash_context_); |
+ DCHECK_LE(hash_result_length, static_cast<size_t>(HASH_LENGTH_MAX)); |
+ |
+ HASH_End(hash_context_, result, result_size, hash_result_length); |
+ |
+ if (*result_size != hash_result_length) |
+ return Status::ErrorUnexpected(); |
+ return Status::Success(); |
+ } |
+ |
+ HASHContext* hash_context_; |
+ blink::WebCryptoAlgorithmId algorithm_id_; |
+ unsigned char result_[HASH_LENGTH_MAX]; |
+}; |
+ |
Status ImportKeyRaw(const blink::WebCryptoAlgorithm& algorithm, |
const CryptoData& key_data, |
bool extractable, |
@@ -1210,33 +1299,16 @@ void Init() { crypto::EnsureNSSInit(); } |
Status DigestSha(blink::WebCryptoAlgorithmId algorithm, |
const CryptoData& data, |
blink::WebArrayBuffer* buffer) { |
- HASH_HashType hash_type = WebCryptoAlgorithmToNSSHashType(algorithm); |
- if (hash_type == HASH_AlgNULL) |
- return Status::ErrorUnsupported(); |
- |
- HASHContext* context = HASH_Create(hash_type); |
- if (!context) |
- return Status::Error(); |
- |
- HASH_Begin(context); |
- |
- HASH_Update(context, data.bytes(), data.byte_length()); |
- |
- unsigned int hash_result_length = HASH_ResultLenContext(context); |
- DCHECK_LE(hash_result_length, static_cast<size_t>(HASH_LENGTH_MAX)); |
- |
- *buffer = blink::WebArrayBuffer::create(hash_result_length, 1); |
- |
- unsigned char* digest = reinterpret_cast<unsigned char*>(buffer->data()); |
- |
- unsigned int result_length = 0; |
- HASH_End(context, digest, &result_length, hash_result_length); |
- |
- HASH_Destroy(context); |
+ DigestorNSS digestor(algorithm); |
+ Status error = digestor.ConsumeWithStatus(data.bytes(), data.byte_length()); |
+ if (!error.IsSuccess()) |
+ return error; |
+ return digestor.FinishWithWebArrayAndStatus(buffer); |
+} |
- if (result_length != hash_result_length) |
- return Status::ErrorUnexpected(); |
- return Status::Success(); |
+scoped_ptr<blink::WebCryptoDigestor> CreateDigestor( |
+ blink::WebCryptoAlgorithmId algorithm_id) { |
+ return scoped_ptr<blink::WebCryptoDigestor>(new DigestorNSS(algorithm_id)); |
} |
Status GenerateSecretKey(const blink::WebCryptoAlgorithm& algorithm, |