base: Use scoped_ptr for ownership of pointers in unittests.
[chromium-blink-merge.git] / components / proximity_auth / cryptauth / cryptauth_enroller_impl_unittest.cc
blobbee79e434044f3e6e894079888b4dc218770da7b
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::_;
15 namespace proximity_auth {
17 namespace {
19 const char kClientSessionPublicKey[] = "throw away after one use";
20 const char kServerSessionPublicKey[] = "disposables are not eco-friendly";
21 const char kClientPersistentPublicKey[] = "saves 50 trees a year";
23 cryptauth::InvocationReason kInvocationReason =
24 cryptauth::INVOCATION_REASON_MANUAL;
25 const int kGCMMetadataVersion = 1;
26 const char kSupportedEnrollmentTypeGcmV1[] = "gcmV1";
27 const char kResponseStatusOk[] = "OK";
28 const char kResponseStatusNotOk[] = "Your key was too bland.";
29 const char kEnrollmentSessionId[] = "0123456789876543210";
30 const char kFinishEnrollmentError[] = "A hungry router ate all your packets.";
32 const char kDeviceId[] = "2015 AD";
33 const cryptauth::DeviceType kDeviceType = cryptauth::CHROME;
34 const char kDeviceOsVersion[] = "41.0.0";
36 // Creates and returns the GcmDeviceInfo message to be uploaded.
37 cryptauth::GcmDeviceInfo GetDeviceInfo() {
38 cryptauth::GcmDeviceInfo device_info;
39 device_info.set_long_device_id(kDeviceId);
40 device_info.set_device_type(kDeviceType);
41 device_info.set_device_os_version(kDeviceOsVersion);
42 device_info.set_user_public_key(kClientPersistentPublicKey);
43 device_info.set_key_handle(kClientPersistentPublicKey);
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(false)),
105 secure_message_delegate_(new FakeSecureMessageDelegate()),
106 enroller_(make_scoped_ptr(client_factory_),
107 make_scoped_ptr(secure_message_delegate_)) {
108 client_factory_->AddObserver(this);
111 // Starts the enroller.
112 void StartEnroller(const cryptauth::GcmDeviceInfo& device_info) {
113 secure_message_delegate_->set_next_public_key(kClientSessionPublicKey);
114 enroller_result_.reset();
115 enroller_.Enroll(
116 device_info, kInvocationReason,
117 base::Bind(&ProximityAuthCryptAuthEnrollerTest::OnEnrollerCompleted,
118 base::Unretained(this)));
121 // Verifies that |serialized_message| is a valid SecureMessage sent with the
122 // FinishEnrollment API call.
123 void ValidateEnrollmentMessage(const std::string& serialized_message) {
124 // Derive the session symmetric key.
125 std::string server_session_private_key =
126 secure_message_delegate_->GetPrivateKeyForPublicKey(
127 kServerSessionPublicKey);
128 std::string symmetric_key;
129 secure_message_delegate_->DeriveKey(
130 server_session_private_key, kClientSessionPublicKey,
131 base::Bind(&SaveDerivedKey, &symmetric_key));
133 std::string inner_message;
134 std::string inner_payload;
136 // Unwrap the outer message.
137 bool verified;
138 securemessage::Header header;
139 SecureMessageDelegate::UnwrapOptions unwrap_options;
140 unwrap_options.encryption_scheme = securemessage::AES_256_CBC;
141 unwrap_options.signature_scheme = securemessage::HMAC_SHA256;
142 secure_message_delegate_->UnwrapSecureMessage(
143 serialized_message, symmetric_key, unwrap_options,
144 base::Bind(&SaveUnwrapResults, &verified, &inner_message, &header));
145 EXPECT_TRUE(verified);
147 cryptauth::GcmMetadata metadata;
148 ASSERT_TRUE(metadata.ParseFromString(header.public_metadata()));
149 EXPECT_EQ(kGCMMetadataVersion, metadata.version());
150 EXPECT_EQ(cryptauth::MessageType::ENROLLMENT, metadata.type());
154 // Unwrap inner message.
155 bool verified;
156 securemessage::Header header;
157 SecureMessageDelegate::UnwrapOptions unwrap_options;
158 unwrap_options.encryption_scheme = securemessage::NONE;
159 unwrap_options.signature_scheme = securemessage::ECDSA_P256_SHA256;
160 secure_message_delegate_->UnwrapSecureMessage(
161 inner_message, kClientSessionPublicKey, unwrap_options,
162 base::Bind(&SaveUnwrapResults, &verified, &inner_payload, &header));
163 EXPECT_TRUE(verified);
164 EXPECT_EQ(kClientSessionPublicKey, header.verification_key_id());
167 // Check that the decrypted GcmDeviceInfo is correct.
168 cryptauth::GcmDeviceInfo device_info;
169 ASSERT_TRUE(device_info.ParseFromString(inner_payload));
170 EXPECT_EQ(kDeviceId, device_info.long_device_id());
171 EXPECT_EQ(kDeviceType, device_info.device_type());
172 EXPECT_EQ(kDeviceOsVersion, device_info.device_os_version());
173 EXPECT_EQ(kClientPersistentPublicKey, device_info.user_public_key());
174 EXPECT_EQ(kClientPersistentPublicKey, device_info.key_handle());
175 EXPECT_EQ(kEnrollmentSessionId, device_info.enrollment_session_id());
178 protected:
179 // MockCryptAuthClientFactory::Observer:
180 void OnCryptAuthClientCreated(MockCryptAuthClient* client) override {
181 ON_CALL(*client, SetupEnrollment(_, _, _))
182 .WillByDefault(Invoke(
183 this, &ProximityAuthCryptAuthEnrollerTest::OnSetupEnrollment));
185 ON_CALL(*client, FinishEnrollment(_, _, _))
186 .WillByDefault(Invoke(
187 this, &ProximityAuthCryptAuthEnrollerTest::OnFinishEnrollment));
190 void OnEnrollerCompleted(bool success) {
191 EXPECT_FALSE(enroller_result_.get());
192 enroller_result_.reset(new bool(success));
195 void OnSetupEnrollment(
196 const cryptauth::SetupEnrollmentRequest& request,
197 const CryptAuthClient::SetupEnrollmentCallback& callback,
198 const CryptAuthClient::ErrorCallback& error_callback) {
199 // Check that SetupEnrollment is called before FinishEnrollment.
200 EXPECT_FALSE(setup_request_.get());
201 EXPECT_FALSE(finish_request_.get());
202 EXPECT_TRUE(setup_callback_.is_null());
203 EXPECT_TRUE(error_callback_.is_null());
205 setup_request_.reset(new cryptauth::SetupEnrollmentRequest(request));
206 setup_callback_ = callback;
207 error_callback_ = error_callback;
210 void OnFinishEnrollment(
211 const cryptauth::FinishEnrollmentRequest& request,
212 const CryptAuthClient::FinishEnrollmentCallback& callback,
213 const CryptAuthClient::ErrorCallback& error_callback) {
214 // Check that FinishEnrollment is called after SetupEnrollment.
215 EXPECT_TRUE(setup_request_.get());
216 EXPECT_FALSE(finish_request_.get());
217 EXPECT_TRUE(finish_callback_.is_null());
219 finish_request_.reset(new cryptauth::FinishEnrollmentRequest(request));
220 finish_callback_ = callback;
221 error_callback_ = error_callback;
224 // Owned by |enroller_|.
225 MockCryptAuthClientFactory* client_factory_;
226 // Owned by |enroller_|.
227 FakeSecureMessageDelegate* secure_message_delegate_;
228 // The CryptAuthEnroller under test.
229 CryptAuthEnrollerImpl enroller_;
231 // Stores the result of running |enroller_|.
232 scoped_ptr<bool> enroller_result_;
234 // Stored callbacks and requests for SetupEnrollment and FinishEnrollment.
235 scoped_ptr<cryptauth::SetupEnrollmentRequest> setup_request_;
236 scoped_ptr<cryptauth::FinishEnrollmentRequest> finish_request_;
237 CryptAuthClient::SetupEnrollmentCallback setup_callback_;
238 CryptAuthClient::FinishEnrollmentCallback finish_callback_;
239 CryptAuthClient::ErrorCallback error_callback_;
241 DISALLOW_COPY_AND_ASSIGN(ProximityAuthCryptAuthEnrollerTest);
244 TEST_F(ProximityAuthCryptAuthEnrollerTest, EnrollmentSucceeds) {
245 StartEnroller(GetDeviceInfo());
247 // Handle SetupEnrollment request.
248 EXPECT_TRUE(setup_request_.get());
249 EXPECT_EQ(kInvocationReason, setup_request_->invocation_reason());
250 ASSERT_EQ(1, setup_request_->types_size());
251 EXPECT_EQ(kSupportedEnrollmentTypeGcmV1, setup_request_->types(0));
252 ASSERT_FALSE(setup_callback_.is_null());
253 setup_callback_.Run(GetSetupEnrollmentResponse(true));
255 // Handle FinishEnrollment request.
256 EXPECT_TRUE(finish_request_.get());
257 EXPECT_EQ(kEnrollmentSessionId, finish_request_->enrollment_session_id());
258 EXPECT_EQ(kClientSessionPublicKey, finish_request_->device_ephemeral_key());
259 ValidateEnrollmentMessage(finish_request_->enrollment_message());
260 EXPECT_EQ(kInvocationReason, finish_request_->invocation_reason());
262 ASSERT_FALSE(finish_callback_.is_null());
263 finish_callback_.Run(GetFinishEnrollmentResponse(true));
265 ASSERT_TRUE(enroller_result_.get());
266 EXPECT_TRUE(*enroller_result_);
269 TEST_F(ProximityAuthCryptAuthEnrollerTest, SetupEnrollmentApiCallError) {
270 StartEnroller(GetDeviceInfo());
272 EXPECT_TRUE(setup_request_.get());
273 ASSERT_FALSE(error_callback_.is_null());
274 error_callback_.Run("Setup enrollment failed network");
276 EXPECT_TRUE(finish_callback_.is_null());
277 ASSERT_TRUE(enroller_result_.get());
278 EXPECT_FALSE(*enroller_result_);
281 TEST_F(ProximityAuthCryptAuthEnrollerTest, SetupEnrollmentBadStatus) {
282 StartEnroller(GetDeviceInfo());
284 EXPECT_TRUE(setup_request_.get());
285 setup_callback_.Run(GetSetupEnrollmentResponse(false));
287 EXPECT_TRUE(finish_callback_.is_null());
288 ASSERT_TRUE(enroller_result_.get());
289 EXPECT_FALSE(*enroller_result_);
292 TEST_F(ProximityAuthCryptAuthEnrollerTest, SetupEnrollmentNoInfosReturned) {
293 StartEnroller(GetDeviceInfo());
294 EXPECT_TRUE(setup_request_.get());
295 cryptauth::SetupEnrollmentResponse response;
296 response.set_status(kResponseStatusOk);
297 setup_callback_.Run(response);
299 EXPECT_TRUE(finish_callback_.is_null());
300 ASSERT_TRUE(enroller_result_.get());
301 EXPECT_FALSE(*enroller_result_);
304 TEST_F(ProximityAuthCryptAuthEnrollerTest, FinishEnrollmentApiCallError) {
305 StartEnroller(GetDeviceInfo());
306 setup_callback_.Run(GetSetupEnrollmentResponse(true));
307 ASSERT_FALSE(error_callback_.is_null());
308 error_callback_.Run("finish enrollment oauth error");
309 ASSERT_TRUE(enroller_result_.get());
310 EXPECT_FALSE(*enroller_result_);
313 TEST_F(ProximityAuthCryptAuthEnrollerTest, FinishEnrollmentBadStatus) {
314 StartEnroller(GetDeviceInfo());
315 setup_callback_.Run(GetSetupEnrollmentResponse(true));
316 ASSERT_FALSE(finish_callback_.is_null());
317 finish_callback_.Run(GetFinishEnrollmentResponse(false));
318 ASSERT_TRUE(enroller_result_.get());
319 EXPECT_FALSE(*enroller_result_);
322 TEST_F(ProximityAuthCryptAuthEnrollerTest, ReuseEnroller) {
323 StartEnroller(GetDeviceInfo());
324 setup_callback_.Run(GetSetupEnrollmentResponse(true));
325 finish_callback_.Run(GetFinishEnrollmentResponse(true));
326 EXPECT_TRUE(*enroller_result_);
328 StartEnroller(GetDeviceInfo());
329 EXPECT_FALSE(*enroller_result_);
332 TEST_F(ProximityAuthCryptAuthEnrollerTest, IncompleteDeviceInfo) {
333 StartEnroller(cryptauth::GcmDeviceInfo());
334 ASSERT_TRUE(enroller_result_.get());
335 EXPECT_FALSE(*enroller_result_);
338 } // namespace proximity_auth