1 // Copyright 2012 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 "net/base/hash_value.h"
6
7 #include <stdlib.h>
8
9 #include <algorithm>
10 #include <ostream>
11
12 #include "base/base64.h"
13 #include "base/check_op.h"
14 #include "base/notreached.h"
15 #include "base/strings/string_split.h"
16 #include "base/strings/string_util.h"
17 #include "crypto/sha2.h"
18
19 namespace net {
20
21 namespace {
22
23 // LessThan comparator for use with std::binary_search() in determining
24 // whether a SHA-256 HashValue appears within a sorted array of
25 // SHA256HashValues.
26 struct SHA256ToHashValueComparator {
operator ()net::__anon3e26efa40111::SHA256ToHashValueComparator27 bool operator()(const SHA256HashValue& lhs, const HashValue& rhs) const {
28 DCHECK_EQ(HASH_VALUE_SHA256, rhs.tag());
29 return memcmp(lhs.data, rhs.data(), rhs.size()) < 0;
30 }
31
operator ()net::__anon3e26efa40111::SHA256ToHashValueComparator32 bool operator()(const HashValue& lhs, const SHA256HashValue& rhs) const {
33 DCHECK_EQ(HASH_VALUE_SHA256, lhs.tag());
34 return memcmp(lhs.data(), rhs.data, lhs.size()) < 0;
35 }
36 };
37
38 } // namespace
39
40
HashValue(const SHA256HashValue & hash)41 HashValue::HashValue(const SHA256HashValue& hash)
42 : HashValue(HASH_VALUE_SHA256) {
43 fingerprint.sha256 = hash;
44 }
45
FromString(const base::StringPiece value)46 bool HashValue::FromString(const base::StringPiece value) {
47 base::StringPiece base64_str;
48 if (base::StartsWith(value, "sha256/")) {
49 tag_ = HASH_VALUE_SHA256;
50 base64_str = value.substr(7);
51 } else {
52 return false;
53 }
54
55 std::string decoded;
56 if (!base::Base64Decode(base64_str, &decoded) || decoded.size() != size())
57 return false;
58
59 memcpy(data(), decoded.data(), size());
60 return true;
61 }
62
ToString() const63 std::string HashValue::ToString() const {
64 std::string base64_str;
65 base::Base64Encode(base::StringPiece(reinterpret_cast<const char*>(data()),
66 size()), &base64_str);
67 switch (tag_) {
68 case HASH_VALUE_SHA256:
69 return std::string("sha256/") + base64_str;
70 }
71
72 NOTREACHED() << "Unknown HashValueTag " << tag_;
73 return std::string("unknown/" + base64_str);
74 }
75
size() const76 size_t HashValue::size() const {
77 switch (tag_) {
78 case HASH_VALUE_SHA256:
79 return sizeof(fingerprint.sha256.data);
80 }
81
82 NOTREACHED() << "Unknown HashValueTag " << tag_;
83 // While an invalid tag should not happen, return a non-zero length
84 // to avoid compiler warnings when the result of size() is
85 // used with functions like memset.
86 return sizeof(fingerprint.sha256.data);
87 }
88
data()89 unsigned char* HashValue::data() {
90 return const_cast<unsigned char*>(const_cast<const HashValue*>(this)->data());
91 }
92
data() const93 const unsigned char* HashValue::data() const {
94 switch (tag_) {
95 case HASH_VALUE_SHA256:
96 return fingerprint.sha256.data;
97 }
98
99 NOTREACHED() << "Unknown HashValueTag " << tag_;
100 return nullptr;
101 }
102
operator ==(const HashValue & lhs,const HashValue & rhs)103 bool operator==(const HashValue& lhs, const HashValue& rhs) {
104 if (lhs.tag_ != rhs.tag_)
105 return false;
106
107 switch (lhs.tag_) {
108 case HASH_VALUE_SHA256:
109 return lhs.fingerprint.sha256 == rhs.fingerprint.sha256;
110 }
111
112 NOTREACHED();
113 return false;
114 }
115
operator !=(const HashValue & lhs,const HashValue & rhs)116 bool operator!=(const HashValue& lhs, const HashValue& rhs) {
117 return !(lhs == rhs);
118 }
119
operator <(const HashValue & lhs,const HashValue & rhs)120 bool operator<(const HashValue& lhs, const HashValue& rhs) {
121 if (lhs.tag_ != rhs.tag_)
122 return lhs.tag_ < rhs.tag_;
123
124 switch (lhs.tag_) {
125 case HASH_VALUE_SHA256:
126 return lhs.fingerprint.sha256 < rhs.fingerprint.sha256;
127 }
128
129 NOTREACHED();
130 return false;
131 }
132
operator >(const HashValue & lhs,const HashValue & rhs)133 bool operator>(const HashValue& lhs, const HashValue& rhs) {
134 return rhs < lhs;
135 }
136
operator <=(const HashValue & lhs,const HashValue & rhs)137 bool operator<=(const HashValue& lhs, const HashValue& rhs) {
138 return !(lhs > rhs);
139 }
140
operator >=(const HashValue & lhs,const HashValue & rhs)141 bool operator>=(const HashValue& lhs, const HashValue& rhs) {
142 return !(lhs < rhs);
143 }
144
IsSHA256HashInSortedArray(const HashValue & hash,base::span<const SHA256HashValue> array)145 bool IsSHA256HashInSortedArray(const HashValue& hash,
146 base::span<const SHA256HashValue> array) {
147 return std::binary_search(array.begin(), array.end(), hash,
148 SHA256ToHashValueComparator());
149 }
150
IsAnySHA256HashInSortedArray(base::span<const HashValue> hashes,base::span<const SHA256HashValue> array)151 bool IsAnySHA256HashInSortedArray(base::span<const HashValue> hashes,
152 base::span<const SHA256HashValue> array) {
153 for (const auto& hash : hashes) {
154 if (hash.tag() != HASH_VALUE_SHA256)
155 continue;
156
157 if (IsSHA256HashInSortedArray(hash, array))
158 return true;
159 }
160 return false;
161 }
162
163 } // namespace net
164