• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifdef UNSAFE_BUFFERS_BUILD
6 // TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
7 #pragma allow_unsafe_buffers
8 #endif
9 
10 #include "net/base/hash_value.h"
11 
12 #include <stdlib.h>
13 
14 #include <algorithm>
15 #include <ostream>
16 
17 #include "base/base64.h"
18 #include "base/check_op.h"
19 #include "base/containers/span.h"
20 #include "base/notreached.h"
21 #include "base/strings/string_split.h"
22 #include "base/strings/string_util.h"
23 #include "crypto/sha2.h"
24 
25 namespace net {
26 
27 namespace {
28 
29 constexpr std::string_view kSha256Slash = "sha256/";
30 
31 // LessThan comparator for use with std::binary_search() in determining
32 // whether a SHA-256 HashValue appears within a sorted array of
33 // SHA256HashValues.
34 struct SHA256ToHashValueComparator {
operator ()net::__anonb8d3abdb0111::SHA256ToHashValueComparator35   bool operator()(const SHA256HashValue& lhs, const HashValue& rhs) const {
36     DCHECK_EQ(HASH_VALUE_SHA256, rhs.tag());
37     return memcmp(lhs.data, rhs.data(), rhs.size()) < 0;
38   }
39 
operator ()net::__anonb8d3abdb0111::SHA256ToHashValueComparator40   bool operator()(const HashValue& lhs, const SHA256HashValue& rhs) const {
41     DCHECK_EQ(HASH_VALUE_SHA256, lhs.tag());
42     return memcmp(lhs.data(), rhs.data, lhs.size()) < 0;
43   }
44 };
45 
46 }  // namespace
47 
48 
HashValue(const SHA256HashValue & hash)49 HashValue::HashValue(const SHA256HashValue& hash)
50     : HashValue(HASH_VALUE_SHA256) {
51   fingerprint.sha256 = hash;
52 }
53 
FromString(std::string_view value)54 bool HashValue::FromString(std::string_view value) {
55   if (!value.starts_with(kSha256Slash)) {
56     return false;
57   }
58 
59   std::string_view base64_str = value.substr(kSha256Slash.size());
60 
61   auto decoded = base::Base64Decode(base64_str);
62   if (!decoded || decoded->size() != size()) {
63     return false;
64   }
65   tag_ = HASH_VALUE_SHA256;
66   memcpy(data(), decoded->data(), size());
67   return true;
68 }
69 
ToString() const70 std::string HashValue::ToString() const {
71   std::string base64_str = base::Base64Encode(base::span(data(), size()));
72   switch (tag_) {
73     case HASH_VALUE_SHA256:
74       return std::string(kSha256Slash) + base64_str;
75   }
76 
77   NOTREACHED();
78 }
79 
size() const80 size_t HashValue::size() const {
81   switch (tag_) {
82     case HASH_VALUE_SHA256:
83       return sizeof(fingerprint.sha256.data);
84   }
85 
86   NOTREACHED();
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();
100 }
101 
operator ==(const HashValue & lhs,const HashValue & rhs)102 bool operator==(const HashValue& lhs, const HashValue& rhs) {
103   if (lhs.tag_ != rhs.tag_)
104     return false;
105 
106   switch (lhs.tag_) {
107     case HASH_VALUE_SHA256:
108       return lhs.fingerprint.sha256 == rhs.fingerprint.sha256;
109   }
110 
111   NOTREACHED();
112 }
113 
operator !=(const HashValue & lhs,const HashValue & rhs)114 bool operator!=(const HashValue& lhs, const HashValue& rhs) {
115   return !(lhs == rhs);
116 }
117 
operator <(const HashValue & lhs,const HashValue & rhs)118 bool operator<(const HashValue& lhs, const HashValue& rhs) {
119   if (lhs.tag_ != rhs.tag_)
120     return lhs.tag_ < rhs.tag_;
121 
122   switch (lhs.tag_) {
123     case HASH_VALUE_SHA256:
124       return lhs.fingerprint.sha256 < rhs.fingerprint.sha256;
125   }
126 
127   NOTREACHED();
128 }
129 
operator >(const HashValue & lhs,const HashValue & rhs)130 bool operator>(const HashValue& lhs, const HashValue& rhs) {
131   return rhs < lhs;
132 }
133 
operator <=(const HashValue & lhs,const HashValue & rhs)134 bool operator<=(const HashValue& lhs, const HashValue& rhs) {
135   return !(lhs > rhs);
136 }
137 
operator >=(const HashValue & lhs,const HashValue & rhs)138 bool operator>=(const HashValue& lhs, const HashValue& rhs) {
139   return !(lhs < rhs);
140 }
141 
IsSHA256HashInSortedArray(const HashValue & hash,base::span<const SHA256HashValue> array)142 bool IsSHA256HashInSortedArray(const HashValue& hash,
143                                base::span<const SHA256HashValue> array) {
144   return std::binary_search(array.begin(), array.end(), hash,
145                             SHA256ToHashValueComparator());
146 }
147 
IsAnySHA256HashInSortedArray(base::span<const HashValue> hashes,base::span<const SHA256HashValue> array)148 bool IsAnySHA256HashInSortedArray(base::span<const HashValue> hashes,
149                                   base::span<const SHA256HashValue> array) {
150   for (const auto& hash : hashes) {
151     if (hash.tag() != HASH_VALUE_SHA256)
152       continue;
153 
154     if (IsSHA256HashInSortedArray(hash, array))
155       return true;
156   }
157   return false;
158 }
159 
160 }  // namespace net
161