Aktualizr
C++ SOTA Client
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 "libaktualizr/types.h"
9 #include "storage/sqlstorage.h"
10 #include "utilities/utils.h"
11 
12 StorageType current_storage_type{StorageType::kSqlite};
13 
14 std::unique_ptr<INvStorage> Storage(const boost::filesystem::path &dir) {
15  StorageConfig storage_config;
16  storage_config.type = current_storage_type;
17  storage_config.path = dir;
18 
19  if (storage_config.type == StorageType::kSqlite) {
20  return std::unique_ptr<INvStorage>(new SQLStorage(storage_config, false));
21  } else {
22  throw std::runtime_error("Invalid config type");
23  }
24 }
25 
26 StorageConfig MakeConfig(StorageType type, const boost::filesystem::path &storage_dir) {
27  StorageConfig config;
28 
29  config.type = type;
30  if (config.type == StorageType::kSqlite) {
31  config.sqldb_path = storage_dir / "test.db";
32  } else {
33  throw std::runtime_error("Invalid config type");
34  }
35  return config;
36 }
37 
38 /* Load and store Primary keys. */
39 TEST(StorageCommon, LoadStorePrimaryKeys) {
40  TemporaryDirectory temp_dir;
41  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
42 
43  storage->storePrimaryKeys("", "");
44  storage->storePrimaryKeys("pr_public", "pr_private");
45 
46  std::string pubkey;
47  std::string privkey;
48 
49  EXPECT_TRUE(storage->loadPrimaryKeys(&pubkey, &privkey));
50  EXPECT_EQ(pubkey, "pr_public");
51  EXPECT_EQ(privkey, "pr_private");
52  storage->clearPrimaryKeys();
53  EXPECT_FALSE(storage->loadPrimaryKeys(nullptr, nullptr));
54 }
55 
56 /* Load and store TLS credentials. */
57 TEST(StorageCommon, LoadStoreTls) {
58  TemporaryDirectory temp_dir;
59  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
60 
61  storage->storeTlsCreds("", "", "");
62  storage->storeTlsCreds("ca", "cert", "priv");
63  std::string ca;
64  std::string cert;
65  std::string priv;
66 
67  EXPECT_TRUE(storage->loadTlsCreds(&ca, &cert, &priv));
68 
69  EXPECT_EQ(ca, "ca");
70  EXPECT_EQ(cert, "cert");
71  EXPECT_EQ(priv, "priv");
72  storage->clearTlsCreds();
73  EXPECT_FALSE(storage->loadTlsCreds(nullptr, nullptr, nullptr));
74 }
75 
76 /* Load and store Uptane metadata. */
77 TEST(StorageCommon, LoadStoreMetadata) {
78  TemporaryDirectory temp_dir;
79  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
80 
81  Json::Value root_json;
82  root_json["_type"] = "Root";
83  root_json["consistent_snapshot"] = false;
84  root_json["expires"] = "2038-01-19T03:14:06Z";
85  root_json["keys"]["firstid"]["keytype"] = "ed25519";
86  root_json["keys"]["firstid"]["keyval"]["public"] = "firstval";
87  root_json["keys"]["secondid"]["keytype"] = "ed25519";
88  root_json["keys"]["secondid"]["keyval"]["public"] = "secondval";
89 
90  root_json["roles"]["root"]["threshold"] = 1;
91  root_json["roles"]["root"]["keyids"][0] = "firstid";
92  root_json["roles"]["snapshot"]["threshold"] = 1;
93  root_json["roles"]["snapshot"]["keyids"][0] = "firstid";
94  root_json["roles"]["targets"]["threshold"] = 1;
95  root_json["roles"]["targets"]["keyids"][0] = "firstid";
96  root_json["roles"]["timestamp"]["threshold"] = 1;
97  root_json["roles"]["timestamp"]["keyids"][0] = "firstid";
98 
99  Json::Value meta_root;
100  meta_root["signed"] = root_json;
101  std::string director_root = Utils::jsonToStr(meta_root);
102  std::string image_root = Utils::jsonToStr(meta_root);
103 
104  Json::Value targets_json;
105  targets_json["_type"] = "Targets";
106  targets_json["expires"] = "2038-01-19T03:14:06Z";
107  targets_json["targets"]["file1"]["custom"]["ecu_identifier"] = "ecu1";
108  targets_json["targets"]["file1"]["custom"]["hardware_identifier"] = "hw1";
109  targets_json["targets"]["file1"]["hashes"]["sha256"] = "12ab";
110  targets_json["targets"]["file1"]["length"] = 1;
111  targets_json["targets"]["file2"]["custom"]["ecu_identifier"] = "ecu2";
112  targets_json["targets"]["file2"]["custom"]["hardware_identifier"] = "hw2";
113  targets_json["targets"]["file2"]["hashes"]["sha512"] = "12ab";
114  targets_json["targets"]["file2"]["length"] = 11;
115 
116  Json::Value meta_targets;
117  meta_targets["signed"] = targets_json;
118  std::string director_targets = Utils::jsonToStr(meta_targets);
119  std::string image_targets = Utils::jsonToStr(meta_targets);
120 
121  Json::Value timestamp_json;
122  timestamp_json["signed"]["_type"] = "Timestamp";
123  timestamp_json["signed"]["expires"] = "2038-01-19T03:14:06Z";
124  std::string image_timestamp = Utils::jsonToStr(timestamp_json);
125 
126  Json::Value snapshot_json;
127  snapshot_json["_type"] = "Snapshot";
128  snapshot_json["expires"] = "2038-01-19T03:14:06Z";
129  snapshot_json["meta"]["root.json"]["version"] = 1;
130  snapshot_json["meta"]["targets.json"]["version"] = 2;
131  snapshot_json["meta"]["timestamp.json"]["version"] = 3;
132  snapshot_json["meta"]["snapshot.json"]["version"] = 4;
133 
134  Json::Value meta_snapshot;
135  meta_snapshot["signed"] = snapshot_json;
136  std::string image_snapshot = Utils::jsonToStr(meta_snapshot);
137 
138  storage->storeRoot(director_root, Uptane::RepositoryType::Director(), Uptane::Version(1));
139  storage->storeNonRoot(director_targets, Uptane::RepositoryType::Director(), Uptane::Role::Targets());
140  storage->storeRoot(image_root, Uptane::RepositoryType::Image(), Uptane::Version(1));
141  storage->storeNonRoot(image_targets, Uptane::RepositoryType::Image(), Uptane::Role::Targets());
142  storage->storeNonRoot(image_timestamp, Uptane::RepositoryType::Image(), Uptane::Role::Timestamp());
143  storage->storeNonRoot(image_snapshot, Uptane::RepositoryType::Image(), Uptane::Role::Snapshot());
144 
145  std::string loaded_director_root;
146  std::string loaded_director_targets;
147  std::string loaded_image_root;
148  std::string loaded_image_targets;
149  std::string loaded_image_timestamp;
150  std::string loaded_image_snapshot;
151 
152  EXPECT_TRUE(storage->loadLatestRoot(&loaded_director_root, Uptane::RepositoryType::Director()));
153  EXPECT_TRUE(
154  storage->loadNonRoot(&loaded_director_targets, Uptane::RepositoryType::Director(), Uptane::Role::Targets()));
155  EXPECT_TRUE(storage->loadLatestRoot(&loaded_image_root, Uptane::RepositoryType::Image()));
156  EXPECT_TRUE(storage->loadNonRoot(&loaded_image_targets, Uptane::RepositoryType::Image(), Uptane::Role::Targets()));
157  EXPECT_TRUE(
158  storage->loadNonRoot(&loaded_image_timestamp, Uptane::RepositoryType::Image(), Uptane::Role::Timestamp()));
159  EXPECT_TRUE(storage->loadNonRoot(&loaded_image_snapshot, Uptane::RepositoryType::Image(), Uptane::Role::Snapshot()));
160  EXPECT_EQ(director_root, loaded_director_root);
161  EXPECT_EQ(director_targets, loaded_director_targets);
162  EXPECT_EQ(image_root, loaded_image_root);
163  EXPECT_EQ(image_targets, loaded_image_targets);
164  EXPECT_EQ(image_timestamp, loaded_image_timestamp);
165  EXPECT_EQ(image_snapshot, loaded_image_snapshot);
166 
167  storage->clearNonRootMeta(Uptane::RepositoryType::Director());
168  storage->clearNonRootMeta(Uptane::RepositoryType::Image());
169  EXPECT_FALSE(
170  storage->loadNonRoot(&loaded_director_targets, Uptane::RepositoryType::Director(), Uptane::Role::Targets()));
171  EXPECT_FALSE(
172  storage->loadNonRoot(&loaded_image_timestamp, Uptane::RepositoryType::Image(), Uptane::Role::Timestamp()));
173 }
174 
175 /* Load and store Uptane roots. */
176 TEST(StorageCommon, LoadStoreRoot) {
177  TemporaryDirectory temp_dir;
178  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
179 
180  Json::Value root_json;
181  root_json["_type"] = "Root";
182  root_json["consistent_snapshot"] = false;
183  root_json["expires"] = "2038-01-19T03:14:06Z";
184  root_json["keys"]["firstid"]["keytype"] = "ed25519";
185  root_json["keys"]["firstid"]["keyval"]["public"] = "firstval";
186  root_json["keys"]["secondid"]["keytype"] = "ed25519";
187  root_json["keys"]["secondid"]["keyval"]["public"] = "secondval";
188 
189  root_json["roles"]["root"]["threshold"] = 1;
190  root_json["roles"]["root"]["keyids"][0] = "firstid";
191  root_json["roles"]["snapshot"]["threshold"] = 1;
192  root_json["roles"]["snapshot"]["keyids"][0] = "firstid";
193  root_json["roles"]["targets"]["threshold"] = 1;
194  root_json["roles"]["targets"]["keyids"][0] = "firstid";
195  root_json["roles"]["timestamp"]["threshold"] = 1;
196  root_json["roles"]["timestamp"]["keyids"][0] = "firstid";
197 
198  Json::Value meta_root;
199  meta_root["signed"] = root_json;
200 
201  std::string loaded_root;
202 
203  storage->storeRoot(Utils::jsonToStr(meta_root), Uptane::RepositoryType::Director(), Uptane::Version(2));
204  EXPECT_TRUE(storage->loadRoot(&loaded_root, Uptane::RepositoryType::Director(), Uptane::Version(2)));
205  EXPECT_EQ(Utils::jsonToStr(meta_root), loaded_root);
206 
207  EXPECT_TRUE(storage->loadLatestRoot(&loaded_root, Uptane::RepositoryType::Director()));
208  EXPECT_EQ(Utils::jsonToStr(meta_root), loaded_root);
209 }
210 
211 /* Load and store the device ID. */
212 TEST(StorageCommon, LoadStoreDeviceId) {
213  TemporaryDirectory temp_dir;
214  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
215 
216  storage->storeDeviceId("");
217  storage->storeDeviceId("device_id");
218 
219  std::string device_id;
220 
221  EXPECT_TRUE(storage->loadDeviceId(&device_id));
222 
223  EXPECT_EQ(device_id, "device_id");
224  storage->clearDeviceId();
225  EXPECT_FALSE(storage->loadDeviceId(nullptr));
226 }
227 
228 /* Load and store ECU serials.
229  * Preserve ECU ordering between store and load calls.
230  */
231 TEST(StorageCommon, LoadStoreEcuSerials) {
232  TemporaryDirectory temp_dir;
233  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
234 
235  storage->storeEcuSerials({{Uptane::EcuSerial("a"), Uptane::HardwareIdentifier("")}});
236  EcuSerials serials{{Uptane::EcuSerial("primary"), Uptane::HardwareIdentifier("primary_hw")},
237  {Uptane::EcuSerial("secondary_1"), Uptane::HardwareIdentifier("secondary_hw")},
238  {Uptane::EcuSerial("secondary_2"), Uptane::HardwareIdentifier("secondary_hw")}};
239  storage->storeEcuSerials(serials);
240 
241  EcuSerials serials_out;
242 
243  EXPECT_TRUE(storage->loadEcuSerials(&serials_out));
244 
245  EXPECT_EQ(serials, serials_out);
246  storage->clearEcuSerials();
247  EXPECT_FALSE(storage->loadEcuSerials(nullptr));
248 }
249 
250 /* Load and store a list of misconfigured ECUs. */
251 TEST(StorageCommon, LoadStoreMisconfiguredEcus) {
252  TemporaryDirectory temp_dir;
253  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
254 
255  storage->saveMisconfiguredEcu(
256  {Uptane::EcuSerial("primary"), Uptane::HardwareIdentifier("primary_hw"), EcuState::kOld});
257 
258  std::vector<MisconfiguredEcu> ecus_out;
259 
260  EXPECT_TRUE(storage->loadMisconfiguredEcus(&ecus_out));
261 
262  EXPECT_EQ(ecus_out.size(), 1);
263  EXPECT_EQ(ecus_out[0].serial, Uptane::EcuSerial("primary"));
264  EXPECT_EQ(ecus_out[0].hardware_id, Uptane::HardwareIdentifier("primary_hw"));
265  EXPECT_EQ(ecus_out[0].state, EcuState::kOld);
266 
267  storage->clearMisconfiguredEcus();
268  ecus_out.clear();
269  EXPECT_FALSE(storage->loadMisconfiguredEcus(&ecus_out));
270 }
271 
272 /* Load and store a flag indicating successful registration. */
273 TEST(StorageCommon, LoadStoreEcuRegistered) {
274  TemporaryDirectory temp_dir;
275  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
276 
277  EXPECT_THROW(storage->storeEcuRegistered(), std::runtime_error);
278  storage->storeDeviceId("test");
279  storage->storeEcuRegistered();
280  storage->storeEcuRegistered();
281 
282  EXPECT_TRUE(storage->loadEcuRegistered());
283 
284  storage->clearEcuRegistered();
285  EXPECT_FALSE(storage->loadEcuRegistered());
286 }
287 
288 /* Load and store installed versions. */
289 TEST(StorageCommon, LoadStoreInstalledVersions) {
290  TemporaryDirectory temp_dir;
291  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
292 
293  // Test lazy Primary installed version: Primary ECU serial is not defined yet
294  const std::vector<Hash> hashes = {
295  Hash{Hash::Type::kSha256, "2561"},
296  Hash{Hash::Type::kSha512, "5121"},
297  };
298  Uptane::EcuMap primary_ecu{{Uptane::EcuSerial("primary"), Uptane::HardwareIdentifier("primary_hw")}};
299  Uptane::Target t1{"update.bin", primary_ecu, hashes, 1, "corrid"};
300  Json::Value custom;
301  custom["version"] = 42;
302  custom["foo"] = "bar";
303  t1.updateCustom(custom);
304  storage->savePrimaryInstalledVersion(t1, InstalledVersionUpdateMode::kCurrent);
305  {
306  std::vector<Uptane::Target> log;
307  storage->loadPrimaryInstallationLog(&log, true);
308  EXPECT_EQ(log.size(), 1);
309  EXPECT_EQ(log[0].filename(), "update.bin");
310  }
311 
312  EcuSerials serials{{Uptane::EcuSerial("primary"), Uptane::HardwareIdentifier("primary_hw")},
313  {Uptane::EcuSerial("secondary_1"), Uptane::HardwareIdentifier("secondary_hw")},
314  {Uptane::EcuSerial("secondary_2"), Uptane::HardwareIdentifier("secondary_hw")}};
315  storage->storeEcuSerials(serials);
316 
317  {
318  boost::optional<Uptane::Target> current;
319  EXPECT_TRUE(storage->loadInstalledVersions("primary", &current, nullptr));
320  EXPECT_FALSE(storage->hasPendingInstall());
321  EXPECT_TRUE(!!current);
322  EXPECT_EQ(current->filename(), "update.bin");
323  EXPECT_EQ(current->sha256Hash(), "2561");
324  EXPECT_EQ(current->hashes(), hashes);
325  EXPECT_EQ(current->ecus(), primary_ecu);
326  EXPECT_EQ(current->correlation_id(), "corrid");
327  EXPECT_EQ(current->length(), 1);
328  EXPECT_EQ(current->custom_data()["foo"], "bar");
329  EXPECT_EQ(current->custom_data()["version"], 42);
330  }
331 
332  // Set t2 as a pending version
333  Uptane::Target t2{"update2.bin", primary_ecu, {Hash{Hash::Type::kSha256, "2562"}}, 2};
334  storage->savePrimaryInstalledVersion(t2, InstalledVersionUpdateMode::kPending);
335 
336  {
337  boost::optional<Uptane::Target> pending;
338  EXPECT_TRUE(storage->loadInstalledVersions("primary", nullptr, &pending));
339  EXPECT_TRUE(!!pending);
340  EXPECT_TRUE(storage->hasPendingInstall());
341  EXPECT_EQ(pending->filename(), "update2.bin");
342  }
343 
344  // Set t3 as the new pending
345  Uptane::Target t3{"update3.bin", primary_ecu, {Hash{Hash::Type::kSha256, "2563"}}, 3};
346  storage->savePrimaryInstalledVersion(t3, InstalledVersionUpdateMode::kPending);
347 
348  {
349  boost::optional<Uptane::Target> pending;
350  EXPECT_TRUE(storage->loadInstalledVersions("primary", nullptr, &pending));
351  EXPECT_TRUE(!!pending);
352  EXPECT_TRUE(storage->hasPendingInstall());
353  EXPECT_EQ(pending->filename(), "update3.bin");
354  }
355 
356  // Set t3 as current: should replace the pending flag but not create a new
357  // version
358  storage->savePrimaryInstalledVersion(t3, InstalledVersionUpdateMode::kCurrent);
359  {
360  boost::optional<Uptane::Target> current;
361  boost::optional<Uptane::Target> pending;
362  EXPECT_TRUE(storage->loadInstalledVersions("primary", &current, &pending));
363  EXPECT_TRUE(!!current);
364  EXPECT_EQ(current->filename(), "update3.bin");
365  EXPECT_FALSE(!!pending);
366  EXPECT_FALSE(storage->hasPendingInstall());
367 
368  std::vector<Uptane::Target> log;
369  storage->loadInstallationLog("primary", &log, true);
370  EXPECT_EQ(log.size(), 2);
371  EXPECT_EQ(log.back().filename(), "update3.bin");
372  }
373 
374  // Set t1 as current: the log should have grown even though we rolled back
375  {
376  storage->savePrimaryInstalledVersion(t1, InstalledVersionUpdateMode::kCurrent);
377  std::vector<Uptane::Target> log;
378  storage->loadInstallationLog("primary", &log, true);
379  EXPECT_EQ(log.size(), 3);
380  EXPECT_EQ(log.back().filename(), "update.bin");
381  EXPECT_FALSE(storage->hasPendingInstall());
382  }
383 
384  // Set t2 as the new pending and t3 as current afterwards: the pending flag
385  // should disappear
386  storage->savePrimaryInstalledVersion(t2, InstalledVersionUpdateMode::kPending);
387  storage->savePrimaryInstalledVersion(t3, InstalledVersionUpdateMode::kCurrent);
388 
389  {
390  boost::optional<Uptane::Target> current;
391  boost::optional<Uptane::Target> pending;
392  EXPECT_TRUE(storage->loadInstalledVersions("primary", &current, &pending));
393  EXPECT_TRUE(!!current);
394  EXPECT_EQ(current->filename(), "update3.bin");
395  EXPECT_FALSE(!!pending);
396  EXPECT_FALSE(storage->hasPendingInstall());
397 
398  std::vector<Uptane::Target> log;
399  storage->loadInstallationLog("primary", &log, true);
400  EXPECT_EQ(log.size(), 4);
401  EXPECT_EQ(log.back().filename(), "update3.bin");
402  EXPECT_EQ(log[0].custom_data()["foo"], "bar");
403  }
404 
405  // Add a Secondary installed version
406  Uptane::EcuMap secondary_ecu{{Uptane::EcuSerial("secondary1"), Uptane::HardwareIdentifier("secondary_hw")}};
407  Uptane::Target tsec{"secondary.bin", secondary_ecu, {Hash{Hash::Type::kSha256, "256s"}}, 4};
408  storage->saveInstalledVersion("secondary_1", tsec, InstalledVersionUpdateMode::kCurrent);
409 
410  {
411  EXPECT_TRUE(storage->loadInstalledVersions("primary", nullptr, nullptr));
412  EXPECT_TRUE(storage->loadInstalledVersions("secondary_1", nullptr, nullptr));
413 
414  std::vector<Uptane::Target> log;
415  storage->loadInstallationLog("secondary_1", &log, true);
416  EXPECT_EQ(log.size(), 1);
417  EXPECT_EQ(log.back().filename(), "secondary.bin");
418  }
419 }
420 
421 /*
422  * Load and store an ECU installation result in an SQL database.
423  * Load and store a device installation result in an SQL database.
424  */
425 TEST(StorageCommon, LoadStoreInstallationResults) {
426  TemporaryDirectory temp_dir;
427  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
428 
429  EcuSerials serials{{Uptane::EcuSerial("primary"), Uptane::HardwareIdentifier("primary_hw")},
430  {Uptane::EcuSerial("secondary_1"), Uptane::HardwareIdentifier("secondary_hw")},
431  {Uptane::EcuSerial("secondary_2"), Uptane::HardwareIdentifier("secondary_hw")}};
432  storage->storeEcuSerials(serials);
433 
434  storage->saveEcuInstallationResult(Uptane::EcuSerial("secondary_2"), data::InstallationResult());
435  storage->saveEcuInstallationResult(Uptane::EcuSerial("primary"), data::InstallationResult());
436  storage->saveEcuInstallationResult(Uptane::EcuSerial("primary"),
438 
439  std::vector<std::pair<Uptane::EcuSerial, data::InstallationResult>> res;
440  EXPECT_TRUE(storage->loadEcuInstallationResults(&res));
441  EXPECT_EQ(res.size(), 2);
442  EXPECT_EQ(res.at(0).first.ToString(), "primary");
443  EXPECT_EQ(res.at(0).second.result_code.num_code, data::ResultCode::Numeric::kGeneralError);
444  EXPECT_EQ(res.at(1).first.ToString(), "secondary_2");
445  EXPECT_EQ(res.at(1).second.result_code.num_code, data::ResultCode::Numeric::kOk);
446 
447  storage->storeDeviceInstallationResult(data::InstallationResult(data::ResultCode::Numeric::kGeneralError, ""), "raw",
448  "corrid");
449 
450  data::InstallationResult dev_res;
451  std::string report;
452  std::string correlation_id;
453  EXPECT_TRUE(storage->loadDeviceInstallationResult(&dev_res, &report, &correlation_id));
454  EXPECT_EQ(dev_res.result_code.num_code, data::ResultCode::Numeric::kGeneralError);
455  EXPECT_EQ(report, "raw");
456  EXPECT_EQ(correlation_id, "corrid");
457  EXPECT_TRUE(storage->storeDeviceInstallationRawReport("user's raw report"));
458 
459  storage->clearInstallationResults();
460  res.clear();
461  EXPECT_FALSE(storage->loadEcuInstallationResults(&res));
462  EXPECT_EQ(res.size(), 0);
463  EXPECT_FALSE(storage->loadDeviceInstallationResult(&dev_res, &report, &correlation_id));
464  EXPECT_FALSE(storage->storeDeviceInstallationRawReport(
465  "This call will return a negative value since the installation report was cleaned!"));
466 }
467 
468 TEST(StorageCommon, DownloadedFilesInfo) {
469  TemporaryDirectory temp_dir;
470  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
471 
472  storage->storeTargetFilename("target1", "file1");
473  storage->storeTargetFilename("target2", "file2");
474  ASSERT_EQ(storage->getTargetFilename("target1"), "file1");
475  ASSERT_EQ(storage->getTargetFilename("target2"), "file2");
476 
477  auto names = storage->getAllTargetNames();
478  ASSERT_EQ(names.size(), 2);
479  ASSERT_EQ(names.at(0), "target1");
480  ASSERT_EQ(names.at(1), "target2");
481 
482  storage->deleteTargetInfo("target1");
483  names = storage->getAllTargetNames();
484  ASSERT_EQ(names.size(), 1);
485  ASSERT_EQ(names.at(0), "target2");
486 }
487 
488 TEST(StorageCommon, LoadStoreSecondaryInfo) {
489  TemporaryDirectory temp_dir;
490  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
491 
492  // note: this can be done before the ECU is known
493  storage->saveSecondaryData(Uptane::EcuSerial("secondary_2"), "data2");
494 
495  EcuSerials serials{{Uptane::EcuSerial("primary"), Uptane::HardwareIdentifier("primary_hw")},
496  {Uptane::EcuSerial("secondary_1"), Uptane::HardwareIdentifier("secondary_hw")},
497  {Uptane::EcuSerial("secondary_2"), Uptane::HardwareIdentifier("secondary_hw")}};
498  storage->storeEcuSerials(serials);
499 
500  storage->saveSecondaryInfo(Uptane::EcuSerial("secondary_1"), "ip", PublicKey("key1", KeyType::kED25519));
501 
502  EXPECT_THROW(storage->saveSecondaryInfo(Uptane::EcuSerial("primary"), "ip", PublicKey("key0", KeyType::kRSA2048)),
503  std::logic_error);
504 
505  std::vector<SecondaryInfo> sec_infos;
506  EXPECT_TRUE(storage->loadSecondariesInfo(&sec_infos));
507 
508  ASSERT_EQ(sec_infos.size(), 2);
509  EXPECT_EQ(sec_infos[0].serial.ToString(), "secondary_1");
510  EXPECT_EQ(sec_infos[0].hw_id.ToString(), "secondary_hw");
511  EXPECT_EQ(sec_infos[0].type, "ip");
512  EXPECT_EQ(sec_infos[0].pub_key.Value(), "key1");
513  EXPECT_EQ(sec_infos[0].pub_key.Type(), KeyType::kED25519);
514  EXPECT_EQ(sec_infos[1].pub_key.Type(), KeyType::kUnknown);
515  EXPECT_EQ(sec_infos[1].type, "");
516  EXPECT_EQ(sec_infos[1].extra, "data2");
517 
518  // test update of data
519  storage->saveSecondaryInfo(Uptane::EcuSerial("secondary_1"), "ip", PublicKey("key2", KeyType::kED25519));
520  storage->saveSecondaryData(Uptane::EcuSerial("secondary_1"), "data1");
521  EXPECT_TRUE(storage->loadSecondariesInfo(&sec_infos));
522 
523  ASSERT_EQ(sec_infos.size(), 2);
524  EXPECT_EQ(sec_infos[0].pub_key.Value(), "key2");
525  EXPECT_EQ(sec_infos[0].extra, "data1");
526 }
527 
528 /* Import keys and credentials from file into storage.
529  * Re-import updated credentials from file into storage.
530  * Reject new certificate with a different device ID. */
531 TEST(StorageImport, ImportData) {
532  TemporaryDirectory temp_dir;
533  std::unique_ptr<INvStorage> storage = Storage(temp_dir.Path());
534  boost::filesystem::create_directories(temp_dir / "import");
535 
536  ImportConfig import_config;
537  import_config.base_path = temp_dir.Path() / "import";
538  import_config.uptane_private_key_path = utils::BasedPath("private");
539  import_config.uptane_public_key_path = utils::BasedPath("public");
540  import_config.tls_cacert_path = utils::BasedPath("ca");
541  import_config.tls_clientcert_path = utils::BasedPath("cert");
542  import_config.tls_pkey_path = utils::BasedPath("pkey");
543 
544  std::string tls_cert_in1;
545  std::string tls_pkey_in1;
546  const std::string device_id1 = "test_id1";
547  StructGuard<X509> certificate1 = Crypto::generateCert(1024, 365, "", "", "", device_id1, true);
548  Crypto::serializeCert(&tls_pkey_in1, &tls_cert_in1, certificate1.get());
549 
550  Utils::writeFile(import_config.uptane_private_key_path.get(import_config.base_path).string(),
551  std::string("uptane_private_1"));
552  Utils::writeFile(import_config.uptane_public_key_path.get(import_config.base_path).string(),
553  std::string("uptane_public_1"));
554  Utils::writeFile(import_config.tls_cacert_path.get(import_config.base_path).string(), std::string("tls_cacert_1"));
555  Utils::writeFile(import_config.tls_clientcert_path.get(import_config.base_path).string(), tls_cert_in1);
556  Utils::writeFile(import_config.tls_pkey_path.get(import_config.base_path).string(), tls_pkey_in1);
557 
558  // Initially the storage is empty.
559  EXPECT_FALSE(storage->loadPrimaryPublic(nullptr));
560  EXPECT_FALSE(storage->loadPrimaryPrivate(nullptr));
561  EXPECT_FALSE(storage->loadTlsCa(nullptr));
562  EXPECT_FALSE(storage->loadTlsCert(nullptr));
563  EXPECT_FALSE(storage->loadTlsPkey(nullptr));
564 
565  storage->importData(import_config);
566  // Set the device ID to simulate initialization with the given certificate.
567  storage->storeDeviceId(device_id1);
568 
569  std::string primary_public;
570  std::string primary_private;
571  std::string tls_ca;
572  std::string tls_cert;
573  std::string tls_pkey;
574 
575  // Verify that the data has been imported.
576  EXPECT_TRUE(storage->loadPrimaryPublic(&primary_public));
577  EXPECT_TRUE(storage->loadPrimaryPrivate(&primary_private));
578  EXPECT_TRUE(storage->loadTlsCa(&tls_ca));
579  EXPECT_TRUE(storage->loadTlsCert(&tls_cert));
580  EXPECT_TRUE(storage->loadTlsPkey(&tls_pkey));
581 
582  EXPECT_EQ(primary_private, "uptane_private_1");
583  EXPECT_EQ(primary_public, "uptane_public_1");
584  EXPECT_EQ(tls_ca, "tls_cacert_1");
585  EXPECT_EQ(tls_cert, tls_cert_in1);
586  EXPECT_EQ(tls_pkey, tls_pkey_in1);
587 
588  // Create second TLS cert/key (with a different device ID) and other dummy
589  // files.
590  std::string tls_cert_in2;
591  std::string tls_pkey_in2;
592  const std::string device_id2 = "test_id2";
593  StructGuard<X509> certificate2 = Crypto::generateCert(1024, 365, "", "", "", device_id2, true);
594  Crypto::serializeCert(&tls_pkey_in2, &tls_cert_in2, certificate2.get());
595  EXPECT_NE(tls_cert_in1, tls_cert_in2);
596  EXPECT_NE(tls_pkey_in1, tls_pkey_in2);
597 
598  Utils::writeFile(import_config.uptane_private_key_path.get(import_config.base_path).string(),
599  std::string("uptane_private_2"));
600  Utils::writeFile(import_config.uptane_public_key_path.get(import_config.base_path).string(),
601  std::string("uptane_public_2"));
602  Utils::writeFile(import_config.tls_cacert_path.get(import_config.base_path).string(), std::string("tls_cacert_2"));
603  Utils::writeFile(import_config.tls_clientcert_path.get(import_config.base_path).string(), tls_cert_in2);
604  Utils::writeFile(import_config.tls_pkey_path.get(import_config.base_path).string(), tls_pkey_in2);
605 
606  // Attempt to re-import, but expect failure because the TLS cert's device ID
607  // changed.
608  EXPECT_THROW(storage->importData(import_config), std::runtime_error);
609 
610  EXPECT_TRUE(storage->loadPrimaryPublic(&primary_public));
611  EXPECT_TRUE(storage->loadPrimaryPrivate(&primary_private));
612  EXPECT_TRUE(storage->loadTlsCa(&tls_ca));
613  EXPECT_TRUE(storage->loadTlsCert(&tls_cert));
614  EXPECT_TRUE(storage->loadTlsPkey(&tls_pkey));
615 
616  // Nothing should be updated. Uptane keys cannot be updated, and the TLS
617  // credentials should have failed.
618  EXPECT_EQ(primary_private, "uptane_private_1");
619  EXPECT_EQ(primary_public, "uptane_public_1");
620  EXPECT_EQ(tls_ca, "tls_cacert_1");
621  EXPECT_EQ(tls_cert, tls_cert_in1);
622  EXPECT_EQ(tls_pkey, tls_pkey_in1);
623 
624  // Create third TLS cert/key (with the same device ID as the first) and other
625  // dummy files.
626  std::string tls_cert_in3;
627  std::string tls_pkey_in3;
628  StructGuard<X509> certificate3 = Crypto::generateCert(1024, 365, "", "", "", device_id1, true);
629  Crypto::serializeCert(&tls_pkey_in3, &tls_cert_in3, certificate3.get());
630  EXPECT_NE(tls_cert_in1, tls_cert_in3);
631  EXPECT_NE(tls_pkey_in1, tls_pkey_in3);
632 
633  Utils::writeFile(import_config.tls_clientcert_path.get(import_config.base_path).string(), tls_cert_in3);
634  Utils::writeFile(import_config.tls_pkey_path.get(import_config.base_path).string(), tls_pkey_in3);
635 
636  storage->importData(import_config);
637 
638  EXPECT_TRUE(storage->loadPrimaryPublic(&primary_public));
639  EXPECT_TRUE(storage->loadPrimaryPrivate(&primary_private));
640  EXPECT_TRUE(storage->loadTlsCa(&tls_ca));
641  EXPECT_TRUE(storage->loadTlsCert(&tls_cert));
642  EXPECT_TRUE(storage->loadTlsPkey(&tls_pkey));
643 
644  // All TLS objects should be updated.
645  EXPECT_EQ(primary_private, "uptane_private_1");
646  EXPECT_EQ(primary_public, "uptane_public_1");
647  EXPECT_EQ(tls_ca, "tls_cacert_2");
648  EXPECT_EQ(tls_cert, tls_cert_in3);
649  EXPECT_EQ(tls_pkey, tls_pkey_in3);
650 }
651 
652 #ifndef __NO_MAIN__
653 int main(int argc, char **argv) {
654  ::testing::InitGoogleTest(&argc, argv);
655  logger_init();
656  logger_set_threshold(boost::log::trivial::trace);
657 
658  std::cout << "Running tests for SQLStorage" << std::endl;
659  current_storage_type = StorageType::kSqlite;
660  int res_sql = RUN_ALL_TESTS();
661 
662  return res_sql; // 0 indicates success
663 }
664 #endif
Hash
The Hash class The hash of a file or Uptane metadata.
Definition: types.h:159
data::ResultCode::Numeric::kGeneralError
@ kGeneralError
Other error.
types.h
data::InstallationResult
Definition: types.h:277
Uptane::Version
Metadata version numbers.
Definition: tuf.h:120
StorageConfig
Definition: config.h:111
Uptane::HardwareIdentifier
Definition: types.h:315
utils::BasedPath
The BasedPath class Can represent an absolute or relative path, only readable through the BasePath::g...
Definition: types.h:31
Uptane::EcuSerial
Definition: types.h:346
PublicKey
Definition: types.h:119
TemporaryDirectory
Definition: utils.h:82
Uptane::Target
Definition: types.h:379
SQLStorage
Definition: sqlstorage.h:18
ImportConfig
Definition: config.h:130