1 #include <gmock/gmock.h>
2 #include <gtest/gtest.h>
13 #include <boost/filesystem.hpp>
14 #include "json/json.h"
16 #include "crypto/p11engine.h"
18 #include "primary/initializer.h"
19 #include "primary/sotauptaneclient.h"
20 #include "storage/fsstorage_read.h"
21 #include "storage/invstorage.h"
22 #include "test_utils.h"
23 #include "uptane/secondaryinterface.h"
24 #include "uptane/tuf.h"
25 #include "uptane/uptanerepository.h"
26 #include "uptane_test_common.h"
27 #include "utilities/utils.h"
30 #ifndef TEST_PKCS11_MODULE_PATH
31 #define TEST_PKCS11_MODULE_PATH "/usr/local/softhsm/libsofthsm2.so"
35 static Config config_common() {
37 config.uptane.key_type = KeyType::kED25519;
43 auto http = std::make_shared<HttpFake>(temp_dir.Path());
44 Config config = config_common();
45 config.uptane.director_server = http->tls_server +
"/director";
46 config.uptane.repo_server = http->tls_server +
"/repo";
48 config.storage.path = temp_dir.Path();
49 auto storage = INvStorage::newStorage(config.storage);
50 HttpResponse response = http->get(http->tls_server +
"/director/root.json", HttpInterface::kNoLimit);
52 Uptane::Root(Uptane::RepositoryType::Director(), response.getJson(), root);
56 TEST(
Uptane, VerifyDataBad) {
58 auto http = std::make_shared<HttpFake>(temp_dir.Path());
59 Config config = config_common();
60 config.uptane.director_server = http->tls_server +
"/director";
61 config.uptane.repo_server = http->tls_server +
"/repo";
63 config.storage.path = temp_dir.Path();
64 auto storage = INvStorage::newStorage(config.storage);
65 Json::Value data_json = http->get(http->tls_server +
"/director/root.json", HttpInterface::kNoLimit).getJson();
66 data_json.removeMember(
"signatures");
73 TEST(
Uptane, VerifyDataUnknownType) {
75 auto http = std::make_shared<HttpFake>(temp_dir.Path());
76 Config config = config_common();
77 config.uptane.director_server = http->tls_server +
"/director";
78 config.uptane.repo_server = http->tls_server +
"/repo";
80 config.storage.path = temp_dir.Path();
81 auto storage = INvStorage::newStorage(config.storage);
82 Json::Value data_json = http->get(http->tls_server +
"/director/root.json", HttpInterface::kNoLimit).getJson();
83 data_json[
"signatures"][0][
"method"] =
"badsignature";
84 data_json[
"signatures"][1][
"method"] =
"badsignature";
91 TEST(
Uptane, VerifyDataBadKeyId) {
93 auto http = std::make_shared<HttpFake>(temp_dir.Path());
94 Config config = config_common();
95 config.uptane.director_server = http->tls_server +
"/director";
96 config.uptane.repo_server = http->tls_server +
"/repo";
98 config.storage.path = temp_dir.Path();
99 auto storage = INvStorage::newStorage(config.storage);
100 Json::Value data_json = http->get(http->tls_server +
"/director/root.json", HttpInterface::kNoLimit).getJson();
102 data_json[
"signatures"][0][
"keyid"] =
"badkeyid";
109 TEST(
Uptane, VerifyDataBadThreshold) {
111 auto http = std::make_shared<HttpFake>(temp_dir.Path());
112 Config config = config_common();
113 config.uptane.director_server = http->tls_server +
"/director";
114 config.uptane.repo_server = http->tls_server +
"/repo";
116 config.storage.path = temp_dir.Path();
117 auto storage = INvStorage::newStorage(config.storage);
118 Json::Value data_json = http->get(http->tls_server +
"/director/root.json", HttpInterface::kNoLimit).getJson();
119 data_json[
"signed"][
"roles"][
"root"][
"threshold"] = -1;
122 Uptane::Root(Uptane::RepositoryType::Director(), data_json, root);
123 FAIL() <<
"Illegal threshold should have thrown an error.";
131 TEST(
Uptane, AssembleManifestGood) {
133 auto http = std::make_shared<HttpFake>(temp_dir.Path());
134 Config config = config_common();
135 config.storage.path = temp_dir.Path();
136 boost::filesystem::copy_file(
"tests/test_data/cred.zip", (temp_dir /
"cred.zip").
string());
137 boost::filesystem::copy_file(
"tests/test_data/firmware.txt", (temp_dir /
"firmware.txt").
string());
138 boost::filesystem::copy_file(
"tests/test_data/firmware_name.txt", (temp_dir /
"firmware_name.txt").
string());
139 config.provision.provision_path = temp_dir /
"cred.zip";
140 config.provision.mode = ProvisionMode::kSharedCred;
141 config.uptane.director_server = http->tls_server +
"/director";
142 config.uptane.repo_server = http->tls_server +
"/repo";
143 config.provision.primary_ecu_serial =
"testecuserial";
144 config.pacman.type = PACKAGE_MANAGER_NONE;
145 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hardware");
147 auto storage = INvStorage::newStorage(config.storage);
148 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
149 EXPECT_NO_THROW(sota_client->initialize());
151 Json::Value manifest = sota_client->AssembleManifest()[
"ecu_version_manifests"];
152 EXPECT_EQ(manifest.size(), 2);
153 EXPECT_EQ(manifest[
"testecuserial"][
"signed"][
"ecu_serial"].asString(), config.provision.primary_ecu_serial);
154 EXPECT_EQ(manifest[
"secondary_ecu_serial"][
"signed"][
"ecu_serial"].asString(),
"secondary_ecu_serial");
156 EXPECT_FALSE(manifest[
"testecuserial"][
"signed"].isMember(
"custom"));
157 EXPECT_FALSE(manifest[
"secondary_ecu_serial"][
"signed"].isMember(
"custom"));
159 std::string counter_str = manifest[
"testecuserial"][
"signed"][
"report_counter"].asString();
160 int64_t primary_ecu_report_counter = std::stoll(counter_str);
161 Json::Value manifest2 = sota_client->AssembleManifest()[
"ecu_version_manifests"];
162 std::string counter_str2 = manifest2[
"testecuserial"][
"signed"][
"report_counter"].asString();
163 int64_t primary_ecu_report_counter2 = std::stoll(counter_str2);
164 EXPECT_EQ(primary_ecu_report_counter2, primary_ecu_report_counter + 1);
168 TEST(
Uptane, AssembleManifestBad) {
170 auto http = std::make_shared<HttpFake>(temp_dir.Path());
171 Config config = config_common();
172 config.storage.path = temp_dir.Path();
173 boost::filesystem::copy_file(
"tests/test_data/cred.zip", (temp_dir /
"cred.zip").
string());
174 boost::filesystem::copy_file(
"tests/test_data/firmware.txt", (temp_dir /
"firmware.txt").
string());
175 boost::filesystem::copy_file(
"tests/test_data/firmware_name.txt", (temp_dir /
"firmware_name.txt").
string());
176 config.provision.provision_path = temp_dir /
"cred.zip";
177 config.provision.mode = ProvisionMode::kSharedCred;
178 config.uptane.director_server = http->tls_server +
"/director";
179 config.uptane.repo_server = http->tls_server +
"/repo";
180 config.provision.primary_ecu_serial =
"testecuserial";
181 config.pacman.type = PACKAGE_MANAGER_NONE;
183 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hardware");
186 std::string private_key, public_key;
187 ASSERT_TRUE(Crypto::generateKeyPair(ecu_config.key_type, &public_key, &private_key));
188 Utils::writeFile(ecu_config.full_client_dir / ecu_config.ecu_private_key, private_key);
189 public_key = Utils::readFile(
"tests/test_data/public.key");
190 Utils::writeFile(ecu_config.full_client_dir / ecu_config.ecu_public_key, public_key);
192 auto storage = INvStorage::newStorage(config.storage);
193 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
194 EXPECT_NO_THROW(sota_client->initialize());
196 Json::Value manifest = sota_client->AssembleManifest()[
"ecu_version_manifests"];
197 EXPECT_EQ(manifest.size(), 1);
198 EXPECT_EQ(manifest[
"testecuserial"][
"signed"][
"ecu_serial"].asString(), config.provision.primary_ecu_serial);
200 EXPECT_FALSE(manifest[
"testecuserial"][
"signed"].isMember(
"custom"));
201 EXPECT_FALSE(manifest[
"secondary_ecu_serial"][
"signed"].isMember(
"custom"));
207 TEST(
Uptane, PutManifest) {
209 auto http = std::make_shared<HttpFake>(temp_dir.Path());
210 Config config = config_common();
211 config.storage.path = temp_dir.Path();
212 boost::filesystem::copy_file(
"tests/test_data/cred.zip", (temp_dir /
"cred.zip").
string());
213 boost::filesystem::copy_file(
"tests/test_data/firmware.txt", (temp_dir /
"firmware.txt").
string());
214 boost::filesystem::copy_file(
"tests/test_data/firmware_name.txt", (temp_dir /
"firmware_name.txt").
string());
215 config.provision.provision_path = temp_dir /
"cred.zip";
216 config.provision.mode = ProvisionMode::kSharedCred;
217 config.uptane.director_server = http->tls_server +
"/director";
218 config.uptane.repo_server = http->tls_server +
"/repo";
219 config.provision.primary_ecu_serial =
"testecuserial";
220 config.pacman.type = PACKAGE_MANAGER_NONE;
221 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hardware");
223 auto storage = INvStorage::newStorage(config.storage);
225 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
226 EXPECT_NO_THROW(sota_client->initialize());
227 EXPECT_TRUE(sota_client->putManifestSimple());
229 Json::Value json = http->last_manifest;
231 EXPECT_EQ(json[
"signatures"].size(), 1u);
232 EXPECT_EQ(json[
"signed"][
"primary_ecu_serial"].asString(),
"testecuserial");
234 json[
"signed"][
"ecu_version_manifests"][
"testecuserial"][
"signed"][
"installed_image"][
"filepath"].asString(),
236 EXPECT_EQ(json[
"signed"][
"ecu_version_manifests"].size(), 2u);
237 EXPECT_EQ(json[
"signed"][
"ecu_version_manifests"][
"secondary_ecu_serial"][
"signed"][
"ecu_serial"].asString(),
238 "secondary_ecu_serial");
239 EXPECT_EQ(json[
"signed"][
"ecu_version_manifests"][
"secondary_ecu_serial"][
"signed"][
"installed_image"][
"filepath"]
248 HttpResponse put(
const std::string &url,
const Json::Value &
data)
override {
254 int num_events_PutManifestError = 0;
255 void process_events_PutManifestError(
const std::shared_ptr<event::BaseEvent> &
event) {
256 std::cout <<
event->variant <<
"\n";
257 if (
event->variant ==
"PutManifestComplete") {
258 EXPECT_FALSE(std::static_pointer_cast<event::PutManifestComplete>(
event)->success);
259 num_events_PutManifestError++;
266 TEST(
Uptane, PutManifestError) {
268 auto http = std::make_shared<HttpPutManifestFail>(temp_dir.Path());
270 Config conf(
"tests/config/basic.toml");
271 conf.storage.path = temp_dir.Path();
273 auto storage = INvStorage::newStorage(conf.storage);
274 auto events_channel = std::make_shared<event::Channel>();
275 std::function<void(std::shared_ptr<event::BaseEvent>
event)> f_cb = process_events_PutManifestError;
276 events_channel->connect(f_cb);
277 num_events_PutManifestError = 0;
278 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(conf, storage, http, events_channel);
279 EXPECT_NO_THROW(sota_client->initialize());
280 auto result = sota_client->putManifest();
282 EXPECT_EQ(num_events_PutManifestError, 1);
290 TEST(
Uptane, FetchMetaFail) {
292 auto http = std::make_shared<HttpPutManifestFail>(temp_dir.Path(),
"noupdates");
294 Config conf(
"tests/config/basic.toml");
295 conf.provision.primary_ecu_serial =
"CA:FE:A6:D2:84:9D";
296 conf.provision.primary_ecu_hardware_id =
"primary_hw";
297 conf.uptane.director_server = http->tls_server +
"/director";
298 conf.uptane.repo_server = http->tls_server +
"/repo";
299 conf.storage.path = temp_dir.Path();
300 conf.tls.server = http->tls_server;
302 auto storage = INvStorage::newStorage(conf.storage);
303 auto up = std_::make_unique<UptaneTestCommon::TestUptaneClient>(conf, storage, http);
305 EXPECT_NO_THROW(up->initialize());
307 EXPECT_EQ(
result.status, result::UpdateStatus::kNoUpdatesAvailable);
310 unsigned int num_events_InstallTarget = 0;
311 unsigned int num_events_AllInstalls = 0;
312 void process_events_Install(
const std::shared_ptr<event::BaseEvent> &
event) {
313 if (
event->variant ==
"InstallTargetComplete") {
314 auto concrete_event = std::static_pointer_cast<event::InstallTargetComplete>(
event);
315 if (num_events_InstallTarget <= 1) {
316 EXPECT_TRUE(concrete_event->success);
318 EXPECT_FALSE(concrete_event->success);
320 num_events_InstallTarget++;
322 if (
event->variant ==
"AllInstallsComplete") {
323 auto concrete_event = std::static_pointer_cast<event::AllInstallsComplete>(
event);
324 if (num_events_AllInstalls == 0) {
325 EXPECT_TRUE(concrete_event->result.dev_report.isSuccess());
327 EXPECT_FALSE(concrete_event->result.dev_report.isSuccess());
330 num_events_AllInstalls++;
344 TEST(
Uptane, InstallFakeGood) {
345 Config conf(
"tests/config/basic.toml");
347 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates");
348 conf.uptane.director_server = http->tls_server +
"director";
349 conf.uptane.repo_server = http->tls_server +
"repo";
350 conf.pacman.type = PACKAGE_MANAGER_NONE;
351 conf.provision.primary_ecu_serial =
"CA:FE:A6:D2:84:9D";
352 conf.provision.primary_ecu_hardware_id =
"primary_hw";
353 conf.storage.path = temp_dir.Path();
354 conf.tls.server = http->tls_server;
355 UptaneTestCommon::addDefaultSecondary(conf, temp_dir,
"secondary_ecu_serial",
"secondary_hw");
356 conf.postUpdateValues();
358 auto storage = INvStorage::newStorage(conf.storage);
359 auto events_channel = std::make_shared<event::Channel>();
360 std::function<void(std::shared_ptr<event::BaseEvent>
event)> f_cb = process_events_Install;
361 events_channel->connect(f_cb);
362 auto up = std_::make_unique<UptaneTestCommon::TestUptaneClient>(conf, storage, http, events_channel);
363 EXPECT_NO_THROW(up->initialize());
366 EXPECT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
367 result::Download download_result = up->downloadImages(update_result.updates);
368 EXPECT_EQ(download_result.status, result::DownloadStatus::kSuccess);
369 result::Install install_result1 = up->uptaneInstall(download_result.updates);
370 EXPECT_TRUE(install_result1.dev_report.isSuccess());
371 EXPECT_EQ(install_result1.dev_report.result_code, data::ResultCode::Numeric::kOk);
374 Json::Value manifest = up->AssembleManifest();
375 EXPECT_EQ(manifest[
"ecu_version_manifests"][
"CA:FE:A6:D2:84:9D"][
"signed"][
"installed_image"][
"filepath"].asString(),
376 "primary_firmware.txt");
378 manifest[
"ecu_version_manifests"][
"secondary_ecu_serial"][
"signed"][
"installed_image"][
"filepath"].asString(),
379 "secondary_firmware.txt");
381 EXPECT_EQ(num_events_InstallTarget, 2);
382 EXPECT_EQ(num_events_AllInstalls, 1);
383 Json::Value installation_report = manifest[
"installation_report"][
"report"];
384 EXPECT_EQ(installation_report[
"result"][
"success"].asBool(),
true);
385 EXPECT_EQ(installation_report[
"result"][
"code"].asString(),
"OK");
386 EXPECT_EQ(installation_report[
"items"][0][
"ecu"].asString(),
"CA:FE:A6:D2:84:9D");
387 EXPECT_EQ(installation_report[
"items"][0][
"result"][
"success"].asBool(),
true);
388 EXPECT_EQ(installation_report[
"items"][0][
"result"][
"code"].asString(),
"OK");
389 EXPECT_EQ(installation_report[
"items"][1][
"ecu"].asString(),
"secondary_ecu_serial");
390 EXPECT_EQ(installation_report[
"items"][1][
"result"][
"success"].asBool(),
true);
391 EXPECT_EQ(installation_report[
"items"][1][
"result"][
"code"].asString(),
"OK");
394 result::Install install_result2 = up->uptaneInstall(download_result.updates);
395 EXPECT_FALSE(install_result2.dev_report.isSuccess());
397 EXPECT_EQ(num_events_InstallTarget, 2);
398 EXPECT_EQ(num_events_AllInstalls, 2);
399 manifest = up->AssembleManifest();
400 installation_report = manifest[
"installation_report"][
"report"];
401 EXPECT_EQ(installation_report[
"result"][
"success"].asBool(),
false);
408 TEST(
Uptane, InstallFakeBad) {
409 Config conf(
"tests/config/basic.toml");
411 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates");
412 conf.uptane.director_server = http->tls_server +
"director";
413 conf.uptane.repo_server = http->tls_server +
"repo";
414 conf.pacman.type = PACKAGE_MANAGER_NONE;
415 conf.provision.primary_ecu_serial =
"CA:FE:A6:D2:84:9D";
416 conf.provision.primary_ecu_hardware_id =
"primary_hw";
417 conf.storage.path = temp_dir.Path();
418 conf.tls.server = http->tls_server;
419 UptaneTestCommon::addDefaultSecondary(conf, temp_dir,
"secondary_ecu_serial",
"secondary_hw");
420 conf.postUpdateValues();
422 auto storage = INvStorage::newStorage(conf.storage);
423 std::function<void(std::shared_ptr<event::BaseEvent>
event)> f_cb = process_events_Install;
424 auto up = std_::make_unique<UptaneTestCommon::TestUptaneClient>(conf, storage, http);
425 EXPECT_NO_THROW(up->initialize());
428 EXPECT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
429 result::Download download_result = up->downloadImages(update_result.updates);
430 EXPECT_EQ(download_result.status, result::DownloadStatus::kSuccess);
432 std::string hash = download_result.updates[0].sha256Hash();
433 std::transform(hash.begin(), hash.end(), hash.begin(), ::toupper);
434 boost::filesystem::path image = temp_dir /
"images" / hash;
438 auto rhandle = storage->openTargetFile(download_result.updates[0]);
439 const uint64_t length = download_result.updates[0].length();
440 uint8_t content[length];
441 EXPECT_EQ(rhandle->rread(content, length), length);
443 auto whandle = storage->allocateTargetFile(download_result.updates[0]);
444 uint8_t content_bad[length + 1];
445 memset(content_bad, 0, length + 1);
446 EXPECT_EQ(whandle->wfeed(content_bad, 3), 3);
449 result::Install install_result = up->uptaneInstall(download_result.updates);
450 EXPECT_FALSE(install_result.dev_report.isSuccess());
454 whandle = storage->allocateTargetFile(download_result.updates[0]);
455 EXPECT_EQ(whandle->wfeed(content_bad, length + 1), length + 1);
458 install_result = up->uptaneInstall(download_result.updates);
459 EXPECT_FALSE(install_result.dev_report.isSuccess());
464 whandle = storage->allocateTargetFile(download_result.updates[0]);
465 EXPECT_EQ(whandle->wfeed(content_bad, length), length);
468 install_result = up->uptaneInstall(download_result.updates);
469 EXPECT_FALSE(install_result.dev_report.isSuccess());
473 whandle = storage->allocateTargetFile(download_result.updates[0]);
474 EXPECT_EQ(whandle->wfeed(reinterpret_cast<uint8_t *>(content), length - 1), length - 1);
477 install_result = up->uptaneInstall(download_result.updates);
478 EXPECT_FALSE(install_result.dev_report.isSuccess());
482 whandle = storage->allocateTargetFile(download_result.updates[0]);
483 EXPECT_EQ(whandle->wfeed(reinterpret_cast<uint8_t *>(content), length), length);
486 install_result = up->uptaneInstall(download_result.updates);
487 EXPECT_TRUE(install_result.dev_report.isSuccess());
488 EXPECT_EQ(install_result.dev_report.result_code, data::ResultCode::Numeric::kOk);
491 bool EcuInstallationStartedReportGot =
false;
494 HttpFakeEvents(
const boost::filesystem::path &test_dir_in, std::string flavor =
"")
495 :
HttpFake(test_dir_in, std::move(flavor)) {}
497 virtual HttpResponse handle_event(
const std::string &url,
const Json::Value &
data)
override {
499 if (
event[
"eventType"][
"id"].asString() ==
"EcuInstallationStarted") {
500 if (
event[
"event"][
"ecu"].asString() ==
"secondary_ecu_serial") {
501 EcuInstallationStartedReportGot =
true;
512 std::string private_key, public_key;
513 if (!Crypto::generateKeyPair(sconfig.key_type, &public_key, &private_key)) {
514 throw std::runtime_error(
"Key generation failure");
516 public_key_ =
PublicKey(public_key, sconfig.key_type);
517 Json::Value manifest_unsigned;
518 manifest_unsigned[
"key"] =
"value";
520 std::string b64sig = Utils::toBase64(
521 Crypto::Sign(sconfig.key_type,
nullptr, private_key, Utils::jsonToCanonicalStr(manifest_unsigned)));
522 Json::Value signature;
523 signature[
"method"] =
"rsassa-pss";
524 signature[
"sig"] = b64sig;
525 signature[
"keyid"] = public_key_.KeyId();
526 manifest_[
"signed"] = manifest_unsigned;
527 manifest_[
"signatures"].append(signature);
529 std::string Type()
const override {
return "mock"; }
530 PublicKey getPublicKey()
const override {
return public_key_; }
534 if (!sconfig.ecu_serial.empty()) {
540 bool ping()
const override {
return true; }
542 MOCK_METHOD(int32_t, getRootVersionMock, (
bool), (
const));
545 putMetadataMock(meta_pack);
548 int32_t getRootVersion(
bool director)
const override {
return getRootVersionMock(director); }
550 bool putRoot(
const std::string &,
bool)
override {
return true; }
551 bool sendFirmware(
const std::string &)
override {
return true; }
555 Json::Value manifest_;
560 MATCHER_P(matchMeta, meta,
"") {
561 return (arg.director_root == meta.director_root) && (arg.image_root == meta.image_root) &&
562 (arg.director_targets == meta.director_targets) && (arg.image_timestamp == meta.image_timestamp) &&
563 (arg.image_snapshot == meta.image_snapshot) && (arg.image_targets == meta.image_targets);
570 TEST(
Uptane, SendMetadataToSecondary) {
571 Config conf(
"tests/config/basic.toml");
573 auto http = std::make_shared<HttpFakeEvents>(temp_dir.Path(),
"hasupdates");
574 conf.provision.primary_ecu_serial =
"CA:FE:A6:D2:84:9D";
575 conf.provision.primary_ecu_hardware_id =
"primary_hw";
576 conf.uptane.director_server = http->tls_server +
"/director";
577 conf.uptane.repo_server = http->tls_server +
"/repo";
578 conf.storage.path = temp_dir.Path();
579 conf.tls.server = http->tls_server;
582 ecu_config.partial_verifying =
false;
583 ecu_config.full_client_dir = temp_dir.Path();
584 ecu_config.ecu_serial =
"secondary_ecu_serial";
585 ecu_config.ecu_hardware_id =
"secondary_hw";
586 ecu_config.ecu_private_key =
"sec.priv";
587 ecu_config.ecu_public_key =
"sec.pub";
588 ecu_config.firmware_path = temp_dir /
"firmware.txt";
589 ecu_config.target_name_path = temp_dir /
"firmware_name.txt";
590 ecu_config.metadata_path = temp_dir /
"secondary_metadata";
592 auto sec = std::make_shared<SecondaryInterfaceMock>(ecu_config);
593 auto storage = INvStorage::newStorage(conf.storage);
594 auto up = std_::make_unique<UptaneTestCommon::TestUptaneClient>(conf, storage, http);
595 up->addSecondary(sec);
596 EXPECT_NO_THROW(up->initialize());
598 EXPECT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
601 storage->loadLatestRoot(&meta.director_root, Uptane::RepositoryType::Director());
602 storage->loadNonRoot(&meta.director_targets, Uptane::RepositoryType::Director(), Uptane::Role::Targets());
603 storage->loadLatestRoot(&meta.image_root, Uptane::RepositoryType::Image());
604 storage->loadNonRoot(&meta.image_timestamp, Uptane::RepositoryType::Image(), Uptane::Role::Timestamp());
605 storage->loadNonRoot(&meta.image_snapshot, Uptane::RepositoryType::Image(), Uptane::Role::Snapshot());
606 storage->loadNonRoot(&meta.image_targets, Uptane::RepositoryType::Image(), Uptane::Role::Targets());
608 EXPECT_CALL(*sec, putMetadataMock(matchMeta(meta)));
609 result::Download download_result = up->downloadImages(update_result.updates);
610 EXPECT_EQ(download_result.status, result::DownloadStatus::kSuccess);
611 result::Install install_result = up->uptaneInstall(download_result.updates);
612 EXPECT_TRUE(install_result.dev_report.isSuccess());
613 EXPECT_EQ(install_result.dev_report.result_code, data::ResultCode::Numeric::kOk);
614 EXPECT_TRUE(EcuInstallationStartedReportGot);
618 TEST(
Uptane, UptaneSecondaryAdd) {
620 auto http = std::make_shared<HttpFake>(temp_dir.Path());
621 Config config = config_common();
622 boost::filesystem::copy_file(
"tests/test_data/cred.zip", temp_dir /
"cred.zip");
623 config.provision.provision_path = temp_dir /
"cred.zip";
624 config.provision.mode = ProvisionMode::kSharedCred;
625 config.uptane.director_server = http->tls_server +
"/director";
626 config.uptane.repo_server = http->tls_server +
"/repo";
627 config.tls.server = http->tls_server;
628 config.provision.primary_ecu_serial =
"testecuserial";
629 config.storage.path = temp_dir.Path();
630 config.pacman.type = PACKAGE_MANAGER_NONE;
631 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hardware");
633 auto storage = INvStorage::newStorage(config.storage);
634 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
635 EXPECT_NO_THROW(sota_client->initialize());
639 Json::Value ecu_data = Utils::parseJSONFile(temp_dir /
"post.json");
640 EXPECT_EQ(ecu_data[
"ecus"].size(), 2);
641 EXPECT_EQ(ecu_data[
"primary_ecu_serial"].asString(), config.provision.primary_ecu_serial);
642 EXPECT_EQ(ecu_data[
"ecus"][1][
"ecu_serial"].asString(),
"secondary_ecu_serial");
643 EXPECT_EQ(ecu_data[
"ecus"][1][
"hardware_identifier"].asString(),
"secondary_hardware");
644 EXPECT_EQ(ecu_data[
"ecus"][1][
"clientKey"][
"keytype"].asString(),
"RSA");
645 EXPECT_TRUE(ecu_data[
"ecus"][1][
"clientKey"][
"keyval"][
"public"].asString().size() > 0);
649 TEST(
Uptane, UptaneSecondaryAddSameSerial) {
651 auto http = std::make_shared<HttpFake>(temp_dir.Path());
652 boost::filesystem::copy_file(
"tests/test_data/cred.zip", temp_dir /
"cred.zip");
653 Config config = config_common();
654 config.provision.provision_path = temp_dir /
"cred.zip";
655 config.provision.mode = ProvisionMode::kSharedCred;
656 config.pacman.type = PACKAGE_MANAGER_NONE;
657 config.storage.path = temp_dir.Path();
659 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hardware");
661 auto storage = INvStorage::newStorage(config.storage);
662 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
663 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hardware_new");
664 EXPECT_THROW(sota_client->addSecondary(std::make_shared<Primary::VirtualSecondary>(
665 Primary::VirtualSecondaryConfig::create_from_file(config.uptane.secondary_config_file)[0])),
676 TEST(
Uptane, UptaneSecondaryMisconfigured) {
678 boost::filesystem::copy_file(
"tests/test_data/cred.zip", temp_dir /
"cred.zip");
679 auto http = std::make_shared<HttpFake>(temp_dir.Path());
681 Config config = config_common();
682 config.provision.provision_path = temp_dir /
"cred.zip";
683 config.provision.mode = ProvisionMode::kSharedCred;
684 config.pacman.type = PACKAGE_MANAGER_NONE;
685 config.storage.path = temp_dir.Path();
686 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hardware");
688 auto storage = INvStorage::newStorage(config.storage);
689 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
690 EXPECT_NO_THROW(sota_client->initialize());
692 std::vector<MisconfiguredEcu> ecus;
693 storage->loadMisconfiguredEcus(&ecus);
694 EXPECT_EQ(ecus.size(), 0);
697 Config config = config_common();
698 config.provision.provision_path = temp_dir /
"cred.zip";
699 config.provision.mode = ProvisionMode::kSharedCred;
700 config.pacman.type = PACKAGE_MANAGER_NONE;
701 config.storage.path = temp_dir.Path();
702 auto storage = INvStorage::newStorage(config.storage);
703 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"new_secondary_ecu_serial",
"new_secondary_hardware");
704 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
705 EXPECT_NO_THROW(sota_client->initialize());
707 std::vector<MisconfiguredEcu> ecus;
708 storage->loadMisconfiguredEcus(&ecus);
709 EXPECT_EQ(ecus.size(), 2);
710 if (ecus[0].serial.ToString() ==
"new_secondary_ecu_serial") {
711 EXPECT_EQ(ecus[0].state, EcuState::kNotRegistered);
712 EXPECT_EQ(ecus[1].serial.ToString(),
"secondary_ecu_serial");
713 EXPECT_EQ(ecus[1].state, EcuState::kOld);
714 }
else if (ecus[0].serial.ToString() ==
"secondary_ecu_serial") {
715 EXPECT_EQ(ecus[0].state, EcuState::kOld);
716 EXPECT_EQ(ecus[1].serial.ToString(),
"new_secondary_ecu_serial");
717 EXPECT_EQ(ecus[1].state, EcuState::kNotRegistered);
719 FAIL() <<
"Unexpected Secondary serial in storage: " << ecus[0].serial.ToString();
723 Config config = config_common();
724 config.provision.provision_path = temp_dir /
"cred.zip";
725 config.provision.mode = ProvisionMode::kSharedCred;
726 config.pacman.type = PACKAGE_MANAGER_NONE;
727 config.storage.path = temp_dir.Path();
728 auto storage = INvStorage::newStorage(config.storage);
729 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hardware");
730 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
731 EXPECT_NO_THROW(sota_client->initialize());
733 std::vector<MisconfiguredEcu> ecus;
734 storage->loadMisconfiguredEcus(&ecus);
735 EXPECT_EQ(ecus.size(), 0);
749 HttpFakeProv(
const boost::filesystem::path &test_dir_in, std::string flavor =
"")
750 :
HttpFake(test_dir_in, std::move(flavor)) {}
752 HttpResponse post(
const std::string &url,
const Json::Value &
data)
override {
753 std::cout <<
"post " << url <<
"\n";
755 if (url.find(
"/devices") != std::string::npos) {
757 EXPECT_EQ(
data[
"deviceId"].asString(),
"tst149_device_id");
758 return HttpResponse(Utils::readFile(
"tests/test_data/cred.p12"), 200, CURLE_OK,
"");
759 }
else if (url.find(
"/director/ecus") != std::string::npos) {
762 EXPECT_EQ(
data[
"primary_ecu_serial"].asString(),
"CA:FE:A6:D2:84:9D");
763 EXPECT_EQ(
data[
"ecus"][0][
"hardware_identifier"].asString(),
"primary_hw");
764 EXPECT_EQ(
data[
"ecus"][0][
"ecu_serial"].asString(),
"CA:FE:A6:D2:84:9D");
765 if (ecus_count == 1) {
768 return HttpResponse(R
"({"code":"ecu_already_registered"})", 409, CURLE_OK, "");
770 }
else if (url.find(
"/events") != std::string::npos) {
771 return handle_event(url,
data);
773 EXPECT_EQ(0, 1) <<
"Unexpected post to URL: " << url;
778 if (
event[
"eventType"][
"id"] ==
"DownloadProgressReport") {
781 const std::string event_type =
event[
"eventType"][
"id"].asString();
782 const std::string serial =
event[
"event"][
"ecu"].asString();
783 std::cout <<
"Got " << event_type <<
" event\n";
785 switch (events_seen) {
787 EXPECT_EQ(event_type,
"SendDeviceDataComplete");
793 if (event_type ==
"EcuDownloadStarted") {
794 if (serial ==
"CA:FE:A6:D2:84:9D") {
795 ++primary_download_start;
796 }
else if (serial ==
"secondary_ecu_serial") {
797 ++secondary_download_start;
799 }
else if (event_type ==
"EcuDownloadCompleted") {
800 if (serial ==
"CA:FE:A6:D2:84:9D") {
801 ++primary_download_complete;
802 }
else if (serial ==
"secondary_ecu_serial") {
803 ++secondary_download_complete;
806 if (events_seen == 4) {
807 EXPECT_EQ(primary_download_start, 1);
808 EXPECT_EQ(primary_download_complete, 1);
809 EXPECT_EQ(secondary_download_start, 1);
810 EXPECT_EQ(secondary_download_complete, 1);
815 EXPECT_EQ(event_type,
"EcuInstallationStarted");
816 EXPECT_EQ(serial,
"CA:FE:A6:D2:84:9D");
820 EXPECT_EQ(event_type,
"EcuInstallationCompleted");
821 EXPECT_EQ(serial,
"CA:FE:A6:D2:84:9D");
825 EXPECT_EQ(event_type,
"EcuInstallationStarted");
826 EXPECT_EQ(serial,
"secondary_ecu_serial");
830 EXPECT_EQ(event_type,
"EcuInstallationCompleted");
831 EXPECT_EQ(serial,
"secondary_ecu_serial");
834 std::cout <<
"Unexpected event: " << event_type;
840 HttpResponse handle_event(
const std::string &url,
const Json::Value &
data)
override {
842 for (
const Json::Value &ev :
data) {
843 handle_event_single(ev);
848 HttpResponse put(
const std::string &url,
const Json::Value &
data)
override {
849 std::cout <<
"put " << url <<
"\n";
850 if (url.find(
"core/installed") != std::string::npos) {
853 EXPECT_EQ(
data.size(), 1);
854 EXPECT_EQ(
data[0][
"name"].asString(),
"fake-package");
855 EXPECT_EQ(
data[0][
"version"].asString(),
"1.0");
856 }
else if (url.find(
"/director/manifest") != std::string::npos) {
861 std::string file_primary;
862 std::string file_secondary;
863 std::string hash_primary;
864 std::string hash_secondary;
865 if (manifest_count <= 2) {
866 file_primary =
"unknown";
867 file_secondary =
"noimage";
869 hash_primary = boost::algorithm::to_lower_copy(boost::algorithm::hex(Crypto::sha256digest(
"")));
870 hash_secondary = boost::algorithm::to_lower_copy(boost::algorithm::hex(Crypto::sha256digest(
"")));
872 file_primary =
"primary_firmware.txt";
873 file_secondary =
"secondary_firmware.txt";
874 const Json::Value json = Utils::parseJSON(Utils::readFile(meta_dir /
"director/targets_hasupdates.json"));
875 const Json::Value targets_list = json[
"signed"][
"targets"];
876 hash_primary = targets_list[
"primary_firmware.txt"][
"hashes"][
"sha256"].asString();
877 hash_secondary = targets_list[
"secondary_firmware.txt"][
"hashes"][
"sha256"].asString();
879 const Json::Value manifest =
data[
"signed"][
"ecu_version_manifests"];
880 const Json::Value manifest_primary = manifest[
"CA:FE:A6:D2:84:9D"][
"signed"][
"installed_image"];
881 const Json::Value manifest_secondary = manifest[
"secondary_ecu_serial"][
"signed"][
"installed_image"];
882 EXPECT_EQ(file_primary, manifest_primary[
"filepath"].asString());
883 EXPECT_EQ(file_secondary, manifest_secondary[
"filepath"].asString());
884 EXPECT_EQ(manifest_primary[
"fileinfo"][
"hashes"][
"sha256"].asString(), hash_primary);
885 EXPECT_EQ(manifest_secondary[
"fileinfo"][
"hashes"][
"sha256"].asString(), hash_secondary);
886 }
else if (url.find(
"/system_info/network") != std::string::npos) {
889 Json::Value nwinfo = Utils::getNetworkInfo();
890 EXPECT_EQ(nwinfo[
"local_ipv4"].asString(),
data[
"local_ipv4"].asString());
891 EXPECT_EQ(nwinfo[
"mac"].asString(),
data[
"mac"].asString());
892 EXPECT_EQ(nwinfo[
"hostname"].asString(),
data[
"hostname"].asString());
893 }
else if (url.find(
"/system_info") != std::string::npos) {
896 Json::Value hwinfo = Utils::getHardwareInfo();
897 EXPECT_EQ(hwinfo[
"id"].asString(),
data[
"id"].asString());
898 EXPECT_EQ(hwinfo[
"description"].asString(),
data[
"description"].asString());
899 EXPECT_EQ(hwinfo[
"class"].asString(),
data[
"class"].asString());
900 EXPECT_EQ(hwinfo[
"product"].asString(),
data[
"product"].asString());
902 EXPECT_EQ(0, 1) <<
"Unexpected put to URL: " << url;
905 return HttpFake::put(url,
data);
908 size_t events_seen{0};
909 int devices_count{0};
911 int manifest_count{0};
912 int installed_count{0};
913 int system_info_count{0};
914 int network_count{0};
917 int primary_download_start{0};
918 int primary_download_complete{0};
919 int secondary_download_start{0};
920 int secondary_download_complete{0};
928 TEST(
Uptane, ProvisionOnServer) {
929 RecordProperty(
"zephyr_key",
"OTA-984,TST-149");
931 Config config(
"tests/config/basic.toml");
932 auto http = std::make_shared<HttpFakeProv>(temp_dir.Path(),
"hasupdates");
933 const std::string &server = http->tls_server;
934 config.provision.server = server;
935 config.tls.server = server;
936 config.uptane.director_server = server +
"/director";
937 config.uptane.repo_server = server +
"/repo";
938 config.provision.ecu_registration_endpoint = server +
"/director/ecus";
939 config.provision.device_id =
"tst149_device_id";
940 config.provision.primary_ecu_serial =
"CA:FE:A6:D2:84:9D";
941 config.provision.primary_ecu_hardware_id =
"primary_hw";
942 config.storage.path = temp_dir.Path();
943 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hw");
945 auto storage = INvStorage::newStorage(config.storage);
946 auto events_channel = std::make_shared<event::Channel>();
947 auto up = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http, events_channel);
949 EXPECT_EQ(http->devices_count, 0);
950 EXPECT_EQ(http->ecus_count, 0);
951 EXPECT_EQ(http->manifest_count, 0);
952 EXPECT_EQ(http->installed_count, 0);
953 EXPECT_EQ(http->system_info_count, 0);
954 EXPECT_EQ(http->network_count, 0);
956 EXPECT_NO_THROW(up->initialize());
958 storage->loadEcuSerials(&serials);
959 EXPECT_EQ(serials[0].second.ToString(),
"primary_hw");
961 EXPECT_EQ(http->devices_count, 1);
962 EXPECT_EQ(http->ecus_count, 1);
964 EXPECT_NO_THROW(up->sendDeviceData());
965 EXPECT_EQ(http->manifest_count, 1);
966 EXPECT_EQ(http->installed_count, 1);
967 EXPECT_EQ(http->system_info_count, 1);
968 EXPECT_EQ(http->network_count, 1);
971 EXPECT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
972 EXPECT_EQ(http->manifest_count, 2);
975 result::Download download_result = up->downloadImages(update_result.updates);
976 EXPECT_EQ(download_result.status, result::DownloadStatus::kSuccess);
977 result::Install install_result = up->uptaneInstall(download_result.updates);
978 EXPECT_TRUE(install_result.dev_report.isSuccess());
979 EXPECT_EQ(install_result.dev_report.result_code, data::ResultCode::Numeric::kOk);
982 EXPECT_EQ(http->devices_count, 1);
983 EXPECT_EQ(http->ecus_count, 1);
984 EXPECT_EQ(http->manifest_count, 3);
985 EXPECT_EQ(http->installed_count, 1);
986 EXPECT_EQ(http->system_info_count, 1);
987 EXPECT_EQ(http->network_count, 1);
988 EXPECT_EQ(http->events_seen, 8);
992 TEST(
Uptane, FsToSqlFull) {
994 Utils::copyDir(
"tests/test_data/prov", temp_dir.Path());
995 ASSERT_GE(chmod(temp_dir.Path().c_str(), S_IRWXU), 0);
997 config.type = StorageType::kSqlite;
998 config.path = temp_dir.Path();
1002 std::string public_key;
1003 std::string private_key;
1004 fs_storage.loadPrimaryKeys(&public_key, &private_key);
1009 fs_storage.loadTlsCreds(&ca, &cert, &pkey);
1011 std::string device_id;
1012 fs_storage.loadDeviceId(&device_id);
1015 fs_storage.loadEcuSerials(&serials);
1017 bool ecu_registered = fs_storage.loadEcuRegistered();
1019 std::vector<Uptane::Target> fs_installed_versions;
1020 std::vector<Uptane::Target> fixed_installed_versions;
1021 fs_storage.loadInstalledVersions(&fs_installed_versions,
nullptr);
1024 for (
auto &target : fs_installed_versions) {
1025 Json::Value dump = target.toDebugJson();
1026 dump[
"custom"][
"ecuIdentifiers"][serials[0].first.ToString()][
"hardwareId"] = serials[0].second.ToString();
1027 fixed_installed_versions.emplace_back(
Uptane::Target(target.filename(), dump));
1030 std::string director_root;
1031 std::string director_targets;
1032 std::string image_root;
1033 std::string image_targets;
1034 std::string image_timestamp;
1035 std::string image_snapshot;
1037 EXPECT_TRUE(fs_storage.loadLatestRoot(&director_root, Uptane::RepositoryType::Director()));
1038 EXPECT_TRUE(fs_storage.loadNonRoot(&director_targets, Uptane::RepositoryType::Director(), Uptane::Role::Targets()));
1039 EXPECT_TRUE(fs_storage.loadLatestRoot(&image_root, Uptane::RepositoryType::Image()));
1040 EXPECT_TRUE(fs_storage.loadNonRoot(&image_targets, Uptane::RepositoryType::Image(), Uptane::Role::Targets()));
1041 EXPECT_TRUE(fs_storage.loadNonRoot(&image_timestamp, Uptane::RepositoryType::Image(), Uptane::Role::Timestamp()));
1042 EXPECT_TRUE(fs_storage.loadNonRoot(&image_snapshot, Uptane::RepositoryType::Image(), Uptane::Role::Snapshot()));
1044 EXPECT_TRUE(boost::filesystem::exists(config.uptane_public_key_path.get(config.path)));
1045 EXPECT_TRUE(boost::filesystem::exists(config.uptane_private_key_path.get(config.path)));
1046 EXPECT_TRUE(boost::filesystem::exists(config.tls_cacert_path.get(config.path)));
1047 EXPECT_TRUE(boost::filesystem::exists(config.tls_clientcert_path.get(config.path)));
1048 EXPECT_TRUE(boost::filesystem::exists(config.tls_pkey_path.get(config.path)));
1050 boost::filesystem::path image_path = config.uptane_metadata_path.get(config.path) /
"repo";
1051 boost::filesystem::path director_path = config.uptane_metadata_path.get(config.path) /
"director";
1052 EXPECT_TRUE(boost::filesystem::exists(director_path /
"1.root.json"));
1053 EXPECT_TRUE(boost::filesystem::exists(director_path /
"targets.json"));
1054 EXPECT_TRUE(boost::filesystem::exists(image_path /
"1.root.json"));
1055 EXPECT_TRUE(boost::filesystem::exists(image_path /
"targets.json"));
1056 EXPECT_TRUE(boost::filesystem::exists(image_path /
"timestamp.json"));
1057 EXPECT_TRUE(boost::filesystem::exists(image_path /
"snapshot.json"));
1058 EXPECT_TRUE(boost::filesystem::exists(Utils::absolutePath(config.path,
"device_id")));
1059 EXPECT_TRUE(boost::filesystem::exists(Utils::absolutePath(config.path,
"is_registered")));
1060 EXPECT_TRUE(boost::filesystem::exists(Utils::absolutePath(config.path,
"primary_ecu_serial")));
1061 EXPECT_TRUE(boost::filesystem::exists(Utils::absolutePath(config.path,
"primary_ecu_hardware_id")));
1062 EXPECT_TRUE(boost::filesystem::exists(Utils::absolutePath(config.path,
"secondaries_list")));
1063 auto sql_storage = INvStorage::newStorage(config);
1065 EXPECT_FALSE(boost::filesystem::exists(config.uptane_public_key_path.get(config.path)));
1066 EXPECT_FALSE(boost::filesystem::exists(config.uptane_private_key_path.get(config.path)));
1067 EXPECT_FALSE(boost::filesystem::exists(config.tls_cacert_path.get(config.path)));
1068 EXPECT_FALSE(boost::filesystem::exists(config.tls_clientcert_path.get(config.path)));
1069 EXPECT_FALSE(boost::filesystem::exists(config.tls_pkey_path.get(config.path)));
1071 EXPECT_FALSE(boost::filesystem::exists(director_path /
"root.json"));
1072 EXPECT_FALSE(boost::filesystem::exists(director_path /
"targets.json"));
1073 EXPECT_FALSE(boost::filesystem::exists(director_path /
"root.json"));
1074 EXPECT_FALSE(boost::filesystem::exists(director_path /
"targets.json"));
1075 EXPECT_FALSE(boost::filesystem::exists(image_path /
"timestamp.json"));
1076 EXPECT_FALSE(boost::filesystem::exists(image_path /
"snapshot.json"));
1077 EXPECT_FALSE(boost::filesystem::exists(Utils::absolutePath(config.path,
"device_id")));
1078 EXPECT_FALSE(boost::filesystem::exists(Utils::absolutePath(config.path,
"is_registered")));
1079 EXPECT_FALSE(boost::filesystem::exists(Utils::absolutePath(config.path,
"primary_ecu_serial")));
1080 EXPECT_FALSE(boost::filesystem::exists(Utils::absolutePath(config.path,
"primary_ecu_hardware_id")));
1081 EXPECT_FALSE(boost::filesystem::exists(Utils::absolutePath(config.path,
"secondaries_list")));
1083 std::string sql_public_key;
1084 std::string sql_private_key;
1085 sql_storage->loadPrimaryKeys(&sql_public_key, &sql_private_key);
1088 std::string sql_cert;
1089 std::string sql_pkey;
1090 sql_storage->loadTlsCreds(&sql_ca, &sql_cert, &sql_pkey);
1092 std::string sql_device_id;
1093 sql_storage->loadDeviceId(&sql_device_id);
1095 EcuSerials sql_serials;
1096 sql_storage->loadEcuSerials(&sql_serials);
1098 bool sql_ecu_registered = sql_storage->loadEcuRegistered();
1100 std::vector<Uptane::Target> sql_installed_versions;
1101 sql_storage->loadPrimaryInstallationLog(&sql_installed_versions,
true);
1103 std::string sql_director_root;
1104 std::string sql_director_targets;
1105 std::string sql_image_root;
1106 std::string sql_image_targets;
1107 std::string sql_image_timestamp;
1108 std::string sql_image_snapshot;
1110 sql_storage->loadLatestRoot(&sql_director_root, Uptane::RepositoryType::Director());
1111 sql_storage->loadNonRoot(&sql_director_targets, Uptane::RepositoryType::Director(), Uptane::Role::Targets());
1112 sql_storage->loadLatestRoot(&sql_image_root, Uptane::RepositoryType::Image());
1113 sql_storage->loadNonRoot(&sql_image_targets, Uptane::RepositoryType::Image(), Uptane::Role::Targets());
1114 sql_storage->loadNonRoot(&sql_image_timestamp, Uptane::RepositoryType::Image(), Uptane::Role::Timestamp());
1115 sql_storage->loadNonRoot(&sql_image_snapshot, Uptane::RepositoryType::Image(), Uptane::Role::Snapshot());
1117 EXPECT_EQ(sql_public_key, public_key);
1118 EXPECT_EQ(sql_private_key, private_key);
1119 EXPECT_EQ(sql_ca, ca);
1120 EXPECT_EQ(sql_cert, cert);
1121 EXPECT_EQ(sql_pkey, pkey);
1122 EXPECT_EQ(sql_device_id, device_id);
1123 EXPECT_EQ(sql_serials, serials);
1124 EXPECT_EQ(sql_ecu_registered, ecu_registered);
1125 EXPECT_TRUE(Uptane::MatchTargetVector(sql_installed_versions, fixed_installed_versions));
1127 EXPECT_EQ(sql_director_root, director_root);
1128 EXPECT_EQ(sql_director_targets, director_targets);
1129 EXPECT_EQ(sql_image_root, image_root);
1130 EXPECT_EQ(sql_image_targets, image_targets);
1131 EXPECT_EQ(sql_image_timestamp, image_timestamp);
1132 EXPECT_EQ(sql_image_snapshot, image_snapshot);
1136 TEST(
Uptane, InstalledVersionImport) {
1137 Config config = config_common();
1140 Utils::createDirectories(temp_dir /
"import", S_IRWXU);
1141 config.storage.path = temp_dir.Path();
1142 config.import.base_path = temp_dir /
"import";
1143 config.postUpdateValues();
1145 boost::filesystem::copy_file(
"tests/test_data/prov/installed_versions",
1146 temp_dir.Path() /
"import/installed_versions");
1149 auto storage = INvStorage::newStorage(config.storage);
1150 storage->importData(config.import);
1152 boost::optional<Uptane::Target> current_version;
1153 storage->loadPrimaryInstalledVersions(¤t_version,
nullptr);
1154 EXPECT_TRUE(!!current_version);
1155 EXPECT_EQ(current_version->filename(),
"master-863de625f305413dc3be306afab7c3f39d8713045cfff812b3af83f9722851f0");
1159 Json::Value target_json;
1160 target_json[
"hashes"][
"sha256"] =
"a0fb2e119cf812f1aa9e993d01f5f07cb41679096cb4492f1265bff5ac901d0d";
1161 target_json[
"length"] = 123;
1163 storage->savePrimaryInstalledVersion(new_installed_version, InstalledVersionUpdateMode::kCurrent);
1165 auto new_storage = INvStorage::newStorage(config.storage);
1166 new_storage->importData(config.import);
1168 current_version = boost::none;
1169 new_storage->loadPrimaryInstalledVersions(¤t_version,
nullptr);
1170 EXPECT_TRUE(!!current_version);
1171 EXPECT_EQ(current_version->filename(),
"filename");
1175 TEST(
Uptane, SaveAndLoadVersion) {
1177 Config config = config_common();
1178 config.storage.path = temp_dir.Path();
1179 config.provision.device_id =
"device_id";
1180 config.postUpdateValues();
1181 auto storage = INvStorage::newStorage(config.storage);
1183 Json::Value target_json;
1184 target_json[
"hashes"][
"sha256"] =
"a0fb2e119cf812f1aa9e993d01f5f07cb41679096cb4492f1265bff5ac901d0d";
1185 target_json[
"length"] = 123;
1188 storage->savePrimaryInstalledVersion(t, InstalledVersionUpdateMode::kCurrent);
1190 boost::optional<Uptane::Target> current_version;
1191 storage->loadPrimaryInstalledVersions(¤t_version,
nullptr);
1193 EXPECT_TRUE(!!current_version);
1194 EXPECT_EQ(current_version->sha256Hash(),
"a0fb2e119cf812f1aa9e993d01f5f07cb41679096cb4492f1265bff5ac901d0d");
1195 EXPECT_EQ(current_version->length(), 123);
1196 EXPECT_TRUE(current_version->MatchTarget(t));
1202 HttpResponse get(
const std::string &url, int64_t maxsize)
override {
1203 if (unstable_valid_count >= unstable_valid_num) {
1206 ++unstable_valid_count;
1207 return HttpFake::get(url, maxsize);
1211 void setUnstableValidNum(
int num) {
1212 unstable_valid_num = num;
1213 unstable_valid_count = 0;
1216 int unstable_valid_num{0};
1217 int unstable_valid_count{0};
1229 TEST(
Uptane, restoreVerify) {
1231 auto http = std::make_shared<HttpFakeUnstable>(temp_dir.Path());
1232 Config config(
"tests/config/basic.toml");
1233 config.storage.path = temp_dir.Path();
1234 config.pacman.type = PACKAGE_MANAGER_NONE;
1235 config.uptane.director_server = http->tls_server +
"director";
1236 config.uptane.repo_server = http->tls_server +
"repo";
1237 config.provision.primary_ecu_serial =
"CA:FE:A6:D2:84:9D";
1238 config.provision.primary_ecu_hardware_id =
"primary_hw";
1239 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hw");
1240 config.postUpdateValues();
1242 auto storage = INvStorage::newStorage(config.storage);
1243 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
1245 EXPECT_NO_THROW(sota_client->initialize());
1246 sota_client->AssembleManifest();
1249 EXPECT_FALSE(storage->loadLatestRoot(
nullptr, Uptane::RepositoryType::Director()));
1252 http->setUnstableValidNum(1);
1254 EXPECT_TRUE(storage->loadLatestRoot(
nullptr, Uptane::RepositoryType::Director()));
1255 EXPECT_FALSE(storage->loadNonRoot(
nullptr, Uptane::RepositoryType::Director(), Uptane::Role::Targets()));
1258 http->setUnstableValidNum(2);
1260 EXPECT_TRUE(storage->loadLatestRoot(
nullptr, Uptane::RepositoryType::Director()));
1261 EXPECT_TRUE(storage->loadNonRoot(
nullptr, Uptane::RepositoryType::Director(), Uptane::Role::Targets()));
1262 EXPECT_FALSE(storage->loadLatestRoot(
nullptr, Uptane::RepositoryType::Image()));
1265 http->setUnstableValidNum(3);
1267 EXPECT_TRUE(storage->loadLatestRoot(
nullptr, Uptane::RepositoryType::Image()));
1268 EXPECT_FALSE(storage->loadNonRoot(
nullptr, Uptane::RepositoryType::Image(), Uptane::Role::Timestamp()));
1271 http->setUnstableValidNum(4);
1273 EXPECT_TRUE(storage->loadNonRoot(
nullptr, Uptane::RepositoryType::Image(), Uptane::Role::Timestamp()));
1274 EXPECT_FALSE(storage->loadNonRoot(
nullptr, Uptane::RepositoryType::Image(), Uptane::Role::Snapshot()));
1277 http->setUnstableValidNum(5);
1279 EXPECT_TRUE(storage->loadNonRoot(
nullptr, Uptane::RepositoryType::Image(), Uptane::Role::Snapshot()));
1280 EXPECT_FALSE(storage->loadNonRoot(
nullptr, Uptane::RepositoryType::Image(), Uptane::Role::Targets()));
1283 http->setUnstableValidNum(6);
1284 EXPECT_NO_THROW(sota_client->uptaneIteration(
nullptr,
nullptr));
1285 EXPECT_TRUE(storage->loadNonRoot(
nullptr, Uptane::RepositoryType::Image(), Uptane::Role::Targets()));
1293 TEST(
Uptane, offlineIteration) {
1295 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates");
1296 Config config(
"tests/config/basic.toml");
1297 config.storage.path = temp_dir.Path();
1298 config.uptane.director_server = http->tls_server +
"director";
1299 config.uptane.repo_server = http->tls_server +
"repo";
1300 config.pacman.type = PACKAGE_MANAGER_NONE;
1301 config.provision.primary_ecu_serial =
"CA:FE:A6:D2:84:9D";
1302 config.provision.primary_ecu_hardware_id =
"primary_hw";
1303 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hw");
1304 config.postUpdateValues();
1306 auto storage = INvStorage::newStorage(config.storage);
1307 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
1308 EXPECT_NO_THROW(sota_client->initialize());
1310 std::vector<Uptane::Target> targets_online;
1311 EXPECT_NO_THROW(sota_client->uptaneIteration(&targets_online,
nullptr));
1313 std::vector<Uptane::Target> targets_offline;
1314 EXPECT_NO_THROW(sota_client->uptaneOfflineIteration(&targets_offline,
nullptr));
1315 EXPECT_TRUE(Uptane::MatchTargetVector(targets_online, targets_offline));
1322 TEST(
Uptane, IgnoreUnknownUpdate) {
1324 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates");
1325 Config config(
"tests/config/basic.toml");
1326 config.storage.path = temp_dir.Path();
1327 config.uptane.director_server = http->tls_server +
"director";
1328 config.uptane.repo_server = http->tls_server +
"repo";
1329 config.pacman.type = PACKAGE_MANAGER_NONE;
1330 config.provision.primary_ecu_serial =
"primary_ecu";
1331 config.provision.primary_ecu_hardware_id =
"primary_hw";
1332 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hw");
1333 config.postUpdateValues();
1335 auto storage = INvStorage::newStorage(config.storage);
1336 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
1338 EXPECT_NO_THROW(sota_client->initialize());
1340 auto result = sota_client->fetchMeta();
1341 EXPECT_EQ(
result.status, result::UpdateStatus::kError);
1342 std::vector<Uptane::Target> packages_to_install = UptaneTestCommon::makePackage(
"testecuserial",
"testecuhwid");
1343 auto report = sota_client->uptaneInstall(packages_to_install);
1344 EXPECT_EQ(report.ecu_reports.size(), 0);
1348 TEST(
Uptane, Pkcs11Provision) {
1351 Utils::createDirectories(temp_dir /
"import", S_IRWXU);
1352 boost::filesystem::copy_file(
"tests/test_data/device_cred_prov/ca.pem", temp_dir /
"import/root.crt");
1353 config.tls.cert_source = CryptoSource::kPkcs11;
1354 config.tls.pkey_source = CryptoSource::kPkcs11;
1355 config.p11.module = TEST_PKCS11_MODULE_PATH;
1356 config.p11.pass =
"1234";
1357 config.p11.tls_clientcert_id =
"01";
1358 config.p11.tls_pkey_id =
"02";
1359 config.import.base_path = (temp_dir /
"import").
string();
1360 config.import.tls_cacert_path =
BasedPath(
"root.crt");
1362 config.storage.path = temp_dir.Path();
1363 config.postUpdateValues();
1365 auto storage = INvStorage::newStorage(config.storage);
1366 storage->importData(config.import);
1367 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates");
1368 KeyManager keys(storage, config.keymanagerConfig());
1370 EXPECT_NO_THROW(
Initializer(config.provision, storage, http, keys, {}));
1375 int main(
int argc,
char **argv) {
1376 ::testing::InitGoogleTest(&argc, argv);
1379 logger_set_threshold(boost::log::trivial::trace);
1381 return RUN_ALL_TESTS();