1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
8 #include "base/stl_util.h"
9 #include "content/child/webcrypto/algorithm_implementation.h"
10 #include "content/child/webcrypto/crypto_data.h"
11 #include "content/child/webcrypto/nss/util_nss.h"
12 #include "content/child/webcrypto/status.h"
13 #include "content/child/webcrypto/webcrypto_util.h"
14 #include "crypto/nss_util.h"
15 #include "crypto/scoped_nss_types.h"
23 HASH_HashType
WebCryptoAlgorithmToNSSHashType(
24 blink::WebCryptoAlgorithmId algorithm
) {
26 case blink::WebCryptoAlgorithmIdSha1
:
28 case blink::WebCryptoAlgorithmIdSha256
:
29 return HASH_AlgSHA256
;
30 case blink::WebCryptoAlgorithmIdSha384
:
31 return HASH_AlgSHA384
;
32 case blink::WebCryptoAlgorithmIdSha512
:
33 return HASH_AlgSHA512
;
35 // Not a digest algorithm.
40 // Implementation of blink::WebCryptoDigester, an internal Blink detail not
41 // part of WebCrypto, that allows chunks of data to be streamed in before
42 // computing a SHA-* digest (as opposed to ShaImplementation, which computes
43 // digests over complete messages)
44 class DigestorNSS
: public blink::WebCryptoDigestor
{
46 explicit DigestorNSS(blink::WebCryptoAlgorithmId algorithm_id
)
47 : hash_context_(NULL
), algorithm_id_(algorithm_id
) {}
49 ~DigestorNSS() override
{
53 HASH_Destroy(hash_context_
);
57 bool consume(const unsigned char* data
, unsigned int size
) override
{
58 return ConsumeWithStatus(data
, size
).IsSuccess();
61 Status
ConsumeWithStatus(const unsigned char* data
, unsigned int size
) {
62 // Initialize everything if the object hasn't been initialized yet.
64 Status error
= Init();
65 if (!error
.IsSuccess())
69 HASH_Update(hash_context_
, data
, size
);
71 return Status::Success();
74 bool finish(unsigned char*& result_data
,
75 unsigned int& result_data_size
) override
{
76 Status error
= FinishInternal(result_
, &result_data_size
);
77 if (!error
.IsSuccess())
79 result_data
= result_
;
83 Status
FinishWithVectorAndStatus(std::vector
<uint8_t>* result
) {
85 return Status::ErrorUnexpected();
87 unsigned int result_length
= HASH_ResultLenContext(hash_context_
);
88 result
->resize(result_length
);
89 unsigned char* digest
= vector_as_array(result
);
90 unsigned int digest_size
; // ignored
91 return FinishInternal(digest
, &digest_size
);
96 HASH_HashType hash_type
= WebCryptoAlgorithmToNSSHashType(algorithm_id_
);
98 if (hash_type
== HASH_AlgNULL
)
99 return Status::ErrorUnsupported();
101 hash_context_
= HASH_Create(hash_type
);
103 return Status::OperationError();
105 HASH_Begin(hash_context_
);
107 return Status::Success();
110 Status
FinishInternal(unsigned char* result
, unsigned int* result_size
) {
111 if (!hash_context_
) {
112 Status error
= Init();
113 if (!error
.IsSuccess())
117 unsigned int hash_result_length
= HASH_ResultLenContext(hash_context_
);
118 DCHECK_LE(hash_result_length
, static_cast<size_t>(HASH_LENGTH_MAX
));
120 HASH_End(hash_context_
, result
, result_size
, hash_result_length
);
122 if (*result_size
!= hash_result_length
)
123 return Status::ErrorUnexpected();
124 return Status::Success();
127 HASHContext
* hash_context_
;
128 blink::WebCryptoAlgorithmId algorithm_id_
;
129 unsigned char result_
[HASH_LENGTH_MAX
];
132 class ShaImplementation
: public AlgorithmImplementation
{
134 Status
Digest(const blink::WebCryptoAlgorithm
& algorithm
,
135 const CryptoData
& data
,
136 std::vector
<uint8_t>* buffer
) const override
{
137 DigestorNSS
digestor(algorithm
.id());
138 Status error
= digestor
.ConsumeWithStatus(data
.bytes(), data
.byte_length());
139 // http://crbug.com/366427: the spec does not define any other failures for
140 // digest, so none of the subsequent errors are spec compliant.
141 if (!error
.IsSuccess())
143 return digestor
.FinishWithVectorAndStatus(buffer
);
149 AlgorithmImplementation
* CreatePlatformShaImplementation() {
150 return new ShaImplementation();
153 scoped_ptr
<blink::WebCryptoDigestor
> CreatePlatformDigestor(
154 blink::WebCryptoAlgorithmId algorithm
) {
155 return scoped_ptr
<blink::WebCryptoDigestor
>(new DigestorNSS(algorithm
));
158 } // namespace webcrypto
160 } // namespace content