1 #include "managedsecondary.h" 7 #include <boost/algorithm/hex.hpp> 8 #include <boost/filesystem.hpp> 10 #include "crypto/crypto.h" 11 #include "logging/logging.h" 12 #include "uptane/manifest.h" 13 #include "uptane/uptanerepository.h" 14 #include "utilities/exceptions.h" 15 #include "utilities/fault_injection.h" 16 #include "utilities/utils.h" 22 std::string public_key_string;
24 if (!loadKeys(&public_key_string, &private_key)) {
25 if (!Crypto::generateKeyPair(sconfig.key_type, &public_key_string, &private_key)) {
26 LOG_ERROR <<
"Could not generate rsa keys for secondary " << ManagedSecondary::getSerial() <<
"@" 27 << sconfig.ecu_hardware_id;
28 throw std::runtime_error(
"Unable to generate secondary rsa keys");
33 public_key_ =
PublicKey(public_key_string, sconfig.key_type);
37 void ManagedSecondary::Initialize() {
40 if (!boost::filesystem::is_directory(sconfig.metadata_path)) {
41 Utils::createDirectories(sconfig.metadata_path, S_IRWXU);
43 if (stat(sconfig.metadata_path.c_str(), &st) < 0) {
44 throw std::runtime_error(std::string(
"Could not check metadata directory permissions: ") + std::strerror(errno));
46 if ((st.st_mode & (S_IWGRP | S_IWOTH)) != 0) {
47 throw std::runtime_error(
"Secondary metadata directory has unsafe permissions");
50 if (!boost::filesystem::is_directory(sconfig.full_client_dir)) {
51 Utils::createDirectories(sconfig.full_client_dir, S_IRWXU);
53 if (stat(sconfig.full_client_dir.c_str(), &st) < 0) {
54 throw std::runtime_error(std::string(
"Could not check client directory permissions: ") + std::strerror(errno));
56 if ((st.st_mode & (S_IWGRP | S_IWOTH)) != 0) {
57 throw std::runtime_error(
"Secondary client directory has unsafe permissions");
60 storeKeys(public_key_.Value(), private_key);
63 void ManagedSecondary::rawToMeta() {
66 Uptane::RepositoryType::Director(),
67 Utils::parseJSON(getMetaFromBundle(meta_bundle_, Uptane::RepositoryType::Director(), Uptane::Role::Root())));
69 Utils::parseJSON(getMetaFromBundle(meta_bundle_, Uptane::RepositoryType::Director(), Uptane::Role::Targets())));
71 Uptane::RepositoryType::Image(),
72 Utils::parseJSON(getMetaFromBundle(meta_bundle_, Uptane::RepositoryType::Image(), Uptane::Role::Root())));
74 Utils::parseJSON(getMetaFromBundle(meta_bundle_, Uptane::RepositoryType::Image(), Uptane::Role::Timestamp())));
76 Utils::parseJSON(getMetaFromBundle(meta_bundle_, Uptane::RepositoryType::Image(), Uptane::Role::Snapshot())));
78 Utils::parseJSON(getMetaFromBundle(meta_bundle_, Uptane::RepositoryType::Image(), Uptane::Role::Targets())));
82 Uptane::MetaBundle temp_bundle;
83 if (!secondary_provider_->getMetadata(&temp_bundle, target)) {
85 "Unable to load stored metadata from Primary");
91 meta_bundle_ = std::move(temp_bundle);
93 if (!current_meta.isConsistent()) {
95 "Error verifying metadata received from Primary");
102 int ManagedSecondary::getRootVersion(
const bool director)
const {
104 return current_meta.director_root.version();
106 return current_meta.image_root.version();
110 const Uptane::RepositoryType repo = (director) ? Uptane::RepositoryType::Director() : Uptane::RepositoryType::Image();
111 Uptane::Root &prev_root = (director) ? current_meta.director_root : current_meta.image_root;
112 const std::string prev_raw_root = getMetaFromBundle(meta_bundle_, repo, Uptane::Role::Root());
116 if (new_root.version() == prev_root.version() + 1) {
117 prev_root = new_root;
118 meta_bundle_.insert({std::make_pair(repo, Uptane::Role::Root()), root});
120 detected_attack =
"Tried to update Root version " + std::to_string(prev_root.version()) +
" with version " +
121 std::to_string(new_root.version());
124 if (!current_meta.isConsistent()) {
137 auto str = secondary_provider_->getTargetFileHandle(target);
138 std::ofstream out_file(sconfig.firmware_path.string(), std::ios::binary);
139 out_file << str.rdbuf();
143 Utils::writeFile(sconfig.target_name_path, target.filename());
149 if (!getFirmwareInfo(firmware_info)) {
150 return Json::Value(Json::nullValue);
153 Json::Value manifest = Uptane::ManifestIssuer::assembleManifest(firmware_info, getSerial());
157 manifest[
"attacks_detected"] = detected_attack;
159 Json::Value signed_ecu_version;
161 std::string b64sig = Utils::toBase64(Crypto::RSAPSSSign(
nullptr, private_key, Utils::jsonToCanonicalStr(manifest)));
162 Json::Value signature;
163 signature[
"method"] =
"rsassa-pss";
164 signature[
"sig"] = b64sig;
166 signature[
"keyid"] = public_key_.KeyId();
167 signed_ecu_version[
"signed"] = manifest;
168 signed_ecu_version[
"signatures"] = Json::Value(Json::arrayValue);
169 signed_ecu_version[
"signatures"].append(signature);
171 return signed_ecu_version;
177 if (!boost::filesystem::exists(sconfig.target_name_path) || !boost::filesystem::exists(sconfig.firmware_path)) {
178 firmware_info.name = std::string(
"noimage");
181 firmware_info.name = Utils::readFile(sconfig.target_name_path.string());
182 content = Utils::readFile(sconfig.firmware_path.string());
184 firmware_info.hash = Uptane::ManifestIssuer::generateVersionHashStr(content);
185 firmware_info.len = content.size();
190 void ManagedSecondary::storeKeys(
const std::string &pub_key,
const std::string &priv_key) {
191 Utils::writeFile((sconfig.full_client_dir / sconfig.ecu_private_key), priv_key);
192 Utils::writeFile((sconfig.full_client_dir / sconfig.ecu_public_key), pub_key);
195 bool ManagedSecondary::loadKeys(std::string *pub_key, std::string *priv_key) {
196 boost::filesystem::path public_key_path = sconfig.full_client_dir / sconfig.ecu_public_key;
197 boost::filesystem::path private_key_path = sconfig.full_client_dir / sconfig.ecu_private_key;
199 if (!boost::filesystem::exists(public_key_path) || !boost::filesystem::exists(private_key_path)) {
203 *priv_key = Utils::readFile(private_key_path.string());
204 *pub_key = Utils::readFile(public_key_path.string());
208 bool MetaPack::isConsistent()
const {
211 if (director_root.original() != Json::nullValue) {
213 Uptane::Root new_root(Uptane::RepositoryType::Director(), director_root.original(), new_root);
214 if (director_targets.original() != Json::nullValue) {
215 Uptane::Targets(Uptane::RepositoryType::Director(), Uptane::Role::Targets(), director_targets.original(),
216 std::make_shared<Uptane::MetaWithKeys>(original_root));
219 }
catch (
const std::logic_error &exc) {
220 LOG_WARNING <<
"Inconsistent metadata: " << exc.what();
Metadata verification failed.
SWM Internal integrity error.