1 #include <gmock/gmock.h>
2 #include <gtest/gtest.h>
13 #include <boost/filesystem.hpp>
14 #include "json/json.h"
16 #include "libaktualizr/secondaryinterface.h"
18 #include "crypto/p11engine.h"
20 #include "primary/initializer.h"
21 #include "primary/sotauptaneclient.h"
22 #include "storage/fsstorage_read.h"
23 #include "storage/invstorage.h"
24 #include "test_utils.h"
25 #include "uptane/tuf.h"
26 #include "uptane/uptanerepository.h"
27 #include "uptane_test_common.h"
28 #include "utilities/utils.h"
31 #ifndef TEST_PKCS11_MODULE_PATH
32 #define TEST_PKCS11_MODULE_PATH "/usr/local/softhsm/libsofthsm2.so"
36 static Config config_common() {
38 config.uptane.key_type = KeyType::kED25519;
44 auto http = std::make_shared<HttpFake>(temp_dir.Path());
45 Config config = config_common();
46 config.uptane.director_server = http->tls_server +
"/director";
47 config.uptane.repo_server = http->tls_server +
"/repo";
49 config.storage.path = temp_dir.Path();
50 auto storage = INvStorage::newStorage(config.storage);
51 HttpResponse response = http->get(http->tls_server +
"/director/root.json", HttpInterface::kNoLimit);
53 Uptane::Root(Uptane::RepositoryType::Director(), response.getJson(), root);
57 TEST(
Uptane, VerifyDataBad) {
59 auto http = std::make_shared<HttpFake>(temp_dir.Path());
60 Config config = config_common();
61 config.uptane.director_server = http->tls_server +
"/director";
62 config.uptane.repo_server = http->tls_server +
"/repo";
64 config.storage.path = temp_dir.Path();
65 auto storage = INvStorage::newStorage(config.storage);
66 Json::Value data_json = http->get(http->tls_server +
"/director/root.json", HttpInterface::kNoLimit).getJson();
67 data_json.removeMember(
"signatures");
74 TEST(
Uptane, VerifyDataUnknownType) {
76 auto http = std::make_shared<HttpFake>(temp_dir.Path());
77 Config config = config_common();
78 config.uptane.director_server = http->tls_server +
"/director";
79 config.uptane.repo_server = http->tls_server +
"/repo";
81 config.storage.path = temp_dir.Path();
82 auto storage = INvStorage::newStorage(config.storage);
83 Json::Value data_json = http->get(http->tls_server +
"/director/root.json", HttpInterface::kNoLimit).getJson();
84 data_json[
"signatures"][0][
"method"] =
"badsignature";
85 data_json[
"signatures"][1][
"method"] =
"badsignature";
92 TEST(
Uptane, VerifyDataBadKeyId) {
94 auto http = std::make_shared<HttpFake>(temp_dir.Path());
95 Config config = config_common();
96 config.uptane.director_server = http->tls_server +
"/director";
97 config.uptane.repo_server = http->tls_server +
"/repo";
99 config.storage.path = temp_dir.Path();
100 auto storage = INvStorage::newStorage(config.storage);
101 Json::Value data_json = http->get(http->tls_server +
"/director/root.json", HttpInterface::kNoLimit).getJson();
103 data_json[
"signatures"][0][
"keyid"] =
"badkeyid";
110 TEST(
Uptane, VerifyDataBadThreshold) {
112 auto http = std::make_shared<HttpFake>(temp_dir.Path());
113 Config config = config_common();
114 config.uptane.director_server = http->tls_server +
"/director";
115 config.uptane.repo_server = http->tls_server +
"/repo";
117 config.storage.path = temp_dir.Path();
118 auto storage = INvStorage::newStorage(config.storage);
119 Json::Value data_json = http->get(http->tls_server +
"/director/root.json", HttpInterface::kNoLimit).getJson();
120 data_json[
"signed"][
"roles"][
"root"][
"threshold"] = -1;
123 Uptane::Root(Uptane::RepositoryType::Director(), data_json, root);
124 FAIL() <<
"Illegal threshold should have thrown an error.";
132 TEST(
Uptane, AssembleManifestGood) {
134 auto http = std::make_shared<HttpFake>(temp_dir.Path());
135 Config config = config_common();
136 config.storage.path = temp_dir.Path();
137 boost::filesystem::copy_file(
"tests/test_data/cred.zip", (temp_dir /
"cred.zip").
string());
138 boost::filesystem::copy_file(
"tests/test_data/firmware.txt", (temp_dir /
"firmware.txt").
string());
139 boost::filesystem::copy_file(
"tests/test_data/firmware_name.txt", (temp_dir /
"firmware_name.txt").
string());
140 config.provision.provision_path = temp_dir /
"cred.zip";
141 config.provision.mode = ProvisionMode::kSharedCred;
142 config.uptane.director_server = http->tls_server +
"/director";
143 config.uptane.repo_server = http->tls_server +
"/repo";
144 config.provision.primary_ecu_serial =
"testecuserial";
145 config.pacman.type = PACKAGE_MANAGER_NONE;
146 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hardware");
148 auto storage = INvStorage::newStorage(config.storage);
149 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
150 EXPECT_NO_THROW(sota_client->initialize());
152 Json::Value manifest = sota_client->AssembleManifest()[
"ecu_version_manifests"];
153 EXPECT_EQ(manifest.size(), 2);
154 EXPECT_EQ(manifest[
"testecuserial"][
"signed"][
"ecu_serial"].asString(), config.provision.primary_ecu_serial);
155 EXPECT_EQ(manifest[
"secondary_ecu_serial"][
"signed"][
"ecu_serial"].asString(),
"secondary_ecu_serial");
157 EXPECT_FALSE(manifest[
"testecuserial"][
"signed"].isMember(
"custom"));
158 EXPECT_FALSE(manifest[
"secondary_ecu_serial"][
"signed"].isMember(
"custom"));
160 std::string counter_str = manifest[
"testecuserial"][
"signed"][
"report_counter"].asString();
161 int64_t primary_ecu_report_counter = std::stoll(counter_str);
162 Json::Value manifest2 = sota_client->AssembleManifest()[
"ecu_version_manifests"];
163 std::string counter_str2 = manifest2[
"testecuserial"][
"signed"][
"report_counter"].asString();
164 int64_t primary_ecu_report_counter2 = std::stoll(counter_str2);
165 EXPECT_EQ(primary_ecu_report_counter2, primary_ecu_report_counter + 1);
169 TEST(
Uptane, AssembleManifestBad) {
171 auto http = std::make_shared<HttpFake>(temp_dir.Path());
172 Config config = config_common();
173 config.storage.path = temp_dir.Path();
174 boost::filesystem::copy_file(
"tests/test_data/cred.zip", (temp_dir /
"cred.zip").
string());
175 boost::filesystem::copy_file(
"tests/test_data/firmware.txt", (temp_dir /
"firmware.txt").
string());
176 boost::filesystem::copy_file(
"tests/test_data/firmware_name.txt", (temp_dir /
"firmware_name.txt").
string());
177 config.provision.provision_path = temp_dir /
"cred.zip";
178 config.provision.mode = ProvisionMode::kSharedCred;
179 config.uptane.director_server = http->tls_server +
"/director";
180 config.uptane.repo_server = http->tls_server +
"/repo";
181 config.provision.primary_ecu_serial =
"testecuserial";
182 config.pacman.type = PACKAGE_MANAGER_NONE;
184 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hardware");
187 std::string private_key, public_key;
188 ASSERT_TRUE(Crypto::generateKeyPair(ecu_config.key_type, &public_key, &private_key));
189 Utils::writeFile(ecu_config.full_client_dir / ecu_config.ecu_private_key, private_key);
190 public_key = Utils::readFile(
"tests/test_data/public.key");
191 Utils::writeFile(ecu_config.full_client_dir / ecu_config.ecu_public_key, public_key);
193 auto storage = INvStorage::newStorage(config.storage);
194 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
195 EXPECT_NO_THROW(sota_client->initialize());
197 Json::Value manifest = sota_client->AssembleManifest()[
"ecu_version_manifests"];
198 EXPECT_EQ(manifest.size(), 1);
199 EXPECT_EQ(manifest[
"testecuserial"][
"signed"][
"ecu_serial"].asString(), config.provision.primary_ecu_serial);
201 EXPECT_FALSE(manifest[
"testecuserial"][
"signed"].isMember(
"custom"));
202 EXPECT_FALSE(manifest[
"secondary_ecu_serial"][
"signed"].isMember(
"custom"));
208 TEST(
Uptane, PutManifest) {
210 auto http = std::make_shared<HttpFake>(temp_dir.Path());
211 Config config = config_common();
212 config.storage.path = temp_dir.Path();
213 boost::filesystem::copy_file(
"tests/test_data/cred.zip", (temp_dir /
"cred.zip").
string());
214 config.provision.provision_path = temp_dir /
"cred.zip";
215 config.provision.mode = ProvisionMode::kSharedCred;
216 config.uptane.director_server = http->tls_server +
"/director";
217 config.uptane.repo_server = http->tls_server +
"/repo";
218 config.provision.primary_ecu_serial =
"testecuserial";
219 config.pacman.type = PACKAGE_MANAGER_NONE;
221 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hardware");
222 boost::filesystem::copy_file(
"tests/test_data/firmware.txt", sec_config.firmware_path);
223 boost::filesystem::copy_file(
"tests/test_data/firmware_name.txt", sec_config.target_name_path);
225 auto storage = INvStorage::newStorage(config.storage);
227 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
228 EXPECT_NO_THROW(sota_client->initialize());
229 EXPECT_TRUE(sota_client->putManifestSimple());
231 Json::Value json = http->last_manifest;
233 EXPECT_EQ(json[
"signatures"].size(), 1u);
234 EXPECT_EQ(json[
"signed"][
"primary_ecu_serial"].asString(),
"testecuserial");
236 json[
"signed"][
"ecu_version_manifests"][
"testecuserial"][
"signed"][
"installed_image"][
"filepath"].asString(),
238 EXPECT_EQ(json[
"signed"][
"ecu_version_manifests"].size(), 2u);
239 EXPECT_EQ(json[
"signed"][
"ecu_version_manifests"][
"secondary_ecu_serial"][
"signed"][
"ecu_serial"].asString(),
240 "secondary_ecu_serial");
241 EXPECT_EQ(json[
"signed"][
"ecu_version_manifests"][
"secondary_ecu_serial"][
"signed"][
"installed_image"][
"filepath"]
250 HttpResponse put(
const std::string &url,
const Json::Value &
data)
override {
256 int num_events_PutManifestError = 0;
257 void process_events_PutManifestError(
const std::shared_ptr<event::BaseEvent> &
event) {
258 std::cout <<
event->variant <<
"\n";
259 if (
event->variant ==
"PutManifestComplete") {
260 EXPECT_FALSE(std::static_pointer_cast<event::PutManifestComplete>(
event)->success);
261 num_events_PutManifestError++;
268 TEST(
Uptane, PutManifestError) {
270 auto http = std::make_shared<HttpPutManifestFail>(temp_dir.Path());
272 Config conf(
"tests/config/basic.toml");
273 conf.storage.path = temp_dir.Path();
275 auto storage = INvStorage::newStorage(conf.storage);
276 auto events_channel = std::make_shared<event::Channel>();
277 std::function<void(std::shared_ptr<event::BaseEvent>
event)> f_cb = process_events_PutManifestError;
278 events_channel->connect(f_cb);
279 num_events_PutManifestError = 0;
280 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(conf, storage, http, events_channel);
281 EXPECT_NO_THROW(sota_client->initialize());
282 auto result = sota_client->putManifest();
284 EXPECT_EQ(num_events_PutManifestError, 1);
292 TEST(
Uptane, FetchMetaFail) {
294 auto http = std::make_shared<HttpPutManifestFail>(temp_dir.Path(),
"noupdates");
296 Config conf(
"tests/config/basic.toml");
297 conf.provision.primary_ecu_serial =
"CA:FE:A6:D2:84:9D";
298 conf.provision.primary_ecu_hardware_id =
"primary_hw";
299 conf.uptane.director_server = http->tls_server +
"/director";
300 conf.uptane.repo_server = http->tls_server +
"/repo";
301 conf.storage.path = temp_dir.Path();
302 conf.tls.server = http->tls_server;
304 auto storage = INvStorage::newStorage(conf.storage);
305 auto up = std_::make_unique<UptaneTestCommon::TestUptaneClient>(conf, storage, http);
307 EXPECT_NO_THROW(up->initialize());
309 EXPECT_EQ(
result.status, result::UpdateStatus::kNoUpdatesAvailable);
312 unsigned int num_events_InstallTarget = 0;
313 unsigned int num_events_AllInstalls = 0;
314 void process_events_Install(
const std::shared_ptr<event::BaseEvent> &
event) {
315 if (
event->variant ==
"InstallTargetComplete") {
316 auto concrete_event = std::static_pointer_cast<event::InstallTargetComplete>(
event);
317 if (num_events_InstallTarget <= 1) {
318 EXPECT_TRUE(concrete_event->success);
320 EXPECT_FALSE(concrete_event->success);
322 num_events_InstallTarget++;
324 if (
event->variant ==
"AllInstallsComplete") {
325 auto concrete_event = std::static_pointer_cast<event::AllInstallsComplete>(
event);
326 if (num_events_AllInstalls == 0) {
327 EXPECT_TRUE(concrete_event->result.dev_report.isSuccess());
328 }
else if (num_events_AllInstalls == 1) {
329 EXPECT_FALSE(concrete_event->result.dev_report.isSuccess());
332 EXPECT_FALSE(concrete_event->result.dev_report.isSuccess());
335 num_events_AllInstalls++;
351 TEST(
Uptane, InstallFakeGood) {
352 Config conf(
"tests/config/basic.toml");
354 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates");
355 conf.uptane.director_server = http->tls_server +
"director";
356 conf.uptane.repo_server = http->tls_server +
"repo";
357 conf.pacman.type = PACKAGE_MANAGER_NONE;
358 conf.pacman.images_path = temp_dir.Path() /
"images";
359 conf.provision.primary_ecu_serial =
"CA:FE:A6:D2:84:9D";
360 conf.provision.primary_ecu_hardware_id =
"primary_hw";
361 conf.storage.path = temp_dir.Path();
362 conf.tls.server = http->tls_server;
363 UptaneTestCommon::addDefaultSecondary(conf, temp_dir,
"secondary_ecu_serial",
"secondary_hw");
364 conf.postUpdateValues();
366 auto storage = INvStorage::newStorage(conf.storage);
367 auto events_channel = std::make_shared<event::Channel>();
368 std::function<void(std::shared_ptr<event::BaseEvent>
event)> f_cb = process_events_Install;
369 events_channel->connect(f_cb);
370 auto up = std_::make_unique<UptaneTestCommon::TestUptaneClient>(conf, storage, http, events_channel);
371 EXPECT_NO_THROW(up->initialize());
374 EXPECT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
375 result::Download download_result = up->downloadImages(update_result.updates);
376 EXPECT_EQ(download_result.status, result::DownloadStatus::kSuccess);
377 result::Install install_result1 = up->uptaneInstall(download_result.updates);
378 EXPECT_TRUE(install_result1.dev_report.isSuccess());
379 EXPECT_EQ(install_result1.dev_report.result_code, data::ResultCode::Numeric::kOk);
382 Json::Value manifest = up->AssembleManifest();
383 EXPECT_EQ(manifest[
"ecu_version_manifests"][
"CA:FE:A6:D2:84:9D"][
"signed"][
"installed_image"][
"filepath"].asString(),
384 "primary_firmware.txt");
386 manifest[
"ecu_version_manifests"][
"secondary_ecu_serial"][
"signed"][
"installed_image"][
"filepath"].asString(),
387 "secondary_firmware.txt");
389 EXPECT_EQ(num_events_InstallTarget, 2);
390 EXPECT_EQ(num_events_AllInstalls, 1);
391 Json::Value installation_report = manifest[
"installation_report"][
"report"];
392 EXPECT_EQ(installation_report[
"result"][
"success"].asBool(),
true);
393 EXPECT_EQ(installation_report[
"result"][
"code"].asString(),
"OK");
394 EXPECT_EQ(installation_report[
"items"][0][
"ecu"].asString(),
"CA:FE:A6:D2:84:9D");
395 EXPECT_EQ(installation_report[
"items"][0][
"result"][
"success"].asBool(),
true);
396 EXPECT_EQ(installation_report[
"items"][0][
"result"][
"code"].asString(),
"OK");
397 EXPECT_EQ(installation_report[
"items"][1][
"ecu"].asString(),
"secondary_ecu_serial");
398 EXPECT_EQ(installation_report[
"items"][1][
"result"][
"success"].asBool(),
true);
399 EXPECT_EQ(installation_report[
"items"][1][
"result"][
"code"].asString(),
"OK");
403 result::Install install_result2 = up->uptaneInstall(download_result.updates);
404 EXPECT_FALSE(install_result2.dev_report.isSuccess());
406 EXPECT_EQ(num_events_InstallTarget, 2);
407 EXPECT_EQ(num_events_AllInstalls, 2);
408 manifest = up->AssembleManifest();
409 installation_report = manifest[
"installation_report"][
"report"];
410 EXPECT_EQ(installation_report[
"result"][
"success"].asBool(),
false);
415 EXPECT_EQ(update_result2.status, result::UpdateStatus::kNoUpdatesAvailable);
419 boost::optional<Uptane::Target> current_version;
420 EXPECT_TRUE(storage->loadInstalledVersions(
"CA:FE:A6:D2:84:9D", ¤t_version,
nullptr));
421 const auto bad_target =
Uptane::Target(current_version->filename(), current_version->ecus(), std::vector<Hash>{},
422 current_version->length());
423 storage->saveInstalledVersion(
"CA:FE:A6:D2:84:9D", bad_target, InstalledVersionUpdateMode::kCurrent);
427 result::Install install_result3 = up->uptaneInstall(download_result.updates);
428 EXPECT_FALSE(install_result3.dev_report.isSuccess());
431 EXPECT_EQ(num_events_InstallTarget, 2);
432 EXPECT_EQ(num_events_AllInstalls, 3);
439 TEST(
Uptane, InstallFakeBad) {
440 Config conf(
"tests/config/basic.toml");
442 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates");
443 conf.uptane.director_server = http->tls_server +
"director";
444 conf.uptane.repo_server = http->tls_server +
"repo";
445 conf.pacman.type = PACKAGE_MANAGER_NONE;
446 conf.pacman.images_path = temp_dir.Path() /
"images";
447 conf.provision.primary_ecu_serial =
"CA:FE:A6:D2:84:9D";
448 conf.provision.primary_ecu_hardware_id =
"primary_hw";
449 conf.storage.path = temp_dir.Path();
450 conf.tls.server = http->tls_server;
451 UptaneTestCommon::addDefaultSecondary(conf, temp_dir,
"secondary_ecu_serial",
"secondary_hw");
452 conf.postUpdateValues();
454 auto storage = INvStorage::newStorage(conf.storage);
455 std::function<void(std::shared_ptr<event::BaseEvent>
event)> f_cb = process_events_Install;
456 auto up = std_::make_unique<UptaneTestCommon::TestUptaneClient>(conf, storage, http);
457 EXPECT_NO_THROW(up->initialize());
460 EXPECT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
461 result::Download download_result = up->downloadImages(update_result.updates);
462 EXPECT_EQ(download_result.status, result::DownloadStatus::kSuccess);
464 std::string hash = download_result.updates[0].sha256Hash();
465 std::transform(hash.begin(), hash.end(), hash.begin(), ::toupper);
466 auto image = (conf.pacman.images_path / hash).
string();
470 const uint64_t length = download_result.updates[0].length();
471 char content[length];
472 auto r = std::ifstream(image, std::ios::binary);
473 r.read(content,
static_cast<std::streamsize
>(length));
474 EXPECT_EQ(r.gcount(), length);
476 auto w = std::ofstream(image, std::ios::binary | std::ios::ate);
477 char content_bad[length + 1];
478 memset(content_bad, 0, length + 1);
479 w.write(content_bad, 3);
482 result::Install install_result = up->uptaneInstall(download_result.updates);
483 EXPECT_FALSE(install_result.dev_report.isSuccess());
487 w = std::ofstream(image, std::ios::binary | std::ios::ate);
488 w.write(content_bad,
static_cast<std::streamsize
>(length + 1));
491 install_result = up->uptaneInstall(download_result.updates);
492 EXPECT_FALSE(install_result.dev_report.isSuccess());
497 w = std::ofstream(image, std::ios::binary | std::ios::ate);
498 w.write(content_bad,
static_cast<std::streamsize
>(length));
501 install_result = up->uptaneInstall(download_result.updates);
502 EXPECT_FALSE(install_result.dev_report.isSuccess());
506 w = std::ofstream(image, std::ios::binary | std::ios::ate);
507 w.write(content,
static_cast<std::streamsize
>(length - 1));
510 install_result = up->uptaneInstall(download_result.updates);
511 EXPECT_FALSE(install_result.dev_report.isSuccess());
515 w = std::ofstream(image, std::ios::binary | std::ios::ate);
516 w.write(content,
static_cast<std::streamsize
>(length));
519 install_result = up->uptaneInstall(download_result.updates);
520 EXPECT_TRUE(install_result.dev_report.isSuccess());
521 EXPECT_EQ(install_result.dev_report.result_code, data::ResultCode::Numeric::kOk);
524 bool EcuInstallationStartedReportGot =
false;
527 HttpFakeEvents(
const boost::filesystem::path &test_dir_in, std::string flavor =
"")
528 :
HttpFake(test_dir_in, std::move(flavor)) {}
530 virtual HttpResponse handle_event(
const std::string &url,
const Json::Value &
data)
override {
532 if (
event[
"eventType"][
"id"].asString() ==
"EcuInstallationStarted") {
533 if (
event[
"event"][
"ecu"].asString() ==
"secondary_ecu_serial") {
534 EcuInstallationStartedReportGot =
true;
545 std::string private_key, public_key;
546 if (!Crypto::generateKeyPair(sconfig.key_type, &public_key, &private_key)) {
547 throw std::runtime_error(
"Key generation failure");
549 public_key_ =
PublicKey(public_key, sconfig.key_type);
550 Json::Value manifest_unsigned;
551 manifest_unsigned[
"key"] =
"value";
553 std::string b64sig = Utils::toBase64(
554 Crypto::Sign(sconfig.key_type,
nullptr, private_key, Utils::jsonToCanonicalStr(manifest_unsigned)));
555 Json::Value signature;
556 signature[
"method"] =
"rsassa-pss";
557 signature[
"sig"] = b64sig;
558 signature[
"keyid"] = public_key_.KeyId();
559 manifest_[
"signed"] = manifest_unsigned;
560 manifest_[
"signatures"].append(signature);
562 void init(std::shared_ptr<SecondaryProvider> secondary_provider_in)
override {
563 secondary_provider_ = std::move(secondary_provider_in);
565 std::string Type()
const override {
return "mock"; }
566 PublicKey getPublicKey()
const override {
return public_key_; }
570 if (!sconfig.ecu_serial.empty()) {
576 bool ping()
const override {
return true; }
577 MOCK_METHOD(
bool, putMetadataMock, (
const Uptane::MetaBundle &));
578 MOCK_METHOD(int32_t, getRootVersionMock, (
bool), (
const));
581 Uptane::MetaBundle meta_bundle;
582 if (!secondary_provider_->getMetadata(&meta_bundle, target)) {
584 "Unable to load stored metadata from Primary");
586 putMetadataMock(meta_bundle);
589 int32_t getRootVersion(
bool director)
const override {
return getRootVersionMock(director); }
601 std::shared_ptr<SecondaryProvider> secondary_provider_;
603 Json::Value manifest_;
608 MATCHER_P(matchMeta, meta_bundle,
"") {
return (arg == meta_bundle); }
614 TEST(
Uptane, SendMetadataToSecondary) {
615 Config conf(
"tests/config/basic.toml");
617 auto http = std::make_shared<HttpFakeEvents>(temp_dir.Path(),
"hasupdates");
618 conf.provision.primary_ecu_serial =
"CA:FE:A6:D2:84:9D";
619 conf.provision.primary_ecu_hardware_id =
"primary_hw";
620 conf.uptane.director_server = http->tls_server +
"/director";
621 conf.uptane.repo_server = http->tls_server +
"/repo";
622 conf.pacman.images_path = temp_dir.Path() /
"images";
623 conf.storage.path = temp_dir.Path();
624 conf.tls.server = http->tls_server;
627 ecu_config.partial_verifying =
false;
628 ecu_config.full_client_dir = temp_dir.Path();
629 ecu_config.ecu_serial =
"secondary_ecu_serial";
630 ecu_config.ecu_hardware_id =
"secondary_hw";
631 ecu_config.ecu_private_key =
"sec.priv";
632 ecu_config.ecu_public_key =
"sec.pub";
633 ecu_config.firmware_path = temp_dir /
"firmware.txt";
634 ecu_config.target_name_path = temp_dir /
"firmware_name.txt";
635 ecu_config.metadata_path = temp_dir /
"secondary_metadata";
637 auto sec = std::make_shared<SecondaryInterfaceMock>(ecu_config);
638 auto storage = INvStorage::newStorage(conf.storage);
639 auto up = std_::make_unique<UptaneTestCommon::TestUptaneClient>(conf, storage, http);
640 up->addSecondary(sec);
641 EXPECT_NO_THROW(up->initialize());
643 EXPECT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
645 Uptane::MetaBundle meta_bundle;
646 std::string metadata;
647 storage->loadLatestRoot(&metadata, Uptane::RepositoryType::Director());
648 meta_bundle.emplace(std::make_pair(Uptane::RepositoryType::Director(), Uptane::Role::Root()), metadata);
649 storage->loadNonRoot(&metadata, Uptane::RepositoryType::Director(), Uptane::Role::Targets());
650 meta_bundle.emplace(std::make_pair(Uptane::RepositoryType::Director(), Uptane::Role::Targets()), metadata);
651 storage->loadLatestRoot(&metadata, Uptane::RepositoryType::Image());
652 meta_bundle.emplace(std::make_pair(Uptane::RepositoryType::Image(), Uptane::Role::Root()), metadata);
653 storage->loadNonRoot(&metadata, Uptane::RepositoryType::Image(), Uptane::Role::Timestamp());
654 meta_bundle.emplace(std::make_pair(Uptane::RepositoryType::Image(), Uptane::Role::Timestamp()), metadata);
655 storage->loadNonRoot(&metadata, Uptane::RepositoryType::Image(), Uptane::Role::Snapshot());
656 meta_bundle.emplace(std::make_pair(Uptane::RepositoryType::Image(), Uptane::Role::Snapshot()), metadata);
657 storage->loadNonRoot(&metadata, Uptane::RepositoryType::Image(), Uptane::Role::Targets());
658 meta_bundle.emplace(std::make_pair(Uptane::RepositoryType::Image(), Uptane::Role::Targets()), metadata);
660 EXPECT_CALL(*sec, putMetadataMock(matchMeta(meta_bundle)));
661 result::Download download_result = up->downloadImages(update_result.updates);
662 EXPECT_EQ(download_result.status, result::DownloadStatus::kSuccess);
663 result::Install install_result = up->uptaneInstall(download_result.updates);
664 EXPECT_TRUE(install_result.dev_report.isSuccess());
665 EXPECT_EQ(install_result.dev_report.result_code, data::ResultCode::Numeric::kOk);
666 EXPECT_TRUE(EcuInstallationStartedReportGot);
670 TEST(
Uptane, UptaneSecondaryAdd) {
672 auto http = std::make_shared<HttpFake>(temp_dir.Path());
673 Config config = config_common();
674 boost::filesystem::copy_file(
"tests/test_data/cred.zip", temp_dir /
"cred.zip");
675 config.provision.provision_path = temp_dir /
"cred.zip";
676 config.provision.mode = ProvisionMode::kSharedCred;
677 config.uptane.director_server = http->tls_server +
"/director";
678 config.uptane.repo_server = http->tls_server +
"/repo";
679 config.tls.server = http->tls_server;
680 config.provision.primary_ecu_serial =
"testecuserial";
681 config.storage.path = temp_dir.Path();
682 config.pacman.type = PACKAGE_MANAGER_NONE;
683 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hardware");
685 auto storage = INvStorage::newStorage(config.storage);
686 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
687 EXPECT_NO_THROW(sota_client->initialize());
691 Json::Value ecu_data = Utils::parseJSONFile(temp_dir /
"post.json");
692 EXPECT_EQ(ecu_data[
"ecus"].size(), 2);
693 EXPECT_EQ(ecu_data[
"primary_ecu_serial"].asString(), config.provision.primary_ecu_serial);
694 EXPECT_EQ(ecu_data[
"ecus"][1][
"ecu_serial"].asString(),
"secondary_ecu_serial");
695 EXPECT_EQ(ecu_data[
"ecus"][1][
"hardware_identifier"].asString(),
"secondary_hardware");
696 EXPECT_EQ(ecu_data[
"ecus"][1][
"clientKey"][
"keytype"].asString(),
"RSA");
697 EXPECT_TRUE(ecu_data[
"ecus"][1][
"clientKey"][
"keyval"][
"public"].asString().size() > 0);
701 TEST(
Uptane, UptaneSecondaryAddSameSerial) {
703 auto http = std::make_shared<HttpFake>(temp_dir.Path());
704 boost::filesystem::copy_file(
"tests/test_data/cred.zip", temp_dir /
"cred.zip");
705 Config config = config_common();
706 config.provision.provision_path = temp_dir /
"cred.zip";
707 config.provision.mode = ProvisionMode::kSharedCred;
708 config.pacman.type = PACKAGE_MANAGER_NONE;
709 config.storage.path = temp_dir.Path();
711 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hardware");
713 auto storage = INvStorage::newStorage(config.storage);
714 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
715 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hardware_new");
716 EXPECT_THROW(sota_client->addSecondary(std::make_shared<Primary::VirtualSecondary>(
717 Primary::VirtualSecondaryConfig::create_from_file(config.uptane.secondary_config_file)[0])),
730 HttpFakeProv(
const boost::filesystem::path &test_dir_in, std::string flavor,
Config &config_in)
731 :
HttpFake(test_dir_in, std::move(flavor)), config(config_in) {}
733 HttpResponse post(
const std::string &url,
const std::string &content_type,
const std::string &
data)
override {
734 std::cout <<
"post " << url <<
"\n";
736 if (url.find(
"/system_info/config") != std::string::npos) {
739 std::stringstream conf_ss;
740 config.writeToStream(conf_ss);
741 EXPECT_EQ(
data, conf_ss.str());
742 EXPECT_EQ(content_type,
"application/toml");
744 EXPECT_EQ(0, 1) <<
"Unexpected post to URL: " << url;
746 return HttpFake::post(url, content_type,
data);
749 HttpResponse post(
const std::string &url,
const Json::Value &
data)
override {
750 std::cout <<
"post " << url <<
"\n";
752 if (url.find(
"/devices") != std::string::npos) {
754 EXPECT_EQ(
data[
"deviceId"].asString(),
"tst149_device_id");
755 return HttpResponse(Utils::readFile(
"tests/test_data/cred.p12"), 200, CURLE_OK,
"");
756 }
else if (url.find(
"/director/ecus") != std::string::npos) {
759 EXPECT_EQ(
data[
"primary_ecu_serial"].asString(),
"CA:FE:A6:D2:84:9D");
760 EXPECT_EQ(
data[
"ecus"][0][
"hardware_identifier"].asString(),
"primary_hw");
761 EXPECT_EQ(
data[
"ecus"][0][
"ecu_serial"].asString(),
"CA:FE:A6:D2:84:9D");
762 if (ecus_count == 1) {
765 return HttpResponse(R
"({"code":"ecu_already_registered"})", 409, CURLE_OK, "");
767 }
else if (url.find(
"/events") != std::string::npos) {
768 return handle_event(url,
data);
770 EXPECT_EQ(0, 1) <<
"Unexpected post to URL: " << url;
775 if (
event[
"eventType"][
"id"] ==
"DownloadProgressReport") {
778 const std::string event_type =
event[
"eventType"][
"id"].asString();
779 const std::string serial =
event[
"event"][
"ecu"].asString();
780 std::cout <<
"Got " << event_type <<
" event\n";
782 switch (events_seen) {
784 EXPECT_EQ(event_type,
"SendDeviceDataComplete");
790 if (event_type ==
"EcuDownloadStarted") {
791 if (serial ==
"CA:FE:A6:D2:84:9D") {
792 ++primary_download_start;
793 }
else if (serial ==
"secondary_ecu_serial") {
794 ++secondary_download_start;
796 }
else if (event_type ==
"EcuDownloadCompleted") {
797 if (serial ==
"CA:FE:A6:D2:84:9D") {
798 ++primary_download_complete;
799 }
else if (serial ==
"secondary_ecu_serial") {
800 ++secondary_download_complete;
803 if (events_seen == 4) {
804 EXPECT_EQ(primary_download_start, 1);
805 EXPECT_EQ(primary_download_complete, 1);
806 EXPECT_EQ(secondary_download_start, 1);
807 EXPECT_EQ(secondary_download_complete, 1);
812 EXPECT_EQ(event_type,
"EcuInstallationStarted");
813 EXPECT_EQ(serial,
"CA:FE:A6:D2:84:9D");
817 EXPECT_EQ(event_type,
"EcuInstallationCompleted");
818 EXPECT_EQ(serial,
"CA:FE:A6:D2:84:9D");
822 EXPECT_EQ(event_type,
"EcuInstallationStarted");
823 EXPECT_EQ(serial,
"secondary_ecu_serial");
827 EXPECT_EQ(event_type,
"EcuInstallationCompleted");
828 EXPECT_EQ(serial,
"secondary_ecu_serial");
831 std::cout <<
"Unexpected event: " << event_type;
837 HttpResponse handle_event(
const std::string &url,
const Json::Value &
data)
override {
839 for (
const Json::Value &ev :
data) {
840 handle_event_single(ev);
845 HttpResponse put(
const std::string &url,
const Json::Value &
data)
override {
846 std::cout <<
"put " << url <<
"\n";
847 if (url.find(
"core/installed") != std::string::npos) {
850 EXPECT_EQ(
data.size(), 1);
851 EXPECT_EQ(
data[0][
"name"].asString(),
"fake-package");
852 EXPECT_EQ(
data[0][
"version"].asString(),
"1.0");
853 }
else if (url.find(
"/director/manifest") != std::string::npos) {
858 std::string file_primary;
859 std::string file_secondary;
860 std::string hash_primary;
861 std::string hash_secondary;
862 if (manifest_count <= 1) {
863 file_primary =
"unknown";
864 file_secondary =
"noimage";
866 hash_primary = boost::algorithm::to_lower_copy(boost::algorithm::hex(Crypto::sha256digest(
"")));
867 hash_secondary = boost::algorithm::to_lower_copy(boost::algorithm::hex(Crypto::sha256digest(
"")));
869 file_primary =
"primary_firmware.txt";
870 file_secondary =
"secondary_firmware.txt";
871 const Json::Value json = Utils::parseJSON(Utils::readFile(meta_dir /
"director/targets_hasupdates.json"));
872 const Json::Value targets_list = json[
"signed"][
"targets"];
873 hash_primary = targets_list[
"primary_firmware.txt"][
"hashes"][
"sha256"].asString();
874 hash_secondary = targets_list[
"secondary_firmware.txt"][
"hashes"][
"sha256"].asString();
876 const Json::Value manifest =
data[
"signed"][
"ecu_version_manifests"];
877 const Json::Value manifest_primary = manifest[
"CA:FE:A6:D2:84:9D"][
"signed"][
"installed_image"];
878 const Json::Value manifest_secondary = manifest[
"secondary_ecu_serial"][
"signed"][
"installed_image"];
879 EXPECT_EQ(file_primary, manifest_primary[
"filepath"].asString());
880 EXPECT_EQ(file_secondary, manifest_secondary[
"filepath"].asString());
881 EXPECT_EQ(manifest_primary[
"fileinfo"][
"hashes"][
"sha256"].asString(), hash_primary);
882 EXPECT_EQ(manifest_secondary[
"fileinfo"][
"hashes"][
"sha256"].asString(), hash_secondary);
883 }
else if (url.find(
"/system_info/network") != std::string::npos) {
886 Json::Value nwinfo = Utils::getNetworkInfo();
887 EXPECT_EQ(nwinfo[
"local_ipv4"].asString(),
data[
"local_ipv4"].asString());
888 EXPECT_EQ(nwinfo[
"mac"].asString(),
data[
"mac"].asString());
889 EXPECT_EQ(nwinfo[
"hostname"].asString(),
data[
"hostname"].asString());
890 }
else if (url.find(
"/system_info") != std::string::npos) {
893 if (system_info_count <= 2) {
894 Json::Value hwinfo = Utils::getHardwareInfo();
895 EXPECT_EQ(hwinfo[
"id"].asString(),
data[
"id"].asString());
896 EXPECT_EQ(hwinfo[
"description"].asString(),
data[
"description"].asString());
897 EXPECT_EQ(hwinfo[
"class"].asString(),
data[
"class"].asString());
898 EXPECT_EQ(hwinfo[
"product"].asString(),
data[
"product"].asString());
900 EXPECT_EQ(custom_hw_info,
data);
903 EXPECT_EQ(0, 1) <<
"Unexpected put to URL: " << url;
906 return HttpFake::put(url,
data);
909 size_t events_seen{0};
910 int devices_count{0};
912 int manifest_count{0};
913 int installed_count{0};
914 int system_info_count{0};
915 int network_count{0};
917 Json::Value custom_hw_info;
921 int primary_download_start{0};
922 int primary_download_complete{0};
923 int secondary_download_start{0};
924 int secondary_download_complete{0};
932 TEST(
Uptane, ProvisionOnServer) {
933 RecordProperty(
"zephyr_key",
"OTA-984,TST-149");
935 Config config(
"tests/config/basic.toml");
936 auto http = std::make_shared<HttpFakeProv>(temp_dir.Path(),
"hasupdates", config);
937 const std::string &server = http->tls_server;
938 config.provision.server = server;
939 config.tls.server = server;
940 config.uptane.director_server = server +
"/director";
941 config.uptane.repo_server = server +
"/repo";
942 config.provision.ecu_registration_endpoint = server +
"/director/ecus";
943 config.provision.device_id =
"tst149_device_id";
944 config.provision.primary_ecu_serial =
"CA:FE:A6:D2:84:9D";
945 config.provision.primary_ecu_hardware_id =
"primary_hw";
946 config.pacman.images_path = temp_dir.Path() /
"images";
947 config.storage.path = temp_dir.Path();
948 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hw");
949 logger_set_threshold(boost::log::trivial::trace);
951 auto storage = INvStorage::newStorage(config.storage);
952 auto events_channel = std::make_shared<event::Channel>();
953 auto up = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http, events_channel);
955 EXPECT_EQ(http->devices_count, 0);
956 EXPECT_EQ(http->ecus_count, 0);
957 EXPECT_EQ(http->manifest_count, 0);
958 EXPECT_EQ(http->installed_count, 0);
959 EXPECT_EQ(http->system_info_count, 0);
960 EXPECT_EQ(http->network_count, 0);
961 EXPECT_EQ(http->config_count, 0);
963 EXPECT_NO_THROW(up->initialize());
965 storage->loadEcuSerials(&serials);
966 EXPECT_EQ(serials[0].second.ToString(),
"primary_hw");
968 EXPECT_EQ(http->devices_count, 1);
969 EXPECT_EQ(http->ecus_count, 1);
971 EXPECT_NO_THROW(up->sendDeviceData());
972 EXPECT_EQ(http->installed_count, 1);
973 EXPECT_EQ(http->system_info_count, 1);
974 EXPECT_EQ(http->network_count, 1);
975 EXPECT_EQ(http->config_count, 1);
978 EXPECT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
979 EXPECT_EQ(http->manifest_count, 1);
982 result::Download download_result = up->downloadImages(update_result.updates);
983 EXPECT_EQ(download_result.status, result::DownloadStatus::kSuccess);
984 result::Install install_result = up->uptaneInstall(download_result.updates);
985 EXPECT_TRUE(install_result.dev_report.isSuccess());
986 EXPECT_EQ(install_result.dev_report.result_code, data::ResultCode::Numeric::kOk);
989 EXPECT_EQ(http->devices_count, 1);
990 EXPECT_EQ(http->ecus_count, 1);
991 EXPECT_EQ(http->manifest_count, 2);
992 EXPECT_EQ(http->installed_count, 1);
993 EXPECT_EQ(http->system_info_count, 1);
994 EXPECT_EQ(http->network_count, 1);
995 EXPECT_EQ(http->config_count, 1);
999 EXPECT_NO_THROW(up->sendDeviceData(http->custom_hw_info));
1000 EXPECT_EQ(http->installed_count, 1);
1001 EXPECT_EQ(http->system_info_count, 1);
1002 EXPECT_EQ(http->network_count, 1);
1003 EXPECT_EQ(http->config_count, 1);
1006 storage->clearDeviceData();
1007 EXPECT_NO_THROW(up->sendDeviceData(http->custom_hw_info));
1008 EXPECT_EQ(http->installed_count, 2);
1009 EXPECT_EQ(http->system_info_count, 2);
1010 EXPECT_EQ(http->network_count, 2);
1011 EXPECT_EQ(http->config_count, 2);
1014 http->custom_hw_info[
"hardware"] =
"test-hw";
1015 EXPECT_NO_THROW(up->sendDeviceData(http->custom_hw_info));
1016 EXPECT_EQ(http->installed_count, 2);
1017 EXPECT_EQ(http->system_info_count, 3);
1018 EXPECT_EQ(http->network_count, 2);
1019 EXPECT_EQ(http->config_count, 2);
1022 http->custom_hw_info[
"hardware"] =
"test-hw";
1023 EXPECT_NO_THROW(up->sendDeviceData(http->custom_hw_info));
1024 EXPECT_EQ(http->installed_count, 2);
1025 EXPECT_EQ(http->system_info_count, 3);
1026 EXPECT_EQ(http->network_count, 2);
1027 EXPECT_EQ(http->config_count, 2);
1032 EXPECT_EQ(http->events_seen, 8);
1036 TEST(
Uptane, FsToSqlFull) {
1038 Utils::copyDir(
"tests/test_data/prov", temp_dir.Path());
1039 ASSERT_GE(chmod(temp_dir.Path().c_str(), S_IRWXU), 0);
1041 config.type = StorageType::kSqlite;
1042 config.path = temp_dir.Path();
1046 std::string public_key;
1047 std::string private_key;
1048 fs_storage.loadPrimaryKeys(&public_key, &private_key);
1053 fs_storage.loadTlsCreds(&ca, &cert, &pkey);
1055 std::string device_id;
1056 fs_storage.loadDeviceId(&device_id);
1059 fs_storage.loadEcuSerials(&serials);
1061 bool ecu_registered = fs_storage.loadEcuRegistered();
1063 std::vector<Uptane::Target> fs_installed_versions;
1064 std::vector<Uptane::Target> fixed_installed_versions;
1065 fs_storage.loadInstalledVersions(&fs_installed_versions,
nullptr);
1068 for (
auto &target : fs_installed_versions) {
1069 Json::Value dump = target.toDebugJson();
1070 dump[
"custom"][
"ecuIdentifiers"][serials[0].first.ToString()][
"hardwareId"] = serials[0].second.ToString();
1071 fixed_installed_versions.emplace_back(
Uptane::Target(target.filename(), dump));
1074 std::string director_root;
1075 std::string director_targets;
1076 std::string image_root;
1077 std::string image_targets;
1078 std::string image_timestamp;
1079 std::string image_snapshot;
1081 EXPECT_TRUE(fs_storage.loadLatestRoot(&director_root, Uptane::RepositoryType::Director()));
1082 EXPECT_TRUE(fs_storage.loadNonRoot(&director_targets, Uptane::RepositoryType::Director(), Uptane::Role::Targets()));
1083 EXPECT_TRUE(fs_storage.loadLatestRoot(&image_root, Uptane::RepositoryType::Image()));
1084 EXPECT_TRUE(fs_storage.loadNonRoot(&image_targets, Uptane::RepositoryType::Image(), Uptane::Role::Targets()));
1085 EXPECT_TRUE(fs_storage.loadNonRoot(&image_timestamp, Uptane::RepositoryType::Image(), Uptane::Role::Timestamp()));
1086 EXPECT_TRUE(fs_storage.loadNonRoot(&image_snapshot, Uptane::RepositoryType::Image(), Uptane::Role::Snapshot()));
1088 EXPECT_TRUE(boost::filesystem::exists(config.uptane_public_key_path.get(config.path)));
1089 EXPECT_TRUE(boost::filesystem::exists(config.uptane_private_key_path.get(config.path)));
1090 EXPECT_TRUE(boost::filesystem::exists(config.tls_cacert_path.get(config.path)));
1091 EXPECT_TRUE(boost::filesystem::exists(config.tls_clientcert_path.get(config.path)));
1092 EXPECT_TRUE(boost::filesystem::exists(config.tls_pkey_path.get(config.path)));
1094 boost::filesystem::path image_path = config.uptane_metadata_path.get(config.path) /
"repo";
1095 boost::filesystem::path director_path = config.uptane_metadata_path.get(config.path) /
"director";
1096 EXPECT_TRUE(boost::filesystem::exists(director_path /
"1.root.json"));
1097 EXPECT_TRUE(boost::filesystem::exists(director_path /
"targets.json"));
1098 EXPECT_TRUE(boost::filesystem::exists(image_path /
"1.root.json"));
1099 EXPECT_TRUE(boost::filesystem::exists(image_path /
"targets.json"));
1100 EXPECT_TRUE(boost::filesystem::exists(image_path /
"timestamp.json"));
1101 EXPECT_TRUE(boost::filesystem::exists(image_path /
"snapshot.json"));
1102 EXPECT_TRUE(boost::filesystem::exists(Utils::absolutePath(config.path,
"device_id")));
1103 EXPECT_TRUE(boost::filesystem::exists(Utils::absolutePath(config.path,
"is_registered")));
1104 EXPECT_TRUE(boost::filesystem::exists(Utils::absolutePath(config.path,
"primary_ecu_serial")));
1105 EXPECT_TRUE(boost::filesystem::exists(Utils::absolutePath(config.path,
"primary_ecu_hardware_id")));
1106 EXPECT_TRUE(boost::filesystem::exists(Utils::absolutePath(config.path,
"secondaries_list")));
1107 auto sql_storage = INvStorage::newStorage(config);
1109 EXPECT_FALSE(boost::filesystem::exists(config.uptane_public_key_path.get(config.path)));
1110 EXPECT_FALSE(boost::filesystem::exists(config.uptane_private_key_path.get(config.path)));
1111 EXPECT_FALSE(boost::filesystem::exists(config.tls_cacert_path.get(config.path)));
1112 EXPECT_FALSE(boost::filesystem::exists(config.tls_clientcert_path.get(config.path)));
1113 EXPECT_FALSE(boost::filesystem::exists(config.tls_pkey_path.get(config.path)));
1115 EXPECT_FALSE(boost::filesystem::exists(director_path /
"root.json"));
1116 EXPECT_FALSE(boost::filesystem::exists(director_path /
"targets.json"));
1117 EXPECT_FALSE(boost::filesystem::exists(director_path /
"root.json"));
1118 EXPECT_FALSE(boost::filesystem::exists(director_path /
"targets.json"));
1119 EXPECT_FALSE(boost::filesystem::exists(image_path /
"timestamp.json"));
1120 EXPECT_FALSE(boost::filesystem::exists(image_path /
"snapshot.json"));
1121 EXPECT_FALSE(boost::filesystem::exists(Utils::absolutePath(config.path,
"device_id")));
1122 EXPECT_FALSE(boost::filesystem::exists(Utils::absolutePath(config.path,
"is_registered")));
1123 EXPECT_FALSE(boost::filesystem::exists(Utils::absolutePath(config.path,
"primary_ecu_serial")));
1124 EXPECT_FALSE(boost::filesystem::exists(Utils::absolutePath(config.path,
"primary_ecu_hardware_id")));
1125 EXPECT_FALSE(boost::filesystem::exists(Utils::absolutePath(config.path,
"secondaries_list")));
1127 std::string sql_public_key;
1128 std::string sql_private_key;
1129 sql_storage->loadPrimaryKeys(&sql_public_key, &sql_private_key);
1132 std::string sql_cert;
1133 std::string sql_pkey;
1134 sql_storage->loadTlsCreds(&sql_ca, &sql_cert, &sql_pkey);
1136 std::string sql_device_id;
1137 sql_storage->loadDeviceId(&sql_device_id);
1139 EcuSerials sql_serials;
1140 sql_storage->loadEcuSerials(&sql_serials);
1142 bool sql_ecu_registered = sql_storage->loadEcuRegistered();
1144 std::vector<Uptane::Target> sql_installed_versions;
1145 sql_storage->loadPrimaryInstallationLog(&sql_installed_versions,
true);
1147 std::string sql_director_root;
1148 std::string sql_director_targets;
1149 std::string sql_image_root;
1150 std::string sql_image_targets;
1151 std::string sql_image_timestamp;
1152 std::string sql_image_snapshot;
1154 sql_storage->loadLatestRoot(&sql_director_root, Uptane::RepositoryType::Director());
1155 sql_storage->loadNonRoot(&sql_director_targets, Uptane::RepositoryType::Director(), Uptane::Role::Targets());
1156 sql_storage->loadLatestRoot(&sql_image_root, Uptane::RepositoryType::Image());
1157 sql_storage->loadNonRoot(&sql_image_targets, Uptane::RepositoryType::Image(), Uptane::Role::Targets());
1158 sql_storage->loadNonRoot(&sql_image_timestamp, Uptane::RepositoryType::Image(), Uptane::Role::Timestamp());
1159 sql_storage->loadNonRoot(&sql_image_snapshot, Uptane::RepositoryType::Image(), Uptane::Role::Snapshot());
1161 EXPECT_EQ(sql_public_key, public_key);
1162 EXPECT_EQ(sql_private_key, private_key);
1163 EXPECT_EQ(sql_ca, ca);
1164 EXPECT_EQ(sql_cert, cert);
1165 EXPECT_EQ(sql_pkey, pkey);
1166 EXPECT_EQ(sql_device_id, device_id);
1167 EXPECT_EQ(sql_serials, serials);
1168 EXPECT_EQ(sql_ecu_registered, ecu_registered);
1169 EXPECT_TRUE(Uptane::MatchTargetVector(sql_installed_versions, fixed_installed_versions));
1171 EXPECT_EQ(sql_director_root, director_root);
1172 EXPECT_EQ(sql_director_targets, director_targets);
1173 EXPECT_EQ(sql_image_root, image_root);
1174 EXPECT_EQ(sql_image_targets, image_targets);
1175 EXPECT_EQ(sql_image_timestamp, image_timestamp);
1176 EXPECT_EQ(sql_image_snapshot, image_snapshot);
1180 TEST(
Uptane, InstalledVersionImport) {
1181 Config config = config_common();
1184 Utils::createDirectories(temp_dir /
"import", S_IRWXU);
1185 config.storage.path = temp_dir.Path();
1186 config.import.base_path = temp_dir /
"import";
1187 config.postUpdateValues();
1189 boost::filesystem::copy_file(
"tests/test_data/prov/installed_versions",
1190 temp_dir.Path() /
"import/installed_versions");
1193 auto storage = INvStorage::newStorage(config.storage);
1194 storage->importData(config.import);
1196 boost::optional<Uptane::Target> current_version;
1197 storage->loadPrimaryInstalledVersions(¤t_version,
nullptr);
1198 EXPECT_TRUE(!!current_version);
1199 EXPECT_EQ(current_version->filename(),
"master-863de625f305413dc3be306afab7c3f39d8713045cfff812b3af83f9722851f0");
1203 Json::Value target_json;
1204 target_json[
"hashes"][
"sha256"] =
"a0fb2e119cf812f1aa9e993d01f5f07cb41679096cb4492f1265bff5ac901d0d";
1205 target_json[
"length"] = 123;
1207 storage->savePrimaryInstalledVersion(new_installed_version, InstalledVersionUpdateMode::kCurrent);
1209 auto new_storage = INvStorage::newStorage(config.storage);
1210 new_storage->importData(config.import);
1212 current_version = boost::none;
1213 new_storage->loadPrimaryInstalledVersions(¤t_version,
nullptr);
1214 EXPECT_TRUE(!!current_version);
1215 EXPECT_EQ(current_version->filename(),
"filename");
1219 TEST(
Uptane, SaveAndLoadVersion) {
1221 Config config = config_common();
1222 config.storage.path = temp_dir.Path();
1223 config.provision.device_id =
"device_id";
1224 config.postUpdateValues();
1225 auto storage = INvStorage::newStorage(config.storage);
1227 Json::Value target_json;
1228 target_json[
"hashes"][
"sha256"] =
"a0fb2e119cf812f1aa9e993d01f5f07cb41679096cb4492f1265bff5ac901d0d";
1229 target_json[
"length"] = 123;
1232 storage->savePrimaryInstalledVersion(t, InstalledVersionUpdateMode::kCurrent);
1234 boost::optional<Uptane::Target> current_version;
1235 storage->loadPrimaryInstalledVersions(¤t_version,
nullptr);
1237 EXPECT_TRUE(!!current_version);
1238 EXPECT_EQ(current_version->sha256Hash(),
"a0fb2e119cf812f1aa9e993d01f5f07cb41679096cb4492f1265bff5ac901d0d");
1239 EXPECT_EQ(current_version->length(), 123);
1240 EXPECT_TRUE(current_version->MatchTarget(t));
1246 HttpResponse get(
const std::string &url, int64_t maxsize)
override {
1247 if (unstable_valid_count >= unstable_valid_num) {
1250 ++unstable_valid_count;
1251 return HttpFake::get(url, maxsize);
1255 void setUnstableValidNum(
int num) {
1256 unstable_valid_num = num;
1257 unstable_valid_count = 0;
1260 int unstable_valid_num{0};
1261 int unstable_valid_count{0};
1273 TEST(
Uptane, restoreVerify) {
1275 auto http = std::make_shared<HttpFakeUnstable>(temp_dir.Path());
1276 Config config(
"tests/config/basic.toml");
1277 config.storage.path = temp_dir.Path();
1278 config.pacman.type = PACKAGE_MANAGER_NONE;
1279 config.uptane.director_server = http->tls_server +
"director";
1280 config.uptane.repo_server = http->tls_server +
"repo";
1281 config.provision.primary_ecu_serial =
"CA:FE:A6:D2:84:9D";
1282 config.provision.primary_ecu_hardware_id =
"primary_hw";
1283 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hw");
1284 config.postUpdateValues();
1286 auto storage = INvStorage::newStorage(config.storage);
1287 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
1289 EXPECT_NO_THROW(sota_client->initialize());
1290 sota_client->AssembleManifest();
1293 EXPECT_FALSE(storage->loadLatestRoot(
nullptr, Uptane::RepositoryType::Director()));
1296 http->setUnstableValidNum(1);
1298 EXPECT_TRUE(storage->loadLatestRoot(
nullptr, Uptane::RepositoryType::Director()));
1299 EXPECT_FALSE(storage->loadNonRoot(
nullptr, Uptane::RepositoryType::Director(), Uptane::Role::Targets()));
1302 http->setUnstableValidNum(2);
1304 EXPECT_TRUE(storage->loadLatestRoot(
nullptr, Uptane::RepositoryType::Director()));
1305 EXPECT_TRUE(storage->loadNonRoot(
nullptr, Uptane::RepositoryType::Director(), Uptane::Role::Targets()));
1306 EXPECT_FALSE(storage->loadLatestRoot(
nullptr, Uptane::RepositoryType::Image()));
1309 http->setUnstableValidNum(3);
1311 EXPECT_TRUE(storage->loadLatestRoot(
nullptr, Uptane::RepositoryType::Image()));
1312 EXPECT_FALSE(storage->loadNonRoot(
nullptr, Uptane::RepositoryType::Image(), Uptane::Role::Timestamp()));
1315 http->setUnstableValidNum(4);
1317 EXPECT_TRUE(storage->loadNonRoot(
nullptr, Uptane::RepositoryType::Image(), Uptane::Role::Timestamp()));
1318 EXPECT_FALSE(storage->loadNonRoot(
nullptr, Uptane::RepositoryType::Image(), Uptane::Role::Snapshot()));
1321 http->setUnstableValidNum(5);
1323 EXPECT_TRUE(storage->loadNonRoot(
nullptr, Uptane::RepositoryType::Image(), Uptane::Role::Snapshot()));
1324 EXPECT_FALSE(storage->loadNonRoot(
nullptr, Uptane::RepositoryType::Image(), Uptane::Role::Targets()));
1327 http->setUnstableValidNum(6);
1328 EXPECT_NO_THROW(sota_client->uptaneIteration(
nullptr,
nullptr));
1329 EXPECT_TRUE(storage->loadNonRoot(
nullptr, Uptane::RepositoryType::Image(), Uptane::Role::Targets()));
1337 TEST(
Uptane, offlineIteration) {
1339 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates");
1340 Config config(
"tests/config/basic.toml");
1341 config.storage.path = temp_dir.Path();
1342 config.uptane.director_server = http->tls_server +
"director";
1343 config.uptane.repo_server = http->tls_server +
"repo";
1344 config.pacman.type = PACKAGE_MANAGER_NONE;
1345 config.provision.primary_ecu_serial =
"CA:FE:A6:D2:84:9D";
1346 config.provision.primary_ecu_hardware_id =
"primary_hw";
1347 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hw");
1348 config.postUpdateValues();
1350 auto storage = INvStorage::newStorage(config.storage);
1351 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
1352 EXPECT_NO_THROW(sota_client->initialize());
1354 std::vector<Uptane::Target> targets_online;
1355 EXPECT_NO_THROW(sota_client->uptaneIteration(&targets_online,
nullptr));
1357 std::vector<Uptane::Target> targets_offline;
1358 EXPECT_NO_THROW(sota_client->uptaneOfflineIteration(&targets_offline,
nullptr));
1359 EXPECT_TRUE(Uptane::MatchTargetVector(targets_online, targets_offline));
1366 TEST(
Uptane, IgnoreUnknownUpdate) {
1368 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates");
1369 Config config(
"tests/config/basic.toml");
1370 config.storage.path = temp_dir.Path();
1371 config.uptane.director_server = http->tls_server +
"director";
1372 config.uptane.repo_server = http->tls_server +
"repo";
1373 config.pacman.type = PACKAGE_MANAGER_NONE;
1374 config.provision.primary_ecu_serial =
"primary_ecu";
1375 config.provision.primary_ecu_hardware_id =
"primary_hw";
1376 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hw");
1377 config.postUpdateValues();
1379 auto storage = INvStorage::newStorage(config.storage);
1380 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
1382 EXPECT_NO_THROW(sota_client->initialize());
1384 auto result = sota_client->fetchMeta();
1385 EXPECT_EQ(
result.status, result::UpdateStatus::kError);
1386 std::vector<Uptane::Target> packages_to_install = UptaneTestCommon::makePackage(
"testecuserial",
"testecuhwid");
1387 auto report = sota_client->uptaneInstall(packages_to_install);
1388 EXPECT_EQ(report.ecu_reports.size(), 0);
1392 TEST(
Uptane, Pkcs11Provision) {
1395 Utils::createDirectories(temp_dir /
"import", S_IRWXU);
1396 boost::filesystem::copy_file(
"tests/test_data/device_cred_prov/ca.pem", temp_dir /
"import/root.crt");
1397 config.tls.cert_source = CryptoSource::kPkcs11;
1398 config.tls.pkey_source = CryptoSource::kPkcs11;
1399 config.p11.module = TEST_PKCS11_MODULE_PATH;
1400 config.p11.pass =
"1234";
1401 config.p11.tls_clientcert_id =
"01";
1402 config.p11.tls_pkey_id =
"02";
1403 config.import.base_path = (temp_dir /
"import").
string();
1406 config.storage.path = temp_dir.Path();
1407 config.postUpdateValues();
1409 auto storage = INvStorage::newStorage(config.storage);
1410 storage->importData(config.import);
1411 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates");
1412 KeyManager keys(storage, config.keymanagerConfig());
1414 EXPECT_NO_THROW(
Initializer(config.provision, storage, http, keys, {}));
1419 int main(
int argc,
char **argv) {
1420 ::testing::InitGoogleTest(&argc, argv);
1423 logger_set_threshold(boost::log::trivial::trace);
1425 return RUN_ALL_TESTS();