| 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,
|
|
|