1 #include "imagerepository.h"
5 void ImageRepository::resetMeta() {
9 timestamp = TimestampMeta();
12 void 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";
23 void ImageRepository::checkTimestampExpired() {
24 if (timestamp.isExpired(TimeStamp::Now())) {
29 void ImageRepository::fetchSnapshot(
INvStorage& storage,
const IMetadataFetcher& fetcher,
const int local_version) {
30 std::string image_snapshot;
31 const int64_t snapshot_size = (snapshotSize() > 0) ? snapshotSize() : kMaxSnapshotSize;
32 fetcher.fetchLatestRole(&image_snapshot, snapshot_size, RepositoryType::Image(), Role::Snapshot());
33 const int remote_version = extractVersionUntrusted(image_snapshot);
41 verifySnapshot(image_snapshot,
false);
43 if (local_version > remote_version) {
45 }
else if (local_version < remote_version) {
46 storage.storeNonRoot(image_snapshot, RepositoryType::Image(), Role::Snapshot());
50 void ImageRepository::verifySnapshot(
const std::string& snapshot_raw,
bool prefetch) {
51 const std::string canonical = Utils::jsonToCanonicalStr(Utils::parseJSON(snapshot_raw));
52 bool hash_exists =
false;
53 for (
const auto& it : timestamp.snapshot_hashes()) {
55 case Hash::Type::kSha256:
56 if (
Hash(Hash::Type::kSha256, boost::algorithm::hex(Crypto::sha256digest(canonical))) != it) {
58 LOG_ERROR <<
"Hash verification for Snapshot metadata failed";
64 case Hash::Type::kSha512:
65 if (
Hash(Hash::Type::kSha512, boost::algorithm::hex(Crypto::sha512digest(canonical))) != it) {
67 LOG_ERROR <<
"Hash verification for Snapshot metadata failed";
79 LOG_ERROR <<
"No hash found for shapshot.json";
85 snapshot = Snapshot(RepositoryType::Image(), Utils::parseJSON(snapshot_raw), std::make_shared<MetaWithKeys>(root));
86 }
catch (
const Exception& e) {
87 LOG_ERROR <<
"Signature verification for Snapshot metadata failed";
91 if (snapshot.version() != timestamp.snapshot_version()) {
96 void ImageRepository::checkSnapshotExpired() {
97 if (snapshot.isExpired(TimeStamp::Now())) {
102 void ImageRepository::fetchTargets(
INvStorage& storage,
const IMetadataFetcher& fetcher,
const int local_version) {
103 std::string image_targets;
104 const Role targets_role = Role::Targets();
106 auto targets_size = getRoleSize(Role::Targets());
107 if (targets_size <= 0) {
108 targets_size = kMaxImageTargetsSize;
111 fetcher.fetchLatestRole(&image_targets, targets_size, RepositoryType::Image(), targets_role);
113 const int remote_version = extractVersionUntrusted(image_targets);
115 verifyTargets(image_targets,
false);
117 if (local_version > remote_version) {
119 }
else if (local_version < remote_version) {
120 storage.storeNonRoot(image_targets, RepositoryType::Image(), targets_role);
124 void ImageRepository::verifyRoleHashes(
const std::string& role_data,
const Uptane::Role& role,
bool prefetch)
const {
125 const std::string canonical = Utils::jsonToCanonicalStr(Utils::parseJSON(role_data));
128 for (
const auto& it : snapshot.role_hashes(role)) {
130 case Hash::Type::kSha256:
131 if (
Hash(Hash::Type::kSha256, boost::algorithm::hex(Crypto::sha256digest(canonical))) != it) {
133 LOG_ERROR <<
"Hash verification for " << role.ToString() <<
" metadata failed";
138 case Hash::Type::kSha512:
139 if (
Hash(Hash::Type::kSha512, boost::algorithm::hex(Crypto::sha512digest(canonical))) != it) {
141 LOG_ERROR <<
"Hash verification for " << role.ToString() <<
" metadata failed";
152 int ImageRepository::getRoleVersion(
const Uptane::Role& role)
const {
return snapshot.role_version(role); }
154 int64_t ImageRepository::getRoleSize(
const Uptane::Role& role)
const {
return snapshot.role_size(role); }
156 void ImageRepository::verifyTargets(
const std::string& targets_raw,
bool prefetch) {
158 verifyRoleHashes(targets_raw, Uptane::Role::Targets(), prefetch);
160 auto targets_json = Utils::parseJSON(targets_raw);
163 auto signer = std::make_shared<MetaWithKeys>(root);
164 targets = std::make_shared<Uptane::Targets>(
165 Targets(RepositoryType::Image(), Uptane::Role::Targets(), targets_json, signer));
167 if (targets->version() != snapshot.role_version(Uptane::Role::Targets())) {
170 }
catch (
const Exception& e) {
171 LOG_ERROR <<
"Signature verification for Image repo Targets metadata failed";
176 std::shared_ptr<Uptane::Targets> ImageRepository::verifyDelegation(
const std::string& delegation_raw,
178 const Targets& parent_target) {
180 const Json::Value delegation_json = Utils::parseJSON(delegation_raw);
181 const std::string canonical = Utils::jsonToCanonicalStr(delegation_json);
184 auto signer = std::make_shared<MetaWithKeys>(parent_target);
185 return std::make_shared<Uptane::Targets>(Targets(RepositoryType::Image(), role, delegation_json, signer));
186 }
catch (
const Exception& e) {
187 LOG_ERROR <<
"Signature verification for Image repo delegated Targets metadata failed";
191 return std::shared_ptr<Uptane::Targets>(
nullptr);
194 void ImageRepository::checkTargetsExpired() {
195 if (targets->isExpired(TimeStamp::Now())) {
200 void ImageRepository::updateMeta(
INvStorage& storage,
const IMetadataFetcher& fetcher) {
203 updateRoot(storage, fetcher, RepositoryType::Image());
207 std::string image_timestamp;
209 fetcher.fetchLatestRole(&image_timestamp, kMaxTimestampSize, RepositoryType::Image(), Role::Timestamp());
210 int remote_version = extractVersionUntrusted(image_timestamp);
213 std::string image_timestamp_stored;
214 if (storage.loadNonRoot(&image_timestamp_stored, RepositoryType::Image(), Role::Timestamp())) {
215 local_version = extractVersionUntrusted(image_timestamp_stored);
220 verifyTimestamp(image_timestamp);
222 if (local_version > remote_version) {
224 }
else if (local_version < remote_version) {
225 storage.storeNonRoot(image_timestamp, RepositoryType::Image(), Role::Timestamp());
228 checkTimestampExpired();
235 bool fetch_snapshot =
true;
237 std::string image_snapshot_stored;
238 if (storage.loadNonRoot(&image_snapshot_stored, RepositoryType::Image(), Role::Snapshot())) {
240 verifySnapshot(image_snapshot_stored,
true);
241 fetch_snapshot =
false;
242 LOG_DEBUG <<
"Skipping Image repo Snapshot download; stored version is still current.";
244 LOG_ERROR <<
"Image repo Snapshot verification failed: " << e.what();
246 local_version = snapshot.version();
252 if (fetch_snapshot) {
253 fetchSnapshot(storage, fetcher, local_version);
256 checkSnapshotExpired();
263 bool fetch_targets =
true;
264 int local_version = -1;
265 std::string image_targets_stored;
266 if (storage.loadNonRoot(&image_targets_stored, RepositoryType::Image(), Role::Targets())) {
268 verifyTargets(image_targets_stored,
true);
269 fetch_targets =
false;
270 LOG_DEBUG <<
"Skipping Image repo Targets download; stored version is still current.";
271 }
catch (
const std::exception& e) {
272 LOG_ERROR <<
"Image repo Target verification failed: " << e.what();
275 local_version = targets->version();
281 fetchTargets(storage, fetcher, local_version);
284 checkTargetsExpired();
288 void ImageRepository::checkMetaOffline(
INvStorage& storage) {
292 std::string image_root;
293 if (!storage.loadLatestRoot(&image_root, RepositoryType::Image())) {
297 initRoot(RepositoryType(RepositoryType::IMAGE), image_root);
306 std::string image_timestamp;
307 if (!storage.loadNonRoot(&image_timestamp, RepositoryType::Image(), Role::Timestamp())) {
311 verifyTimestamp(image_timestamp);
313 checkTimestampExpired();
318 std::string image_snapshot;
320 if (!storage.loadNonRoot(&image_snapshot, RepositoryType::Image(), Role::Snapshot())) {
324 verifySnapshot(image_snapshot,
false);
326 checkSnapshotExpired();
331 std::string image_targets;
332 Role targets_role = Uptane::Role::Targets();
333 if (!storage.loadNonRoot(&image_targets, RepositoryType::Image(), targets_role)) {
337 verifyTargets(image_targets,
false);
339 checkTargetsExpired();