1From bd984b07c2672500cf1344ee16807e52a42cfe0c Mon Sep 17 00:00:00 2001 2From: Soshun Naito <[email protected]> 3Date: Tue, 6 Aug 2024 08:37:44 +0000 4Subject: [PATCH] base: Add base::Token class 5 6This CL is a cherry-pick of the following CL: https://crrev.com/c/1320190 7It adds token.h and token.cc introduced in the CL above. These files are 8requried to build ARC with [Uuid] attribute in Mojo enabled. 9This CL also replaces unguessable_token.h and unguessable_token.cc with 10those in the original CL to let base::UnguessableToken to inherit 11base::Token. 12 13Bug: b:357737923, b:41420830 14Test: m 15 16Change-Id: I93cc0a588a4268416d3a3ba28e170992794e479d 17--- 18 Android.bp | 2 ++ 19 base/token.cc | 28 +++++++++++++++ 20 base/token.h | 72 +++++++++++++++++++++++++++++++++++++++ 21 base/unguessable_token.cc | 20 +++++------ 22 base/unguessable_token.h | 36 ++++++++++++-------- 23 5 files changed, 132 insertions(+), 26 deletions(-) 24 create mode 100644 base/token.cc 25 create mode 100644 base/token.h 26 27diff --git a/Android.bp b/Android.bp 28index 340a194ac..c9b031519 100644 29--- a/Android.bp 30+++ b/Android.bp 31@@ -458,6 +458,7 @@ filegroup { 32 "base/timer/hi_res_timer_manager.h", 33 "base/timer/mock_timer.h", 34 "base/timer/timer.h", 35+ "base/token.h", 36 "base/trace_event/common/trace_event_common.h", 37 "base/trace_event/heap_profiler.h", 38 "base/trace_event/trace_event.h", 39@@ -736,6 +737,7 @@ libchromeCommonSrc = [ 40 "base/time/time_override.cc", 41 "base/timer/elapsed_timer.cc", 42 "base/timer/timer.cc", 43+ "base/token.cc", 44 "base/unguessable_token.cc", 45 "base/value_iterators.cc", 46 "base/values.cc", 47diff --git a/base/token.cc b/base/token.cc 48new file mode 100644 49index 000000000..e7ad89671 50--- /dev/null 51+++ b/base/token.cc 52@@ -0,0 +1,28 @@ 53+// Copyright 2018 The Chromium Authors. All rights reserved. 54+// Use of this source code is governed by a BSD-style license that can be 55+// found in the LICENSE file. 56+ 57+#include "base/token.h" 58+ 59+#include <inttypes.h> 60+ 61+#include "base/rand_util.h" 62+#include "base/strings/stringprintf.h" 63+ 64+namespace base { 65+ 66+// static 67+Token Token::CreateRandom() { 68+ Token token; 69+ 70+ // Use base::RandBytes instead of crypto::RandBytes, because crypto calls the 71+ // base version directly, and to prevent the dependency from base/ to crypto/. 72+ base::RandBytes(&token, sizeof(token)); 73+ return token; 74+} 75+ 76+std::string Token::ToString() const { 77+ return base::StringPrintf("%016" PRIX64 "%016" PRIX64, high_, low_); 78+} 79+ 80+} // namespace base 81diff --git a/base/token.h b/base/token.h 82new file mode 100644 83index 000000000..f12277e11 84--- /dev/null 85+++ b/base/token.h 86@@ -0,0 +1,72 @@ 87+// Copyright 2018 The Chromium Authors. All rights reserved. 88+// Use of this source code is governed by a BSD-style license that can be 89+// found in the LICENSE file. 90+ 91+#ifndef BASE_TOKEN_H_ 92+#define BASE_TOKEN_H_ 93+ 94+#include <stdint.h> 95+ 96+#include <iosfwd> 97+#include <tuple> 98+ 99+#include "base/base_export.h" 100+#include "base/hash.h" 101+ 102+namespace base { 103+ 104+// A Token is a randomly chosen 128-bit integer. This class supports generation 105+// from a cryptographically strong random source, or constexpr construction over 106+// fixed values (e.g. to store a pre-generated constant value). Tokens are 107+// similar in spirit and purpose to UUIDs, without many of the constraints and 108+// expectations (such as byte layout and string representation) clasically 109+// associated with UUIDs. 110+class BASE_EXPORT Token { 111+ public: 112+ // Constructs a zero Token. 113+ constexpr Token() : high_(0), low_(0) {} 114+ 115+ // Constructs a Token with |high| and |low| as its contents. 116+ constexpr Token(uint64_t high, uint64_t low) : high_(high), low_(low) {} 117+ 118+ // Constructs a new Token with random |high| and |low| values taken from a 119+ // cryptographically strong random source. 120+ static Token CreateRandom(); 121+ 122+ // The high and low 64 bits of this Token. 123+ uint64_t high() const { return high_; } 124+ uint64_t low() const { return low_; } 125+ 126+ bool is_zero() const { return high_ == 0 && low_ == 0; } 127+ 128+ bool operator==(const Token& other) const { 129+ return high_ == other.high_ && low_ == other.low_; 130+ } 131+ 132+ bool operator!=(const Token& other) const { return !(*this == other); } 133+ 134+ bool operator<(const Token& other) const { 135+ return std::tie(high_, low_) < std::tie(other.high_, other.low_); 136+ } 137+ 138+ // Generates a string representation of this Token useful for e.g. logging. 139+ std::string ToString() const; 140+ 141+ private: 142+ // Note: Two uint64_t are used instead of uint8_t[16] in order to have a 143+ // simpler implementation, paricularly for |ToString()|, |is_zero()|, and 144+ // constexpr value construction. 145+ uint64_t high_; 146+ uint64_t low_; 147+}; 148+ 149+// For use in std::unordered_map. 150+struct TokenHash { 151+ size_t operator()(const base::Token& token) const { 152+ return base::HashInts64(token.high(), token.low()); 153+ } 154+}; 155+ 156+} // namespace base 157+ 158+#endif // BASE_TOKEN_H_ 159\ No newline at end of file 160diff --git a/base/unguessable_token.cc b/base/unguessable_token.cc 161index 0d8aad39c..973b4167b 100644 162--- a/base/unguessable_token.cc 163+++ b/base/unguessable_token.cc 164@@ -5,25 +5,23 @@ 165 #include "base/unguessable_token.h" 166 167 #include "base/format_macros.h" 168+#include "base/no_destructor.h" 169 #include "base/rand_util.h" 170 #include "base/strings/stringprintf.h" 171 172 namespace base { 173 174-UnguessableToken::UnguessableToken(uint64_t high, uint64_t low) 175- : high_(high), low_(low) {} 176+UnguessableToken::UnguessableToken(const base::Token& token) : token_(token) {} 177 178-std::string UnguessableToken::ToString() const { 179- return base::StringPrintf("%016" PRIX64 "%016" PRIX64, high_, low_); 180+// static 181+UnguessableToken UnguessableToken::Create() { 182+ return UnguessableToken(Token::CreateRandom()); 183 } 184 185 // static 186-UnguessableToken UnguessableToken::Create() { 187- UnguessableToken token; 188- // Use base::RandBytes instead of crypto::RandBytes, because crypto calls the 189- // base version directly, and to prevent the dependency from base/ to crypto/. 190- base::RandBytes(&token, sizeof(token)); 191- return token; 192+const UnguessableToken& UnguessableToken::Null() { 193+ static const NoDestructor<UnguessableToken> null_token; 194+ return *null_token; 195 } 196 197 // static 198@@ -31,7 +29,7 @@ UnguessableToken UnguessableToken::Deserialize(uint64_t high, uint64_t low) { 199 // Receiving a zeroed out UnguessableToken from another process means that it 200 // was never initialized via Create(). Treat this case as a security issue. 201 DCHECK(!(high == 0 && low == 0)); 202- return UnguessableToken(high, low); 203+ return UnguessableToken(Token{high, low}); 204 } 205 206 std::ostream& operator<<(std::ostream& out, const UnguessableToken& token) { 207diff --git a/base/unguessable_token.h b/base/unguessable_token.h 208index 6858e22a4..7f7b59a3a 100644 209--- a/base/unguessable_token.h 210+++ b/base/unguessable_token.h 211@@ -13,14 +13,17 @@ 212 #include "base/base_export.h" 213 #include "base/hash.h" 214 #include "base/logging.h" 215+#include "base/token.h" 216 217 namespace base { 218 219 struct UnguessableTokenHash; 220 221-// A UnguessableToken is an 128-bit token generated from a cryptographically 222-// strong random source. It can be used as part of a larger aggregate type, 223-// or as an ID in and of itself. 224+// UnguessableToken is, like Token, a randomly chosen 128-bit value. Unlike 225+// Token however, a new UnguessableToken must always be generated at runtime 226+// from a cryptographically strong random source (or copied or serialized and 227+// deserialized from another such UnguessableToken). It can be used as part of a 228+// larger aggregate type, or as an ID in and of itself. 229 // 230 // UnguessableToken can be used to implement "Capability-Based Security". 231 // In other words, UnguessableToken can be used when the resource associated 232@@ -42,6 +45,12 @@ class BASE_EXPORT UnguessableToken { 233 // Create a unique UnguessableToken. 234 static UnguessableToken Create(); 235 236+ // Returns a reference to a global null UnguessableToken. This should only be 237+ // used for functions that need to return a reference to an UnguessableToken, 238+ // and should not be used as a general-purpose substitute for invoking the 239+ // default constructor. 240+ static const UnguessableToken& Null(); 241+ 242 // Return a UnguessableToken built from the high/low bytes provided. 243 // It should only be used in deserialization scenarios. 244 // 245@@ -56,28 +65,28 @@ class BASE_EXPORT UnguessableToken { 246 // NOTE: Serializing an empty UnguessableToken is an illegal operation. 247 uint64_t GetHighForSerialization() const { 248 DCHECK(!is_empty()); 249- return high_; 250+ return token_.high(); 251 } 252 253 // NOTE: Serializing an empty UnguessableToken is an illegal operation. 254 uint64_t GetLowForSerialization() const { 255 DCHECK(!is_empty()); 256- return low_; 257+ return token_.low(); 258 } 259 260- bool is_empty() const { return high_ == 0 && low_ == 0; } 261+ bool is_empty() const { return token_.is_zero(); } 262 263 // Hex representation of the unguessable token. 264- std::string ToString() const; 265+ std::string ToString() const { return token_.ToString(); } 266 267 explicit operator bool() const { return !is_empty(); } 268 269 bool operator<(const UnguessableToken& other) const { 270- return std::tie(high_, low_) < std::tie(other.high_, other.low_); 271+ return token_ < other.token_; 272 } 273 274 bool operator==(const UnguessableToken& other) const { 275- return high_ == other.high_ && low_ == other.low_; 276+ return token_ == other.token_; 277 } 278 279 bool operator!=(const UnguessableToken& other) const { 280@@ -86,12 +95,9 @@ class BASE_EXPORT UnguessableToken { 281 282 private: 283 friend struct UnguessableTokenHash; 284- UnguessableToken(uint64_t high, uint64_t low); 285+ explicit UnguessableToken(const Token& token); 286 287- // Note: Two uint64_t are used instead of uint8_t[16], in order to have a 288- // simpler ToString() and is_empty(). 289- uint64_t high_ = 0; 290- uint64_t low_ = 0; 291+ base::Token token_; 292 }; 293 294 BASE_EXPORT std::ostream& operator<<(std::ostream& out, 295@@ -101,7 +107,7 @@ BASE_EXPORT std::ostream& operator<<(std::ostream& out, 296 struct UnguessableTokenHash { 297 size_t operator()(const base::UnguessableToken& token) const { 298 DCHECK(token); 299- return base::HashInts64(token.high_, token.low_); 300+ return TokenHash()(token.token_); 301 } 302 }; 303 304-- 3052.46.0.rc2.264.g509ed76dc8-goog 306 307