1*6777b538SAndroid Build Coastguard Worker // Copyright 2018 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 #include "base/token.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <inttypes.h>
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker #include <optional>
10*6777b538SAndroid Build Coastguard Worker
11*6777b538SAndroid Build Coastguard Worker #include "base/check.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/hash/hash.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/pickle.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/rand_util.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_piece.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/strings/stringprintf.h"
17*6777b538SAndroid Build Coastguard Worker
18*6777b538SAndroid Build Coastguard Worker namespace base {
19*6777b538SAndroid Build Coastguard Worker
20*6777b538SAndroid Build Coastguard Worker // static
CreateRandom()21*6777b538SAndroid Build Coastguard Worker Token Token::CreateRandom() {
22*6777b538SAndroid Build Coastguard Worker Token token;
23*6777b538SAndroid Build Coastguard Worker
24*6777b538SAndroid Build Coastguard Worker // Use base::RandBytes instead of crypto::RandBytes, because crypto calls the
25*6777b538SAndroid Build Coastguard Worker // base version directly, and to prevent the dependency from base/ to crypto/.
26*6777b538SAndroid Build Coastguard Worker base::RandBytes(&token, sizeof(token));
27*6777b538SAndroid Build Coastguard Worker
28*6777b538SAndroid Build Coastguard Worker CHECK(!token.is_zero());
29*6777b538SAndroid Build Coastguard Worker
30*6777b538SAndroid Build Coastguard Worker return token;
31*6777b538SAndroid Build Coastguard Worker }
32*6777b538SAndroid Build Coastguard Worker
ToString() const33*6777b538SAndroid Build Coastguard Worker std::string Token::ToString() const {
34*6777b538SAndroid Build Coastguard Worker return base::StringPrintf("%016" PRIX64 "%016" PRIX64, words_[0], words_[1]);
35*6777b538SAndroid Build Coastguard Worker }
36*6777b538SAndroid Build Coastguard Worker
37*6777b538SAndroid Build Coastguard Worker // static
FromString(StringPiece string_representation)38*6777b538SAndroid Build Coastguard Worker std::optional<Token> Token::FromString(StringPiece string_representation) {
39*6777b538SAndroid Build Coastguard Worker if (string_representation.size() != 32) {
40*6777b538SAndroid Build Coastguard Worker return std::nullopt;
41*6777b538SAndroid Build Coastguard Worker }
42*6777b538SAndroid Build Coastguard Worker uint64_t words[2];
43*6777b538SAndroid Build Coastguard Worker for (size_t i = 0; i < 2; i++) {
44*6777b538SAndroid Build Coastguard Worker uint64_t word = 0;
45*6777b538SAndroid Build Coastguard Worker // This j loop is similar to HexStringToUInt64 but we are intentionally
46*6777b538SAndroid Build Coastguard Worker // strict about case, accepting 'A' but rejecting 'a'.
47*6777b538SAndroid Build Coastguard Worker for (size_t j = 0; j < 16; j++) {
48*6777b538SAndroid Build Coastguard Worker const char c = string_representation[(16 * i) + j];
49*6777b538SAndroid Build Coastguard Worker if (('0' <= c) && (c <= '9')) {
50*6777b538SAndroid Build Coastguard Worker word = (word << 4) | static_cast<uint64_t>(c - '0');
51*6777b538SAndroid Build Coastguard Worker } else if (('A' <= c) && (c <= 'F')) {
52*6777b538SAndroid Build Coastguard Worker word = (word << 4) | static_cast<uint64_t>(c - 'A' + 10);
53*6777b538SAndroid Build Coastguard Worker } else {
54*6777b538SAndroid Build Coastguard Worker return std::nullopt;
55*6777b538SAndroid Build Coastguard Worker }
56*6777b538SAndroid Build Coastguard Worker }
57*6777b538SAndroid Build Coastguard Worker words[i] = word;
58*6777b538SAndroid Build Coastguard Worker }
59*6777b538SAndroid Build Coastguard Worker return std::optional<Token>(std::in_place, words[0], words[1]);
60*6777b538SAndroid Build Coastguard Worker }
61*6777b538SAndroid Build Coastguard Worker
WriteTokenToPickle(Pickle * pickle,const Token & token)62*6777b538SAndroid Build Coastguard Worker void WriteTokenToPickle(Pickle* pickle, const Token& token) {
63*6777b538SAndroid Build Coastguard Worker pickle->WriteUInt64(token.high());
64*6777b538SAndroid Build Coastguard Worker pickle->WriteUInt64(token.low());
65*6777b538SAndroid Build Coastguard Worker }
66*6777b538SAndroid Build Coastguard Worker
ReadTokenFromPickle(PickleIterator * pickle_iterator)67*6777b538SAndroid Build Coastguard Worker std::optional<Token> ReadTokenFromPickle(PickleIterator* pickle_iterator) {
68*6777b538SAndroid Build Coastguard Worker uint64_t high;
69*6777b538SAndroid Build Coastguard Worker if (!pickle_iterator->ReadUInt64(&high))
70*6777b538SAndroid Build Coastguard Worker return std::nullopt;
71*6777b538SAndroid Build Coastguard Worker
72*6777b538SAndroid Build Coastguard Worker uint64_t low;
73*6777b538SAndroid Build Coastguard Worker if (!pickle_iterator->ReadUInt64(&low))
74*6777b538SAndroid Build Coastguard Worker return std::nullopt;
75*6777b538SAndroid Build Coastguard Worker
76*6777b538SAndroid Build Coastguard Worker return Token(high, low);
77*6777b538SAndroid Build Coastguard Worker }
78*6777b538SAndroid Build Coastguard Worker
operator ()(const Token & token) const79*6777b538SAndroid Build Coastguard Worker size_t TokenHash::operator()(const Token& token) const {
80*6777b538SAndroid Build Coastguard Worker return HashInts64(token.high(), token.low());
81*6777b538SAndroid Build Coastguard Worker }
82*6777b538SAndroid Build Coastguard Worker
83*6777b538SAndroid Build Coastguard Worker } // namespace base
84