1 #include "imagerepository.h"
5 void ImageRepository::resetMeta() {
9 timestamp = TimestampMeta();
12 bool ImageRepository::verifyTimestamp(
const std::string& timestamp_raw) {
16 TimestampMeta(RepositoryType::Image(), Utils::parseJSON(timestamp_raw), std::make_shared<MetaWithKeys>(root));
17 }
catch (
const Exception& e) {
18 LOG_ERROR <<
"Signature verification for Timestamp metadata failed";
25 bool ImageRepository::timestampExpired() {
26 if (timestamp.isExpired(TimeStamp::Now())) {
33 bool ImageRepository::fetchSnapshot(
INvStorage& storage,
const IMetadataFetcher& fetcher,
const int local_version) {
34 std::string image_snapshot;
35 const int64_t snapshot_size = (snapshotSize() > 0) ? snapshotSize() : kMaxSnapshotSize;
36 if (!fetcher.fetchLatestRole(&image_snapshot, snapshot_size, RepositoryType::Image(), Role::Snapshot())) {
39 const int remote_version = extractVersionUntrusted(image_snapshot);
47 if (!verifySnapshot(image_snapshot,
false)) {
51 if (local_version > remote_version) {
53 }
else if (local_version < remote_version) {
54 storage.storeNonRoot(image_snapshot, RepositoryType::Image(), Role::Snapshot());
60 bool ImageRepository::verifySnapshot(
const std::string& snapshot_raw,
bool prefetch) {
62 const std::string canonical = Utils::jsonToCanonicalStr(Utils::parseJSON(snapshot_raw));
63 bool hash_exists =
false;
64 for (
const auto& it : timestamp.snapshot_hashes()) {
66 case Hash::Type::kSha256:
67 if (Hash(Hash::Type::kSha256, boost::algorithm::hex(Crypto::sha256digest(canonical))) != it) {
69 LOG_ERROR <<
"Hash verification for Snapshot metadata failed";
75 case Hash::Type::kSha512:
76 if (Hash(Hash::Type::kSha512, boost::algorithm::hex(Crypto::sha512digest(canonical))) != it) {
78 LOG_ERROR <<
"Hash verification for Snapshot metadata failed";
89 LOG_ERROR <<
"No hash found for shapshot.json";
93 snapshot = Snapshot(RepositoryType::Image(), Utils::parseJSON(snapshot_raw), std::make_shared<MetaWithKeys>(root));
94 if (snapshot.version() != timestamp.snapshot_version()) {
97 }
catch (
const Exception& e) {
98 LOG_ERROR <<
"Signature verification for Snapshot metadata failed";
105 bool ImageRepository::snapshotExpired() {
106 if (snapshot.isExpired(TimeStamp::Now())) {
113 bool ImageRepository::fetchTargets(
INvStorage& storage,
const IMetadataFetcher& fetcher,
const int local_version) {
114 std::string image_targets;
115 const Role targets_role = Role::Targets();
117 auto targets_size = getRoleSize(Role::Targets());
118 if (targets_size <= 0) {
119 targets_size = kMaxImageTargetsSize;
121 if (!fetcher.fetchLatestRole(&image_targets, targets_size, RepositoryType::Image(), targets_role)) {
124 const int remote_version = extractVersionUntrusted(image_targets);
126 if (!verifyTargets(image_targets,
false)) {
130 if (local_version > remote_version) {
132 }
else if (local_version < remote_version) {
133 storage.storeNonRoot(image_targets, RepositoryType::Image(), targets_role);
139 bool ImageRepository::verifyRoleHashes(
const std::string& role_data,
const Uptane::Role& role,
bool prefetch)
const {
140 const std::string canonical = Utils::jsonToCanonicalStr(Utils::parseJSON(role_data));
143 for (
const auto& it : snapshot.role_hashes(role)) {
145 case Hash::Type::kSha256:
146 if (Hash(Hash::Type::kSha256, boost::algorithm::hex(Crypto::sha256digest(canonical))) != it) {
148 LOG_ERROR <<
"Hash verification for " << role.ToString() <<
" metadata failed";
153 case Hash::Type::kSha512:
154 if (Hash(Hash::Type::kSha512, boost::algorithm::hex(Crypto::sha512digest(canonical))) != it) {
156 LOG_ERROR <<
"Hash verification for " << role.ToString() <<
" metadata failed";
169 int ImageRepository::getRoleVersion(
const Uptane::Role& role)
const {
return snapshot.role_version(role); }
171 int64_t ImageRepository::getRoleSize(
const Uptane::Role& role)
const {
return snapshot.role_size(role); }
173 bool ImageRepository::verifyTargets(
const std::string& targets_raw,
bool prefetch) {
175 if (!verifyRoleHashes(targets_raw, Uptane::Role::Targets(), prefetch)) {
179 auto targets_json = Utils::parseJSON(targets_raw);
182 auto signer = std::make_shared<MetaWithKeys>(root);
183 targets = std::make_shared<Uptane::Targets>(
184 Targets(RepositoryType::Image(), Uptane::Role::Targets(), targets_json, signer));
186 if (targets->version() != snapshot.role_version(Uptane::Role::Targets())) {
189 }
catch (
const Exception& e) {
190 LOG_ERROR <<
"Signature verification for Image repo Targets metadata failed";
197 std::shared_ptr<Uptane::Targets> ImageRepository::verifyDelegation(
const std::string& delegation_raw,
199 const Targets& parent_target) {
201 const Json::Value delegation_json = Utils::parseJSON(delegation_raw);
202 const std::string canonical = Utils::jsonToCanonicalStr(delegation_json);
205 auto signer = std::make_shared<MetaWithKeys>(parent_target);
206 return std::make_shared<Uptane::Targets>(Targets(RepositoryType::Image(), role, delegation_json, signer));
207 }
catch (
const Exception& e) {
208 LOG_ERROR <<
"Signature verification for Image repo delegated Targets metadata failed";
212 return std::shared_ptr<Uptane::Targets>(
nullptr);
215 bool ImageRepository::targetsExpired() {
216 if (targets->isExpired(TimeStamp::Now())) {
223 bool ImageRepository::updateMeta(
INvStorage& storage,
const IMetadataFetcher& fetcher) {
226 if (!updateRoot(storage, fetcher, RepositoryType::Image())) {
232 std::string image_timestamp;
234 if (!fetcher.fetchLatestRole(&image_timestamp, kMaxTimestampSize, RepositoryType::Image(), Role::Timestamp())) {
237 int remote_version = extractVersionUntrusted(image_timestamp);
240 std::string image_timestamp_stored;
241 if (storage.loadNonRoot(&image_timestamp_stored, RepositoryType::Image(), Role::Timestamp())) {
242 local_version = extractVersionUntrusted(image_timestamp_stored);
247 if (!verifyTimestamp(image_timestamp)) {
251 if (local_version > remote_version) {
253 }
else if (local_version < remote_version) {
254 storage.storeNonRoot(image_timestamp, RepositoryType::Image(), Role::Timestamp());
257 if (timestampExpired()) {
266 bool fetch_snapshot =
true;
268 std::string image_snapshot_stored;
269 if (storage.loadNonRoot(&image_snapshot_stored, RepositoryType::Image(), Role::Snapshot())) {
270 if (verifySnapshot(image_snapshot_stored,
true)) {
271 fetch_snapshot =
false;
272 LOG_DEBUG <<
"Skipping Image repo Snapshot download; stored version is still current.";
274 local_version = snapshot.version();
280 if (fetch_snapshot) {
281 if (!fetchSnapshot(storage, fetcher, local_version)) {
286 if (snapshotExpired()) {
295 bool fetch_targets =
true;
296 int local_version = -1;
297 std::string image_targets_stored;
298 if (storage.loadNonRoot(&image_targets_stored, RepositoryType::Image(), Role::Targets())) {
299 if (verifyTargets(image_targets_stored,
true)) {
300 fetch_targets =
false;
301 LOG_DEBUG <<
"Skipping Image repo Targets download; stored version is still current.";
304 local_version = targets->version();
310 if (!fetchTargets(storage, fetcher, local_version)) {
315 if (targetsExpired()) {
323 bool ImageRepository::checkMetaOffline(
INvStorage& storage) {
327 std::string image_root;
328 if (!storage.loadLatestRoot(&image_root, RepositoryType::Image())) {
332 if (!initRoot(image_root)) {
343 std::string image_timestamp;
344 if (!storage.loadNonRoot(&image_timestamp, RepositoryType::Image(), Role::Timestamp())) {
348 if (!verifyTimestamp(image_timestamp)) {
352 if (timestampExpired()) {
359 std::string image_snapshot;
361 if (!storage.loadNonRoot(&image_snapshot, RepositoryType::Image(), Role::Snapshot())) {
365 if (!verifySnapshot(image_snapshot,
false)) {
369 if (snapshotExpired()) {
376 std::string image_targets;
377 Role targets_role = Uptane::Role::Targets();
378 if (!storage.loadNonRoot(&image_targets, RepositoryType::Image(), targets_role)) {
382 if (!verifyTargets(image_targets,
false)) {
386 if (targetsExpired()) {