1 // Copyright 2024 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "crypto/hash.h"
6
7 #include "base/notreached.h"
8 #include "third_party/boringssl/src/include/openssl/digest.h"
9 #include "third_party/boringssl/src/include/openssl/evp.h"
10
11 namespace crypto::hash {
12
13 namespace {
14
EVPMDForHashKind(HashKind kind)15 const EVP_MD* EVPMDForHashKind(HashKind kind) {
16 switch (kind) {
17 case HashKind::kSha1:
18 return EVP_sha1();
19 case HashKind::kSha256:
20 return EVP_sha256();
21 case HashKind::kSha512:
22 return EVP_sha512();
23 }
24 NOTREACHED();
25 }
26
27 } // namespace
28
Hash(HashKind kind,base::span<const uint8_t> data,base::span<uint8_t> digest)29 void Hash(HashKind kind,
30 base::span<const uint8_t> data,
31 base::span<uint8_t> digest) {
32 const EVP_MD* md = EVPMDForHashKind(kind);
33 CHECK_EQ(digest.size(), EVP_MD_size(md));
34
35 CHECK(EVP_Digest(data.data(), data.size(), digest.data(), nullptr, md,
36 nullptr));
37 }
38
Sha1(base::span<const uint8_t> data)39 std::array<uint8_t, kSha1Size> Sha1(base::span<const uint8_t> data) {
40 std::array<uint8_t, kSha1Size> result;
41 Hash(HashKind::kSha1, data, result);
42 return result;
43 }
44
Sha256(base::span<const uint8_t> data)45 std::array<uint8_t, kSha256Size> Sha256(base::span<const uint8_t> data) {
46 std::array<uint8_t, kSha256Size> result;
47 Hash(HashKind::kSha256, data, result);
48 return result;
49 }
50
Sha512(base::span<const uint8_t> data)51 std::array<uint8_t, kSha512Size> Sha512(base::span<const uint8_t> data) {
52 std::array<uint8_t, kSha512Size> result;
53 Hash(HashKind::kSha512, data, result);
54 return result;
55 }
56
Hasher(HashKind kind)57 Hasher::Hasher(HashKind kind) {
58 CHECK(EVP_DigestInit(ctx_.get(), EVPMDForHashKind(kind)));
59 }
60
Hasher(const Hasher & other)61 Hasher::Hasher(const Hasher& other) {
62 *this = other;
63 }
64
Hasher(Hasher && other)65 Hasher::Hasher(Hasher&& other) {
66 *this = other;
67 }
68
operator =(const Hasher & other)69 Hasher& Hasher::operator=(const Hasher& other) {
70 CHECK(EVP_MD_CTX_copy_ex(ctx_.get(), other.ctx_.get()));
71 return *this;
72 }
73
operator =(Hasher && other)74 Hasher& Hasher::operator=(Hasher&& other) {
75 ctx_ = std::move(other.ctx_);
76 return *this;
77 }
78
79 Hasher::~Hasher() = default;
80
Update(base::span<const uint8_t> data)81 void Hasher::Update(base::span<const uint8_t> data) {
82 CHECK(EVP_DigestUpdate(ctx_.get(), data.data(), data.size()));
83 }
84
Finish(base::span<uint8_t> digest)85 void Hasher::Finish(base::span<uint8_t> digest) {
86 CHECK_EQ(digest.size(), EVP_MD_CTX_size(ctx_.get()));
87 CHECK(EVP_DigestFinal(ctx_.get(), digest.data(), nullptr));
88 }
89
90 } // namespace crypto::hash
91