1*14675a02SAndroid Build Coastguard Worker /* 2*14675a02SAndroid Build Coastguard Worker * Copyright 2019 Google LLC 3*14675a02SAndroid Build Coastguard Worker * 4*14675a02SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*14675a02SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*14675a02SAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*14675a02SAndroid Build Coastguard Worker * 8*14675a02SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*14675a02SAndroid Build Coastguard Worker * 10*14675a02SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*14675a02SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*14675a02SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*14675a02SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*14675a02SAndroid Build Coastguard Worker * limitations under the License. 15*14675a02SAndroid Build Coastguard Worker */ 16*14675a02SAndroid Build Coastguard Worker 17*14675a02SAndroid Build Coastguard Worker #ifndef FCP_BASE_RANDOM_TOKEN_H_ 18*14675a02SAndroid Build Coastguard Worker #define FCP_BASE_RANDOM_TOKEN_H_ 19*14675a02SAndroid Build Coastguard Worker 20*14675a02SAndroid Build Coastguard Worker #include <stdint.h> 21*14675a02SAndroid Build Coastguard Worker 22*14675a02SAndroid Build Coastguard Worker #include <array> 23*14675a02SAndroid Build Coastguard Worker #include <string> 24*14675a02SAndroid Build Coastguard Worker #include <utility> 25*14675a02SAndroid Build Coastguard Worker 26*14675a02SAndroid Build Coastguard Worker #include "absl/types/span.h" 27*14675a02SAndroid Build Coastguard Worker 28*14675a02SAndroid Build Coastguard Worker namespace fcp { 29*14675a02SAndroid Build Coastguard Worker 30*14675a02SAndroid Build Coastguard Worker enum { kRandomTokenSizeInBytes = 16 }; 31*14675a02SAndroid Build Coastguard Worker 32*14675a02SAndroid Build Coastguard Worker /** 33*14675a02SAndroid Build Coastguard Worker * A RandomToken is a unique and "unguessable" value, thus usable as a 34*14675a02SAndroid Build Coastguard Worker * 'password-capability' (even in an adversarial / network context). Each is 35*14675a02SAndroid Build Coastguard Worker * comprised of 128 random bits, sourced from a CSRNG. 36*14675a02SAndroid Build Coastguard Worker * 37*14675a02SAndroid Build Coastguard Worker * The current implementation uses BoringSSL's RAND_bytes. Unless someone calls 38*14675a02SAndroid Build Coastguard Worker * RAND_enable_fork_unsafe_buffering, it should be well-behaved even under 39*14675a02SAndroid Build Coastguard Worker * fork(); i.e. tokens should not collide with those generated by new child 40*14675a02SAndroid Build Coastguard Worker * processes. 41*14675a02SAndroid Build Coastguard Worker */ 42*14675a02SAndroid Build Coastguard Worker class RandomToken { 43*14675a02SAndroid Build Coastguard Worker public: 44*14675a02SAndroid Build Coastguard Worker /** 45*14675a02SAndroid Build Coastguard Worker * Generates a new token. This sources bits from a CSRNG. The returned token 46*14675a02SAndroid Build Coastguard Worker * can be assumed to have the desired properties (unique and unguessable) - 47*14675a02SAndroid Build Coastguard Worker * unlike one that was deserialized from an untrusted source. 48*14675a02SAndroid Build Coastguard Worker */ 49*14675a02SAndroid Build Coastguard Worker static RandomToken Generate(); 50*14675a02SAndroid Build Coastguard Worker 51*14675a02SAndroid Build Coastguard Worker /** 52*14675a02SAndroid Build Coastguard Worker * Deserializes a token, serialized with ToBytes() or ToString(). 53*14675a02SAndroid Build Coastguard Worker * Note that tokens from untrusted sources might not have been generated 54*14675a02SAndroid Build Coastguard Worker * correctly, so should not be assumed unique and unguessable. 55*14675a02SAndroid Build Coastguard Worker * 56*14675a02SAndroid Build Coastguard Worker * Precondition: bytes.size() == kRandomTokenSizeInBytes 57*14675a02SAndroid Build Coastguard Worker */ 58*14675a02SAndroid Build Coastguard Worker static RandomToken FromBytes(absl::Span<char const> bytes); 59*14675a02SAndroid Build Coastguard Worker 60*14675a02SAndroid Build Coastguard Worker /** 61*14675a02SAndroid Build Coastguard Worker * Serializes a token, to something usable by FromBytes(). 62*14675a02SAndroid Build Coastguard Worker */ 63*14675a02SAndroid Build Coastguard Worker std::array<char, kRandomTokenSizeInBytes> ToBytes() const; 64*14675a02SAndroid Build Coastguard Worker 65*14675a02SAndroid Build Coastguard Worker /** 66*14675a02SAndroid Build Coastguard Worker * Serializes a token, to an std::string usable by FromBytes(). 67*14675a02SAndroid Build Coastguard Worker * 68*14675a02SAndroid Build Coastguard Worker * Postcondition: returned_string.size() == kRandomTokenSizeInBytes. 69*14675a02SAndroid Build Coastguard Worker */ 70*14675a02SAndroid Build Coastguard Worker std::string ToString() const; 71*14675a02SAndroid Build Coastguard Worker 72*14675a02SAndroid Build Coastguard Worker /** 73*14675a02SAndroid Build Coastguard Worker * Returns a hex-string representation (suitable for log output etc.) 74*14675a02SAndroid Build Coastguard Worker */ 75*14675a02SAndroid Build Coastguard Worker std::string ToPrintableString() const; 76*14675a02SAndroid Build Coastguard Worker 77*14675a02SAndroid Build Coastguard Worker constexpr bool operator==(RandomToken other) const { 78*14675a02SAndroid Build Coastguard Worker return words_[0] == other.words_[0] && words_[1] == other.words_[1]; 79*14675a02SAndroid Build Coastguard Worker } 80*14675a02SAndroid Build Coastguard Worker 81*14675a02SAndroid Build Coastguard Worker constexpr bool operator!=(RandomToken other) const { 82*14675a02SAndroid Build Coastguard Worker return !(*this == other); 83*14675a02SAndroid Build Coastguard Worker } 84*14675a02SAndroid Build Coastguard Worker 85*14675a02SAndroid Build Coastguard Worker template <typename H> AbslHashValue(H h,RandomToken t)86*14675a02SAndroid Build Coastguard Worker friend H AbslHashValue(H h, RandomToken t) { 87*14675a02SAndroid Build Coastguard Worker return H::combine(std::move(h), t.words_[0], t.words_[1]); 88*14675a02SAndroid Build Coastguard Worker } 89*14675a02SAndroid Build Coastguard Worker 90*14675a02SAndroid Build Coastguard Worker private: RandomToken(uint64_t a,uint64_t b)91*14675a02SAndroid Build Coastguard Worker explicit constexpr RandomToken(uint64_t a, uint64_t b) : words_{a, b} {} 92*14675a02SAndroid Build Coastguard Worker 93*14675a02SAndroid Build Coastguard Worker // It would have been nice to write char bytes[16], with alignas(16). 94*14675a02SAndroid Build Coastguard Worker // Surprisingly, even current compilers were found prone to unrolling 95*14675a02SAndroid Build Coastguard Worker // byte-by-byte comparison loops etc. This representation yields very compact 96*14675a02SAndroid Build Coastguard Worker // code. 97*14675a02SAndroid Build Coastguard Worker uint64_t words_[2]; 98*14675a02SAndroid Build Coastguard Worker }; 99*14675a02SAndroid Build Coastguard Worker 100*14675a02SAndroid Build Coastguard Worker static_assert(sizeof(RandomToken) == kRandomTokenSizeInBytes, 101*14675a02SAndroid Build Coastguard Worker "Incorrect RandomToken size"); 102*14675a02SAndroid Build Coastguard Worker 103*14675a02SAndroid Build Coastguard Worker } // namespace fcp 104*14675a02SAndroid Build Coastguard Worker 105*14675a02SAndroid Build Coastguard Worker #endif // FCP_BASE_RANDOM_TOKEN_H_ 106