1c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
2c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Copyright (C) 2013 The Android Open Source Project
3c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
4c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Licensed under the Apache License, Version 2.0 (the "License");
5c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// you may not use this file except in compliance with the License.
6c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// You may obtain a copy of the License at
7c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
8c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//      http://www.apache.org/licenses/LICENSE-2.0
9c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
10c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Unless required by applicable law or agreed to in writing, software
11c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// distributed under the License is distributed on an "AS IS" BASIS,
12c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// See the License for the specific language governing permissions and
14c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// limitations under the License.
15c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
165a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
175a3f23a122566b53e230b1132c0241411016386aChristopher Wiley#ifndef SHILL_CRYPTO_UTIL_PROXY_H_
185a3f23a122566b53e230b1132c0241411016386aChristopher Wiley#define SHILL_CRYPTO_UTIL_PROXY_H_
195a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
20cd47732488cd101eaf0d3558dde5a7d4e4fc260bBen Chan#include <memory>
215a3f23a122566b53e230b1132c0241411016386aChristopher Wiley#include <string>
225a3f23a122566b53e230b1132c0241411016386aChristopher Wiley#include <vector>
235a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
245a3f23a122566b53e230b1132c0241411016386aChristopher Wiley#include <base/cancelable_callback.h>
25cc67c52a2c00f90e877971d552208dd99825d84eBen Chan#include <base/macros.h>
265a3f23a122566b53e230b1132c0241411016386aChristopher Wiley#include <base/memory/weak_ptr.h>
27a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan#include <base/strings/stringprintf.h>
2803e6719bae1e0903d94853b896673a033196bcf5Alex Vakulenko#include <brillo/minijail/minijail.h>
295a3f23a122566b53e230b1132c0241411016386aChristopher Wiley#include <gtest/gtest_prod.h>  // for FRIEND_TEST
305a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
315a3f23a122566b53e230b1132c0241411016386aChristopher Wiley#include "shill/callbacks.h"
325a3f23a122566b53e230b1132c0241411016386aChristopher Wiley#include "shill/error.h"
338d6b59704591ba9fad57751858835dc332dbdd37Peter Qiu#include "shill/net/io_handler.h"
349151894faea5fa8ccd7d538976390fc95f37d13eSamuel Tan#include "shill/shims/protos/crypto_util.pb.h"
355a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
365a3f23a122566b53e230b1132c0241411016386aChristopher Wileynamespace shill {
375a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
385a3f23a122566b53e230b1132c0241411016386aChristopher Wileyclass EventDispatcher;
395a3f23a122566b53e230b1132c0241411016386aChristopher Wileyclass FileIO;
40304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawalclass ProcessManager;
415a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
425a3f23a122566b53e230b1132c0241411016386aChristopher Wileyclass CryptoUtilProxy : public base::SupportsWeakPtr<CryptoUtilProxy> {
435a3f23a122566b53e230b1132c0241411016386aChristopher Wiley public:
445a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  static const char kCommandVerify[];
455a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  static const char kCommandEncrypt[];
465a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  static const char kCryptoUtilShimPath[];
475a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
4813d581fa047118d065f41eb1d0da203cf0a49b07mukesh agrawal  explicit CryptoUtilProxy(EventDispatcher* dispatcher);
495a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  virtual ~CryptoUtilProxy();
505a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
515a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  // Verify credentials for the currently connected endpoint of
525a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  // |connected_service|.  This is a fairly expensive/time consuming operation.
535a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  // Returns true if we've succeeded in kicking off a job to an external shim
545a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  // to verify credentials.  |result_callback| will be called with the actual
555a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  // result of the job, either true, or false with a descriptive error.
565447d2e616b657a36ef878ae35c77f7d2f4d2c8eChristopher Wiley  //
575447d2e616b657a36ef878ae35c77f7d2f4d2c8eChristopher Wiley  // |certificate| should be a device certificate in PEM format.
585447d2e616b657a36ef878ae35c77f7d2f4d2c8eChristopher Wiley  // |public_key| is a base64 encoded DER RSAPublicKey format public key.
595447d2e616b657a36ef878ae35c77f7d2f4d2c8eChristopher Wiley  // |nonce| has no particular format requirements.
605447d2e616b657a36ef878ae35c77f7d2f4d2c8eChristopher Wiley  // |signed_data| is the base64 encoded signed string given by the device.
615447d2e616b657a36ef878ae35c77f7d2f4d2c8eChristopher Wiley  // |destination_udn| has no format requirements.
625447d2e616b657a36ef878ae35c77f7d2f4d2c8eChristopher Wiley  // |ssid| has no constraints.
635447d2e616b657a36ef878ae35c77f7d2f4d2c8eChristopher Wiley  // |bssid| should be in the human readable format: 00:11:22:33:44:55.
64a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart  virtual bool VerifyDestination(const std::string& certificate,
65a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart                                 const std::string& public_key,
66a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart                                 const std::string& nonce,
67a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart                                 const std::string& signed_data,
68a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart                                 const std::string& destination_udn,
69a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart                                 const std::vector<uint8_t>& ssid,
70a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart                                 const std::string& bssid,
71a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart                                 const ResultBoolCallback& result_callback,
72a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart                                 Error* error);
735a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
745447d2e616b657a36ef878ae35c77f7d2f4d2c8eChristopher Wiley  // Encrypt |data| under |public_key|.  This is a fairly time consuming
755a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  // process.  Returns true if we've succeeded in kicking off a job to an
765a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  // external shim to sign the data.  |result_callback| will be called with the
775a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  // results of the operation: an empty string and a descriptive error or the
785a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  // base64 encoded bytes of the encrypted data.
795447d2e616b657a36ef878ae35c77f7d2f4d2c8eChristopher Wiley  //
805447d2e616b657a36ef878ae35c77f7d2f4d2c8eChristopher Wiley  // |public_key| is a base64 encoded DER RSAPublicKey format public key.
815447d2e616b657a36ef878ae35c77f7d2f4d2c8eChristopher Wiley  // |data| has no particular format requirements.
82a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart  virtual bool EncryptData(const std::string& public_key,
83a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart                           const std::string& data,
84a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart                           const ResultStringCallback& result_callback,
85a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart                           Error* error);
868a5322984f2d81bcbfd8d44c59747a11bd9b904bAlex Vakulenko
875a3f23a122566b53e230b1132c0241411016386aChristopher Wiley private:
885a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  friend class CryptoUtilProxyTest;
895a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  friend class MockCryptoUtilProxy;
905a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  FRIEND_TEST(CryptoUtilProxyTest, BasicAPIUsage);
915a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  FRIEND_TEST(CryptoUtilProxyTest, FailuresReturnValues);
925a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  FRIEND_TEST(CryptoUtilProxyTest, OnlyOneInstanceInFlightAtATime);
935a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  FRIEND_TEST(CryptoUtilProxyTest, ShimLifeTime);
945a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  FRIEND_TEST(CryptoUtilProxyTest, TimeoutsTriggerFailure);
95b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley  FRIEND_TEST(CryptoUtilProxyTest, ShimCleanedBeforeCallback);
965a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
975a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  static const char kDestinationVerificationUser[];
98304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal  static const uint64_t kRequiredCapabilities;
995a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  static const int kShimJobTimeoutMilliseconds;
1005a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
1015a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  // Helper method for parsing the proto buffer return codes sent back by the
1025a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  // shim.
103a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart  static bool ParseResponseReturnCode(int proto_return_code, Error* e);
1045a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
1055a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  // Kick off a run of the shim to verify credentials or sign data.  Callers
1065a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  // pass in the command they want to run on the shim (literally a command line
1075a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  // argument to the shim), and a handler to handle the result.  The handler is
1085a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  // called both on errors, timeouts, and success.  Behind the scenes, we first
1095a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  // send |input| down to the shim through a pipe to its stdin, then wait for
1105a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  // bytes to comes back over a pipe connected to the shim's stdout.
111a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart  virtual bool StartShimForCommand(const std::string& command,
112a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart                                   const std::string& input,
113a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart                                   const StringCallback& result_handler);
1145a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  // This is the big hammer we use to clean up past shim state.
115a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart  virtual void CleanupShim(const Error& shim_result);
116304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal  virtual void OnShimDeath(int exit_status);
1175a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
11813d581fa047118d065f41eb1d0da203cf0a49b07mukesh agrawal  // Callbacks that handle IO operations between shill and the shim.
11913d581fa047118d065f41eb1d0da203cf0a49b07mukesh agrawal  // Called on changes in file descriptor state.
1205a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  void HandleShimStdinReady(int fd);
121a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart  void HandleShimOutput(InputData* data);
122a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart  void HandleShimReadError(const std::string& error_msg);
123a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart  void HandleShimError(const Error& error);
1245a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  void HandleShimTimeout();
1255a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  // Used to handle the final result of both operations.  |result| is a
1265a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  // seriallized protocol buffer or an empty string on error.  On error,
1275a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  // |error| is filled in with an appropriate error condition.
1285a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  // |result_callback| is a callback from the original caller (the manager).
129a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart  void HandleVerifyResult(const ResultBoolCallback& result_handler,
130a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart                          const std::string& result,
131a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart                          const Error& error);
132a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart  void HandleEncryptResult(const ResultStringCallback& result_handler,
133a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart                           const std::string& result,
134a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart                           const Error& error);
135a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart
136a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart  EventDispatcher* dispatcher_;
137304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal  ProcessManager* process_manager_;
138a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart  FileIO* file_io_;
1395a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  std::string input_buffer_;
1405a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  std::string::const_iterator next_input_byte_;
1415a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  std::string output_buffer_;
1425a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  int shim_stdin_;
1435a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  int shim_stdout_;
1445a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  pid_t shim_pid_;
145cd47732488cd101eaf0d3558dde5a7d4e4fc260bBen Chan  std::unique_ptr<IOHandler> shim_stdin_handler_;
146cd47732488cd101eaf0d3558dde5a7d4e4fc260bBen Chan  std::unique_ptr<IOHandler> shim_stdout_handler_;
14767e425e5af9b28ffff2c17f879e70f9f6a4e10e9Christopher Wiley  Error shim_result_;
1485a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  StringCallback result_handler_;
1495a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  base::CancelableClosure shim_job_timeout_callback_;
1505a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
1515a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  DISALLOW_COPY_AND_ASSIGN(CryptoUtilProxy);
1525a3f23a122566b53e230b1132c0241411016386aChristopher Wiley};
1535a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
1545a3f23a122566b53e230b1132c0241411016386aChristopher Wiley}  // namespace shill
1555a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
1565a3f23a122566b53e230b1132c0241411016386aChristopher Wiley#endif  // SHILL_CRYPTO_UTIL_PROXY_H_
157