| // 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: " << static_cast<int>(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(" Force enroll:\n"); |
| printf(" --enroll --pca=<type>\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, sha256_rsa_pss\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; |
| if (cl->HasSwitch("provision")) { |
| std::string cert_label = cl->GetSwitchValueASCII("label"); |
| if (cert_label.empty()) { |
| PrintHelp(); |
| return 2; |
| } |
| |
| 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 " << static_cast<int>(sts); |
| return 3; |
| } |
| VLOG(1) << "ProvisionCertificate returned " << static_cast<int>(sts); |
| } else if (cl->HasSwitch("enroll")) { |
| 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; |
| } |
| |
| sts = cert_provision::ForceEnroll(pca_type, std::string(), |
| base::Bind(&ProgressCallback)); |
| if (sts != cert_provision::Status::Success) { |
| LOG(ERROR) << "ForceEnroll returned " << static_cast<int>(sts); |
| return 3; |
| } |
| VLOG(1) << "ForceEnroll returned " << static_cast<int>(sts); |
| } else if (cl->HasSwitch("get")) { |
| std::string cert_label = cl->GetSwitchValueASCII("label"); |
| if (cert_label.empty()) { |
| PrintHelp(); |
| return 2; |
| } |
| |
| std::string certificate; |
| sts = cert_provision::GetCertificate( |
| cert_label, cl->HasSwitch("include_chain"), &certificate); |
| if (sts != cert_provision::Status::Success) { |
| LOG(ERROR) << "GetCertificate returned " << static_cast<int>(sts); |
| return 3; |
| } |
| VLOG(1) << "GetCertificate returned " << static_cast<int>(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")) { |
| std::string cert_label = cl->GetSwitchValueASCII("label"); |
| if (cert_label.empty()) { |
| PrintHelp(); |
| return 2; |
| } |
| |
| 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 if (mechanism == "sha256_rsa_pss") { |
| sign_mechanism = cert_provision::SHA256_RSA_PSS; |
| } 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 " << static_cast<int>(sts); |
| return 3; |
| } |
| VLOG(1) << "Sign returned " << static_cast<int>(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; |
| } |