From bd984b07c2672500cf1344ee16807e52a42cfe0c Mon Sep 17 00:00:00 2001 From: Soshun Naito Date: Tue, 6 Aug 2024 08:37:44 +0000 Subject: [PATCH] base: Add base::Token class This CL is a cherry-pick of the following CL: https://crrev.com/c/1320190 It adds token.h and token.cc introduced in the CL above. These files are requried to build ARC with [Uuid] attribute in Mojo enabled. This CL also replaces unguessable_token.h and unguessable_token.cc with those in the original CL to let base::UnguessableToken to inherit base::Token. Bug: b:357737923, b:41420830 Test: m Change-Id: I93cc0a588a4268416d3a3ba28e170992794e479d --- Android.bp | 2 ++ base/token.cc | 28 +++++++++++++++ base/token.h | 72 +++++++++++++++++++++++++++++++++++++++ base/unguessable_token.cc | 20 +++++------ base/unguessable_token.h | 36 ++++++++++++-------- 5 files changed, 132 insertions(+), 26 deletions(-) create mode 100644 base/token.cc create mode 100644 base/token.h diff --git a/Android.bp b/Android.bp index 340a194ac..c9b031519 100644 --- a/Android.bp +++ b/Android.bp @@ -458,6 +458,7 @@ filegroup { "base/timer/hi_res_timer_manager.h", "base/timer/mock_timer.h", "base/timer/timer.h", + "base/token.h", "base/trace_event/common/trace_event_common.h", "base/trace_event/heap_profiler.h", "base/trace_event/trace_event.h", @@ -736,6 +737,7 @@ libchromeCommonSrc = [ "base/time/time_override.cc", "base/timer/elapsed_timer.cc", "base/timer/timer.cc", + "base/token.cc", "base/unguessable_token.cc", "base/value_iterators.cc", "base/values.cc", diff --git a/base/token.cc b/base/token.cc new file mode 100644 index 000000000..e7ad89671 --- /dev/null +++ b/base/token.cc @@ -0,0 +1,28 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/token.h" + +#include + +#include "base/rand_util.h" +#include "base/strings/stringprintf.h" + +namespace base { + +// static +Token Token::CreateRandom() { + Token token; + + // Use base::RandBytes instead of crypto::RandBytes, because crypto calls the + // base version directly, and to prevent the dependency from base/ to crypto/. + base::RandBytes(&token, sizeof(token)); + return token; +} + +std::string Token::ToString() const { + return base::StringPrintf("%016" PRIX64 "%016" PRIX64, high_, low_); +} + +} // namespace base diff --git a/base/token.h b/base/token.h new file mode 100644 index 000000000..f12277e11 --- /dev/null +++ b/base/token.h @@ -0,0 +1,72 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_TOKEN_H_ +#define BASE_TOKEN_H_ + +#include + +#include +#include + +#include "base/base_export.h" +#include "base/hash.h" + +namespace base { + +// A Token is a randomly chosen 128-bit integer. This class supports generation +// from a cryptographically strong random source, or constexpr construction over +// fixed values (e.g. to store a pre-generated constant value). Tokens are +// similar in spirit and purpose to UUIDs, without many of the constraints and +// expectations (such as byte layout and string representation) clasically +// associated with UUIDs. +class BASE_EXPORT Token { + public: + // Constructs a zero Token. + constexpr Token() : high_(0), low_(0) {} + + // Constructs a Token with |high| and |low| as its contents. + constexpr Token(uint64_t high, uint64_t low) : high_(high), low_(low) {} + + // Constructs a new Token with random |high| and |low| values taken from a + // cryptographically strong random source. + static Token CreateRandom(); + + // The high and low 64 bits of this Token. + uint64_t high() const { return high_; } + uint64_t low() const { return low_; } + + bool is_zero() const { return high_ == 0 && low_ == 0; } + + bool operator==(const Token& other) const { + return high_ == other.high_ && low_ == other.low_; + } + + bool operator!=(const Token& other) const { return !(*this == other); } + + bool operator<(const Token& other) const { + return std::tie(high_, low_) < std::tie(other.high_, other.low_); + } + + // Generates a string representation of this Token useful for e.g. logging. + std::string ToString() const; + + private: + // Note: Two uint64_t are used instead of uint8_t[16] in order to have a + // simpler implementation, paricularly for |ToString()|, |is_zero()|, and + // constexpr value construction. + uint64_t high_; + uint64_t low_; +}; + +// For use in std::unordered_map. +struct TokenHash { + size_t operator()(const base::Token& token) const { + return base::HashInts64(token.high(), token.low()); + } +}; + +} // namespace base + +#endif // BASE_TOKEN_H_ \ No newline at end of file diff --git a/base/unguessable_token.cc b/base/unguessable_token.cc index 0d8aad39c..973b4167b 100644 --- a/base/unguessable_token.cc +++ b/base/unguessable_token.cc @@ -5,25 +5,23 @@ #include "base/unguessable_token.h" #include "base/format_macros.h" +#include "base/no_destructor.h" #include "base/rand_util.h" #include "base/strings/stringprintf.h" namespace base { -UnguessableToken::UnguessableToken(uint64_t high, uint64_t low) - : high_(high), low_(low) {} +UnguessableToken::UnguessableToken(const base::Token& token) : token_(token) {} -std::string UnguessableToken::ToString() const { - return base::StringPrintf("%016" PRIX64 "%016" PRIX64, high_, low_); +// static +UnguessableToken UnguessableToken::Create() { + return UnguessableToken(Token::CreateRandom()); } // static -UnguessableToken UnguessableToken::Create() { - UnguessableToken token; - // Use base::RandBytes instead of crypto::RandBytes, because crypto calls the - // base version directly, and to prevent the dependency from base/ to crypto/. - base::RandBytes(&token, sizeof(token)); - return token; +const UnguessableToken& UnguessableToken::Null() { + static const NoDestructor null_token; + return *null_token; } // static @@ -31,7 +29,7 @@ UnguessableToken UnguessableToken::Deserialize(uint64_t high, uint64_t low) { // Receiving a zeroed out UnguessableToken from another process means that it // was never initialized via Create(). Treat this case as a security issue. DCHECK(!(high == 0 && low == 0)); - return UnguessableToken(high, low); + return UnguessableToken(Token{high, low}); } std::ostream& operator<<(std::ostream& out, const UnguessableToken& token) { diff --git a/base/unguessable_token.h b/base/unguessable_token.h index 6858e22a4..7f7b59a3a 100644 --- a/base/unguessable_token.h +++ b/base/unguessable_token.h @@ -13,14 +13,17 @@ #include "base/base_export.h" #include "base/hash.h" #include "base/logging.h" +#include "base/token.h" namespace base { struct UnguessableTokenHash; -// A UnguessableToken is an 128-bit token generated from a cryptographically -// strong random source. It can be used as part of a larger aggregate type, -// or as an ID in and of itself. +// UnguessableToken is, like Token, a randomly chosen 128-bit value. Unlike +// Token however, a new UnguessableToken must always be generated at runtime +// from a cryptographically strong random source (or copied or serialized and +// deserialized from another such UnguessableToken). It can be used as part of a +// larger aggregate type, or as an ID in and of itself. // // UnguessableToken can be used to implement "Capability-Based Security". // In other words, UnguessableToken can be used when the resource associated @@ -42,6 +45,12 @@ class BASE_EXPORT UnguessableToken { // Create a unique UnguessableToken. static UnguessableToken Create(); + // Returns a reference to a global null UnguessableToken. This should only be + // used for functions that need to return a reference to an UnguessableToken, + // and should not be used as a general-purpose substitute for invoking the + // default constructor. + static const UnguessableToken& Null(); + // Return a UnguessableToken built from the high/low bytes provided. // It should only be used in deserialization scenarios. // @@ -56,28 +65,28 @@ class BASE_EXPORT UnguessableToken { // NOTE: Serializing an empty UnguessableToken is an illegal operation. uint64_t GetHighForSerialization() const { DCHECK(!is_empty()); - return high_; + return token_.high(); } // NOTE: Serializing an empty UnguessableToken is an illegal operation. uint64_t GetLowForSerialization() const { DCHECK(!is_empty()); - return low_; + return token_.low(); } - bool is_empty() const { return high_ == 0 && low_ == 0; } + bool is_empty() const { return token_.is_zero(); } // Hex representation of the unguessable token. - std::string ToString() const; + std::string ToString() const { return token_.ToString(); } explicit operator bool() const { return !is_empty(); } bool operator<(const UnguessableToken& other) const { - return std::tie(high_, low_) < std::tie(other.high_, other.low_); + return token_ < other.token_; } bool operator==(const UnguessableToken& other) const { - return high_ == other.high_ && low_ == other.low_; + return token_ == other.token_; } bool operator!=(const UnguessableToken& other) const { @@ -86,12 +95,9 @@ class BASE_EXPORT UnguessableToken { private: friend struct UnguessableTokenHash; - UnguessableToken(uint64_t high, uint64_t low); + explicit UnguessableToken(const Token& token); - // Note: Two uint64_t are used instead of uint8_t[16], in order to have a - // simpler ToString() and is_empty(). - uint64_t high_ = 0; - uint64_t low_ = 0; + base::Token token_; }; BASE_EXPORT std::ostream& operator<<(std::ostream& out, @@ -101,7 +107,7 @@ BASE_EXPORT std::ostream& operator<<(std::ostream& out, struct UnguessableTokenHash { size_t operator()(const base::UnguessableToken& token) const { DCHECK(token); - return base::HashInts64(token.high_, token.low_); + return TokenHash()(token.token_); } }; -- 2.46.0.rc2.264.g509ed76dc8-goog