Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(161)

Side by Side Diff: content/renderer/origin_trials/trial_token.cc

Issue 1742053002: Move trial token code to content/common. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/renderer/origin_trials/trial_token.h"
6
7 #include <openssl/curve25519.h>
8
9 #include <vector>
10
11 #include "base/base64.h"
12 #include "base/macros.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/string_split.h"
15 #include "base/strings/string_util.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "base/time/time.h"
18 #include "url/gurl.h"
19 #include "url/origin.h"
20
21 namespace content {
22
23 namespace {
24
25 // Version 1 is the only token version currently supported
26 const uint8_t kVersion1 = 1;
27
28 const char* kFieldSeparator = "|";
29
30 } // namespace
31
32 TrialToken::~TrialToken() {}
33
34 scoped_ptr<TrialToken> TrialToken::Parse(const std::string& token_text) {
35 if (token_text.empty()) {
36 return nullptr;
37 }
38
39 // Extract the version from the token. The version must be the first part of
40 // the token, separated from the remainder, as:
41 // version|<version-specific contents>
42 size_t version_end = token_text.find(kFieldSeparator);
43 if (version_end == std::string::npos) {
44 return nullptr;
45 }
46
47 std::string version_string = token_text.substr(0, version_end);
48 unsigned int version = 0;
49 if (!base::StringToUint(version_string, &version) || version > UINT8_MAX) {
50 return nullptr;
51 }
52
53 // Only version 1 currently supported
54 if (version != kVersion1) {
55 return nullptr;
56 }
57
58 // Extract the version-specific contents of the token
59 std::string token_contents = token_text.substr(version_end + 1);
60
61 // The contents of a valid version 1 token should resemble:
62 // signature|origin|feature_name|expiry_timestamp
63 std::vector<std::string> parts =
64 SplitString(token_contents, kFieldSeparator, base::KEEP_WHITESPACE,
65 base::SPLIT_WANT_ALL);
66 if (parts.size() != 4) {
67 return nullptr;
68 }
69
70 const std::string& signature = parts[0];
71 const std::string& origin_string = parts[1];
72 const std::string& feature_name = parts[2];
73 const std::string& expiry_string = parts[3];
74
75 uint64_t expiry_timestamp;
76 if (!base::StringToUint64(expiry_string, &expiry_timestamp)) {
77 return nullptr;
78 }
79
80 // Ensure that the origin is a valid (non-unique) origin URL
81 url::Origin origin = url::Origin(GURL(origin_string));
82 if (origin.unique()) {
83 return nullptr;
84 }
85
86 // Signed data is (origin + "|" + feature_name + "|" + expiry).
87 std::string data = token_contents.substr(signature.length() + 1);
88
89 return make_scoped_ptr(new TrialToken(version, signature, data, origin,
90 feature_name, expiry_timestamp));
91 }
92
93 bool TrialToken::IsAppropriate(const url::Origin& origin,
94 base::StringPiece feature_name) const {
95 return ValidateOrigin(origin) && ValidateFeatureName(feature_name);
96 }
97
98 bool TrialToken::IsValid(const base::Time& now,
99 base::StringPiece public_key) const {
100 // TODO(iclelland): Allow for multiple signing keys, and iterate over all
101 // active keys here. https://crbug.com/543220
102 return ValidateDate(now) && ValidateSignature(public_key);
103 }
104
105 bool TrialToken::ValidateOrigin(const url::Origin& origin) const {
106 return origin == origin_;
107 }
108
109 bool TrialToken::ValidateFeatureName(base::StringPiece feature_name) const {
110 return feature_name == feature_name_;
111 }
112
113 bool TrialToken::ValidateDate(const base::Time& now) const {
114 return expiry_time_ > now;
115 }
116
117 bool TrialToken::ValidateSignature(base::StringPiece public_key) const {
118 return ValidateSignature(signature_, data_, public_key);
119 }
120
121 // static
122 bool TrialToken::ValidateSignature(const std::string& signature_text,
123 const std::string& data,
124 base::StringPiece public_key) {
125 // Public key must be 32 bytes long for Ed25519.
126 CHECK_EQ(public_key.length(), 32UL);
127
128 std::string signature;
129 // signature_text is base64-encoded; decode first.
130 if (!base::Base64Decode(signature_text, &signature)) {
131 return false;
132 }
133
134 // Signature must be 64 bytes long
135 if (signature.length() != 64) {
136 return false;
137 }
138
139 int result = ED25519_verify(
140 reinterpret_cast<const uint8_t*>(data.data()), data.length(),
141 reinterpret_cast<const uint8_t*>(signature.data()),
142 reinterpret_cast<const uint8_t*>(public_key.data()));
143 return (result != 0);
144 }
145
146 TrialToken::TrialToken(uint8_t version,
147 const std::string& signature,
148 const std::string& data,
149 const url::Origin& origin,
150 const std::string& feature_name,
151 uint64_t expiry_timestamp)
152 : version_(version),
153 signature_(signature),
154 data_(data),
155 origin_(origin),
156 feature_name_(feature_name),
157 expiry_time_(base::Time::FromDoubleT(expiry_timestamp)) {}
158
159 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698