Aktualizr
C++ SOTA Client
All Classes Namespaces Files Functions Variables Enumerations Enumerator Pages
storage_common_test.cc
1 #include <gtest/gtest.h>
2 
3 #include <memory>
4 #include <string>
5 
6 #include <boost/filesystem.hpp>
7 
8 #include "logging/logging.h"
9 #include "storage/sqlstorage.h"
10 #include "utilities/types.h"
11 #include "utilities/utils.h"
12 
13 StorageType current_storage_type{StorageType::kSqlite};
14 
15 std::unique_ptr<INvStorage> Storage(const boost::filesystem::path &dir) {
16  StorageConfig storage_config;
17  storage_config.type = current_storage_type;
18  storage_config.path = dir;
19 
20  if (storage_config.type == StorageType::kSqlite) {
21  return std::unique_ptr<INvStorage>(new SQLStorage(storage_config, false));
22  } else {
23  throw std::runtime_error("Invalid config type");
24  }
25 }
26 
27 StorageConfig MakeConfig(StorageType type, const boost::filesystem::path &storage_dir) {
28  StorageConfig config;
29 
30  config.type = type;
31  if (config.type == StorageType::kSqlite) {
32  config.sqldb_path = storage_dir / "test.db";
33  } else {
34  throw std::runtime_error("Invalid config type");
35  }
36  return config;
37 }
38 
39 /* Load and store Primary keys. */
40 TEST(storage, load_store_primary_keys) {
41  TemporaryDirectory temp_dir;
42  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
43 
44  storage->storePrimaryKeys("", "");
45  storage->storePrimaryKeys("pr_public", "pr_private");
46 
47  std::string pubkey;
48  std::string privkey;
49 
50  EXPECT_TRUE(storage->loadPrimaryKeys(&pubkey, &privkey));
51  EXPECT_EQ(pubkey, "pr_public");
52  EXPECT_EQ(privkey, "pr_private");
53  storage->clearPrimaryKeys();
54  EXPECT_FALSE(storage->loadPrimaryKeys(nullptr, nullptr));
55 }
56 
57 /* Load and store TLS credentials. */
58 TEST(storage, load_store_tls) {
59  TemporaryDirectory temp_dir;
60  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
61 
62  storage->storeTlsCreds("", "", "");
63  storage->storeTlsCreds("ca", "cert", "priv");
64  std::string ca;
65  std::string cert;
66  std::string priv;
67 
68  EXPECT_TRUE(storage->loadTlsCreds(&ca, &cert, &priv));
69 
70  EXPECT_EQ(ca, "ca");
71  EXPECT_EQ(cert, "cert");
72  EXPECT_EQ(priv, "priv");
73  storage->clearTlsCreds();
74  EXPECT_FALSE(storage->loadTlsCreds(nullptr, nullptr, nullptr));
75 }
76 
77 /* Load and store Uptane metadata. */
78 TEST(storage, load_store_metadata) {
79  TemporaryDirectory temp_dir;
80  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
81 
82  Json::Value root_json;
83  root_json["_type"] = "Root";
84  root_json["consistent_snapshot"] = false;
85  root_json["expires"] = "2038-01-19T03:14:06Z";
86  root_json["keys"]["firstid"]["keytype"] = "ed25519";
87  root_json["keys"]["firstid"]["keyval"]["public"] = "firstval";
88  root_json["keys"]["secondid"]["keytype"] = "ed25519";
89  root_json["keys"]["secondid"]["keyval"]["public"] = "secondval";
90 
91  root_json["roles"]["root"]["threshold"] = 1;
92  root_json["roles"]["root"]["keyids"][0] = "firstid";
93  root_json["roles"]["snapshot"]["threshold"] = 1;
94  root_json["roles"]["snapshot"]["keyids"][0] = "firstid";
95  root_json["roles"]["targets"]["threshold"] = 1;
96  root_json["roles"]["targets"]["keyids"][0] = "firstid";
97  root_json["roles"]["timestamp"]["threshold"] = 1;
98  root_json["roles"]["timestamp"]["keyids"][0] = "firstid";
99 
100  Json::Value meta_root;
101  meta_root["signed"] = root_json;
102  std::string director_root = Utils::jsonToStr(meta_root);
103  std::string image_root = Utils::jsonToStr(meta_root);
104 
105  Json::Value targets_json;
106  targets_json["_type"] = "Targets";
107  targets_json["expires"] = "2038-01-19T03:14:06Z";
108  targets_json["targets"]["file1"]["custom"]["ecu_identifier"] = "ecu1";
109  targets_json["targets"]["file1"]["custom"]["hardware_identifier"] = "hw1";
110  targets_json["targets"]["file1"]["hashes"]["sha256"] = "12ab";
111  targets_json["targets"]["file1"]["length"] = 1;
112  targets_json["targets"]["file2"]["custom"]["ecu_identifier"] = "ecu2";
113  targets_json["targets"]["file2"]["custom"]["hardware_identifier"] = "hw2";
114  targets_json["targets"]["file2"]["hashes"]["sha512"] = "12ab";
115  targets_json["targets"]["file2"]["length"] = 11;
116 
117  Json::Value meta_targets;
118  meta_targets["signed"] = targets_json;
119  std::string director_targets = Utils::jsonToStr(meta_targets);
120  std::string image_targets = Utils::jsonToStr(meta_targets);
121 
122  Json::Value timestamp_json;
123  timestamp_json["signed"]["_type"] = "Timestamp";
124  timestamp_json["signed"]["expires"] = "2038-01-19T03:14:06Z";
125  std::string image_timestamp = Utils::jsonToStr(timestamp_json);
126 
127  Json::Value snapshot_json;
128  snapshot_json["_type"] = "Snapshot";
129  snapshot_json["expires"] = "2038-01-19T03:14:06Z";
130  snapshot_json["meta"]["root.json"]["version"] = 1;
131  snapshot_json["meta"]["targets.json"]["version"] = 2;
132  snapshot_json["meta"]["timestamp.json"]["version"] = 3;
133  snapshot_json["meta"]["snapshot.json"]["version"] = 4;
134 
135  Json::Value meta_snapshot;
136  meta_snapshot["signed"] = snapshot_json;
137  std::string image_snapshot = Utils::jsonToStr(meta_snapshot);
138 
139  storage->storeRoot(director_root, Uptane::RepositoryType::Director(), Uptane::Version(1));
140  storage->storeNonRoot(director_targets, Uptane::RepositoryType::Director(), Uptane::Role::Targets());
141  storage->storeRoot(image_root, Uptane::RepositoryType::Image(), Uptane::Version(1));
142  storage->storeNonRoot(image_targets, Uptane::RepositoryType::Image(), Uptane::Role::Targets());
143  storage->storeNonRoot(image_timestamp, Uptane::RepositoryType::Image(), Uptane::Role::Timestamp());
144  storage->storeNonRoot(image_snapshot, Uptane::RepositoryType::Image(), Uptane::Role::Snapshot());
145 
146  std::string loaded_director_root;
147  std::string loaded_director_targets;
148  std::string loaded_image_root;
149  std::string loaded_image_targets;
150  std::string loaded_image_timestamp;
151  std::string loaded_image_snapshot;
152 
153  EXPECT_TRUE(storage->loadLatestRoot(&loaded_director_root, Uptane::RepositoryType::Director()));
154  EXPECT_TRUE(
155  storage->loadNonRoot(&loaded_director_targets, Uptane::RepositoryType::Director(), Uptane::Role::Targets()));
156  EXPECT_TRUE(storage->loadLatestRoot(&loaded_image_root, Uptane::RepositoryType::Image()));
157  EXPECT_TRUE(storage->loadNonRoot(&loaded_image_targets, Uptane::RepositoryType::Image(), Uptane::Role::Targets()));
158  EXPECT_TRUE(
159  storage->loadNonRoot(&loaded_image_timestamp, Uptane::RepositoryType::Image(), Uptane::Role::Timestamp()));
160  EXPECT_TRUE(storage->loadNonRoot(&loaded_image_snapshot, Uptane::RepositoryType::Image(), Uptane::Role::Snapshot()));
161  EXPECT_EQ(director_root, loaded_director_root);
162  EXPECT_EQ(director_targets, loaded_director_targets);
163  EXPECT_EQ(image_root, loaded_image_root);
164  EXPECT_EQ(image_targets, loaded_image_targets);
165  EXPECT_EQ(image_timestamp, loaded_image_timestamp);
166  EXPECT_EQ(image_snapshot, loaded_image_snapshot);
167 
168  storage->clearNonRootMeta(Uptane::RepositoryType::Director());
169  storage->clearNonRootMeta(Uptane::RepositoryType::Image());
170  EXPECT_FALSE(
171  storage->loadNonRoot(&loaded_director_targets, Uptane::RepositoryType::Director(), Uptane::Role::Targets()));
172  EXPECT_FALSE(
173  storage->loadNonRoot(&loaded_image_timestamp, Uptane::RepositoryType::Image(), Uptane::Role::Timestamp()));
174 }
175 
176 /* Load and store Uptane roots. */
177 TEST(storage, load_store_root) {
178  TemporaryDirectory temp_dir;
179  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
180 
181  Json::Value root_json;
182  root_json["_type"] = "Root";
183  root_json["consistent_snapshot"] = false;
184  root_json["expires"] = "2038-01-19T03:14:06Z";
185  root_json["keys"]["firstid"]["keytype"] = "ed25519";
186  root_json["keys"]["firstid"]["keyval"]["public"] = "firstval";
187  root_json["keys"]["secondid"]["keytype"] = "ed25519";
188  root_json["keys"]["secondid"]["keyval"]["public"] = "secondval";
189 
190  root_json["roles"]["root"]["threshold"] = 1;
191  root_json["roles"]["root"]["keyids"][0] = "firstid";
192  root_json["roles"]["snapshot"]["threshold"] = 1;
193  root_json["roles"]["snapshot"]["keyids"][0] = "firstid";
194  root_json["roles"]["targets"]["threshold"] = 1;
195  root_json["roles"]["targets"]["keyids"][0] = "firstid";
196  root_json["roles"]["timestamp"]["threshold"] = 1;
197  root_json["roles"]["timestamp"]["keyids"][0] = "firstid";
198 
199  Json::Value meta_root;
200  meta_root["signed"] = root_json;
201 
202  std::string loaded_root;
203 
204  storage->storeRoot(Utils::jsonToStr(meta_root), Uptane::RepositoryType::Director(), Uptane::Version(2));
205  EXPECT_TRUE(storage->loadRoot(&loaded_root, Uptane::RepositoryType::Director(), Uptane::Version(2)));
206  EXPECT_EQ(Utils::jsonToStr(meta_root), loaded_root);
207 
208  EXPECT_TRUE(storage->loadLatestRoot(&loaded_root, Uptane::RepositoryType::Director()));
209  EXPECT_EQ(Utils::jsonToStr(meta_root), loaded_root);
210 }
211 
212 /* Load and store the device ID. */
213 TEST(storage, load_store_deviceid) {
214  TemporaryDirectory temp_dir;
215  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
216 
217  storage->storeDeviceId("");
218  storage->storeDeviceId("device_id");
219 
220  std::string device_id;
221 
222  EXPECT_TRUE(storage->loadDeviceId(&device_id));
223 
224  EXPECT_EQ(device_id, "device_id");
225  storage->clearDeviceId();
226  EXPECT_FALSE(storage->loadDeviceId(nullptr));
227 }
228 
229 /* Load and store ECU serials.
230  * Preserve ECU ordering between store and load calls.
231  */
232 TEST(storage, load_store_ecu_serials) {
233  TemporaryDirectory temp_dir;
234  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
235 
236  storage->storeEcuSerials({{Uptane::EcuSerial("a"), Uptane::HardwareIdentifier("")}});
237  EcuSerials serials{{Uptane::EcuSerial("primary"), Uptane::HardwareIdentifier("primary_hw")},
238  {Uptane::EcuSerial("secondary_1"), Uptane::HardwareIdentifier("secondary_hw")},
239  {Uptane::EcuSerial("secondary_2"), Uptane::HardwareIdentifier("secondary_hw")}};
240  storage->storeEcuSerials(serials);
241 
242  EcuSerials serials_out;
243 
244  EXPECT_TRUE(storage->loadEcuSerials(&serials_out));
245 
246  EXPECT_EQ(serials, serials_out);
247  storage->clearEcuSerials();
248  EXPECT_FALSE(storage->loadEcuSerials(nullptr));
249 }
250 
251 /* Load and store a list of misconfigured ECUs. */
252 TEST(storage, load_store_misconfigured_ecus) {
253  TemporaryDirectory temp_dir;
254  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
255 
256  std::vector<MisconfiguredEcu> ecus;
257  ecus.push_back(MisconfiguredEcu(Uptane::EcuSerial("primary"), Uptane::HardwareIdentifier("primary_hw"),
258  EcuState::kNotRegistered));
259 
260  storage->storeMisconfiguredEcus(ecus);
261 
262  std::vector<MisconfiguredEcu> ecus_out;
263 
264  EXPECT_TRUE(storage->loadMisconfiguredEcus(&ecus_out));
265 
266  EXPECT_EQ(ecus_out.size(), ecus.size());
267  EXPECT_EQ(ecus_out[0].serial, Uptane::EcuSerial("primary"));
268  EXPECT_EQ(ecus_out[0].hardware_id, Uptane::HardwareIdentifier("primary_hw"));
269  EXPECT_EQ(ecus_out[0].state, EcuState::kNotRegistered);
270 
271  storage->clearMisconfiguredEcus();
272  ecus_out.clear();
273  EXPECT_FALSE(storage->loadMisconfiguredEcus(&ecus_out));
274 }
275 
276 /* Load and store a flag indicating successful registration. */
277 TEST(storage, load_store_ecu_registered) {
278  TemporaryDirectory temp_dir;
279  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
280 
281  EXPECT_THROW(storage->storeEcuRegistered(), std::runtime_error);
282  storage->storeDeviceId("test");
283  storage->storeEcuRegistered();
284  storage->storeEcuRegistered();
285 
286  EXPECT_TRUE(storage->loadEcuRegistered());
287 
288  storage->clearEcuRegistered();
289  EXPECT_FALSE(storage->loadEcuRegistered());
290 }
291 
292 /* Load and store installed versions. */
293 TEST(storage, load_store_installed_versions) {
294  TemporaryDirectory temp_dir;
295  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
296 
297  // Test lazy Primary installed version: Primary ECU serial is not defined yet
298  const std::vector<Hash> hashes = {
299  Hash{Hash::Type::kSha256, "2561"},
300  Hash{Hash::Type::kSha512, "5121"},
301  };
302  Uptane::EcuMap primary_ecu{{Uptane::EcuSerial("primary"), Uptane::HardwareIdentifier("primary_hw")}};
303  Uptane::Target t1{"update.bin", primary_ecu, hashes, 1, "corrid"};
304  Json::Value custom;
305  custom["version"] = 42;
306  custom["foo"] = "bar";
307  t1.updateCustom(custom);
308  storage->savePrimaryInstalledVersion(t1, InstalledVersionUpdateMode::kCurrent);
309  {
310  std::vector<Uptane::Target> log;
311  storage->loadPrimaryInstallationLog(&log, true);
312  EXPECT_EQ(log.size(), 1);
313  EXPECT_EQ(log[0].filename(), "update.bin");
314  }
315 
316  EcuSerials serials{{Uptane::EcuSerial("primary"), Uptane::HardwareIdentifier("primary_hw")},
317  {Uptane::EcuSerial("secondary_1"), Uptane::HardwareIdentifier("secondary_hw")},
318  {Uptane::EcuSerial("secondary_2"), Uptane::HardwareIdentifier("secondary_hw")}};
319  storage->storeEcuSerials(serials);
320 
321  {
322  boost::optional<Uptane::Target> current;
323  EXPECT_TRUE(storage->loadInstalledVersions("primary", &current, nullptr));
324  EXPECT_FALSE(storage->hasPendingInstall());
325  EXPECT_TRUE(!!current);
326  EXPECT_EQ(current->filename(), "update.bin");
327  EXPECT_EQ(current->sha256Hash(), "2561");
328  EXPECT_EQ(current->hashes(), hashes);
329  EXPECT_EQ(current->ecus(), primary_ecu);
330  EXPECT_EQ(current->correlation_id(), "corrid");
331  EXPECT_EQ(current->length(), 1);
332  EXPECT_EQ(current->custom_data()["foo"], "bar");
333  EXPECT_EQ(current->custom_data()["version"], 42);
334  }
335 
336  // Set t2 as a pending version
337  Uptane::Target t2{"update2.bin", primary_ecu, {Hash{Hash::Type::kSha256, "2562"}}, 2};
338  storage->savePrimaryInstalledVersion(t2, InstalledVersionUpdateMode::kPending);
339 
340  {
341  boost::optional<Uptane::Target> pending;
342  EXPECT_TRUE(storage->loadInstalledVersions("primary", nullptr, &pending));
343  EXPECT_TRUE(!!pending);
344  EXPECT_TRUE(storage->hasPendingInstall());
345  EXPECT_EQ(pending->filename(), "update2.bin");
346  }
347 
348  // Set t3 as the new pending
349  Uptane::Target t3{"update3.bin", primary_ecu, {Hash{Hash::Type::kSha256, "2563"}}, 3};
350  storage->savePrimaryInstalledVersion(t3, InstalledVersionUpdateMode::kPending);
351 
352  {
353  boost::optional<Uptane::Target> pending;
354  EXPECT_TRUE(storage->loadInstalledVersions("primary", nullptr, &pending));
355  EXPECT_TRUE(!!pending);
356  EXPECT_TRUE(storage->hasPendingInstall());
357  EXPECT_EQ(pending->filename(), "update3.bin");
358  }
359 
360  // Set t3 as current: should replace the pending flag but not create a new
361  // version
362  storage->savePrimaryInstalledVersion(t3, InstalledVersionUpdateMode::kCurrent);
363  {
364  boost::optional<Uptane::Target> current;
365  boost::optional<Uptane::Target> pending;
366  EXPECT_TRUE(storage->loadInstalledVersions("primary", &current, &pending));
367  EXPECT_TRUE(!!current);
368  EXPECT_EQ(current->filename(), "update3.bin");
369  EXPECT_FALSE(!!pending);
370  EXPECT_FALSE(storage->hasPendingInstall());
371 
372  std::vector<Uptane::Target> log;
373  storage->loadInstallationLog("primary", &log, true);
374  EXPECT_EQ(log.size(), 2);
375  EXPECT_EQ(log.back().filename(), "update3.bin");
376  }
377 
378  // Set t1 as current: the log should have grown even though we rolled back
379  {
380  storage->savePrimaryInstalledVersion(t1, InstalledVersionUpdateMode::kCurrent);
381  std::vector<Uptane::Target> log;
382  storage->loadInstallationLog("primary", &log, true);
383  EXPECT_EQ(log.size(), 3);
384  EXPECT_EQ(log.back().filename(), "update.bin");
385  EXPECT_FALSE(storage->hasPendingInstall());
386  }
387 
388  // Set t2 as the new pending and t3 as current afterwards: the pending flag
389  // should disappear
390  storage->savePrimaryInstalledVersion(t2, InstalledVersionUpdateMode::kPending);
391  storage->savePrimaryInstalledVersion(t3, InstalledVersionUpdateMode::kCurrent);
392 
393  {
394  boost::optional<Uptane::Target> current;
395  boost::optional<Uptane::Target> pending;
396  EXPECT_TRUE(storage->loadInstalledVersions("primary", &current, &pending));
397  EXPECT_TRUE(!!current);
398  EXPECT_EQ(current->filename(), "update3.bin");
399  EXPECT_FALSE(!!pending);
400  EXPECT_FALSE(storage->hasPendingInstall());
401 
402  std::vector<Uptane::Target> log;
403  storage->loadInstallationLog("primary", &log, true);
404  EXPECT_EQ(log.size(), 4);
405  EXPECT_EQ(log.back().filename(), "update3.bin");
406  EXPECT_EQ(log[0].custom_data()["foo"], "bar");
407  }
408 
409  // Add a Secondary installed version
410  Uptane::EcuMap secondary_ecu{{Uptane::EcuSerial("secondary1"), Uptane::HardwareIdentifier("secondary_hw")}};
411  Uptane::Target tsec{"secondary.bin", secondary_ecu, {Hash{Hash::Type::kSha256, "256s"}}, 4};
412  storage->saveInstalledVersion("secondary_1", tsec, InstalledVersionUpdateMode::kCurrent);
413 
414  {
415  EXPECT_TRUE(storage->loadInstalledVersions("primary", nullptr, nullptr));
416  EXPECT_TRUE(storage->loadInstalledVersions("secondary_1", nullptr, nullptr));
417 
418  std::vector<Uptane::Target> log;
419  storage->loadInstallationLog("secondary_1", &log, true);
420  EXPECT_EQ(log.size(), 1);
421  EXPECT_EQ(log.back().filename(), "secondary.bin");
422  }
423 }
424 
425 /*
426  * Load and store an ECU installation result in an SQL database.
427  * Load and store a device installation result in an SQL database.
428  */
429 TEST(storage, load_store_installation_results) {
430  TemporaryDirectory temp_dir;
431  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
432 
433  EcuSerials serials{{Uptane::EcuSerial("primary"), Uptane::HardwareIdentifier("primary_hw")},
434  {Uptane::EcuSerial("secondary_1"), Uptane::HardwareIdentifier("secondary_hw")},
435  {Uptane::EcuSerial("secondary_2"), Uptane::HardwareIdentifier("secondary_hw")}};
436  storage->storeEcuSerials(serials);
437 
438  storage->saveEcuInstallationResult(Uptane::EcuSerial("secondary_2"), data::InstallationResult());
439  storage->saveEcuInstallationResult(Uptane::EcuSerial("primary"), data::InstallationResult());
440  storage->saveEcuInstallationResult(Uptane::EcuSerial("primary"),
442 
443  std::vector<std::pair<Uptane::EcuSerial, data::InstallationResult>> res;
444  EXPECT_TRUE(storage->loadEcuInstallationResults(&res));
445  EXPECT_EQ(res.size(), 2);
446  EXPECT_EQ(res.at(0).first.ToString(), "primary");
447  EXPECT_EQ(res.at(0).second.result_code.num_code, data::ResultCode::Numeric::kGeneralError);
448  EXPECT_EQ(res.at(1).first.ToString(), "secondary_2");
449  EXPECT_EQ(res.at(1).second.result_code.num_code, data::ResultCode::Numeric::kOk);
450 
451  storage->storeDeviceInstallationResult(data::InstallationResult(data::ResultCode::Numeric::kGeneralError, ""), "raw",
452  "corrid");
453 
454  data::InstallationResult dev_res;
455  std::string report;
456  std::string correlation_id;
457  EXPECT_TRUE(storage->loadDeviceInstallationResult(&dev_res, &report, &correlation_id));
458  EXPECT_EQ(dev_res.result_code.num_code, data::ResultCode::Numeric::kGeneralError);
459  EXPECT_EQ(report, "raw");
460  EXPECT_EQ(correlation_id, "corrid");
461 
462  storage->clearInstallationResults();
463  res.clear();
464  EXPECT_FALSE(storage->loadEcuInstallationResults(&res));
465  EXPECT_EQ(res.size(), 0);
466  EXPECT_FALSE(storage->loadDeviceInstallationResult(&dev_res, &report, &correlation_id));
467 }
468 
469 /* Load and store targets. */
470 TEST(storage, store_target) {
471  TemporaryDirectory temp_dir;
472  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
473 
474  Json::Value target_json;
475  target_json["hashes"]["sha256"] = "hash";
476  target_json["length"] = 2;
477  Uptane::Target target("some.deb", target_json);
478 
479  // write
480  {
481  std::unique_ptr<StorageTargetWHandle> fhandle = storage->allocateTargetFile(target);
482  const uint8_t wb[] = "ab";
483  fhandle->wfeed(wb, 1);
484  fhandle->wfeed(wb + 1, 1);
485  fhandle->wcommit();
486  }
487 
488  // read
489  {
490  std::unique_ptr<StorageTargetRHandle> rhandle = storage->openTargetFile(target);
491  uint8_t rb[3] = {0};
492  EXPECT_EQ(rhandle->rsize(), 2);
493  rhandle->rread(rb, 1);
494  rhandle->rread(rb + 1, 1);
495  rhandle->rclose();
496  EXPECT_STREQ(reinterpret_cast<char *>(rb), "ab");
497  }
498 
499  // write again
500  {
501  std::unique_ptr<StorageTargetWHandle> fhandle = storage->allocateTargetFile(target);
502  const uint8_t wb[] = "ab";
503  fhandle->wfeed(wb, 1);
504  fhandle->wfeed(wb + 1, 1);
505  fhandle->wcommit();
506  }
507 
508  // delete
509  {
510  storage->removeTargetFile(target.filename());
511  EXPECT_THROW(storage->openTargetFile(target), StorageTargetRHandle::ReadError);
512  EXPECT_THROW(storage->removeTargetFile(target.filename()), std::runtime_error);
513  }
514 
515  // write stream
516  {
517  std::unique_ptr<StorageTargetWHandle> fhandle = storage->allocateTargetFile(target);
518  std::stringstream("ab") >> *fhandle;
519  }
520 
521  // read stream
522  {
523  std::stringstream sstr;
524  std::unique_ptr<StorageTargetRHandle> rhandle = storage->openTargetFile(target);
525  sstr << *rhandle;
526  EXPECT_STREQ(sstr.str().c_str(), "ab");
527  }
528 }
529 
530 /*
531  * List targets currently in storage.
532  * Remove a target binary from storage.
533  */
534 TEST(storage, list_remove_targets) {
535  TemporaryDirectory temp_dir;
536  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
537 
538  Json::Value target_json;
539  target_json["hashes"]["sha256"] = "HASH";
540  target_json["length"] = 2;
541  Uptane::Target target("some.deb", target_json);
542 
543  auto tfs = storage->getTargetFiles();
544  EXPECT_EQ(tfs.size(), 0);
545 
546  // write
547  {
548  std::unique_ptr<StorageTargetWHandle> fhandle = storage->allocateTargetFile(target);
549  const uint8_t wb[] = "ab";
550  fhandle->wfeed(wb, 1);
551  fhandle->wfeed(wb + 1, 1);
552  fhandle->wcommit();
553  }
554 
555  tfs = storage->getTargetFiles();
556  ASSERT_EQ(tfs.size(), 1);
557 
558  auto tf = tfs.at(0);
559 
560  EXPECT_EQ(tf.filename(), "some.deb");
561  EXPECT_EQ(tf.length(), 2);
562  EXPECT_EQ(tf.hashes().size(), 1);
563  EXPECT_EQ(tf.hashes().at(0), Hash(Hash::Type::kSha256, "HASH"));
564 
565  // note: implementation specific
566  EXPECT_TRUE(boost::filesystem::exists(temp_dir.Path() / "images" / "HASH"));
567 
568  storage->removeTargetFile(tf.filename());
569 
570  tfs = storage->getTargetFiles();
571  EXPECT_EQ(tfs.size(), 0);
572  EXPECT_FALSE(boost::filesystem::exists(temp_dir.Path() / "images" / "HASH"));
573 }
574 
575 TEST(storage, load_store_secondary_info) {
576  TemporaryDirectory temp_dir;
577  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
578 
579  // note: this can be done before the ECU is known
580  storage->saveSecondaryData(Uptane::EcuSerial("secondary_2"), "data2");
581 
582  EcuSerials serials{{Uptane::EcuSerial("primary"), Uptane::HardwareIdentifier("primary_hw")},
583  {Uptane::EcuSerial("secondary_1"), Uptane::HardwareIdentifier("secondary_hw")},
584  {Uptane::EcuSerial("secondary_2"), Uptane::HardwareIdentifier("secondary_hw")}};
585  storage->storeEcuSerials(serials);
586 
587  storage->saveSecondaryInfo(Uptane::EcuSerial("secondary_1"), "ip", PublicKey("key1", KeyType::kED25519));
588 
589  EXPECT_THROW(storage->saveSecondaryInfo(Uptane::EcuSerial("primary"), "ip", PublicKey("key0", KeyType::kRSA2048)),
590  std::runtime_error);
591 
592  std::vector<SecondaryInfo> sec_infos;
593  EXPECT_TRUE(storage->loadSecondariesInfo(&sec_infos));
594 
595  ASSERT_EQ(sec_infos.size(), 2);
596  EXPECT_EQ(sec_infos[0].serial.ToString(), "secondary_1");
597  EXPECT_EQ(sec_infos[0].hw_id.ToString(), "secondary_hw");
598  EXPECT_EQ(sec_infos[0].type, "ip");
599  EXPECT_EQ(sec_infos[0].pub_key.Value(), "key1");
600  EXPECT_EQ(sec_infos[0].pub_key.Type(), KeyType::kED25519);
601  EXPECT_EQ(sec_infos[1].pub_key.Type(), KeyType::kUnknown);
602  EXPECT_EQ(sec_infos[1].type, "");
603  EXPECT_EQ(sec_infos[1].extra, "data2");
604 
605  // test update of data
606  storage->saveSecondaryInfo(Uptane::EcuSerial("secondary_1"), "ip", PublicKey("key2", KeyType::kED25519));
607  storage->saveSecondaryData(Uptane::EcuSerial("secondary_1"), "data1");
608  EXPECT_TRUE(storage->loadSecondariesInfo(&sec_infos));
609 
610  ASSERT_EQ(sec_infos.size(), 2);
611  EXPECT_EQ(sec_infos[0].pub_key.Value(), "key2");
612  EXPECT_EQ(sec_infos[0].extra, "data1");
613 }
614 
615 TEST(storage, checksum) {
616  TemporaryDirectory temp_dir;
617  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
618 
619  Json::Value target_json1;
620  target_json1["hashes"]["sha256"] = "hash1";
621  target_json1["length"] = 2;
622  Uptane::Target target1("some.deb", target_json1);
623  Json::Value target_json2;
624  target_json2["length"] = 2;
625  target_json2["hashes"]["sha256"] = "hash2";
626  Uptane::Target target2("some.deb", target_json2);
627 
628  // write target1
629  {
630  std::unique_ptr<StorageTargetWHandle> fhandle = storage->allocateTargetFile(target1);
631  const uint8_t wb[] = "ab";
632  fhandle->wfeed(wb, 2);
633  fhandle->wcommit();
634  }
635 
636  // read target 1
637  {
638  std::unique_ptr<StorageTargetRHandle> rhandle = storage->openTargetFile(target1);
639  uint8_t rb[3] = {0};
640  EXPECT_EQ(rhandle->rsize(), 2);
641  rhandle->rread(rb, 2);
642  rhandle->rclose();
643  EXPECT_STREQ(reinterpret_cast<char *>(rb), "ab");
644  }
645 
646  // read target 2
647  { EXPECT_THROW(storage->openTargetFile(target2), StorageTargetRHandle::ReadError); }
648 }
649 
650 TEST(storage, partial) {
651  TemporaryDirectory temp_dir;
652  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
653 
654  Json::Value target_json;
655  target_json["hashes"]["sha256"] = "hash1";
656  target_json["length"] = 3;
657  Uptane::Target target("some.deb", target_json);
658 
659  // write partial target
660  {
661  std::unique_ptr<StorageTargetWHandle> fhandle = storage->allocateTargetFile(target);
662  const uint8_t wb[] = "a";
663  fhandle->wfeed(wb, 1);
664  fhandle->wcommit();
665  }
666 
667  // read and check partial target
668  {
669  std::unique_ptr<StorageTargetRHandle> rhandle = storage->openTargetFile(target);
670  uint8_t rb[2] = {0};
671  EXPECT_EQ(rhandle->rsize(), 1);
672  EXPECT_TRUE(rhandle->isPartial());
673  rhandle->rread(rb, 1);
674  rhandle->rclose();
675  EXPECT_STREQ(reinterpret_cast<char *>(rb), "a");
676  }
677 
678  // Append without committing, should commit in whandle destructor
679  {
680  std::unique_ptr<StorageTargetWHandle> whandle = storage->openTargetFile(target)->toWriteHandle();
681  const uint8_t wb[] = "b";
682  whandle->wfeed(wb, 1);
683  }
684 
685  // read and check partial target
686  {
687  std::unique_ptr<StorageTargetRHandle> rhandle = storage->openTargetFile(target);
688  uint8_t rb[3] = {0};
689  EXPECT_EQ(rhandle->rsize(), 2);
690  EXPECT_TRUE(rhandle->isPartial());
691  rhandle->rread(rb, 2);
692  rhandle->rclose();
693  EXPECT_STREQ(reinterpret_cast<char *>(rb), "ab");
694  }
695 
696  // Append partial
697  {
698  std::unique_ptr<StorageTargetWHandle> whandle = storage->openTargetFile(target)->toWriteHandle();
699  const uint8_t wb[] = "c";
700  whandle->wfeed(wb, 1);
701  whandle->wcommit();
702  }
703 
704  // Check full target
705  {
706  std::unique_ptr<StorageTargetRHandle> rhandle = storage->openTargetFile(target);
707  EXPECT_EQ(rhandle->rsize(), 3);
708  EXPECT_FALSE(rhandle->isPartial());
709  }
710 }
711 
712 /* Import keys and credentials from file into storage. */
713 TEST(storage, import_data) {
714  TemporaryDirectory temp_dir;
715  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
716  boost::filesystem::create_directories(temp_dir / "import");
717 
718  ImportConfig import_config;
719  import_config.base_path = temp_dir.Path() / "import";
720  import_config.uptane_private_key_path = BasedPath("private");
721  import_config.uptane_public_key_path = BasedPath("public");
722  import_config.tls_cacert_path = BasedPath("ca");
723  import_config.tls_clientcert_path = BasedPath("cert");
724  import_config.tls_pkey_path = BasedPath("pkey");
725 
726  Utils::writeFile(import_config.uptane_private_key_path.get(import_config.base_path).string(),
727  std::string("uptane_private_1"));
728  Utils::writeFile(import_config.uptane_public_key_path.get(import_config.base_path).string(),
729  std::string("uptane_public_1"));
730  Utils::writeFile(import_config.tls_cacert_path.get(import_config.base_path).string(), std::string("tls_cacert_1"));
731  Utils::writeFile(import_config.tls_clientcert_path.get(import_config.base_path).string(), std::string("tls_cert_1"));
732  Utils::writeFile(import_config.tls_pkey_path.get(import_config.base_path).string(), std::string("tls_pkey_1"));
733 
734  // Initially the storage is empty
735  EXPECT_FALSE(storage->loadPrimaryPublic(nullptr));
736  EXPECT_FALSE(storage->loadPrimaryPrivate(nullptr));
737  EXPECT_FALSE(storage->loadTlsCa(nullptr));
738  EXPECT_FALSE(storage->loadTlsCert(nullptr));
739  EXPECT_FALSE(storage->loadTlsPkey(nullptr));
740 
741  storage->importData(import_config);
742 
743  std::string primary_public;
744  std::string primary_private;
745  std::string tls_ca;
746  std::string tls_cert;
747  std::string tls_pkey;
748 
749  // the data has been imported
750  EXPECT_TRUE(storage->loadPrimaryPublic(&primary_public));
751  EXPECT_TRUE(storage->loadPrimaryPrivate(&primary_private));
752  EXPECT_TRUE(storage->loadTlsCa(&tls_ca));
753  EXPECT_TRUE(storage->loadTlsCert(&tls_cert));
754  EXPECT_TRUE(storage->loadTlsPkey(&tls_pkey));
755 
756  EXPECT_EQ(primary_private, "uptane_private_1");
757  EXPECT_EQ(primary_public, "uptane_public_1");
758  EXPECT_EQ(tls_ca, "tls_cacert_1");
759  EXPECT_EQ(tls_cert, "tls_cert_1");
760  EXPECT_EQ(tls_pkey, "tls_pkey_1");
761 
762  Utils::writeFile(import_config.uptane_private_key_path.get(import_config.base_path).string(),
763  std::string("uptane_private_2"));
764  Utils::writeFile(import_config.uptane_public_key_path.get(import_config.base_path).string(),
765  std::string("uptane_public_2"));
766  Utils::writeFile(import_config.tls_cacert_path.get(import_config.base_path).string(), std::string("tls_cacert_2"));
767  Utils::writeFile(import_config.tls_clientcert_path.get(import_config.base_path).string(), std::string("tls_cert_2"));
768  Utils::writeFile(import_config.tls_pkey_path.get(import_config.base_path).string(), std::string("tls_pkey_2"));
769 
770  storage->importData(import_config);
771 
772  EXPECT_TRUE(storage->loadPrimaryPublic(&primary_public));
773  EXPECT_TRUE(storage->loadPrimaryPrivate(&primary_private));
774  EXPECT_TRUE(storage->loadTlsCa(&tls_ca));
775  EXPECT_TRUE(storage->loadTlsCert(&tls_cert));
776  EXPECT_TRUE(storage->loadTlsPkey(&tls_pkey));
777 
778  // only root cert is being updated
779  EXPECT_EQ(primary_private, "uptane_private_1");
780  EXPECT_EQ(primary_public, "uptane_public_1");
781  EXPECT_EQ(tls_ca, "tls_cacert_2");
782  EXPECT_EQ(tls_cert, "tls_cert_1");
783  EXPECT_EQ(tls_pkey, "tls_pkey_1");
784 }
785 
786 #ifndef __NO_MAIN__
787 int main(int argc, char **argv) {
788  ::testing::InitGoogleTest(&argc, argv);
789  logger_init();
790  logger_set_threshold(boost::log::trivial::trace);
791 
792  std::cout << "Running tests for SQLStorage" << std::endl;
793  current_storage_type = StorageType::kSqlite;
794  int res_sql = RUN_ALL_TESTS();
795 
796  return res_sql; // 0 indicates success
797 }
798 #endif
Metadata version numbers.
Definition: tuf.h:119
The hash of a file or Uptane metadata.
Definition: crypto.h:65