Skip to content
This repository has been archived by the owner on May 21, 2024. It is now read-only.

Generate for each role own key #1028

Merged
merged 5 commits into from
Dec 14, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/aktualizr_info/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@ int main(int argc, char **argv) {
std::string director_targets;
std::string images_root;
std::string images_targets;
bool has_metadata = storage->loadLatestRoot(&director_root, Uptane::RepositoryType::Director);
storage->loadLatestRoot(&images_root, Uptane::RepositoryType::Images);
storage->loadNonRoot(&director_targets, Uptane::RepositoryType::Director, Uptane::Role::Targets());
storage->loadNonRoot(&images_targets, Uptane::RepositoryType::Images, Uptane::Role::Targets());
bool has_metadata = storage->loadLatestRoot(&director_root, Uptane::RepositoryType::Director());
storage->loadLatestRoot(&images_root, Uptane::RepositoryType::Image());
storage->loadNonRoot(&director_targets, Uptane::RepositoryType::Director(), Uptane::Role::Targets());
storage->loadNonRoot(&images_targets, Uptane::RepositoryType::Image(), Uptane::Role::Targets());

std::string device_id;
if (!storage->loadDeviceId(&device_id)) {
Expand Down
6 changes: 3 additions & 3 deletions src/aktualizr_repo/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

set(AKTUALIZR_REPO_SRC repo.cc)
set(AKTUALIZR_REPO_HDR repo.h)
set(AKTUALIZR_REPO_SRC repo.cc director_repo.cc image_repo.cc uptane_repo.cc)
set(AKTUALIZR_REPO_HDR repo.h director_repo.h image_repo.h uptane_repo.h)

set(AKTUALIZR_REPO_LIBS
aktualizr_static_lib
Expand All @@ -16,7 +16,7 @@ install(TARGETS aktualizr-repo

aktualizr_source_file_checks(${AKTUALIZR_REPO_SRC} ${AKTUALIZR_REPO_HDR})
list(APPEND TEST_LIBS ${AKTUALIZR_REPO_LIBS} aktualizr_repo_lib)
add_aktualizr_test(NAME aktualizr_repo SOURCES repo_test.cc PROJECT_WORKING_DIRECTORY)
add_aktualizr_test(NAME aktualizr_repo SOURCES repo_test.cc PROJECT_WORKING_DIRECTORY ARGS $<TARGET_FILE:aktualizr-repo>)
target_link_libraries(t_aktualizr_repo ${TEST_LIBS} aktualizr_repo_lib)

aktualizr_source_file_checks(${TEST_SOURCES} main.cc)
Expand Down
40 changes: 40 additions & 0 deletions src/aktualizr_repo/director_repo.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include "director_repo.h"

void DirectorRepo::addTarget(const std::string &target_name, const Json::Value &target, const std::string &hardware_id,
const std::string &ecu_serial) {
const boost::filesystem::path current = path_ / "repo/director/targets.json";
const boost::filesystem::path staging = path_ / "repo/director/staging/targets.json";

Json::Value director_targets;
if (boost::filesystem::exists(staging)) {
director_targets = Utils::parseJSONFile(staging);
} else if (boost::filesystem::exists(current)) {
director_targets = Utils::parseJSONFile(current)["signed"];
} else {
throw std::runtime_error(std::string("targets.json not found at ") + staging.c_str() + " or " + current.c_str() +
"!");
}
director_targets["targets"][target_name] = target;
director_targets["targets"][target_name]["custom"]["ecuIdentifiers"][ecu_serial]["hardwareId"] = hardware_id;
director_targets["version"] = (Utils::parseJSONFile(current)["signed"]["version"].asUInt()) + 1;
Utils::writeFile(staging, Utils::jsonToCanonicalStr(director_targets));
}
pattivacek marked this conversation as resolved.
Show resolved Hide resolved

void DirectorRepo::signTargets() {
const boost::filesystem::path current = path_ / "repo/director/targets.json";
const boost::filesystem::path staging = path_ / "repo/director/staging/targets.json";
Json::Value targets_unsigned;

if (boost::filesystem::exists(staging)) {
targets_unsigned = Utils::parseJSONFile(staging);
} else if (boost::filesystem::exists(current)) {
targets_unsigned = Utils::parseJSONFile(current)["signed"];
} else {
throw std::runtime_error(std::string("targets.json not found at ") + staging.c_str() + " or " + current.c_str() +
"!");
}

Utils::writeFile(path_ / "repo/director/targets.json",
Utils::jsonToCanonicalStr(signTuf(Uptane::Role::Targets(), targets_unsigned)));
boost::filesystem::remove(path_ / "repo/director/staging/targets.json");
}
15 changes: 15 additions & 0 deletions src/aktualizr_repo/director_repo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#ifndef DIRECTOR_REPO_H_
#define DIRECTOR_REPO_H_

#include "repo.h"

class DirectorRepo : public Repo {
public:
DirectorRepo(boost::filesystem::path path, const std::string &expires, std::string correlation_id)
: Repo(Uptane::RepositoryType::Director(), std::move(path), expires, std::move(correlation_id)) {}
void addTarget(const std::string &target_name, const Json::Value &target, const std::string &hardware_id,
const std::string &ecu_serial);
void signTargets();
};

#endif // DIRECTOR_REPO_H_
47 changes: 47 additions & 0 deletions src/aktualizr_repo/image_repo.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include "image_repo.h"

void ImageRepo::addImage(const boost::filesystem::path &image_path) {
boost::filesystem::path repo_dir(path_ / "repo/image");

boost::filesystem::path targets_path = repo_dir / "targets";
boost::filesystem::create_directories(targets_path);
if (image_path != targets_path / image_path.filename()) {
boost::filesystem::copy_file(image_path, targets_path / image_path.filename(),
boost::filesystem::copy_option::overwrite_if_exists);
}
std::string image = Utils::readFile(image_path);

Json::Value targets = Utils::parseJSONFile(repo_dir / "targets.json")["signed"];
std::string target_name = image_path.filename().string();
targets["targets"][target_name]["length"] = Json::UInt64(image.size());
targets["targets"][target_name]["hashes"]["sha256"] =
boost::algorithm::to_lower_copy(boost::algorithm::hex(Crypto::sha256digest(image)));
targets["targets"][target_name]["hashes"]["sha512"] =
boost::algorithm::to_lower_copy(boost::algorithm::hex(Crypto::sha512digest(image)));
targets["version"] = (targets["version"].asUInt()) + 1;

std::string signed_targets = Utils::jsonToCanonicalStr(signTuf(Uptane::Role::Targets(), targets));
Utils::writeFile(repo_dir / "targets.json", signed_targets);

Json::Value snapshot = Utils::parseJSONFile(repo_dir / "snapshot.json")["signed"];
snapshot["version"] = (snapshot["version"].asUInt()) + 1;
snapshot["meta"]["targets.json"]["hashes"]["sha256"] =
boost::algorithm::to_lower_copy(boost::algorithm::hex(Crypto::sha256digest(signed_targets)));
snapshot["meta"]["targets.json"]["hashes"]["sha512"] =
boost::algorithm::to_lower_copy(boost::algorithm::hex(Crypto::sha512digest(signed_targets)));
snapshot["meta"]["targets.json"]["length"] = static_cast<Json::UInt>(signed_targets.length());
snapshot["meta"]["targets.json"]["version"] = targets["version"].asUInt();
std::string signed_snapshot = Utils::jsonToCanonicalStr(signTuf(Uptane::Role::Snapshot(), snapshot));
Utils::writeFile(repo_dir / "snapshot.json", signed_snapshot);

Json::Value timestamp = Utils::parseJSONFile(repo_dir / "timestamp.json")["signed"];
timestamp["version"] = (timestamp["version"].asUInt()) + 1;
timestamp["meta"]["snapshot.json"]["hashes"]["sha256"] =
boost::algorithm::to_lower_copy(boost::algorithm::hex(Crypto::sha256digest(signed_snapshot)));
timestamp["meta"]["snapshot.json"]["hashes"]["sha512"] =
boost::algorithm::to_lower_copy(boost::algorithm::hex(Crypto::sha512digest(signed_snapshot)));
timestamp["meta"]["snapshot.json"]["length"] = static_cast<Json::UInt>(signed_snapshot.length());
timestamp["meta"]["snapshot.json"]["version"] = snapshot["version"].asUInt();
Utils::writeFile(repo_dir / "timestamp.json",
Utils::jsonToCanonicalStr(signTuf(Uptane::Role::Timestamp(), timestamp)));
}
13 changes: 13 additions & 0 deletions src/aktualizr_repo/image_repo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#ifndef IMAGE_REPO_H_
#define IMAGE_REPO_H_

#include "repo.h"

class ImageRepo : public Repo {
public:
ImageRepo(boost::filesystem::path path, const std::string &expires, std::string correlation_id)
: Repo(Uptane::RepositoryType::Image(), std::move(path), expires, std::move(correlation_id)) {}
void addImage(const boost::filesystem::path &image_path);
};

#endif // IMAGE_REPO_H_
32 changes: 29 additions & 3 deletions src/aktualizr_repo/main.cc
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
#include <boost/program_options.hpp>
#include <iostream>
#include <istream>
#include <iterator>
#include <ostream>
#include <string>

#include "logging/logging.h"
#include "repo.h"
#include "uptane_repo.h"

namespace po = boost::program_options;

Expand All @@ -12,12 +15,14 @@ int main(int argc, char **argv) {
// clang-format off
desc.add_options()
("help,h", "print usage")
("command", po::value<std::string>(), "generate|image|addtarget|signtargets")
("command", po::value<std::string>(), "generate|sign|image|addtarget|signtargets")
("path", po::value<boost::filesystem::path>(), "path to the repository")
("filename", po::value<std::string>(), "path to the image")
("hwid", po::value<std::string>(), "target hardware identifier")
("serial", po::value<std::string>(), "target ECU serial")
("expires", po::value<std::string>(), "expiration time")
("keyname", po::value<std::string>(), "name of key's role")
("repotype", po::value<std::string>(), "director|image")
("correlationid", po::value<std::string>()->default_value(""), "correlation id")
("keytype", po::value<std::string>()->default_value("RSA2048"), "UPTANE key type");
// clang-format on
Expand Down Expand Up @@ -49,7 +54,7 @@ int main(int argc, char **argv) {
if (vm.count("correlationid") != 0) {
correlation_id = vm["correlationid"].as<std::string>();
}
Repo repo(vm["path"].as<boost::filesystem::path>(), expiration_time, correlation_id);
UptaneRepo repo(vm["path"].as<boost::filesystem::path>(), expiration_time, correlation_id);
std::string command = vm["command"].as<std::string>();
if (command == "generate") {
std::string key_type_arg = vm["keytype"].as<std::string>();
Expand All @@ -63,6 +68,27 @@ int main(int argc, char **argv) {
repo.addTarget(vm["filename"].as<std::string>(), vm["hwid"].as<std::string>(), vm["serial"].as<std::string>());
} else if (command == "signtargets") {
repo.signTargets();
} else if (command == "sign") {
if (vm.count("repotype") == 0 || vm.count("keyname") == 0) {
std::cerr << "--repotype or --keyname is missing\n";
exit(EXIT_FAILURE);
}
std::cin >> std::noskipws;
std::istream_iterator<char> it(std::cin);
std::istream_iterator<char> end;
std::string text_to_sign(it, end);

Repo base_repo(Uptane::RepositoryType(vm["repotype"].as<std::string>()),
vm["path"].as<boost::filesystem::path>(), expiration_time, correlation_id);

auto json_to_sign = Utils::parseJSON(text_to_sign);
if (json_to_sign == Json::nullValue) {
std::cerr << "Text to sign must be valid json\n";
exit(EXIT_FAILURE);
}

auto json_signed = base_repo.signTuf(Uptane::Role(vm["keyname"].as<std::string>()), json_to_sign);
std::cout << Utils::jsonToCanonicalStr(json_signed);
} else {
std::cout << desc << std::endl;
exit(EXIT_FAILURE);
Expand Down
Loading