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

Side by Side Diff: chrome/browser/local_discovery/privetv3_session_unittest.cc

Issue 877613002: Added pairing with Spake SHA224 key exchange. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@brillo1
Patch Set: Thu Jan 29 23:44:10 PST 2015 Created 5 years, 10 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
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/local_discovery/privetv3_session.h" 5 #include "chrome/browser/local_discovery/privetv3_session.h"
6 6
7 #include "base/base64.h"
8 #include "base/strings/stringprintf.h"
7 #include "chrome/browser/local_discovery/privet_http.h" 9 #include "chrome/browser/local_discovery/privet_http.h"
8 #include "content/public/test/test_utils.h" 10 #include "content/public/test/test_utils.h"
11 #include "crypto/hmac.h"
12 #include "crypto/p224_spake.h"
9 #include "net/url_request/test_url_fetcher_factory.h" 13 #include "net/url_request/test_url_fetcher_factory.h"
14 #include "net/url_request/url_request_test_util.h"
10 #include "testing/gmock/include/gmock/gmock.h" 15 #include "testing/gmock/include/gmock/gmock.h"
11 #include "testing/gtest/include/gtest/gtest.h" 16 #include "testing/gtest/include/gtest/gtest.h"
12 17
13 namespace local_discovery { 18 namespace local_discovery {
14 19
15 namespace { 20 namespace {
16 21
17 using testing::Invoke; 22 using testing::Invoke;
18 using testing::InvokeWithoutArgs; 23 using testing::SaveArg;
19 using testing::StrictMock; 24 using testing::StrictMock;
20 using testing::_; 25 using testing::_;
21 26
27 using PairingType = PrivetV3Session::PairingType;
28 using Result = PrivetV3Session::Result;
29
30 const char kInfoResponse[] =
31 "{\"version\":\"3.0\","
32 "\"endpoints\":{\"httpsPort\": 443},"
33 "\"authentication\":{"
34 " \"mode\":[\"anonymous\",\"pairing\",\"cloud\"],"
35 " \"pairing\":[\"pinCode\",\"embeddedCode\"],"
36 " \"crypto\":[\"p224_spake2\"]"
37 "}}";
38
39 class MockPrivetHTTPClient : public PrivetHTTPClient {
40 public:
41 MockPrivetHTTPClient() {
42 request_context_ =
43 new net::TestURLRequestContextGetter(base::MessageLoopProxy::current());
44 }
45
46 MOCK_METHOD0(GetName, const std::string&());
47 MOCK_METHOD1(
48 CreateInfoOperationPtr,
49 PrivetJSONOperation*(const PrivetJSONOperation::ResultCallback&));
50
51 virtual void RefreshPrivetToken(
52 const PrivetURLFetcher::TokenCallback& callback) override {
53 FAIL();
54 }
55
56 virtual scoped_ptr<PrivetJSONOperation> CreateInfoOperation(
57 const PrivetJSONOperation::ResultCallback& callback) override {
58 return make_scoped_ptr(CreateInfoOperationPtr(callback));
59 }
60
61 virtual scoped_ptr<PrivetURLFetcher> CreateURLFetcher(
62 const GURL& url,
63 net::URLFetcher::RequestType request_type,
64 PrivetURLFetcher::Delegate* delegate) override {
65 return make_scoped_ptr(new PrivetURLFetcher(
66 url, request_type, request_context_.get(), delegate));
67 }
68
69 scoped_refptr<net::TestURLRequestContextGetter> request_context_;
70 };
71
72 } // namespace
73
22 class PrivetV3SessionTest : public testing::Test { 74 class PrivetV3SessionTest : public testing::Test {
23 public: 75 public:
24 PrivetV3SessionTest() : session_(scoped_ptr<PrivetHTTPClient>()) {} 76 PrivetV3SessionTest()
77 : fetcher_factory_(nullptr),
78 session_(make_scoped_ptr(new MockPrivetHTTPClient())) {}
25 79
26 virtual ~PrivetV3SessionTest() {} 80 virtual ~PrivetV3SessionTest() {}
27 81
28 MOCK_METHOD2(OnInitialized, 82 MOCK_METHOD2(OnInitialized, void(Result, const std::vector<PairingType>&));
29 void(PrivetV3Session::Result, 83 MOCK_METHOD1(OnPairingStarted, void(Result));
30 const std::vector<PrivetV3Session::PairingType>&)); 84 MOCK_METHOD1(OnCodeConfirmed, void(Result));
31 MOCK_METHOD1(OnPairingStarted, void(PrivetV3Session::Result)); 85 MOCK_METHOD2(OnMessageSend, void(Result, const base::DictionaryValue& value));
32 MOCK_METHOD1(OnCodeConfirmed, void(PrivetV3Session::Result)); 86 MOCK_METHOD1(OnPostData, void(const base::DictionaryValue& data));
33 MOCK_METHOD2(OnMessageSend,
34 void(PrivetV3Session::Result,
35 const base::DictionaryValue& value));
36 87
37 protected: 88 protected:
38 virtual void SetUp() override { 89 virtual void SetUp() override {
39 EXPECT_CALL(*this, OnInitialized(_, _)).Times(0); 90 EXPECT_CALL(*this, OnInitialized(_, _)).Times(0);
40 EXPECT_CALL(*this, OnPairingStarted(_)).Times(0); 91 EXPECT_CALL(*this, OnPairingStarted(_)).Times(0);
41 EXPECT_CALL(*this, OnCodeConfirmed(_)).Times(0); 92 EXPECT_CALL(*this, OnCodeConfirmed(_)).Times(0);
42 } 93 EXPECT_CALL(*this, OnMessageSend(_, _)).Times(0);
43 94 EXPECT_CALL(*this, OnPostData(_)).Times(0);
44 PrivetV3Session session_; 95 session_.on_post_data_ =
96 base::Bind(&PrivetV3SessionTest::OnPostData, base::Unretained(this));
97 }
98
45 base::MessageLoop loop_; 99 base::MessageLoop loop_;
46 base::Closure quit_closure_; 100 base::Closure quit_closure_;
101 net::FakeURLFetcherFactory fetcher_factory_;
102 PrivetV3Session session_;
47 }; 103 };
48 104
105 TEST_F(PrivetV3SessionTest, InitError) {
106 EXPECT_CALL(*this, OnInitialized(Result::STATUS_CONNECTIONERROR, _)).Times(1);
107 fetcher_factory_.SetFakeResponse(GURL("http://host/privet/info"), "",
108 net::HTTP_OK, net::URLRequestStatus::FAILED);
109 session_.Init(
110 base::Bind(&PrivetV3SessionTest::OnInitialized, base::Unretained(this)));
111 base::RunLoop().RunUntilIdle();
112 }
113
114 TEST_F(PrivetV3SessionTest, VersionError) {
115 std::string response(kInfoResponse);
116 ReplaceFirstSubstringAfterOffset(&response, 0, "3.0", "4.1");
117
118 EXPECT_CALL(*this, OnInitialized(Result::STATUS_SESSIONERROR, _)).Times(1);
119 fetcher_factory_.SetFakeResponse(GURL("http://host/privet/info"), response,
120 net::HTTP_OK,
121 net::URLRequestStatus::SUCCESS);
122 session_.Init(
123 base::Bind(&PrivetV3SessionTest::OnInitialized, base::Unretained(this)));
124 base::RunLoop().RunUntilIdle();
125 }
126
127 TEST_F(PrivetV3SessionTest, ModeError) {
128 std::string response(kInfoResponse);
129 ReplaceFirstSubstringAfterOffset(&response, 0, "mode", "mode_");
130
131 EXPECT_CALL(*this, OnInitialized(Result::STATUS_SESSIONERROR, _)).Times(1);
132 fetcher_factory_.SetFakeResponse(GURL("http://host/privet/info"), response,
133 net::HTTP_OK,
134 net::URLRequestStatus::SUCCESS);
135 session_.Init(
136 base::Bind(&PrivetV3SessionTest::OnInitialized, base::Unretained(this)));
137 base::RunLoop().RunUntilIdle();
138 }
139
49 TEST_F(PrivetV3SessionTest, Pairing) { 140 TEST_F(PrivetV3SessionTest, Pairing) {
50 { 141 std::vector<PairingType> pairings;
51 base::RunLoop run_loop; 142 EXPECT_CALL(*this, OnInitialized(Result::STATUS_SUCCESS, _))
52 EXPECT_CALL(*this, 143 .WillOnce(SaveArg<1>(&pairings));
53 OnInitialized(PrivetV3Session::Result::STATUS_SUCCESS, _)) 144 fetcher_factory_.SetFakeResponse(GURL("http://host/privet/info"),
54 .Times(1) 145 kInfoResponse, net::HTTP_OK,
55 .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit)); 146 net::URLRequestStatus::SUCCESS);
56 session_.Init(base::Bind(&PrivetV3SessionTest::OnInitialized, 147
57 base::Unretained(this))); 148 session_.Init(
58 run_loop.Run(); 149 base::Bind(&PrivetV3SessionTest::OnInitialized, base::Unretained(this)));
59 } 150 base::RunLoop().RunUntilIdle();
60 151
61 { 152 EXPECT_EQ(2u, pairings.size());
62 base::RunLoop run_loop; 153 EXPECT_EQ(PairingType::PAIRING_TYPE_PINCODE, pairings[0]);
63 EXPECT_CALL(*this, 154 EXPECT_EQ(PairingType::PAIRING_TYPE_EMBEDDEDCODE, pairings[1]);
64 OnPairingStarted(PrivetV3Session::Result::STATUS_SUCCESS)) 155
65 .Times(1) 156 crypto::P224EncryptedKeyExchange spake(
66 .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit)); 157 crypto::P224EncryptedKeyExchange::kPeerTypeServer, "testPin");
67 session_.StartPairing(PrivetV3Session::PairingType::PAIRING_TYPE_PINCODE, 158
68 base::Bind(&PrivetV3SessionTest::OnPairingStarted, 159 EXPECT_CALL(*this, OnPairingStarted(Result::STATUS_SUCCESS)).Times(1);
69 base::Unretained(this))); 160 EXPECT_CALL(*this, OnPostData(_))
70 run_loop.Run(); 161 .WillOnce(
71 } 162 testing::Invoke([this, &spake](const base::DictionaryValue& data) {
72 163 std::string pairing_type;
73 { 164 EXPECT_TRUE(data.GetString("pairing", &pairing_type));
74 base::RunLoop run_loop; 165 EXPECT_EQ("embeddedCode", pairing_type);
75 EXPECT_CALL(*this, OnCodeConfirmed(PrivetV3Session::Result::STATUS_SUCCESS)) 166
76 .Times(1) 167 std::string crypto_type;
77 .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit)); 168 EXPECT_TRUE(data.GetString("crypto", &crypto_type));
78 session_.ConfirmCode("1234", 169 EXPECT_EQ("p224_spake2", crypto_type);
79 base::Bind(&PrivetV3SessionTest::OnCodeConfirmed, 170
80 base::Unretained(this))); 171 std::string device_commitment;
81 run_loop.Run(); 172 base::Base64Encode(spake.GetNextMessage(), &device_commitment);
82 } 173 fetcher_factory_.SetFakeResponse(
174 GURL("http://host/privet/v3/pairing/start"),
175 base::StringPrintf(
176 "{\"deviceCommitment\":\"%s\",\"sessionId\":\"testId\"}",
177 device_commitment.c_str()),
178 net::HTTP_OK, net::URLRequestStatus::SUCCESS);
179 }));
180 session_.StartPairing(PairingType::PAIRING_TYPE_EMBEDDEDCODE,
181 base::Bind(&PrivetV3SessionTest::OnPairingStarted,
182 base::Unretained(this)));
183 base::RunLoop().RunUntilIdle();
184
185 EXPECT_CALL(*this, OnCodeConfirmed(Result::STATUS_SUCCESS)).Times(1);
186 EXPECT_CALL(*this, OnPostData(_))
187 .WillOnce(
188 testing::Invoke([this, &spake](const base::DictionaryValue& data) {
189 std::string commitment_base64;
190 EXPECT_TRUE(data.GetString("clientCommitment", &commitment_base64));
191 std::string commitment;
192 EXPECT_TRUE(base::Base64Decode(commitment_base64, &commitment));
193
194 std::string session_id;
195 EXPECT_TRUE(data.GetString("sessionId", &session_id));
196 EXPECT_EQ("testId", session_id);
197
198 EXPECT_EQ(spake.ProcessMessage(commitment),
199 crypto::P224EncryptedKeyExchange::kResultPending);
200
201 std::string fingerprint("testFinterprint");
202 std::string fingerprint_base64;
203 base::Base64Encode(fingerprint, &fingerprint_base64);
204
205 crypto::HMAC hmac(crypto::HMAC::SHA256);
206 const std::string& key = spake.GetUnverifiedKey();
207 EXPECT_TRUE(hmac.Init(key));
208 std::string signature(hmac.DigestLength(), ' ');
209 EXPECT_TRUE(hmac.Sign(fingerprint, reinterpret_cast<unsigned char*>(
210 string_as_array(&signature)),
211 signature.size()));
212
213 std::string signature_base64;
214 base::Base64Encode(signature, &signature_base64);
215
216 fetcher_factory_.SetFakeResponse(
217 GURL("http://host/privet/v3/pairing/confirm"),
218 base::StringPrintf(
219 "{\"certFingerprint\":\"%s\",\"certSignature\":\"%s\"}",
220 fingerprint_base64.c_str(), signature_base64.c_str()),
221 net::HTTP_OK, net::URLRequestStatus::SUCCESS);
222 }));
223 session_.ConfirmCode("testPin",
224 base::Bind(&PrivetV3SessionTest::OnCodeConfirmed,
225 base::Unretained(this)));
226 base::RunLoop().RunUntilIdle();
83 } 227 }
84 228
85 // TODO(vitalybuka): replace PrivetHTTPClient with regular URL fetcher and 229 // TODO(vitalybuka): replace PrivetHTTPClient with regular URL fetcher and
86 // implement SendMessage test. 230 // implement SendMessage test.
87 231
88 } // namespace
89
90 } // namespace local_discovery 232 } // namespace local_discovery
OLDNEW
« no previous file with comments | « chrome/browser/local_discovery/privetv3_session.cc ('k') | chrome/test/data/extensions/api_test/gcd_private/api/session.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698