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