blob: 104886a15b45be58d12533e334c8c180a60801f2 [file] [log] [blame]
// Copyright 2017 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.
//
// Client for cert_provision library.
#include <base/bind.h>
#include <base/command_line.h>
#include <base/files/file_util.h>
#include <base/strings/string_number_conversions.h>
#include <brillo/syslog_logging.h>
#include "cryptohome/cert_provision.h"
void ProgressCallback(cert_provision::Status status,
int progress,
const std::string& message) {
LOG(INFO) << "ProgressCallback: " << status << ", " << progress << "%: "
<< message;
}
void PrintHelp() {
printf("Usage: cert_provision_client <command> [--v=<log_verbosity>]\n");
printf("Commands:\n");
printf(" Provision a certificate:\n");
printf(" --provision --label=<label> --pca=<type> --profile=<profile>\n");
printf(" where type: default, test\n");
printf(" profile: cast, jetstream\n");
printf(" Print the provisioned certificate:\n");
printf(" --get --label=<label> --include_chain\n");
printf(" [--out=<file_out>]\n");
printf(" Sign using the provisioned certificate:\n");
printf(" --sign --label=<label> --in=<file_in> [--out=<file_out>]\n");
printf(" --mechanism=<mechanism>\n");
printf(" where mechanism: sha1_rsa, sha256_rsa\n");
}
int main(int argc, char** argv) {
base::CommandLine::Init(argc, argv);
base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
brillo::InitLog(brillo::kLogToSyslog | brillo::kLogToStderr);
if (cl->HasSwitch("h") || cl->HasSwitch("help")) {
PrintHelp();
return 2;
}
cert_provision::Status sts;
std::string cert_label = cl->GetSwitchValueASCII("label");
if (cert_label.empty()) {
PrintHelp();
return 2;
}
if (cl->HasSwitch("provision")) {
cert_provision::PCAType pca_type;
std::string pca = cl->GetSwitchValueASCII("pca");
if (pca == "default") {
pca_type = cert_provision::PCAType::kDefaultPCA;
} else if (pca == "test") {
pca_type = cert_provision::PCAType::kTestPCA;
} else {
PrintHelp();
return 2;
}
cert_provision::CertificateProfile cert_profile;
std::string profile = cl->GetSwitchValueASCII("profile");
if (profile == "cast") {
cert_profile = cert_provision::CertificateProfile::CAST_CERTIFICATE;
} else if (profile == "jetstream") {
cert_profile = cert_provision::CertificateProfile::JETSTREAM_CERTIFICATE;
} else {
PrintHelp();
return 2;
}
sts = cert_provision::ProvisionCertificate(
pca_type,
std::string(),
cert_label,
cert_profile,
base::Bind(&ProgressCallback));
if (sts != cert_provision::Status::Success) {
LOG(ERROR) << "ProvisionCertificate returned " << sts;
return 3;
}
VLOG(1) << "ProvisionCertificate returned " << sts;
} else if (cl->HasSwitch("get")) {
std::string certificate;
sts = cert_provision::GetCertificate(
cert_label, cl->HasSwitch("include_chain"), &certificate);
if (sts != cert_provision::Status::Success) {
LOG(ERROR) << "GetCertificate returned " << sts;
return 3;
}
VLOG(1) << "GetCertificate returned " << sts;
base::FilePath out(cl->GetSwitchValueASCII("out"));
if (!out.empty()) {
if (base::WriteFile(out, certificate.data(), certificate.size()) < 0) {
LOG(ERROR) << "Failed to write output file: " << out.value();
return 1;
}
} else {
puts(certificate.c_str());
}
} else if (cl->HasSwitch("sign")) {
base::FilePath in(cl->GetSwitchValueASCII("in"));
if (in.empty()) {
PrintHelp();
return 2;
}
cert_provision::SignMechanism sign_mechanism;
std::string mechanism = cl->GetSwitchValueASCII("mechanism");
if (mechanism == "sha1_rsa") {
sign_mechanism = cert_provision::SHA1_RSA_PKCS;
} else if (mechanism == "sha256_rsa") {
sign_mechanism = cert_provision::SHA256_RSA_PKCS;
} else {
PrintHelp();
return 2;
}
std::string data;
if (!base::ReadFileToString(in, &data)) {
LOG(ERROR) << "Failed to read input file: " << in.value();
return 1;
}
std::string sig;
sts = cert_provision::Sign(cert_label, sign_mechanism,
data, &sig);
if (sts != cert_provision::Status::Success) {
LOG(ERROR) << "Sign returned " << sts;
return 3;
}
VLOG(1) << "Sign returned " << sts;
base::FilePath out(cl->GetSwitchValueASCII("out"));
if (!out.empty()) {
if (base::WriteFile(out, sig.data(), sig.size()) < 0) {
LOG(ERROR) << "Failed to write output file: " << out.value();
return 1;
}
} else {
puts(base::HexEncode(sig.data(), sig.size()).c_str());
}
}
return 0;
}