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

Side by Side Diff: components/proximity_auth/cryptauth/cryptauth_enroller_impl_unittest.cc

Issue 2502343003: Moved //components/proximity_auth/cryptauth to //components/cryptauth. (Closed)
Patch Set: Prefixed two test names with "CryptAuth" so that they do not collide with other test names. Created 4 years, 1 month 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 "components/proximity_auth/cryptauth/cryptauth_enroller_impl.h"
6
7 #include "base/bind.h"
8 #include "base/macros.h"
9 #include "base/memory/ptr_util.h"
10 #include "components/proximity_auth/cryptauth/cryptauth_enrollment_utils.h"
11 #include "components/proximity_auth/cryptauth/fake_secure_message_delegate.h"
12 #include "components/proximity_auth/cryptauth/mock_cryptauth_client.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14
15 using ::testing::_;
16 using ::testing::Return;
17
18 namespace proximity_auth {
19
20 namespace {
21
22 const char kAccessTokenUsed[] = "access token used by CryptAuthClient";
23
24 const char kClientSessionPublicKey[] = "throw away after one use";
25 const char kServerSessionPublicKey[] = "disposables are not eco-friendly";
26
27 cryptauth::InvocationReason kInvocationReason =
28 cryptauth::INVOCATION_REASON_MANUAL;
29 const int kGCMMetadataVersion = 1;
30 const char kSupportedEnrollmentTypeGcmV1[] = "gcmV1";
31 const char kResponseStatusOk[] = "ok";
32 const char kResponseStatusNotOk[] = "Your key was too bland.";
33 const char kEnrollmentSessionId[] = "0123456789876543210";
34 const char kFinishEnrollmentError[] = "A hungry router ate all your packets.";
35
36 const char kDeviceId[] = "2015 AD";
37 const cryptauth::DeviceType kDeviceType = cryptauth::CHROME;
38 const char kDeviceOsVersion[] = "41.0.0";
39
40 // Creates and returns the GcmDeviceInfo message to be uploaded.
41 cryptauth::GcmDeviceInfo GetDeviceInfo() {
42 cryptauth::GcmDeviceInfo device_info;
43 device_info.set_long_device_id(kDeviceId);
44 device_info.set_device_type(kDeviceType);
45 device_info.set_device_os_version(kDeviceOsVersion);
46 return device_info;
47 }
48
49 // Creates and returns the SetupEnrollmentResponse message to be returned to the
50 // enroller with the session_. If |success| is false, then a bad response will
51 // be returned.
52 cryptauth::SetupEnrollmentResponse GetSetupEnrollmentResponse(bool success) {
53 cryptauth::SetupEnrollmentResponse response;
54 if (!success) {
55 response.set_status(kResponseStatusNotOk);
56 return response;
57 }
58
59 response.set_status(kResponseStatusOk);
60 cryptauth::SetupEnrollmentInfo* info = response.add_infos();
61 info->set_type(kSupportedEnrollmentTypeGcmV1);
62 info->set_enrollment_session_id(kEnrollmentSessionId);
63 info->set_server_ephemeral_key(kServerSessionPublicKey);
64 return response;
65 }
66
67 // Creates and returns the FinishEnrollmentResponse message to be returned to
68 // the enroller with the session_. If |success| is false, then a bad response
69 // will be returned.
70 cryptauth::FinishEnrollmentResponse GetFinishEnrollmentResponse(bool success) {
71 cryptauth::FinishEnrollmentResponse response;
72 if (success) {
73 response.set_status(kResponseStatusOk);
74 } else {
75 response.set_status(kResponseStatusNotOk);
76 response.set_error_message(kFinishEnrollmentError);
77 }
78 return response;
79 }
80
81 // Callback that saves the key returned by SecureMessageDelegate::DeriveKey().
82 void SaveDerivedKey(std::string* value_out, const std::string& value) {
83 *value_out = value;
84 }
85
86 // Callback that saves the results returned by
87 // SecureMessageDelegate::UnwrapSecureMessage().
88 void SaveUnwrapResults(bool* verified_out,
89 std::string* payload_out,
90 securemessage::Header* header_out,
91 bool verified,
92 const std::string& payload,
93 const securemessage::Header& header) {
94 *verified_out = verified;
95 *payload_out = payload;
96 *header_out = header;
97 }
98
99 } // namespace
100
101 class ProximityAuthCryptAuthEnrollerTest
102 : public testing::Test,
103 public MockCryptAuthClientFactory::Observer {
104 public:
105 ProximityAuthCryptAuthEnrollerTest()
106 : client_factory_(new MockCryptAuthClientFactory(
107 MockCryptAuthClientFactory::MockType::MAKE_NICE_MOCKS)),
108 secure_message_delegate_(new FakeSecureMessageDelegate()),
109 enroller_(base::WrapUnique(client_factory_),
110 base::WrapUnique(secure_message_delegate_)) {
111 client_factory_->AddObserver(this);
112
113 // This call is actually synchronous.
114 secure_message_delegate_->GenerateKeyPair(
115 base::Bind(&ProximityAuthCryptAuthEnrollerTest::OnKeyPairGenerated,
116 base::Unretained(this)));
117 }
118
119 // Starts the enroller.
120 void StartEnroller(const cryptauth::GcmDeviceInfo& device_info) {
121 secure_message_delegate_->set_next_public_key(kClientSessionPublicKey);
122 enroller_result_.reset();
123 enroller_.Enroll(
124 user_public_key_, user_private_key_, device_info, kInvocationReason,
125 base::Bind(&ProximityAuthCryptAuthEnrollerTest::OnEnrollerCompleted,
126 base::Unretained(this)));
127 }
128
129 // Verifies that |serialized_message| is a valid SecureMessage sent with the
130 // FinishEnrollment API call.
131 void ValidateEnrollmentMessage(const std::string& serialized_message) {
132 // Derive the session symmetric key.
133 std::string server_session_private_key =
134 secure_message_delegate_->GetPrivateKeyForPublicKey(
135 kServerSessionPublicKey);
136 std::string symmetric_key;
137 secure_message_delegate_->DeriveKey(
138 server_session_private_key, kClientSessionPublicKey,
139 base::Bind(&SaveDerivedKey, &symmetric_key));
140
141 std::string inner_message;
142 std::string inner_payload;
143 {
144 // Unwrap the outer message.
145 bool verified;
146 securemessage::Header header;
147 SecureMessageDelegate::UnwrapOptions unwrap_options;
148 unwrap_options.encryption_scheme = securemessage::AES_256_CBC;
149 unwrap_options.signature_scheme = securemessage::HMAC_SHA256;
150 secure_message_delegate_->UnwrapSecureMessage(
151 serialized_message, symmetric_key, unwrap_options,
152 base::Bind(&SaveUnwrapResults, &verified, &inner_message, &header));
153 EXPECT_TRUE(verified);
154
155 cryptauth::GcmMetadata metadata;
156 ASSERT_TRUE(metadata.ParseFromString(header.public_metadata()));
157 EXPECT_EQ(kGCMMetadataVersion, metadata.version());
158 EXPECT_EQ(cryptauth::MessageType::ENROLLMENT, metadata.type());
159 }
160
161 {
162 // Unwrap inner message.
163 bool verified;
164 securemessage::Header header;
165 SecureMessageDelegate::UnwrapOptions unwrap_options;
166 unwrap_options.encryption_scheme = securemessage::NONE;
167 unwrap_options.signature_scheme = securemessage::ECDSA_P256_SHA256;
168 secure_message_delegate_->UnwrapSecureMessage(
169 inner_message, user_public_key_, unwrap_options,
170 base::Bind(&SaveUnwrapResults, &verified, &inner_payload, &header));
171 EXPECT_TRUE(verified);
172 EXPECT_EQ(user_public_key_, header.verification_key_id());
173 }
174
175 // Check that the decrypted GcmDeviceInfo is correct.
176 cryptauth::GcmDeviceInfo device_info;
177 ASSERT_TRUE(device_info.ParseFromString(inner_payload));
178 EXPECT_EQ(kDeviceId, device_info.long_device_id());
179 EXPECT_EQ(kDeviceType, device_info.device_type());
180 EXPECT_EQ(kDeviceOsVersion, device_info.device_os_version());
181 EXPECT_EQ(user_public_key_, device_info.user_public_key());
182 EXPECT_EQ(user_public_key_, device_info.key_handle());
183 EXPECT_EQ(kEnrollmentSessionId, device_info.enrollment_session_id());
184 }
185
186 protected:
187 // MockCryptAuthClientFactory::Observer:
188 void OnCryptAuthClientCreated(MockCryptAuthClient* client) override {
189 ON_CALL(*client, SetupEnrollment(_, _, _))
190 .WillByDefault(Invoke(
191 this, &ProximityAuthCryptAuthEnrollerTest::OnSetupEnrollment));
192
193 ON_CALL(*client, FinishEnrollment(_, _, _))
194 .WillByDefault(Invoke(
195 this, &ProximityAuthCryptAuthEnrollerTest::OnFinishEnrollment));
196
197 ON_CALL(*client, GetAccessTokenUsed())
198 .WillByDefault(Return(kAccessTokenUsed));
199 }
200
201 void OnKeyPairGenerated(const std::string& public_key,
202 const std::string& private_key) {
203 user_public_key_ = public_key;
204 user_private_key_ = private_key;
205 }
206
207 void OnEnrollerCompleted(bool success) {
208 EXPECT_FALSE(enroller_result_.get());
209 enroller_result_.reset(new bool(success));
210 }
211
212 void OnSetupEnrollment(
213 const cryptauth::SetupEnrollmentRequest& request,
214 const CryptAuthClient::SetupEnrollmentCallback& callback,
215 const CryptAuthClient::ErrorCallback& error_callback) {
216 // Check that SetupEnrollment is called before FinishEnrollment.
217 EXPECT_FALSE(setup_request_.get());
218 EXPECT_FALSE(finish_request_.get());
219 EXPECT_TRUE(setup_callback_.is_null());
220 EXPECT_TRUE(error_callback_.is_null());
221
222 setup_request_.reset(new cryptauth::SetupEnrollmentRequest(request));
223 setup_callback_ = callback;
224 error_callback_ = error_callback;
225 }
226
227 void OnFinishEnrollment(
228 const cryptauth::FinishEnrollmentRequest& request,
229 const CryptAuthClient::FinishEnrollmentCallback& callback,
230 const CryptAuthClient::ErrorCallback& error_callback) {
231 // Check that FinishEnrollment is called after SetupEnrollment.
232 EXPECT_TRUE(setup_request_.get());
233 EXPECT_FALSE(finish_request_.get());
234 EXPECT_TRUE(finish_callback_.is_null());
235
236 finish_request_.reset(new cryptauth::FinishEnrollmentRequest(request));
237 finish_callback_ = callback;
238 error_callback_ = error_callback;
239 }
240
241 // The persistent user key-pair.
242 std::string user_public_key_;
243 std::string user_private_key_;
244
245 // Owned by |enroller_|.
246 MockCryptAuthClientFactory* client_factory_;
247 // Owned by |enroller_|.
248 FakeSecureMessageDelegate* secure_message_delegate_;
249 // The CryptAuthEnroller under test.
250 CryptAuthEnrollerImpl enroller_;
251
252 // Stores the result of running |enroller_|.
253 std::unique_ptr<bool> enroller_result_;
254
255 // Stored callbacks and requests for SetupEnrollment and FinishEnrollment.
256 std::unique_ptr<cryptauth::SetupEnrollmentRequest> setup_request_;
257 std::unique_ptr<cryptauth::FinishEnrollmentRequest> finish_request_;
258 CryptAuthClient::SetupEnrollmentCallback setup_callback_;
259 CryptAuthClient::FinishEnrollmentCallback finish_callback_;
260 CryptAuthClient::ErrorCallback error_callback_;
261
262 DISALLOW_COPY_AND_ASSIGN(ProximityAuthCryptAuthEnrollerTest);
263 };
264
265 TEST_F(ProximityAuthCryptAuthEnrollerTest, EnrollmentSucceeds) {
266 StartEnroller(GetDeviceInfo());
267
268 // Handle SetupEnrollment request.
269 EXPECT_TRUE(setup_request_.get());
270 EXPECT_EQ(kInvocationReason, setup_request_->invocation_reason());
271 ASSERT_EQ(1, setup_request_->types_size());
272 EXPECT_EQ(kSupportedEnrollmentTypeGcmV1, setup_request_->types(0));
273 ASSERT_FALSE(setup_callback_.is_null());
274 setup_callback_.Run(GetSetupEnrollmentResponse(true));
275
276 // Handle FinishEnrollment request.
277 EXPECT_TRUE(finish_request_.get());
278 EXPECT_EQ(kEnrollmentSessionId, finish_request_->enrollment_session_id());
279 EXPECT_EQ(kClientSessionPublicKey, finish_request_->device_ephemeral_key());
280 ValidateEnrollmentMessage(finish_request_->enrollment_message());
281 EXPECT_EQ(kInvocationReason, finish_request_->invocation_reason());
282
283 ASSERT_FALSE(finish_callback_.is_null());
284 finish_callback_.Run(GetFinishEnrollmentResponse(true));
285
286 ASSERT_TRUE(enroller_result_.get());
287 EXPECT_TRUE(*enroller_result_);
288 }
289
290 TEST_F(ProximityAuthCryptAuthEnrollerTest, SetupEnrollmentApiCallError) {
291 StartEnroller(GetDeviceInfo());
292
293 EXPECT_TRUE(setup_request_.get());
294 ASSERT_FALSE(error_callback_.is_null());
295 error_callback_.Run("Setup enrollment failed network");
296
297 EXPECT_TRUE(finish_callback_.is_null());
298 ASSERT_TRUE(enroller_result_.get());
299 EXPECT_FALSE(*enroller_result_);
300 }
301
302 TEST_F(ProximityAuthCryptAuthEnrollerTest, SetupEnrollmentBadStatus) {
303 StartEnroller(GetDeviceInfo());
304
305 EXPECT_TRUE(setup_request_.get());
306 setup_callback_.Run(GetSetupEnrollmentResponse(false));
307
308 EXPECT_TRUE(finish_callback_.is_null());
309 ASSERT_TRUE(enroller_result_.get());
310 EXPECT_FALSE(*enroller_result_);
311 }
312
313 TEST_F(ProximityAuthCryptAuthEnrollerTest, SetupEnrollmentNoInfosReturned) {
314 StartEnroller(GetDeviceInfo());
315 EXPECT_TRUE(setup_request_.get());
316 cryptauth::SetupEnrollmentResponse response;
317 response.set_status(kResponseStatusOk);
318 setup_callback_.Run(response);
319
320 EXPECT_TRUE(finish_callback_.is_null());
321 ASSERT_TRUE(enroller_result_.get());
322 EXPECT_FALSE(*enroller_result_);
323 }
324
325 TEST_F(ProximityAuthCryptAuthEnrollerTest, FinishEnrollmentApiCallError) {
326 StartEnroller(GetDeviceInfo());
327 setup_callback_.Run(GetSetupEnrollmentResponse(true));
328 ASSERT_FALSE(error_callback_.is_null());
329 error_callback_.Run("finish enrollment oauth error");
330 ASSERT_TRUE(enroller_result_.get());
331 EXPECT_FALSE(*enroller_result_);
332 }
333
334 TEST_F(ProximityAuthCryptAuthEnrollerTest, FinishEnrollmentBadStatus) {
335 StartEnroller(GetDeviceInfo());
336 setup_callback_.Run(GetSetupEnrollmentResponse(true));
337 ASSERT_FALSE(finish_callback_.is_null());
338 finish_callback_.Run(GetFinishEnrollmentResponse(false));
339 ASSERT_TRUE(enroller_result_.get());
340 EXPECT_FALSE(*enroller_result_);
341 }
342
343 TEST_F(ProximityAuthCryptAuthEnrollerTest, ReuseEnroller) {
344 StartEnroller(GetDeviceInfo());
345 setup_callback_.Run(GetSetupEnrollmentResponse(true));
346 finish_callback_.Run(GetFinishEnrollmentResponse(true));
347 EXPECT_TRUE(*enroller_result_);
348
349 StartEnroller(GetDeviceInfo());
350 EXPECT_FALSE(*enroller_result_);
351 }
352
353 TEST_F(ProximityAuthCryptAuthEnrollerTest, IncompleteDeviceInfo) {
354 StartEnroller(cryptauth::GcmDeviceInfo());
355 ASSERT_TRUE(enroller_result_.get());
356 EXPECT_FALSE(*enroller_result_);
357 }
358
359 } // namespace proximity_auth
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698