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"),
1504dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn                        command_line->GetSwitchValueASCII("user"), usage);
1516222defa52eb13c0d90673f642f2647f7753478bDarren Krahn    } else if (args.front() == kInfoCommand) {
1524dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      task = base::Bind(&ClientLoop::CallGetKeyInfo, weak_factory_.GetWeakPtr(),
1536222defa52eb13c0d90673f642f2647f7753478bDarren Krahn                        command_line->GetSwitchValueASCII("label"),
1546222defa52eb13c0d90673f642f2647f7753478bDarren Krahn                        command_line->GetSwitchValueASCII("user"));
155cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn    } else if (args.front() == kEndorsementCommand) {
156cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn      task = base::Bind(&ClientLoop::CallGetEndorsementInfo,
157cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn                        weak_factory_.GetWeakPtr());
158566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn    } else if (args.front() == kAttestationKeyCommand) {
159566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn      task = base::Bind(&ClientLoop::CallGetAttestationKeyInfo,
160566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn                        weak_factory_.GetWeakPtr());
1612e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    } else if (args.front() == kActivateCommand) {
1622e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      if (!command_line->HasSwitch("input")) {
1632e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn        return EX_USAGE;
1642e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      }
1652e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      std::string input;
1662e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      base::FilePath filename(command_line->GetSwitchValueASCII("input"));
1672e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      if (!base::ReadFileToString(filename, &input)) {
1682e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn        LOG(ERROR) << "Failed to read file: " << filename.value();
1692e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn        return EX_NOINPUT;
1702e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      }
1712e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      task = base::Bind(&ClientLoop::CallActivateAttestationKey,
1724dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn                        weak_factory_.GetWeakPtr(), input);
1732e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    } else if (args.front() == kEncryptForActivateCommand) {
1742e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      if (!command_line->HasSwitch("input") ||
1752e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn          !command_line->HasSwitch("output")) {
1762e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn        return EX_USAGE;
1772e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      }
1782e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      std::string input;
1792e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      base::FilePath filename(command_line->GetSwitchValueASCII("input"));
1802e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      if (!base::ReadFileToString(filename, &input)) {
1812e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn        LOG(ERROR) << "Failed to read file: " << filename.value();
1822e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn        return EX_NOINPUT;
1832e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      }
1842e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      task = base::Bind(&ClientLoop::EncryptForActivate,
1854dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn                        weak_factory_.GetWeakPtr(), input);
186bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    } else if (args.front() == kEncryptCommand) {
187bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      if (!command_line->HasSwitch("input") ||
188bc0c74963418442991072b2c87baec839eec9c20Darren Krahn          !command_line->HasSwitch("output")) {
189bc0c74963418442991072b2c87baec839eec9c20Darren Krahn        return EX_USAGE;
190bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      }
191bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      std::string input;
192bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      base::FilePath filename(command_line->GetSwitchValueASCII("input"));
193bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      if (!base::ReadFileToString(filename, &input)) {
194bc0c74963418442991072b2c87baec839eec9c20Darren Krahn        LOG(ERROR) << "Failed to read file: " << filename.value();
195bc0c74963418442991072b2c87baec839eec9c20Darren Krahn        return EX_NOINPUT;
196bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      }
1974dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      task = base::Bind(&ClientLoop::Encrypt, weak_factory_.GetWeakPtr(),
198bc0c74963418442991072b2c87baec839eec9c20Darren Krahn                        command_line->GetSwitchValueASCII("label"),
1994dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn                        command_line->GetSwitchValueASCII("user"), input);
200bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    } else if (args.front() == kDecryptCommand) {
201bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      if (!command_line->HasSwitch("input")) {
202bc0c74963418442991072b2c87baec839eec9c20Darren Krahn        return EX_USAGE;
203bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      }
204bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      std::string input;
205bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      base::FilePath filename(command_line->GetSwitchValueASCII("input"));
206bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      if (!base::ReadFileToString(filename, &input)) {
207bc0c74963418442991072b2c87baec839eec9c20Darren Krahn        LOG(ERROR) << "Failed to read file: " << filename.value();
208bc0c74963418442991072b2c87baec839eec9c20Darren Krahn        return EX_NOINPUT;
209bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      }
2104dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      task = base::Bind(&ClientLoop::CallDecrypt, weak_factory_.GetWeakPtr(),
211bc0c74963418442991072b2c87baec839eec9c20Darren Krahn                        command_line->GetSwitchValueASCII("label"),
2124dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn                        command_line->GetSwitchValueASCII("user"), input);
213ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    } else if (args.front() == kSignCommand) {
214ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      if (!command_line->HasSwitch("input")) {
215ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn        return EX_USAGE;
216ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      }
217ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      std::string input;
218ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      base::FilePath filename(command_line->GetSwitchValueASCII("input"));
219ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      if (!base::ReadFileToString(filename, &input)) {
220ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn        LOG(ERROR) << "Failed to read file: " << filename.value();
221ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn        return EX_NOINPUT;
222ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      }
2234dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      task = base::Bind(&ClientLoop::CallSign, weak_factory_.GetWeakPtr(),
224ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn                        command_line->GetSwitchValueASCII("label"),
2254dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn                        command_line->GetSwitchValueASCII("user"), input);
226ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    } else if (args.front() == kVerifyCommand) {
227ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      if (!command_line->HasSwitch("input") ||
228ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn          !command_line->HasSwitch("signature")) {
229ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn        return EX_USAGE;
230ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      }
231ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      std::string input;
232ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      base::FilePath filename(command_line->GetSwitchValueASCII("input"));
233ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      if (!base::ReadFileToString(filename, &input)) {
234ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn        LOG(ERROR) << "Failed to read file: " << filename.value();
235ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn        return EX_NOINPUT;
236ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      }
237ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      std::string signature;
238ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      base::FilePath filename2(command_line->GetSwitchValueASCII("signature"));
239ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      if (!base::ReadFileToString(filename2, &signature)) {
240ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn        LOG(ERROR) << "Failed to read file: " << filename2.value();
241ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn        return EX_NOINPUT;
242ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      }
2434dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      task = base::Bind(
2444dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn          &ClientLoop::VerifySignature, weak_factory_.GetWeakPtr(),
2454dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn          command_line->GetSwitchValueASCII("label"),
2464dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn          command_line->GetSwitchValueASCII("user"), input, signature);
247594849c7cf872d055575277b930f4f596bef1988Darren Krahn    } else if (args.front() == kRegisterCommand) {
2484dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      task = base::Bind(&ClientLoop::CallRegister, weak_factory_.GetWeakPtr(),
249594849c7cf872d055575277b930f4f596bef1988Darren Krahn                        command_line->GetSwitchValueASCII("label"),
250594849c7cf872d055575277b930f4f596bef1988Darren Krahn                        command_line->GetSwitchValueASCII("user"));
2510752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn    } else {
2520752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn      return EX_USAGE;
2530752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn    }
2540752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn    base::MessageLoop::current()->PostTask(FROM_HERE, task);
2550752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn    return EX_OK;
2560752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn  }
2570752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn
2586222defa52eb13c0d90673f642f2647f7753478bDarren Krahn  template <typename ProtobufType>
2596222defa52eb13c0d90673f642f2647f7753478bDarren Krahn  void PrintReplyAndQuit(const ProtobufType& reply) {
26059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn    printf("%s\n", GetProtoDebugString(reply).c_str());
2610752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn    Quit();
2620752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn  }
2630752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn
2642e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  void WriteOutput(const std::string& output) {
2654dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn    base::FilePath filename(
2664dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn        base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII("output"));
2672e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    if (base::WriteFile(filename, output.data(), output.size()) !=
2682e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn        static_cast<int>(output.size())) {
2692e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      LOG(ERROR) << "Failed to write file: " << filename.value();
2702e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      QuitWithExitCode(EX_IOERR);
2712e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    }
2722e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  }
2732e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn
27459d7aa26782d3c6efd707e3b936d56c893a2555aDarren Krahn  void CallCreateGoogleAttestedKey(const std::string& label,
27559d7aa26782d3c6efd707e3b936d56c893a2555aDarren Krahn                                   const std::string& username) {
276b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn    CreateGoogleAttestedKeyRequest request;
277b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn    request.set_key_label(label);
278b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn    request.set_key_type(KEY_TYPE_RSA);
279b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn    request.set_key_usage(KEY_USAGE_SIGN);
280b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn    request.set_certificate_profile(ENTERPRISE_MACHINE_CERTIFICATE);
281b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn    request.set_username(username);
2820752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn    attestation_->CreateGoogleAttestedKey(
283b48a50fc394b9c8a1059463c9eaba4c8d1985b9bDarren Krahn        request,
2846222defa52eb13c0d90673f642f2647f7753478bDarren Krahn        base::Bind(&ClientLoop::PrintReplyAndQuit<CreateGoogleAttestedKeyReply>,
2856222defa52eb13c0d90673f642f2647f7753478bDarren Krahn                   weak_factory_.GetWeakPtr()));
2866222defa52eb13c0d90673f642f2647f7753478bDarren Krahn  }
2876222defa52eb13c0d90673f642f2647f7753478bDarren Krahn
2886222defa52eb13c0d90673f642f2647f7753478bDarren Krahn  void CallGetKeyInfo(const std::string& label, const std::string& username) {
2896222defa52eb13c0d90673f642f2647f7753478bDarren Krahn    GetKeyInfoRequest request;
2906222defa52eb13c0d90673f642f2647f7753478bDarren Krahn    request.set_key_label(label);
2916222defa52eb13c0d90673f642f2647f7753478bDarren Krahn    request.set_username(username);
2926222defa52eb13c0d90673f642f2647f7753478bDarren Krahn    attestation_->GetKeyInfo(
2934dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn        request, base::Bind(&ClientLoop::PrintReplyAndQuit<GetKeyInfoReply>,
2944dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn                            weak_factory_.GetWeakPtr()));
29545fc1234b4f1a1c1cfdd44774350a70b26b9b630Alex Vakulenko  }
2960752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn
297cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn  void CallGetEndorsementInfo() {
298cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn    GetEndorsementInfoRequest request;
299cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn    request.set_key_type(KEY_TYPE_RSA);
300cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn    attestation_->GetEndorsementInfo(
301cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn        request,
302cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn        base::Bind(&ClientLoop::PrintReplyAndQuit<GetEndorsementInfoReply>,
303cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn                   weak_factory_.GetWeakPtr()));
304cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn  }
305cd5486df897619718b68223ebefc1322a1f5ab29Darren Krahn
306566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn  void CallGetAttestationKeyInfo() {
307566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn    GetAttestationKeyInfoRequest request;
308566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn    request.set_key_type(KEY_TYPE_RSA);
309566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn    attestation_->GetAttestationKeyInfo(
310566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn        request,
311566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn        base::Bind(&ClientLoop::PrintReplyAndQuit<GetAttestationKeyInfoReply>,
312566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn                   weak_factory_.GetWeakPtr()));
313566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn  }
314566c836c403212d5c13428b02ed65e5ff6e49a6bDarren Krahn
3152e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  void CallActivateAttestationKey(const std::string& input) {
3162e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    ActivateAttestationKeyRequest request;
3172e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    request.set_key_type(KEY_TYPE_RSA);
3182e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    request.mutable_encrypted_certificate()->ParseFromString(input);
3192e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    request.set_save_certificate(true);
3202e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    attestation_->ActivateAttestationKey(
3212e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn        request,
3222e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn        base::Bind(&ClientLoop::PrintReplyAndQuit<ActivateAttestationKeyReply>,
3232e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn                   weak_factory_.GetWeakPtr()));
3242e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  }
3252e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn
3262e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  void EncryptForActivate(const std::string& input) {
3272e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    GetEndorsementInfoRequest request;
3282e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    request.set_key_type(KEY_TYPE_RSA);
3292e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    attestation_->GetEndorsementInfo(
3304dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn        request, base::Bind(&ClientLoop::EncryptForActivate2,
3314dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn                            weak_factory_.GetWeakPtr(), input));
3322e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  }
3332e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn
3342e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  void EncryptForActivate2(const std::string& input,
3352e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn                           const GetEndorsementInfoReply& endorsement_info) {
3362e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    if (endorsement_info.status() != STATUS_SUCCESS) {
3372e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      PrintReplyAndQuit(endorsement_info);
3382e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    }
3392e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    GetAttestationKeyInfoRequest request;
3402e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    request.set_key_type(KEY_TYPE_RSA);
3412e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    attestation_->GetAttestationKeyInfo(
3422e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn        request,
3434dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn        base::Bind(&ClientLoop::EncryptForActivate3, weak_factory_.GetWeakPtr(),
3444dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn                   input, endorsement_info));
3452e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  }
3462e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn
3472e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  void EncryptForActivate3(
3482e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      const std::string& input,
3492e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      const GetEndorsementInfoReply& endorsement_info,
3502e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      const GetAttestationKeyInfoReply& attestation_key_info) {
3512e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    if (attestation_key_info.status() != STATUS_SUCCESS) {
3522e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      PrintReplyAndQuit(attestation_key_info);
3532e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    }
3542e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    CryptoUtilityImpl crypto(nullptr);
3552e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    EncryptedIdentityCredential encrypted;
3562e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    if (!crypto.EncryptIdentityCredential(
3574dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn            input, endorsement_info.ek_public_key(),
3584dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn            attestation_key_info.public_key_tpm_format(), &encrypted)) {
3592e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn      QuitWithExitCode(EX_SOFTWARE);
3602e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    }
3612e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    std::string output;
3622e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    encrypted.SerializeToString(&output);
3632e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    WriteOutput(output);
3642e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn    Quit();
3652e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn  }
3662e89ba764046e015ae90a1668f7cb3eb29cf509dDarren Krahn
36762c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  void CallCreateCertifiableKey(const std::string& label,
368bc0c74963418442991072b2c87baec839eec9c20Darren Krahn                                const std::string& username,
369bc0c74963418442991072b2c87baec839eec9c20Darren Krahn                                KeyUsage usage) {
37062c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn    CreateCertifiableKeyRequest request;
37162c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn    request.set_key_label(label);
37262c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn    request.set_username(username);
373bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    request.set_key_type(KEY_TYPE_RSA);
374bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    request.set_key_usage(usage);
37562c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn    attestation_->CreateCertifiableKey(
37662c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn        request,
37762c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn        base::Bind(&ClientLoop::PrintReplyAndQuit<CreateCertifiableKeyReply>,
37862c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn                   weak_factory_.GetWeakPtr()));
37962c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn  }
38062c73fa5a343fbbf6a0b0176dd789352b85c44e5Darren Krahn
381bc0c74963418442991072b2c87baec839eec9c20Darren Krahn  void Encrypt(const std::string& label,
382bc0c74963418442991072b2c87baec839eec9c20Darren Krahn               const std::string& username,
383bc0c74963418442991072b2c87baec839eec9c20Darren Krahn               const std::string& input) {
384bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    GetKeyInfoRequest request;
385bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    request.set_key_label(label);
386bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    request.set_username(username);
3874dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn    attestation_->GetKeyInfo(
3884dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn        request,
3894dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn        base::Bind(&ClientLoop::Encrypt2, weak_factory_.GetWeakPtr(), input));
390bc0c74963418442991072b2c87baec839eec9c20Darren Krahn  }
391bc0c74963418442991072b2c87baec839eec9c20Darren Krahn
3924dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  void Encrypt2(const std::string& input, const GetKeyInfoReply& key_info) {
393bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    CryptoUtilityImpl crypto(nullptr);
394bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    std::string output;
395bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    if (!crypto.EncryptForUnbind(key_info.public_key(), input, &output)) {
396bc0c74963418442991072b2c87baec839eec9c20Darren Krahn      QuitWithExitCode(EX_SOFTWARE);
397bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    }
398bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    WriteOutput(output);
399bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    Quit();
400bc0c74963418442991072b2c87baec839eec9c20Darren Krahn  }
401bc0c74963418442991072b2c87baec839eec9c20Darren Krahn
402bc0c74963418442991072b2c87baec839eec9c20Darren Krahn  void CallDecrypt(const std::string& label,
403bc0c74963418442991072b2c87baec839eec9c20Darren Krahn                   const std::string& username,
404bc0c74963418442991072b2c87baec839eec9c20Darren Krahn                   const std::string& input) {
405bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    DecryptRequest request;
406bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    request.set_key_label(label);
407bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    request.set_username(username);
408bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    request.set_encrypted_data(input);
409bc0c74963418442991072b2c87baec839eec9c20Darren Krahn    attestation_->Decrypt(
4104dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn        request, base::Bind(&ClientLoop::PrintReplyAndQuit<DecryptReply>,
4114dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn                            weak_factory_.GetWeakPtr()));
412bc0c74963418442991072b2c87baec839eec9c20Darren Krahn  }
413bc0c74963418442991072b2c87baec839eec9c20Darren Krahn
414ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn  void CallSign(const std::string& label,
415ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn                const std::string& username,
416ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn                const std::string& input) {
417ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    SignRequest request;
418ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    request.set_key_label(label);
419ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    request.set_username(username);
420ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    request.set_data_to_sign(input);
421ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    attestation_->Sign(request, base::Bind(&ClientLoop::OnSignComplete,
422ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn                                           weak_factory_.GetWeakPtr()));
423ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn  }
424ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn
425ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn  void OnSignComplete(const SignReply& reply) {
426ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    if (reply.status() == STATUS_SUCCESS &&
427ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn        base::CommandLine::ForCurrentProcess()->HasSwitch("output")) {
428ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      WriteOutput(reply.signature());
429ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    }
430ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    PrintReplyAndQuit<SignReply>(reply);
431ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn  }
432ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn
433ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn  void VerifySignature(const std::string& label,
434ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn                       const std::string& username,
435ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn                       const std::string& input,
436ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn                       const std::string& signature) {
437ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    GetKeyInfoRequest request;
438ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    request.set_key_label(label);
439ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    request.set_username(username);
4404dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn    attestation_->GetKeyInfo(
4414dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn        request, base::Bind(&ClientLoop::VerifySignature2,
4424dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn                            weak_factory_.GetWeakPtr(), input, signature));
443ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn  }
444ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn
445ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn  void VerifySignature2(const std::string& input,
446ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn                        const std::string& signature,
447ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn                        const GetKeyInfoReply& key_info) {
448ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    CryptoUtilityImpl crypto(nullptr);
449ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    if (crypto.VerifySignature(key_info.public_key(), input, signature)) {
450ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      printf("Signature is OK!\n");
451ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    } else {
452ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn      printf("Signature is BAD!\n");
453ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    }
454ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn    Quit();
455ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn  }
456ccf90703bb6989e659b12a6494e84fdb921008edDarren Krahn
457594849c7cf872d055575277b930f4f596bef1988Darren Krahn  void CallRegister(const std::string& label, const std::string& username) {
458594849c7cf872d055575277b930f4f596bef1988Darren Krahn    RegisterKeyWithChapsTokenRequest request;
459594849c7cf872d055575277b930f4f596bef1988Darren Krahn    request.set_key_label(label);
460594849c7cf872d055575277b930f4f596bef1988Darren Krahn    request.set_username(username);
4614dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn    attestation_->RegisterKeyWithChapsToken(
4624dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn        request,
4634dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn        base::Bind(
4644dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn            &ClientLoop::PrintReplyAndQuit<RegisterKeyWithChapsTokenReply>,
4654dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn            weak_factory_.GetWeakPtr()));
466594849c7cf872d055575277b930f4f596bef1988Darren Krahn  }
467594849c7cf872d055575277b930f4f596bef1988Darren Krahn
4680752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn  std::unique_ptr<attestation::AttestationInterface> attestation_;
4690752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn
4700752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn  // Declare this last so weak pointers will be destroyed first.
4710752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn  base::WeakPtrFactory<ClientLoop> weak_factory_{this};
4720752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn
4730752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn  DISALLOW_COPY_AND_ASSIGN(ClientLoop);
4740752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn};
4750752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn
4760752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn}  // namespace attestation
4770752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn
4780752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahnint main(int argc, char* argv[]) {
4790752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn  base::CommandLine::Init(argc, argv);
480b3c9cdcef463064d7ac8f1e6b4b88e62433f9d5dUtkarsh Sanghi  brillo::InitLog(brillo::kLogToStderr);
4810752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn  attestation::ClientLoop loop;
4820752bd25ba9f45c07bc989d42bf5272133a85afaDarren Krahn  return loop.Run();
4836bead48129845a2bc0d6ff347f3d7e232004d59Nam T. Nguyen}
484