xref: /aosp_15_r20/external/cronet/net/base/hash_value.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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/containers/span.h"
15 #include "base/notreached.h"
16 #include "base/strings/string_split.h"
17 #include "base/strings/string_util.h"
18 #include "crypto/sha2.h"
19 
20 namespace net {
21 
22 namespace {
23 
24 constexpr std::string_view kSha256Slash = "sha256/";
25 
26 // LessThan comparator for use with std::binary_search() in determining
27 // whether a SHA-256 HashValue appears within a sorted array of
28 // SHA256HashValues.
29 struct SHA256ToHashValueComparator {
operator ()net::__anon4a6dfd150111::SHA256ToHashValueComparator30   bool operator()(const SHA256HashValue& lhs, const HashValue& rhs) const {
31     DCHECK_EQ(HASH_VALUE_SHA256, rhs.tag());
32     return memcmp(lhs.data, rhs.data(), rhs.size()) < 0;
33   }
34 
operator ()net::__anon4a6dfd150111::SHA256ToHashValueComparator35   bool operator()(const HashValue& lhs, const SHA256HashValue& rhs) const {
36     DCHECK_EQ(HASH_VALUE_SHA256, lhs.tag());
37     return memcmp(lhs.data(), rhs.data, lhs.size()) < 0;
38   }
39 };
40 
41 }  // namespace
42 
43 
HashValue(const SHA256HashValue & hash)44 HashValue::HashValue(const SHA256HashValue& hash)
45     : HashValue(HASH_VALUE_SHA256) {
46   fingerprint.sha256 = hash;
47 }
48 
FromString(std::string_view value)49 bool HashValue::FromString(std::string_view value) {
50   if (!value.starts_with(kSha256Slash)) {
51     return false;
52   }
53 
54   std::string_view base64_str = value.substr(kSha256Slash.size());
55 
56   auto decoded = base::Base64Decode(base64_str);
57   if (!decoded || decoded->size() != size()) {
58     return false;
59   }
60   tag_ = HASH_VALUE_SHA256;
61   memcpy(data(), decoded->data(), size());
62   return true;
63 }
64 
ToString() const65 std::string HashValue::ToString() const {
66   std::string base64_str = base::Base64Encode(base::make_span(data(), size()));
67   switch (tag_) {
68     case HASH_VALUE_SHA256:
69       return std::string(kSha256Slash) + base64_str;
70   }
71 
72   NOTREACHED_NORETURN();
73 }
74 
size() const75 size_t HashValue::size() const {
76   switch (tag_) {
77     case HASH_VALUE_SHA256:
78       return sizeof(fingerprint.sha256.data);
79   }
80 
81   NOTREACHED_NORETURN();
82 }
83 
data()84 unsigned char* HashValue::data() {
85   return const_cast<unsigned char*>(const_cast<const HashValue*>(this)->data());
86 }
87 
data() const88 const unsigned char* HashValue::data() const {
89   switch (tag_) {
90     case HASH_VALUE_SHA256:
91       return fingerprint.sha256.data;
92   }
93 
94   NOTREACHED_NORETURN();
95 }
96 
operator ==(const HashValue & lhs,const HashValue & rhs)97 bool operator==(const HashValue& lhs, const HashValue& rhs) {
98   if (lhs.tag_ != rhs.tag_)
99     return false;
100 
101   switch (lhs.tag_) {
102     case HASH_VALUE_SHA256:
103       return lhs.fingerprint.sha256 == rhs.fingerprint.sha256;
104   }
105 
106   NOTREACHED_NORETURN();
107 }
108 
operator !=(const HashValue & lhs,const HashValue & rhs)109 bool operator!=(const HashValue& lhs, const HashValue& rhs) {
110   return !(lhs == rhs);
111 }
112 
operator <(const HashValue & lhs,const HashValue & rhs)113 bool operator<(const HashValue& lhs, const HashValue& rhs) {
114   if (lhs.tag_ != rhs.tag_)
115     return lhs.tag_ < rhs.tag_;
116 
117   switch (lhs.tag_) {
118     case HASH_VALUE_SHA256:
119       return lhs.fingerprint.sha256 < rhs.fingerprint.sha256;
120   }
121 
122   NOTREACHED();
123   return false;
124 }
125 
operator >(const HashValue & lhs,const HashValue & rhs)126 bool operator>(const HashValue& lhs, const HashValue& rhs) {
127   return rhs < lhs;
128 }
129 
operator <=(const HashValue & lhs,const HashValue & rhs)130 bool operator<=(const HashValue& lhs, const HashValue& rhs) {
131   return !(lhs > rhs);
132 }
133 
operator >=(const HashValue & lhs,const HashValue & rhs)134 bool operator>=(const HashValue& lhs, const HashValue& rhs) {
135   return !(lhs < rhs);
136 }
137 
IsSHA256HashInSortedArray(const HashValue & hash,base::span<const SHA256HashValue> array)138 bool IsSHA256HashInSortedArray(const HashValue& hash,
139                                base::span<const SHA256HashValue> array) {
140   return std::binary_search(array.begin(), array.end(), hash,
141                             SHA256ToHashValueComparator());
142 }
143 
IsAnySHA256HashInSortedArray(base::span<const HashValue> hashes,base::span<const SHA256HashValue> array)144 bool IsAnySHA256HashInSortedArray(base::span<const HashValue> hashes,
145                                   base::span<const SHA256HashValue> array) {
146   for (const auto& hash : hashes) {
147     if (hash.tag() != HASH_VALUE_SHA256)
148       continue;
149 
150     if (IsSHA256HashInSortedArray(hash, array))
151       return true;
152   }
153   return false;
154 }
155 
156 }  // namespace net
157