1*6777b538SAndroid Build Coastguard Worker // Copyright 2016 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker 5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_UNGUESSABLE_TOKEN_H_ 6*6777b538SAndroid Build Coastguard Worker #define BASE_UNGUESSABLE_TOKEN_H_ 7*6777b538SAndroid Build Coastguard Worker 8*6777b538SAndroid Build Coastguard Worker #include <stdint.h> 9*6777b538SAndroid Build Coastguard Worker #include <string.h> 10*6777b538SAndroid Build Coastguard Worker #include <compare> 11*6777b538SAndroid Build Coastguard Worker #include <iosfwd> 12*6777b538SAndroid Build Coastguard Worker #include <tuple> 13*6777b538SAndroid Build Coastguard Worker 14*6777b538SAndroid Build Coastguard Worker #include "base/base_export.h" 15*6777b538SAndroid Build Coastguard Worker #include "base/check.h" 16*6777b538SAndroid Build Coastguard Worker #include "base/containers/span.h" 17*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_piece.h" 18*6777b538SAndroid Build Coastguard Worker #include "base/token.h" 19*6777b538SAndroid Build Coastguard Worker 20*6777b538SAndroid Build Coastguard Worker namespace base { 21*6777b538SAndroid Build Coastguard Worker 22*6777b538SAndroid Build Coastguard Worker struct UnguessableTokenHash; 23*6777b538SAndroid Build Coastguard Worker 24*6777b538SAndroid Build Coastguard Worker // UnguessableToken is, like Token, a randomly chosen 128-bit value. Unlike 25*6777b538SAndroid Build Coastguard Worker // Token, a new UnguessableToken is always generated at runtime from a 26*6777b538SAndroid Build Coastguard Worker // cryptographically strong random source (or copied or serialized and 27*6777b538SAndroid Build Coastguard Worker // deserialized from another such UnguessableToken). Also unlike Token, the == 28*6777b538SAndroid Build Coastguard Worker // and != operators are constant time. It can be used as part of a larger 29*6777b538SAndroid Build Coastguard Worker // aggregate type, or as an ID in and of itself. 30*6777b538SAndroid Build Coastguard Worker // 31*6777b538SAndroid Build Coastguard Worker // An UnguessableToken is a strong *bearer token*. Bearer tokens are like HTTP 32*6777b538SAndroid Build Coastguard Worker // cookies: if a caller has the token, the callee thereby considers the caller 33*6777b538SAndroid Build Coastguard Worker // authorized to request the operation the callee performs. 34*6777b538SAndroid Build Coastguard Worker // 35*6777b538SAndroid Build Coastguard Worker // UnguessableToken can be used when the resource associated with the ID needs 36*6777b538SAndroid Build Coastguard Worker // to be protected against manipulation by other untrusted agents in the system, 37*6777b538SAndroid Build Coastguard Worker // and there is no other convenient way to verify the authority of the agent to 38*6777b538SAndroid Build Coastguard Worker // do so (because the resource is part of a table shared across processes, for 39*6777b538SAndroid Build Coastguard Worker // instance). In such a scheme, knowledge of the token value in and of itself is 40*6777b538SAndroid Build Coastguard Worker // sufficient proof of authority to carry out an operation on the associated 41*6777b538SAndroid Build Coastguard Worker // resource. 42*6777b538SAndroid Build Coastguard Worker // 43*6777b538SAndroid Build Coastguard Worker // Use Create() for creating new UnguessableTokens. 44*6777b538SAndroid Build Coastguard Worker // 45*6777b538SAndroid Build Coastguard Worker // NOTE: It is illegal to send empty UnguessableTokens across processes, and 46*6777b538SAndroid Build Coastguard Worker // sending/receiving empty tokens should be treated as a security issue. If 47*6777b538SAndroid Build Coastguard Worker // there is a valid scenario for sending "no token" across processes, use 48*6777b538SAndroid Build Coastguard Worker // std::optional instead of an empty token. 49*6777b538SAndroid Build Coastguard Worker 50*6777b538SAndroid Build Coastguard Worker class BASE_EXPORT UnguessableToken { 51*6777b538SAndroid Build Coastguard Worker public: 52*6777b538SAndroid Build Coastguard Worker // Create a unique UnguessableToken. It's guaranteed to be nonempty. 53*6777b538SAndroid Build Coastguard Worker static UnguessableToken Create(); 54*6777b538SAndroid Build Coastguard Worker 55*6777b538SAndroid Build Coastguard Worker // Returns a reference to a global null UnguessableToken. This should only be 56*6777b538SAndroid Build Coastguard Worker // used for functions that need to return a reference to an UnguessableToken, 57*6777b538SAndroid Build Coastguard Worker // and should not be used as a general-purpose substitute for invoking the 58*6777b538SAndroid Build Coastguard Worker // default constructor. 59*6777b538SAndroid Build Coastguard Worker static const UnguessableToken& Null(); 60*6777b538SAndroid Build Coastguard Worker 61*6777b538SAndroid Build Coastguard Worker // Return an UnguessableToken built from the high/low bytes provided. 62*6777b538SAndroid Build Coastguard Worker // It should only be used in deserialization scenarios. 63*6777b538SAndroid Build Coastguard Worker // 64*6777b538SAndroid Build Coastguard Worker // NOTE: If the returned `std::optional` does not have a value, it means that 65*6777b538SAndroid Build Coastguard Worker // `high` and `low` correspond to an `UnguesssableToken` that was never 66*6777b538SAndroid Build Coastguard Worker // initialized via Create(). This is a security issue, and should be handled. 67*6777b538SAndroid Build Coastguard Worker static std::optional<UnguessableToken> Deserialize(uint64_t high, 68*6777b538SAndroid Build Coastguard Worker uint64_t low); 69*6777b538SAndroid Build Coastguard Worker 70*6777b538SAndroid Build Coastguard Worker // Returns an `UnguessableToken` built from its string representation. It 71*6777b538SAndroid Build Coastguard Worker // should only be used in deserialization scenarios. 72*6777b538SAndroid Build Coastguard Worker // 73*6777b538SAndroid Build Coastguard Worker // NOTE: If the returned `std::optional` does not have a value, it means that 74*6777b538SAndroid Build Coastguard Worker // the given string does not represent a valid serialized `UnguessableToken`. 75*6777b538SAndroid Build Coastguard Worker // This should be handled as a security issue. 76*6777b538SAndroid Build Coastguard Worker static std::optional<UnguessableToken> DeserializeFromString( 77*6777b538SAndroid Build Coastguard Worker StringPiece string_representation); 78*6777b538SAndroid Build Coastguard Worker 79*6777b538SAndroid Build Coastguard Worker // Creates an empty UnguessableToken. 80*6777b538SAndroid Build Coastguard Worker // Assign to it with Create() before using it. 81*6777b538SAndroid Build Coastguard Worker constexpr UnguessableToken() = default; 82*6777b538SAndroid Build Coastguard Worker 83*6777b538SAndroid Build Coastguard Worker constexpr UnguessableToken(const UnguessableToken&) = default; 84*6777b538SAndroid Build Coastguard Worker constexpr UnguessableToken& operator=(const UnguessableToken&) = default; 85*6777b538SAndroid Build Coastguard Worker constexpr UnguessableToken(UnguessableToken&&) noexcept = default; 86*6777b538SAndroid Build Coastguard Worker constexpr UnguessableToken& operator=(UnguessableToken&&) = default; 87*6777b538SAndroid Build Coastguard Worker 88*6777b538SAndroid Build Coastguard Worker // NOTE: Serializing an empty UnguessableToken is an illegal operation. GetHighForSerialization()89*6777b538SAndroid Build Coastguard Worker uint64_t GetHighForSerialization() const { 90*6777b538SAndroid Build Coastguard Worker DCHECK(!is_empty()); 91*6777b538SAndroid Build Coastguard Worker return token_.high(); 92*6777b538SAndroid Build Coastguard Worker } 93*6777b538SAndroid Build Coastguard Worker 94*6777b538SAndroid Build Coastguard Worker // NOTE: Serializing an empty UnguessableToken is an illegal operation. GetLowForSerialization()95*6777b538SAndroid Build Coastguard Worker uint64_t GetLowForSerialization() const { 96*6777b538SAndroid Build Coastguard Worker DCHECK(!is_empty()); 97*6777b538SAndroid Build Coastguard Worker return token_.low(); 98*6777b538SAndroid Build Coastguard Worker } 99*6777b538SAndroid Build Coastguard Worker is_empty()100*6777b538SAndroid Build Coastguard Worker constexpr bool is_empty() const { return token_.is_zero(); } 101*6777b538SAndroid Build Coastguard Worker 102*6777b538SAndroid Build Coastguard Worker // Hex representation of the unguessable token. ToString()103*6777b538SAndroid Build Coastguard Worker std::string ToString() const { return token_.ToString(); } 104*6777b538SAndroid Build Coastguard Worker 105*6777b538SAndroid Build Coastguard Worker explicit constexpr operator bool() const { return !is_empty(); } 106*6777b538SAndroid Build Coastguard Worker AsBytes()107*6777b538SAndroid Build Coastguard Worker span<const uint8_t, 16> AsBytes() const { return token_.AsBytes(); } 108*6777b538SAndroid Build Coastguard Worker 109*6777b538SAndroid Build Coastguard Worker friend constexpr auto operator<=>(const UnguessableToken& lhs, 110*6777b538SAndroid Build Coastguard Worker const UnguessableToken& rhs) = default; 111*6777b538SAndroid Build Coastguard Worker 112*6777b538SAndroid Build Coastguard Worker // operator== uses constant-time comparison for security where available. 113*6777b538SAndroid Build Coastguard Worker friend BASE_EXPORT bool operator==(const UnguessableToken& lhs, 114*6777b538SAndroid Build Coastguard Worker const UnguessableToken& rhs); 115*6777b538SAndroid Build Coastguard Worker 116*6777b538SAndroid Build Coastguard Worker #if defined(UNIT_TEST) CreateForTesting(uint64_t high,uint64_t low)117*6777b538SAndroid Build Coastguard Worker static UnguessableToken CreateForTesting(uint64_t high, uint64_t low) { 118*6777b538SAndroid Build Coastguard Worker std::optional<UnguessableToken> token = Deserialize(high, low); 119*6777b538SAndroid Build Coastguard Worker DCHECK(token.has_value()); 120*6777b538SAndroid Build Coastguard Worker return token.value(); 121*6777b538SAndroid Build Coastguard Worker } 122*6777b538SAndroid Build Coastguard Worker #endif 123*6777b538SAndroid Build Coastguard Worker 124*6777b538SAndroid Build Coastguard Worker private: 125*6777b538SAndroid Build Coastguard Worker friend struct UnguessableTokenHash; 126*6777b538SAndroid Build Coastguard Worker explicit UnguessableToken(const Token& token); 127*6777b538SAndroid Build Coastguard Worker 128*6777b538SAndroid Build Coastguard Worker base::Token token_; 129*6777b538SAndroid Build Coastguard Worker }; 130*6777b538SAndroid Build Coastguard Worker 131*6777b538SAndroid Build Coastguard Worker BASE_EXPORT bool operator==(const UnguessableToken& lhs, 132*6777b538SAndroid Build Coastguard Worker const UnguessableToken& rhs); 133*6777b538SAndroid Build Coastguard Worker 134*6777b538SAndroid Build Coastguard Worker BASE_EXPORT std::ostream& operator<<(std::ostream& out, 135*6777b538SAndroid Build Coastguard Worker const UnguessableToken& token); 136*6777b538SAndroid Build Coastguard Worker 137*6777b538SAndroid Build Coastguard Worker // For use in std::unordered_map. 138*6777b538SAndroid Build Coastguard Worker struct UnguessableTokenHash { operatorUnguessableTokenHash139*6777b538SAndroid Build Coastguard Worker size_t operator()(const base::UnguessableToken& token) const { 140*6777b538SAndroid Build Coastguard Worker DCHECK(token); 141*6777b538SAndroid Build Coastguard Worker return TokenHash()(token.token_); 142*6777b538SAndroid Build Coastguard Worker } 143*6777b538SAndroid Build Coastguard Worker }; 144*6777b538SAndroid Build Coastguard Worker 145*6777b538SAndroid Build Coastguard Worker } // namespace base 146*6777b538SAndroid Build Coastguard Worker 147*6777b538SAndroid Build Coastguard Worker #endif // BASE_UNGUESSABLE_TOKEN_H_ 148