13daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi//
23daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi// Copyright (C) 2014 The Android Open Source Project
33daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi//
43daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi// Licensed under the Apache License, Version 2.0 (the "License");
53daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi// you may not use this file except in compliance with the License.
63daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi// You may obtain a copy of the License at
73daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi//
83daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi//      http://www.apache.org/licenses/LICENSE-2.0
93daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi//
103daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi// Unless required by applicable law or agreed to in writing, software
113daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi// distributed under the License is distributed on an "AS IS" BASIS,
123daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi// See the License for the specific language governing permissions and
143daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi// limitations under the License.
153daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi//
166bead48129845a2bc0d6ff347f3d7e232004d59Nam T. Nguyen
170752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn#include <stdio.h>
180752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn#include <sysexits.h>
190752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn
2045fc1234b4f1a1c1cfdd44774350a70b26b9b630Alex Vakulenko#include <memory>
21b91fd4923f411705be97fbc5c0ada37481c0cd8dDarren Krahn#include <string>
2245fc1234b4f1a1c1cfdd44774350a70b26b9b630Alex Vakulenko
230752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn#include <base/command_line.h>
242e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn#include <base/files/file_util.h>
250752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn#include <base/message_loop/message_loop.h>
26e270d8c69ab46b2ad2973d5b9395aae7c1f52bf6Alex Vakulenko#include <brillo/bind_lambda.h>
27e270d8c69ab46b2ad2973d5b9395aae7c1f52bf6Alex Vakulenko#include <brillo/daemons/daemon.h>
28e270d8c69ab46b2ad2973d5b9395aae7c1f52bf6Alex Vakulenko#include <brillo/syslog_logging.h>
290752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn
30b91fd4923f411705be97fbc5c0ada37481c0cd8dDarren Krahn#include "attestation/client/dbus_proxy.h"
31b91fd4923f411705be97fbc5c0ada37481c0cd8dDarren Krahn#include "attestation/common/attestation_ca.pb.h"
322e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn#include "attestation/common/crypto_utility_impl.h"
33b91fd4923f411705be97fbc5c0ada37481c0cd8dDarren Krahn#include "attestation/common/interface.pb.h"
3459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn#include "attestation/common/print_interface_proto.h"
356bead48129845a2bc0d6ff347f3d7e232004d59Nam T. Nguyen
360752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahnnamespace attestation {
370752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn
3862c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahnconst char kCreateAndCertifyCommand[] = "create_and_certify";
390752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahnconst char kCreateCommand[] = "create";
406222defa52eb13c0d90673f642f2647f7753478bDarren Krahnconst char kInfoCommand[] = "info";
41cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahnconst char kEndorsementCommand[] = "endorsement";
42566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahnconst char kAttestationKeyCommand[] = "attestation_key";
432e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahnconst char kActivateCommand[] = "activate";
442e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahnconst char kEncryptForActivateCommand[] = "encrypt_for_activate";
45bc0c74963418442991072b2c87baec839eec9c20Darren Krahnconst char kEncryptCommand[] = "encrypt";
46bc0c74963418442991072b2c87baec839eec9c20Darren Krahnconst char kDecryptCommand[] = "decrypt";
47ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahnconst char kSignCommand[] = "sign";
48ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahnconst char kVerifyCommand[] = "verify";
49594849c7cf872d055575277b930f4f596bef1988Darren Krahnconst char kRegisterCommand[] = "register";
500752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahnconst char kUsage[] = R"(
510752bd25ba9f45c07bc989d42bf5272133a85afaDarren KrahnUsage: attestation_client <command> [<args>]
520752bd25ba9f45c07bc989d42bf5272133a85afaDarren KrahnCommands:
5362c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  create_and_certify [--user=<email>] [--label=<keylabel>]
5462c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn      Creates a key and requests certification by the Google Attestation CA.
5562c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn      This is the default command.
56bc0c74963418442991072b2c87baec839eec9c20Darren Krahn  create [--user=<email>] [--label=<keylabel] [--usage=sign|decrypt]
5762c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn      Creates a certifiable key.
582e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn
5962c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  info [--user=<email>] [--label=<keylabel>]
6062c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn      Prints info about a key.
6162c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  endorsement
6262c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn      Prints info about the TPM endorsement.
6362c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  attestation_key
6462c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn      Prints info about the TPM attestation key.
652e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn
6662c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  activate --input=<input_file>
6762c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn      Activates an attestation key using the encrypted credential in
6862c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn      |input_file|.
6962c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  encrypt_for_activate --input=<input_file> --output=<output_file>
7062c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn      Encrypts the content of |input_file| as required by the TPM for activating
7162c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn      an attestation key. The result is written to |output_file|.
72bc0c74963418442991072b2c87baec839eec9c20Darren Krahn
73bc0c74963418442991072b2c87baec839eec9c20Darren Krahn  encrypt [--user=<email>] [--label=<keylabel>] --input=<input_file>
74bc0c74963418442991072b2c87baec839eec9c20Darren Krahn          --output=<output_file>
75ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      Encrypts the contents of |input_file| as required by the TPM for a decrypt
76bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      operation. The result is written to |output_file|.
77bc0c74963418442991072b2c87baec839eec9c20Darren Krahn  decrypt [--user=<email>] [--label=<keylabel>] --input=<input_file>
78ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      Decrypts the contents of |input_file|.
79ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn
80ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn  sign [--user=<email>] [--label=<keylabel>] --input=<input_file>
81ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn          [--output=<output_file>]
82ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      Signs the contents of |input_file|.
83ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn  verify [--user=<email>] [--label=<keylabel] --input=<signed_data_file>
84ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn          --signature=<signature_file>
85ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      Verifies the signature in |signature_file| against the contents of
86ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      |input_file|.
87594849c7cf872d055575277b930f4f596bef1988Darren Krahn
88594849c7cf872d055575277b930f4f596bef1988Darren Krahn  register [--user=<email>] [--label=<keylabel]
89594849c7cf872d055575277b930f4f596bef1988Darren Krahn      Registers a key with a PKCS #11 token.
900752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn)";
910752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn
920752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn// The Daemon class works well as a client loop as well.
93e270d8c69ab46b2ad2973d5b9395aae7c1f52bf6Alex Vakulenkousing ClientLoopBase = brillo::Daemon;
940752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn
950752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahnclass ClientLoop : public ClientLoopBase {
960752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn public:
970752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn  ClientLoop() = default;
980752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn  ~ClientLoop() override = default;
990752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn
1000752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn protected:
1010752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn  int OnInit() override {
1020752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn    int exit_code = ClientLoopBase::OnInit();
1030752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn    if (exit_code != EX_OK) {
1040752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn      return exit_code;
1050752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn    }
1060752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn    attestation_.reset(new attestation::DBusProxy());
1070752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn    if (!attestation_->Initialize()) {
1080752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn      return EX_UNAVAILABLE;
1090752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn    }
1100752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn    exit_code = ScheduleCommand();
1110752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn    if (exit_code == EX_USAGE) {
1120752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn      printf("%s", kUsage);
1130752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn    }
1140752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn    return exit_code;
1150752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn  }
1160752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn
1170752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn  void OnShutdown(int* exit_code) override {
1180752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn    attestation_.reset();
1190752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn    ClientLoopBase::OnShutdown(exit_code);
120b91fd4923f411705be97fbc5c0ada37481c0cd8dDarren Krahn  }
1210752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn
1220752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn private:
1230752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn  // Posts tasks according to the command line options.
1240752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn  int ScheduleCommand() {
1250752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn    base::Closure task;
12659d7aa26782d3c6efd707e3b936d56c893a2555aDarren Krahn    base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
12759d7aa26782d3c6efd707e3b936d56c893a2555aDarren Krahn    const auto& args = command_line->GetArgs();
128566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn    if (command_line->HasSwitch("help") || command_line->HasSwitch("h") ||
129bc0c74963418442991072b2c87baec839eec9c20Darren Krahn        (!args.empty() && args.front() == "help")) {
130566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn      return EX_USAGE;
131566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn    }
13262c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn    if (args.empty() || args.front() == kCreateAndCertifyCommand) {
1330752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn      task = base::Bind(&ClientLoop::CallCreateGoogleAttestedKey,
13459d7aa26782d3c6efd707e3b936d56c893a2555aDarren Krahn                        weak_factory_.GetWeakPtr(),
13559d7aa26782d3c6efd707e3b936d56c893a2555aDarren Krahn                        command_line->GetSwitchValueASCII("label"),
13659d7aa26782d3c6efd707e3b936d56c893a2555aDarren Krahn                        command_line->GetSwitchValueASCII("user"));
13762c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn    } else if (args.front() == kCreateCommand) {
138bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      std::string usage_str = command_line->GetSwitchValueASCII("usage");
139bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      KeyUsage usage;
140bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      if (usage_str.empty() || usage_str == "sign") {
141bc0c74963418442991072b2c87baec839eec9c20Darren Krahn        usage = KEY_USAGE_SIGN;
142bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      } else if (usage_str == "decrypt") {
143bc0c74963418442991072b2c87baec839eec9c20Darren Krahn        usage = KEY_USAGE_DECRYPT;
144bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      } else {
145bc0c74963418442991072b2c87baec839eec9c20Darren Krahn        return EX_USAGE;
146bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      }
14762c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn      task = base::Bind(&ClientLoop::CallCreateCertifiableKey,
14862c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn                        weak_factory_.GetWeakPtr(),
14962c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn                        command_line->GetSwitchValueASCII("label"),
150bc0c74963418442991072b2c87baec839eec9c20Darren Krahn                        command_line->GetSwitchValueASCII("user"),
151bc0c74963418442991072b2c87baec839eec9c20Darren Krahn                        usage);
1526222defa52eb13c0d90673f642f2647f7753478bDarren Krahn    } else if (args.front() == kInfoCommand) {
1536222defa52eb13c0d90673f642f2647f7753478bDarren Krahn      task = base::Bind(&ClientLoop::CallGetKeyInfo,
1546222defa52eb13c0d90673f642f2647f7753478bDarren Krahn                        weak_factory_.GetWeakPtr(),
1556222defa52eb13c0d90673f642f2647f7753478bDarren Krahn                        command_line->GetSwitchValueASCII("label"),
1566222defa52eb13c0d90673f642f2647f7753478bDarren Krahn                        command_line->GetSwitchValueASCII("user"));
157cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn    } else if (args.front() == kEndorsementCommand) {
158cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn      task = base::Bind(&ClientLoop::CallGetEndorsementInfo,
159cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn                        weak_factory_.GetWeakPtr());
160566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn    } else if (args.front() == kAttestationKeyCommand) {
161566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn      task = base::Bind(&ClientLoop::CallGetAttestationKeyInfo,
162566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn                        weak_factory_.GetWeakPtr());
1632e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    } else if (args.front() == kActivateCommand) {
1642e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      if (!command_line->HasSwitch("input")) {
1652e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn        return EX_USAGE;
1662e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      }
1672e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      std::string input;
1682e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      base::FilePath filename(command_line->GetSwitchValueASCII("input"));
1692e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      if (!base::ReadFileToString(filename, &input)) {
1702e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn        LOG(ERROR) << "Failed to read file: " << filename.value();
1712e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn        return EX_NOINPUT;
1722e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      }
1732e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      task = base::Bind(&ClientLoop::CallActivateAttestationKey,
1742e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn                        weak_factory_.GetWeakPtr(),
1752e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn                        input);
1762e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    } else if (args.front() == kEncryptForActivateCommand) {
1772e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      if (!command_line->HasSwitch("input") ||
1782e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn          !command_line->HasSwitch("output")) {
1792e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn        return EX_USAGE;
1802e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      }
1812e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      std::string input;
1822e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      base::FilePath filename(command_line->GetSwitchValueASCII("input"));
1832e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      if (!base::ReadFileToString(filename, &input)) {
1842e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn        LOG(ERROR) << "Failed to read file: " << filename.value();
1852e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn        return EX_NOINPUT;
1862e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      }
1872e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      task = base::Bind(&ClientLoop::EncryptForActivate,
1882e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn                        weak_factory_.GetWeakPtr(),
1892e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn                        input);
190bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    } else if (args.front() == kEncryptCommand) {
191bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      if (!command_line->HasSwitch("input") ||
192bc0c74963418442991072b2c87baec839eec9c20Darren Krahn          !command_line->HasSwitch("output")) {
193bc0c74963418442991072b2c87baec839eec9c20Darren Krahn        return EX_USAGE;
194bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      }
195bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      std::string input;
196bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      base::FilePath filename(command_line->GetSwitchValueASCII("input"));
197bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      if (!base::ReadFileToString(filename, &input)) {
198bc0c74963418442991072b2c87baec839eec9c20Darren Krahn        LOG(ERROR) << "Failed to read file: " << filename.value();
199bc0c74963418442991072b2c87baec839eec9c20Darren Krahn        return EX_NOINPUT;
200bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      }
201bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      task = base::Bind(&ClientLoop::Encrypt,
202bc0c74963418442991072b2c87baec839eec9c20Darren Krahn                        weak_factory_.GetWeakPtr(),
203bc0c74963418442991072b2c87baec839eec9c20Darren Krahn                        command_line->GetSwitchValueASCII("label"),
204bc0c74963418442991072b2c87baec839eec9c20Darren Krahn                        command_line->GetSwitchValueASCII("user"),
205bc0c74963418442991072b2c87baec839eec9c20Darren Krahn                        input);
206bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    } else if (args.front() == kDecryptCommand) {
207bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      if (!command_line->HasSwitch("input")) {
208bc0c74963418442991072b2c87baec839eec9c20Darren Krahn        return EX_USAGE;
209bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      }
210bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      std::string input;
211bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      base::FilePath filename(command_line->GetSwitchValueASCII("input"));
212bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      if (!base::ReadFileToString(filename, &input)) {
213bc0c74963418442991072b2c87baec839eec9c20Darren Krahn        LOG(ERROR) << "Failed to read file: " << filename.value();
214bc0c74963418442991072b2c87baec839eec9c20Darren Krahn        return EX_NOINPUT;
215bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      }
216bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      task = base::Bind(&ClientLoop::CallDecrypt,
217bc0c74963418442991072b2c87baec839eec9c20Darren Krahn                        weak_factory_.GetWeakPtr(),
218bc0c74963418442991072b2c87baec839eec9c20Darren Krahn                        command_line->GetSwitchValueASCII("label"),
219bc0c74963418442991072b2c87baec839eec9c20Darren Krahn                        command_line->GetSwitchValueASCII("user"),
220bc0c74963418442991072b2c87baec839eec9c20Darren Krahn                        input);
221ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    } else if (args.front() == kSignCommand) {
222ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      if (!command_line->HasSwitch("input")) {
223ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn        return EX_USAGE;
224ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      }
225ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      std::string input;
226ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      base::FilePath filename(command_line->GetSwitchValueASCII("input"));
227ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      if (!base::ReadFileToString(filename, &input)) {
228ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn        LOG(ERROR) << "Failed to read file: " << filename.value();
229ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn        return EX_NOINPUT;
230ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      }
231ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      task = base::Bind(&ClientLoop::CallSign,
232ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn                        weak_factory_.GetWeakPtr(),
233ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn                        command_line->GetSwitchValueASCII("label"),
234ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn                        command_line->GetSwitchValueASCII("user"),
235ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn                        input);
236ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    } else if (args.front() == kVerifyCommand) {
237ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      if (!command_line->HasSwitch("input") ||
238ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn          !command_line->HasSwitch("signature")) {
239ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn        return EX_USAGE;
240ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      }
241ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      std::string input;
242ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      base::FilePath filename(command_line->GetSwitchValueASCII("input"));
243ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      if (!base::ReadFileToString(filename, &input)) {
244ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn        LOG(ERROR) << "Failed to read file: " << filename.value();
245ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn        return EX_NOINPUT;
246ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      }
247ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      std::string signature;
248ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      base::FilePath filename2(command_line->GetSwitchValueASCII("signature"));
249ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      if (!base::ReadFileToString(filename2, &signature)) {
250ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn        LOG(ERROR) << "Failed to read file: " << filename2.value();
251ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn        return EX_NOINPUT;
252ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      }
253ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      task = base::Bind(&ClientLoop::VerifySignature,
254ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn                        weak_factory_.GetWeakPtr(),
255ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn                        command_line->GetSwitchValueASCII("label"),
256ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn                        command_line->GetSwitchValueASCII("user"),
257ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn                        input,
258ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn                        signature);
259594849c7cf872d055575277b930f4f596bef1988Darren Krahn    } else if (args.front() == kRegisterCommand) {
260594849c7cf872d055575277b930f4f596bef1988Darren Krahn      task = base::Bind(&ClientLoop::CallRegister,
261594849c7cf872d055575277b930f4f596bef1988Darren Krahn                        weak_factory_.GetWeakPtr(),
262594849c7cf872d055575277b930f4f596bef1988Darren Krahn                        command_line->GetSwitchValueASCII("label"),
263594849c7cf872d055575277b930f4f596bef1988Darren Krahn                        command_line->GetSwitchValueASCII("user"));
2640752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn    } else {
2650752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn      return EX_USAGE;
2660752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn    }
2670752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn    base::MessageLoop::current()->PostTask(FROM_HERE, task);
2680752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn    return EX_OK;
2690752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn  }
2700752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn
2716222defa52eb13c0d90673f642f2647f7753478bDarren Krahn  template <typename ProtobufType>
2726222defa52eb13c0d90673f642f2647f7753478bDarren Krahn  void PrintReplyAndQuit(const ProtobufType& reply) {
27359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn    printf("%s\n", GetProtoDebugString(reply).c_str());
2740752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn    Quit();
2750752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn  }
2760752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn
2772e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  void WriteOutput(const std::string& output) {
2782e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    base::FilePath filename(base::CommandLine::ForCurrentProcess()->
2792e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn        GetSwitchValueASCII("output"));
2802e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    if (base::WriteFile(filename, output.data(), output.size()) !=
2812e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn        static_cast<int>(output.size())) {
2822e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      LOG(ERROR) << "Failed to write file: " << filename.value();
2832e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      QuitWithExitCode(EX_IOERR);
2842e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    }
2852e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  }
2862e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn
28759d7aa26782d3c6efd707e3b936d56c893a2555aDarren Krahn  void CallCreateGoogleAttestedKey(const std::string& label,
28859d7aa26782d3c6efd707e3b936d56c893a2555aDarren Krahn                                   const std::string& username) {
289b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn    CreateGoogleAttestedKeyRequest request;
290b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn    request.set_key_label(label);
291b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn    request.set_key_type(KEY_TYPE_RSA);
292b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn    request.set_key_usage(KEY_USAGE_SIGN);
293b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn    request.set_certificate_profile(ENTERPRISE_MACHINE_CERTIFICATE);
294b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn    request.set_username(username);
2950752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn    attestation_->CreateGoogleAttestedKey(
296b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn        request,
2976222defa52eb13c0d90673f642f2647f7753478bDarren Krahn        base::Bind(&ClientLoop::PrintReplyAndQuit<CreateGoogleAttestedKeyReply>,
2986222defa52eb13c0d90673f642f2647f7753478bDarren Krahn                   weak_factory_.GetWeakPtr()));
2996222defa52eb13c0d90673f642f2647f7753478bDarren Krahn  }
3006222defa52eb13c0d90673f642f2647f7753478bDarren Krahn
3016222defa52eb13c0d90673f642f2647f7753478bDarren Krahn  void CallGetKeyInfo(const std::string& label, const std::string& username) {
3026222defa52eb13c0d90673f642f2647f7753478bDarren Krahn    GetKeyInfoRequest request;
3036222defa52eb13c0d90673f642f2647f7753478bDarren Krahn    request.set_key_label(label);
3046222defa52eb13c0d90673f642f2647f7753478bDarren Krahn    request.set_username(username);
3056222defa52eb13c0d90673f642f2647f7753478bDarren Krahn    attestation_->GetKeyInfo(
3066222defa52eb13c0d90673f642f2647f7753478bDarren Krahn        request,
3076222defa52eb13c0d90673f642f2647f7753478bDarren Krahn        base::Bind(&ClientLoop::PrintReplyAndQuit<GetKeyInfoReply>,
3080752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn                   weak_factory_.GetWeakPtr()));
30945fc1234b4f1a1c1cfdd44774350a70b26b9b630Alex Vakulenko  }
3100752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn
311cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn  void CallGetEndorsementInfo() {
312cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn    GetEndorsementInfoRequest request;
313cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn    request.set_key_type(KEY_TYPE_RSA);
314cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn    attestation_->GetEndorsementInfo(
315cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn        request,
316cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn        base::Bind(&ClientLoop::PrintReplyAndQuit<GetEndorsementInfoReply>,
317cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn                   weak_factory_.GetWeakPtr()));
318cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn  }
319cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn
320566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn  void CallGetAttestationKeyInfo() {
321566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn    GetAttestationKeyInfoRequest request;
322566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn    request.set_key_type(KEY_TYPE_RSA);
323566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn    attestation_->GetAttestationKeyInfo(
324566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn        request,
325566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn        base::Bind(&ClientLoop::PrintReplyAndQuit<GetAttestationKeyInfoReply>,
326566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn                   weak_factory_.GetWeakPtr()));
327566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn  }
328566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn
3292e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  void CallActivateAttestationKey(const std::string& input) {
3302e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    ActivateAttestationKeyRequest request;
3312e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    request.set_key_type(KEY_TYPE_RSA);
3322e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    request.mutable_encrypted_certificate()->ParseFromString(input);
3332e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    request.set_save_certificate(true);
3342e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    attestation_->ActivateAttestationKey(
3352e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn        request,
3362e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn        base::Bind(&ClientLoop::PrintReplyAndQuit<ActivateAttestationKeyReply>,
3372e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn                   weak_factory_.GetWeakPtr()));
3382e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  }
3392e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn
3402e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  void EncryptForActivate(const std::string& input) {
3412e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    GetEndorsementInfoRequest request;
3422e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    request.set_key_type(KEY_TYPE_RSA);
3432e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    attestation_->GetEndorsementInfo(
3442e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn        request,
3452e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn        base::Bind(&ClientLoop::EncryptForActivate2,
3462e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn                   weak_factory_.GetWeakPtr(),
3472e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn                   input));
3482e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  }
3492e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn
3502e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  void EncryptForActivate2(const std::string& input,
3512e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn                           const GetEndorsementInfoReply& endorsement_info) {
3522e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    if (endorsement_info.status() != STATUS_SUCCESS) {
3532e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      PrintReplyAndQuit(endorsement_info);
3542e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    }
3552e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    GetAttestationKeyInfoRequest request;
3562e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    request.set_key_type(KEY_TYPE_RSA);
3572e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    attestation_->GetAttestationKeyInfo(
3582e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn        request,
3592e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn        base::Bind(&ClientLoop::EncryptForActivate3,
3602e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn                   weak_factory_.GetWeakPtr(),
3612e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn                   input,
3622e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn                   endorsement_info));
3632e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  }
3642e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn
3652e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  void EncryptForActivate3(
3662e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      const std::string& input,
3672e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      const GetEndorsementInfoReply& endorsement_info,
3682e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      const GetAttestationKeyInfoReply& attestation_key_info) {
3692e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    if (attestation_key_info.status() != STATUS_SUCCESS) {
3702e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      PrintReplyAndQuit(attestation_key_info);
3712e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    }
3722e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    CryptoUtilityImpl crypto(nullptr);
3732e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    EncryptedIdentityCredential encrypted;
3742e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    if (!crypto.EncryptIdentityCredential(
3752e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn        input,
3762e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn        endorsement_info.ek_public_key(),
3772e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn        attestation_key_info.public_key_tpm_format(),
3782e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn        &encrypted)) {
3792e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      QuitWithExitCode(EX_SOFTWARE);
3802e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    }
3812e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    std::string output;
3822e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    encrypted.SerializeToString(&output);
3832e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    WriteOutput(output);
3842e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    Quit();
3852e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  }
3862e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn
38762c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  void CallCreateCertifiableKey(const std::string& label,
388bc0c74963418442991072b2c87baec839eec9c20Darren Krahn                                const std::string& username,
389bc0c74963418442991072b2c87baec839eec9c20Darren Krahn                                KeyUsage usage) {
39062c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn    CreateCertifiableKeyRequest request;
39162c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn    request.set_key_label(label);
39262c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn    request.set_username(username);
393bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    request.set_key_type(KEY_TYPE_RSA);
394bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    request.set_key_usage(usage);
39562c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn    attestation_->CreateCertifiableKey(
39662c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn        request,
39762c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn        base::Bind(&ClientLoop::PrintReplyAndQuit<CreateCertifiableKeyReply>,
39862c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn                   weak_factory_.GetWeakPtr()));
39962c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  }
40062c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn
401bc0c74963418442991072b2c87baec839eec9c20Darren Krahn  void Encrypt(const std::string& label,
402bc0c74963418442991072b2c87baec839eec9c20Darren Krahn               const std::string& username,
403bc0c74963418442991072b2c87baec839eec9c20Darren Krahn               const std::string& input) {
404bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    GetKeyInfoRequest request;
405bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    request.set_key_label(label);
406bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    request.set_username(username);
407bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    attestation_->GetKeyInfo(request, base::Bind(&ClientLoop::Encrypt2,
408bc0c74963418442991072b2c87baec839eec9c20Darren Krahn                                                 weak_factory_.GetWeakPtr(),
409bc0c74963418442991072b2c87baec839eec9c20Darren Krahn                                                 input));
410bc0c74963418442991072b2c87baec839eec9c20Darren Krahn  }
411bc0c74963418442991072b2c87baec839eec9c20Darren Krahn
412bc0c74963418442991072b2c87baec839eec9c20Darren Krahn  void Encrypt2(const std::string& input,
413bc0c74963418442991072b2c87baec839eec9c20Darren Krahn                const GetKeyInfoReply& key_info) {
414bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    CryptoUtilityImpl crypto(nullptr);
415bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    std::string output;
416bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    if (!crypto.EncryptForUnbind(key_info.public_key(), input, &output)) {
417bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      QuitWithExitCode(EX_SOFTWARE);
418bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    }
419bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    WriteOutput(output);
420bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    Quit();
421bc0c74963418442991072b2c87baec839eec9c20Darren Krahn  }
422bc0c74963418442991072b2c87baec839eec9c20Darren Krahn
423bc0c74963418442991072b2c87baec839eec9c20Darren Krahn  void CallDecrypt(const std::string& label,
424bc0c74963418442991072b2c87baec839eec9c20Darren Krahn                   const std::string& username,
425bc0c74963418442991072b2c87baec839eec9c20Darren Krahn                   const std::string& input) {
426bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    DecryptRequest request;
427bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    request.set_key_label(label);
428bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    request.set_username(username);
429bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    request.set_encrypted_data(input);
430bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    attestation_->Decrypt(
431bc0c74963418442991072b2c87baec839eec9c20Darren Krahn        request,
432bc0c74963418442991072b2c87baec839eec9c20Darren Krahn        base::Bind(&ClientLoop::PrintReplyAndQuit<DecryptReply>,
433bc0c74963418442991072b2c87baec839eec9c20Darren Krahn                   weak_factory_.GetWeakPtr()));
434bc0c74963418442991072b2c87baec839eec9c20Darren Krahn  }
435bc0c74963418442991072b2c87baec839eec9c20Darren Krahn
436ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn  void CallSign(const std::string& label,
437ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn                const std::string& username,
438ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn                const std::string& input) {
439ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    SignRequest request;
440ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    request.set_key_label(label);
441ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    request.set_username(username);
442ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    request.set_data_to_sign(input);
443ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    attestation_->Sign(request, base::Bind(&ClientLoop::OnSignComplete,
444ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn                                           weak_factory_.GetWeakPtr()));
445ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn  }
446ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn
447ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn  void OnSignComplete(const SignReply& reply) {
448ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    if (reply.status() == STATUS_SUCCESS &&
449ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn        base::CommandLine::ForCurrentProcess()->HasSwitch("output")) {
450ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      WriteOutput(reply.signature());
451ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    }
452ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    PrintReplyAndQuit<SignReply>(reply);
453ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn  }
454ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn
455ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn  void VerifySignature(const std::string& label,
456ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn                       const std::string& username,
457ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn                       const std::string& input,
458ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn                       const std::string& signature) {
459ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    GetKeyInfoRequest request;
460ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    request.set_key_label(label);
461ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    request.set_username(username);
462ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    attestation_->GetKeyInfo(request, base::Bind(&ClientLoop::VerifySignature2,
463ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn                                                 weak_factory_.GetWeakPtr(),
464ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn                                                 input, signature));
465ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn  }
466ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn
467ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn  void VerifySignature2(const std::string& input,
468ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn                        const std::string& signature,
469ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn                        const GetKeyInfoReply& key_info) {
470ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    CryptoUtilityImpl crypto(nullptr);
471ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    if (crypto.VerifySignature(key_info.public_key(), input, signature)) {
472ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      printf("Signature is OK!\n");
473ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    } else {
474ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      printf("Signature is BAD!\n");
475ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    }
476ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    Quit();
477ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn  }
478ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn
479594849c7cf872d055575277b930f4f596bef1988Darren Krahn  void CallRegister(const std::string& label, const std::string& username) {
480594849c7cf872d055575277b930f4f596bef1988Darren Krahn    RegisterKeyWithChapsTokenRequest request;
481594849c7cf872d055575277b930f4f596bef1988Darren Krahn    request.set_key_label(label);
482594849c7cf872d055575277b930f4f596bef1988Darren Krahn    request.set_username(username);
483594849c7cf872d055575277b930f4f596bef1988Darren Krahn    attestation_->RegisterKeyWithChapsToken(request, base::Bind(
484594849c7cf872d055575277b930f4f596bef1988Darren Krahn        &ClientLoop::PrintReplyAndQuit<RegisterKeyWithChapsTokenReply>,
485594849c7cf872d055575277b930f4f596bef1988Darren Krahn        weak_factory_.GetWeakPtr()));
486594849c7cf872d055575277b930f4f596bef1988Darren Krahn  }
487594849c7cf872d055575277b930f4f596bef1988Darren Krahn
4880752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn  std::unique_ptr<attestation::AttestationInterface> attestation_;
4890752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn
4900752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn  // Declare this last so weak pointers will be destroyed first.
4910752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn  base::WeakPtrFactory<ClientLoop> weak_factory_{this};
4920752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn
4930752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn  DISALLOW_COPY_AND_ASSIGN(ClientLoop);
4940752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn};
4950752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn
4960752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn}  // namespace attestation
4970752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn
4980752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahnint main(int argc, char* argv[]) {
4990752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn  base::CommandLine::Init(argc, argv);
500b3c9cdcef463064d7ac8f1e6b4b88e62433f9d5dUtkarsh Sanghi  brillo::InitLog(brillo::kLogToStderr);
5010752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn  attestation::ClientLoop loop;
5020752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn  return loop.Run();
5036bead48129845a2bc0d6ff347f3d7e232004d59Nam T. Nguyen}
504