blob: d0e2d3e0f6ec4326f8ebd04f74b81fdceb08dcd1 [file] [log] [blame]
// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "hwsec-test-utils/verified_access/verified_access.h"
#include <optional>
#include <stdio.h>
#include <utility>
#include <base/base64.h>
#include <base/command_line.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <brillo/data_encoding.h>
#include <brillo/syslog_logging.h>
namespace {
constexpr char kGenerateCommand[] = "generate";
constexpr char kVerifyCommand[] = "verify";
constexpr char kInputSwitch[] = "input";
constexpr char kBinarySwitch[] = "binary";
const char kUsage[] = R"(
Usage: hwsec-test-va <command> [<args>]
Commands:
|generate|
Generates a VA challenge signed with well-known VA signing key and prints
the base64-encoded result in stdout.
|verify| --input=<filename> [--binary]
Verifies the VA challenge response from attestation service. By default,
reads last argument that follows as the base64-encoded response. If the
input is in binary (i.e., not base64-encoded), specify '--binary'.
)";
constexpr char kExpectedChallengePrefix[] = "EnterpriseKeyChallenge";
void PrintUsage() {
printf("%s", kUsage);
}
} // namespace
int main(int argc, char* argv[]) {
base::CommandLine::Init(argc, argv);
brillo::InitLog(brillo::kLogToStderr);
base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
const auto& args = cl->GetArgs();
if (args.empty()) {
PrintUsage();
return 1;
}
if (args.front() == kGenerateCommand) {
hwsec_test_utils::verified_access::VerifiedAccessChallenge va;
std::optional<attestation::SignedData> challenge =
va.GenerateChallenge(kExpectedChallengePrefix);
if (!challenge) {
printf("Failed to generate VA challenge.\n");
return 1;
}
std::string serialized_challenge;
if (!challenge->SerializeToString(&serialized_challenge)) {
printf("Failed to serialize VA challenge.\n");
return 1;
}
printf("%s",
brillo::data_encoding::Base64Encode(serialized_challenge).c_str());
return 0;
}
if (args.front() == kVerifyCommand) {
const std::string path = cl->GetSwitchValueASCII(kInputSwitch);
if (path.empty()) {
printf("No valid file path specified.\n");
return 1;
}
std::string data;
if (!base::ReadFileToString(base::FilePath(path), &data)) {
printf("Failed to read file.\n");
return 1;
}
if (!cl->HasSwitch(kBinarySwitch)) {
std::string tmp;
if (!brillo::data_encoding::Base64Decode(data, &tmp)) {
printf("Failed to base64 decode the file content.\n");
return 1;
}
data = std::move(tmp);
}
// At this point, |data| is the binary representation regardless of the
// given data format.
attestation::SignedData signed_challenge_response;
if (!signed_challenge_response.ParseFromString(data)) {
printf("Failed to parse serialized |attestation::SignedData|.\n");
return 1;
}
hwsec_test_utils::verified_access::VerifiedAccessChallenge va;
if (!va.VerifyChallengeResponse(signed_challenge_response,
kExpectedChallengePrefix)) {
printf("Failed to verify challenge response.\n");
return 1;
}
printf("Succeeded.\n");
return 0;
}
// None of the command matches; print usage and return non-zero exit status.
PrintUsage();
return 1;
}