1 #ifndef AKTUALIZR_UPTANE_TUF_H_ 2 #define AKTUALIZR_UPTANE_TUF_H_ 13 #include "uptane/exceptions.h" 15 #include "crypto/crypto.h" 23 enum class Type { kUnknown = -1, kImage = 0, kDirector = 1 };
26 static const std::string IMAGE;
27 static const std::string DIRECTOR;
30 static constexpr
int Director() {
return static_cast<int>(Type::kDirector); }
31 static constexpr
int Image() {
return static_cast<int>(Type::kImage); }
32 RepositoryType(
int type) { type_ =
static_cast<RepositoryType::Type
>(type); }
34 if (repo_type == DIRECTOR) {
35 type_ = RepositoryType::Type::kDirector;
36 }
else if (repo_type == IMAGE) {
37 type_ = RepositoryType::Type::kImage;
39 throw std::runtime_error(std::string(
"Incorrect repo type: ") + repo_type);
42 operator int()
const {
return static_cast<int>(type_); }
43 operator std::string()
const {
return toString(); }
45 std::string toString()
const {
46 if (type_ == RepositoryType::Type::kDirector) {
48 }
else if (type_ == RepositoryType::Type::kImage) {
56 using KeyId = std::string;
62 static const std::string ROOT;
63 static const std::string SNAPSHOT;
64 static const std::string TARGETS;
65 static const std::string TIMESTAMP;
70 static Role Timestamp() {
return Role{RoleEnum::kTimestamp}; }
72 static Role InvalidRole() {
return Role{RoleEnum::kInvalidRole}; }
76 static bool IsReserved(
const std::string &name) {
77 return (name == ROOT || name == TARGETS || name == SNAPSHOT || name == TIMESTAMP);
80 explicit Role(
const std::string &role_name,
bool delegation =
false);
81 std::string ToString()
const;
82 int ToInt()
const {
return static_cast<int>(role_); }
83 bool IsDelegation()
const {
return role_ == RoleEnum::kDelegation; }
84 bool operator==(
const Role &other)
const {
return name_ == other.name_; }
85 bool operator!=(
const Role &other)
const {
return !(*
this == other); }
86 bool operator<(
const Role &other)
const {
return name_ < other.name_; }
88 friend std::ostream &operator<<(std::ostream &os,
const Role &role);
93 enum class RoleEnum { kRoot = 0, kSnapshot = 1, kTargets = 2, kTimestamp = 3, kDelegation = 4, kInvalidRole = -1 };
95 explicit Role(RoleEnum role) : role_(role) {
96 if (role_ == RoleEnum::kRoot) {
98 }
else if (role_ == RoleEnum::kSnapshot) {
100 }
else if (role_ == RoleEnum::kTargets) {
102 }
else if (role_ == RoleEnum::kTimestamp) {
105 role_ = RoleEnum::kInvalidRole;
106 name_ =
"invalidrole";
114 std::ostream &operator<<(std::ostream &os,
const Role &role);
121 Version() : version_(ANY_VERSION) {}
122 explicit Version(
int v) : version_(v) {}
123 std::string RoleFileName(
const Role &role)
const;
124 int version()
const {
return version_; }
125 bool operator==(
const Version &rhs)
const {
return version_ == rhs.version_; }
126 bool operator!=(
const Version &rhs)
const {
return version_ != rhs.version_; }
127 bool operator<(
const Version &rhs)
const {
return version_ < rhs.version_; }
130 static const int ANY_VERSION = -1;
132 friend std::ostream &operator<<(std::ostream &os,
const Version &v);
138 : name(std::move(name_in)), len(len_in), hash(std::move(hash_in)) {}
144 std::ostream &operator<<(std::ostream &os,
const Version &v);
149 static const int kMinLength = 0;
150 static const int kMaxLength = 200;
157 if (kMaxLength < hwid.length()) {
158 throw std::out_of_range(
"Hardware Identifier too long");
162 std::string ToString()
const {
return hwid_; }
175 std::ostream &operator<<(std::ostream &os, const HardwareIdentifier &hwid);
180 static const int kMinLength = 1;
181 static const int kMaxLength = 64;
183 static EcuSerial Unknown() { return EcuSerial("Unknown"); }
184 explicit EcuSerial(const std::string &ecu_serial) : ecu_serial_(ecu_serial) {
185 if (ecu_serial.length() < kMinLength) {
186 throw std::out_of_range("Ecu serial identifier is too short");
188 if (kMaxLength < ecu_serial.length()) {
189 throw std::out_of_range("Ecu serial identifier is too long");
193 std::string ToString() const { return ecu_serial_; }
195 bool operator==(const EcuSerial &rhs) const { return ecu_serial_ == rhs.ecu_serial_; }
196 bool operator!=(const EcuSerial &rhs) const { return !(*this == rhs); }
198 bool operator<(const EcuSerial &rhs) const { return ecu_serial_ < rhs.ecu_serial_; }
199 friend std::ostream &operator<<(std::ostream &os, const EcuSerial &ecu_serial);
200 friend struct std::hash<Uptane::EcuSerial>;
203 std::string ecu_serial_;
206 std::ostream &operator<<(std::ostream &os, const EcuSerial &ecu_serial);
208 using EcuMap = std::map<EcuSerial, HardwareIdentifier>;
213 Target(std::string filename, const Json::Value &content);
216 Target(std::string filename, EcuMap ecus, std::vector<Hash> hashes, uint64_t length, std::string correlation_id = "");
218 static Target Unknown();
220 const EcuMap &ecus() const { return ecus_; }
221 std::string filename() const { return filename_; }
222 std::string sha256Hash() const;
223 std::string sha512Hash() const;
224 const std::vector<Hash> &hashes() const { return hashes_; };
225 const std::vector<HardwareIdentifier> &hardwareIds() const { return hwids_; };
226 std::string custom_version() const { return custom_["version"].asString(); }
227 Json::Value custom_data() const { return custom_; }
228 void updateCustom(Json::Value &custom) { custom_ = custom; };
229 std::string correlation_id() const { return correlation_id_; };
230 void setCorrelationId(std::string correlation_id) { correlation_id_ = std::move(correlation_id); };
231 uint64_t length() const { return length_; }
232 bool IsValid() const { return valid; }
233 std::string uri() const { return uri_; };
234 void setUri(std::string uri) { uri_ = std::move(uri); };
235 bool MatchHash(const Hash &hash) const;
237 void InsertEcu(const std::pair<EcuSerial, HardwareIdentifier> &pair) { ecus_.insert(pair); }
239 bool IsForEcu(const EcuSerial &ecuIdentifier) const {
240 return (std::find_if(ecus_.cbegin(), ecus_.cend(),
241 [&ecuIdentifier](const std::pair<EcuSerial, HardwareIdentifier> &pair) {
242 return pair.first == ecuIdentifier;
252 bool IsOstree() const;
253 std::string type() const { return type_; }
256 bool operator==(const Target &t2) = delete;
257 bool MatchTarget(const Target &t2) const;
258 Json::Value toDebugJson() const;
259 friend std::ostream &operator<<(std::ostream &os, const Target &t);
260 InstalledImageInfo getTargetImageInfo() const { return {filename(), length(), sha256Hash()}; }
264 std::string filename_;
267 std::vector<Hash> hashes_;
268 std::vector<HardwareIdentifier> hwids_;
271 std::string correlation_id_;
274 std::string hashString(Hash::Type type) const;
277 std::ostream &operator<<(std::ostream &os, const Target &t);
283 BaseMeta() = default;
284 explicit BaseMeta(const Json::Value &json);
285 BaseMeta(RepositoryType repo, const Role &role, const Json::Value &json, const std::shared_ptr<MetaWithKeys> &signer);
286 int version() const { return version_; }
287 TimeStamp expiry() const { return expiry_; }
288 bool isExpired(const TimeStamp &now) const { return expiry_.IsExpiredAt(now); }
289 Json::Value original() const { return original_object_; }
291 bool operator==(const BaseMeta &rhs) const { return version_ == rhs.version() && expiry_ == rhs.expiry(); }
296 Json::Value original_object_;
299 void init(const Json::Value &json);
302 class MetaWithKeys : public BaseMeta {
304 enum class Policy { kRejectAll, kAcceptAll, kCheck };
308 MetaWithKeys() { version_ = 0; }
314 MetaWithKeys(const Json::Value &json);
315 MetaWithKeys(RepositoryType repo, const Role &role, const Json::Value &json,
316 const std::shared_ptr<MetaWithKeys> &signer);
318 virtual ~MetaWithKeys() = default;
320 void ParseKeys(RepositoryType repo, const Json::Value &keys);
323 void ParseRole(RepositoryType repo, const Json::ValueConstIterator &it, const Role &role,
324 const std::string &meta_role);
340 virtual void UnpackSignedObject(RepositoryType repo, const Role &role, const Json::Value &signed_object);
342 bool operator==(const MetaWithKeys &rhs) const {
343 return version_ == rhs.version_ && expiry_ == rhs.expiry_ && keys_ == rhs.keys_ &&
344 keys_for_role_ == rhs.keys_for_role_ && thresholds_for_role_ == rhs.thresholds_for_role_;
348 static const int64_t kMinSignatures = 1;
349 static const int64_t kMaxSignatures = 1000;
351 std::map<KeyId, PublicKey> keys_;
352 std::set<std::pair<Role, KeyId>> keys_for_role_;
353 std::map<Role, int64_t> thresholds_for_role_;
357 class Root : public MetaWithKeys {
362 explicit Root(Policy policy = Policy::kRejectAll) : policy_(policy) { version_ = 0; }
368 Root(RepositoryType repo, const Json::Value &json);
369 Root(RepositoryType repo, const Json::Value &json, Root &root);
371 ~Root() override = default;
387 void UnpackSignedObject(RepositoryType repo, const Role &role, const Json::Value &signed_object) override;
389 bool operator==(const Root &rhs) const {
390 return version_ == rhs.version_ && expiry_ == rhs.expiry_ && keys_ == rhs.keys_ &&
391 keys_for_role_ == rhs.keys_for_role_ && thresholds_for_role_ == rhs.thresholds_for_role_ &&
392 policy_ == rhs.policy_;
399 static bool MatchTargetVector(const std::vector<Uptane::Target> &v1, const std::vector<Uptane::Target> &v2) {
400 if (v1.size() != v2.size()) {
403 for (size_t i = 0; i < v1.size(); ++i) {
404 if (!v1[i].MatchTarget(v2[i])) {
412 class Targets : public MetaWithKeys {
414 explicit Targets(const Json::Value &json);
415 Targets(RepositoryType repo, const Role &role, const Json::Value &json, const std::shared_ptr<MetaWithKeys> &signer);
417 ~Targets() override = default;
419 bool operator==(const Targets &rhs) const {
420 return version_ == rhs.version() && expiry_ == rhs.expiry() && MatchTargetVector(targets, rhs.targets);
423 const std::string &correlation_id() const { return correlation_id_; }
427 delegated_role_names_.clear();
428 paths_for_role_.clear();
429 terminating_role_.clear();
432 std::vector<Uptane::Target> getTargets(const Uptane::EcuSerial &ecu_id,
433 const Uptane::HardwareIdentifier &hw_id) const {
434 std::vector<Uptane::Target> result;
435 for (auto it = targets.begin(); it != targets.end(); ++it) {
436 auto found_loc = std::find_if(it->ecus().begin(), it->ecus().end(),
437 [ecu_id, hw_id](const std::pair<EcuSerial, HardwareIdentifier> &val) {
438 return ((ecu_id == val.first) && (hw_id == val.second));
441 if (found_loc != it->ecus().end()) {
442 result.push_back(*it);
448 std::vector<Uptane::Target> targets;
449 std::vector<std::string> delegated_role_names_;
450 std::map<Role, std::vector<std::string>> paths_for_role_;
451 std::map<Role, bool> terminating_role_;
454 void init(const Json::Value &json);
457 std::string correlation_id_;
460 class TimestampMeta : public BaseMeta {
462 explicit TimestampMeta(const Json::Value &json);
463 TimestampMeta(RepositoryType repo, const Json::Value &json, const std::shared_ptr<MetaWithKeys> &signer);
464 TimestampMeta() = default;
465 std::vector<Hash> snapshot_hashes() const { return snapshot_hashes_; };
466 int64_t snapshot_size() const { return snapshot_size_; };
467 int snapshot_version() const { return snapshot_version_; };
470 void init(const Json::Value &json);
472 std::vector<Hash> snapshot_hashes_;
473 int64_t snapshot_size_{0};
474 int snapshot_version_{-1};
477 class Snapshot : public BaseMeta {
479 explicit Snapshot(const Json::Value &json);
480 Snapshot(RepositoryType repo, const Json::Value &json, const std::shared_ptr<MetaWithKeys> &signer);
481 Snapshot() = default;
482 std::vector<Hash> role_hashes(const Uptane::Role &role) const;
483 int64_t role_size(const Uptane::Role &role) const;
484 int role_version(const Uptane::Role &role) const;
485 bool operator==(const Snapshot &rhs) const {
486 return version_ == rhs.version() && expiry_ == rhs.expiry() && role_size_ == rhs.role_size_ &&
487 role_version_ == rhs.role_version_ && role_hashes_ == rhs.role_hashes_;
491 void init(const Json::Value &json);
492 std::map<Uptane::Role, int64_t> role_size_;
493 std::map<Uptane::Role, int> role_version_;
494 std::map<Uptane::Role, std::vector<Hash>> role_hashes_;
499 Targets director_targets;
501 Targets image_targets;
502 TimestampMeta image_timestamp;
503 Snapshot image_snapshot;
504 bool isConsistent() const;
508 std::string director_root;
509 std::string director_targets;
510 std::string image_root;
511 std::string image_targets;
512 std::string image_timestamp;
513 std::string image_snapshot;
516 int extractVersionUntrusted(const std::string &meta);
522 struct hash<Uptane::HardwareIdentifier> {
523 size_t operator()(const Uptane::HardwareIdentifier &hwid) const { return std::hash<std::string>()(hwid.hwid_); }
527 struct hash<Uptane::EcuSerial> {
528 size_t operator()(const Uptane::EcuSerial &ecu_serial) const {
529 return std::hash<std::string>()(ecu_serial.ecu_serial_);
Metadata version numbers.
Base data types that are used in The Update Framework (TUF), part of Uptane.