1 #include "uptane/tuf.h" 7 #include <boost/algorithm/hex.hpp> 8 #include <boost/algorithm/string/case_conv.hpp> 11 #include "crypto/crypto.h" 12 #include "logging/logging.h" 13 #include "utilities/exceptions.h" 21 std::ostream &Uptane::operator<<(std::ostream &os,
const Version &v) {
22 if (v.version_ == Version::ANY_VERSION) {
25 os <<
"v" << v.version_;
30 std::ostream &Uptane::operator<<(std::ostream &os,
const HardwareIdentifier &hwid) {
35 std::ostream &Uptane::operator<<(std::ostream &os,
const EcuSerial &ecu_serial) {
36 os << ecu_serial.ecu_serial_;
40 Hash::Hash(
const std::string &type,
const std::string &hash) : hash_(
boost::algorithm::to_upper_copy(hash)) {
41 if (type ==
"sha512") {
42 type_ = Hash::Type::kSha512;
43 }
else if (type ==
"sha256") {
44 type_ = Hash::Type::kSha256;
46 type_ = Hash::Type::kUnknownAlgorithm;
50 Hash::Hash(Type type,
const std::string &hash) : type_(type), hash_(
boost::algorithm::to_upper_copy(hash)) {}
52 bool Hash::operator==(
const Hash &other)
const {
return type_ == other.type_ && hash_ == other.hash_; }
54 std::string Hash::TypeString()
const {
65 Hash::Type Hash::type()
const {
return type_; }
67 std::ostream &Uptane::operator<<(std::ostream &os,
const Hash &h) {
68 os <<
"Hash: " << h.hash_;
72 Target::Target(std::string filename,
const Json::Value &content) : filename_(
std::move(filename)) {
73 if (content.isMember(
"custom")) {
74 Json::Value custom = content[
"custom"];
76 Json::Value ecus = custom[
"ecuIdentifiers"];
77 for (Json::ValueIterator i = ecus.begin(); i != ecus.end(); ++i) {
78 ecus_.insert({EcuSerial(i.key().asString()), HardwareIdentifier((*i)[
"hardwareId"].asString())});
81 if (custom.isMember(
"targetFormat")) {
82 type_ = custom[
"targetFormat"].asString();
86 length_ = content[
"length"].asInt64();
88 Json::Value hashes = content[
"hashes"];
89 for (Json::ValueIterator i = hashes.begin(); i != hashes.end(); ++i) {
90 Hash h(i.key().asString(), (*i).asString());
91 if (h.HaveAlgorithm()) {
96 std::sort(hashes_.begin(), hashes_.end(), [](
const Hash &l,
const Hash &r) {
return l.type() < r.type(); });
99 bool Target::MatchWith(
const Hash &hash)
const {
100 return (std::find(hashes_.begin(), hashes_.end(), hash) != hashes_.end());
103 std::string Target::sha256Hash()
const {
104 std::vector<Uptane::Hash>::const_iterator it;
105 for (it = hashes_.begin(); it != hashes_.end(); it++) {
106 if (it->type() == Hash::Type::kSha256) {
107 return boost::algorithm::to_lower_copy(it->HashString());
110 return std::string(
"");
114 if (type_ ==
"OSTREE") {
117 }
else if (type_.empty() && length() == 0) {
128 Json::Value Target::toDebugJson()
const {
130 for (
auto it = ecus_.begin(); it != ecus_.cend(); ++it) {
131 res[
"custom"][
"ecuIdentifiers"][it->first.ToString()][
"hardwareId"] = it->second.ToString();
133 res[
"custom"][
"targetFormat"] = type_;
135 for (
auto it = hashes_.cbegin(); it != hashes_.cend(); ++it) {
136 res[
"hashes"][it->TypeString()] = it->HashString();
138 res[
"length"] = Json::Value(static_cast<Json::Value::Int64>(length_));
142 std::ostream &Uptane::operator<<(std::ostream &os,
const Target &t) {
143 os <<
"Target(" << t.filename_;
144 os <<
" ecu_identifiers: (";
146 for (
auto it = t.ecus_.begin(); it != t.ecus_.end(); ++it) {
150 <<
" length:" << t.length();
152 for (
auto it = t.hashes_.begin(); it != t.hashes_.end(); ++it) {
160 void Uptane::BaseMeta::init(
const Json::Value &json) {
161 if (!json.isObject() || !json.isMember(
"signed")) {
162 LOG_ERROR <<
"BM FAILURE";
166 version_ = json[
"signed"][
"version"].asInt();
168 expiry_ =
TimeStamp(json[
"signed"][
"expires"].asString());
172 original_object_ = json;
174 Uptane::BaseMeta::BaseMeta(
const Json::Value &json) { init(json); }
176 Uptane::BaseMeta::BaseMeta(
RepositoryType repo,
const Json::Value &json,
Root &root) {
177 if (!json.isObject() || !json.isMember(
"signed")) {
186 void Uptane::Targets::init(
const Json::Value &json) {
187 if (!json.isObject() || json[
"signed"][
"_type"] !=
"Targets") {
191 Json::Value target_list = json[
"signed"][
"targets"];
192 for (Json::ValueIterator t_it = target_list.begin(); t_it != target_list.end(); t_it++) {
193 Target t(t_it.key().asString(), *t_it);
194 targets.push_back(t);
197 if (json[
"signed"][
"custom"].isObject()) {
198 correlation_id_ = json[
"signed"][
"custom"][
"correlationId"].asString();
200 correlation_id_ =
"";
204 Uptane::Targets::Targets(
const Json::Value &json) : BaseMeta(json) { init(json); }
206 Uptane::Targets::Targets(
RepositoryType repo,
const Json::Value &json,
Root &root) : BaseMeta(repo, json, root) {
210 void Uptane::TimestampMeta::init(
const Json::Value &json) {
211 Json::Value hashes_list = json[
"signed"][
"meta"][
"snapshot.json"][
"hashes"];
212 Json::Value meta_size = json[
"signed"][
"meta"][
"snapshot.json"][
"length"];
213 Json::Value meta_version = json[
"signed"][
"meta"][
"snapshot.json"][
"version"];
214 if (!json.isObject() || json[
"signed"][
"_type"] !=
"Timestamp" || !hashes_list.isObject() ||
215 !meta_size.isIntegral() || !meta_version.isIntegral()) {
219 for (Json::ValueIterator it = hashes_list.begin(); it != hashes_list.end(); ++it) {
220 Hash h(it.key().asString(), (*it).asString());
221 snapshot_hashes_.push_back(h);
223 snapshot_size_ = meta_size.asInt();
224 snapshot_version_ = meta_version.asInt();
227 Uptane::TimestampMeta::TimestampMeta(
const Json::Value &json) : BaseMeta(json) { init(json); }
229 Uptane::TimestampMeta::TimestampMeta(
RepositoryType repo,
const Json::Value &json,
Root &root)
230 : BaseMeta(repo, json, root) {
234 void Uptane::Snapshot::init(
const Json::Value &json) {
235 Json::Value hashes_list = json[
"signed"][
"meta"][
"targets.json"][
"hashes"];
236 Json::Value meta_size = json[
"signed"][
"meta"][
"targets.json"][
"length"];
237 Json::Value meta_version = json[
"signed"][
"meta"][
"targets.json"][
"version"];
239 if (!json.isObject() || json[
"signed"][
"_type"] !=
"Snapshot" || !meta_version.isIntegral()) {
243 if (hashes_list.isObject()) {
244 for (Json::ValueIterator it = hashes_list.begin(); it != hashes_list.end(); ++it) {
245 Hash h(it.key().asString(), (*it).asString());
246 targets_hashes_.push_back(h);
250 if (meta_size.isIntegral()) {
251 targets_size_ = meta_size.asInt();
255 targets_version_ = meta_version.asInt();
258 Uptane::Snapshot::Snapshot(
const Json::Value &json) : BaseMeta(json) { init(json); }
260 Uptane::Snapshot::Snapshot(
RepositoryType repo,
const Json::Value &json,
Root &root) : BaseMeta(repo, json, root) {
264 bool MetaPack::isConsistent()
const {
267 if (director_root.original() != Json::nullValue) {
269 Uptane::Root new_root(RepositoryType::Director, director_root.original(), new_root);
270 if (director_targets.original() != Json::nullValue) {
271 Uptane::Targets(RepositoryType::Director, director_targets.original(), original_root);
274 }
catch (
const std::logic_error &exc) {
275 LOG_WARNING <<
"Inconsistent metadata: " << exc.what();
283 case RepositoryType::Director:
285 case RepositoryType::Images:
292 int Uptane::extractVersionUntrusted(
const std::string &meta) {
293 auto version_json = Utils::parseJSON(meta)[
"signed"][
"version"];
294 if (!version_json.isIntegral()) {
297 return version_json.asInt();
Metadata version numbers.
bool IsOstree() const
Is this an OSTree target? OSTree targets need special treatment because the hash doesn't represent th...
RepositoryType
This must match the repo_type table in sqlstorage.
void UnpackSignedObject(RepositoryType repo, const Json::Value &signed_object)
Take a JSON blob that contains a signatures/signed component that is supposedly for a given role...
The hash of a file or TUF metadata.