• 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 #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