blob: b70c9f71fe9aea0a6deeea38606a922559d73efa [file] [log] [blame]
// Copyright 2018 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 "oobe_config/utils.h"
#include <string>
#include <vector>
#include <base/files/file_util.h>
#include <base/strings/string_util.h>
#include <brillo/process.h>
#include <crypto/scoped_openssl_types.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
using base::FilePath;
using std::string;
using std::vector;
namespace oobe_config {
int RunCommand(const vector<string>& command) {
LOG(INFO) << "Command: " << base::JoinString(command, " ");
brillo::ProcessImpl proc;
for (const auto& arg : command) {
proc.AddArg(arg);
}
return proc.Run();
}
bool SignFile(const FilePath& priv_key,
const FilePath& src,
const FilePath& dst) {
// Reading the source file.
string src_content;
if (!base::ReadFileToString(src, &src_content)) {
PLOG(ERROR) << "Failed to read the source file " << src.value();
return false;
}
// Reading the private key.
base::ScopedFILE pkf(base::OpenFile(priv_key, "r"));
if (!pkf) {
PLOG(ERROR) << "Failed to open the private key file " << priv_key.value();
return false;
}
crypto::ScopedEVP_PKEY private_key(
PEM_read_PrivateKey(pkf.get(), nullptr, nullptr, nullptr));
if (!private_key) {
PLOG(ERROR) << "Failed to read the PEM private key file "
<< priv_key.value();
return false;
}
// Creating the context.
crypto::ScopedEVP_MD_CTX mdctx(EVP_MD_CTX_create());
if (!mdctx) {
LOG(ERROR) << "Failed to create a EVP_MD context.";
return false;
}
// Signing the |src| file.
size_t signature_len = 0;
if (EVP_DigestSignInit(mdctx.get(), nullptr, EVP_sha256(), nullptr,
private_key.get()) != 1 ||
EVP_DigestSignUpdate(mdctx.get(), src_content.c_str(),
src_content.length()) != 1 ||
EVP_DigestSignFinal(mdctx.get(), nullptr, &signature_len) != 1) {
LOG(ERROR) << "Failed to sign the source file " << src.value();
}
// Now we know the size of the signature, let's get it.
crypto::ScopedOpenSSLBytes signature(reinterpret_cast<unsigned char*>(
OPENSSL_malloc(sizeof(unsigned char) * signature_len)));
if (!signature) {
PLOG(ERROR) << "Failed to malloc " << signature_len
<< " bytes for the signature.";
return false;
}
if (EVP_DigestSignFinal(mdctx.get(), signature.get(), &signature_len) != 1) {
LOG(ERROR) << "Getting the signature failed; however, technically this"
<< " should not happen!";
return false;
}
if (!base::WriteFile(dst, reinterpret_cast<char*>(signature.get()),
signature_len)) {
PLOG(ERROR) << "Failed to write the signature to file " << dst.value();
return false;
}
return true;
}
} // namespace oobe_config