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_CONST_METHOD1(getRootVersionMock, int32_t(
bool));
544 bool putMetadata(
const Uptane::RawMetaPack &meta_pack)
override {
return putMetadataMock(meta_pack); }
545 int32_t getRootVersion(
bool director)
const override {
return getRootVersionMock(director); }
547 bool putRoot(
const std::string &,
bool)
override {
return true; }
548 bool sendFirmware(
const std::string &)
override {
return true; }
552 Json::Value manifest_;
557 MATCHER_P(matchMeta, meta,
"") {
558 return (arg.director_root == meta.director_root) && (arg.image_root == meta.image_root) &&
559 (arg.director_targets == meta.director_targets) && (arg.image_timestamp == meta.image_timestamp) &&
560 (arg.image_snapshot == meta.image_snapshot) && (arg.image_targets == meta.image_targets);
567 TEST(
Uptane, SendMetadataToSeconadry) {
568 Config conf(
"tests/config/basic.toml");
570 auto http = std::make_shared<HttpFakeEvents>(temp_dir.Path(),
"hasupdates");
571 conf.provision.primary_ecu_serial =
"CA:FE:A6:D2:84:9D";
572 conf.provision.primary_ecu_hardware_id =
"primary_hw";
573 conf.uptane.director_server = http->tls_server +
"/director";
574 conf.uptane.repo_server = http->tls_server +
"/repo";
575 conf.storage.path = temp_dir.Path();
576 conf.tls.server = http->tls_server;
579 ecu_config.partial_verifying =
false;
580 ecu_config.full_client_dir = temp_dir.Path();
581 ecu_config.ecu_serial =
"secondary_ecu_serial";
582 ecu_config.ecu_hardware_id =
"secondary_hw";
583 ecu_config.ecu_private_key =
"sec.priv";
584 ecu_config.ecu_public_key =
"sec.pub";
585 ecu_config.firmware_path = temp_dir /
"firmware.txt";
586 ecu_config.target_name_path = temp_dir /
"firmware_name.txt";
587 ecu_config.metadata_path = temp_dir /
"secondary_metadata";
589 auto sec = std::make_shared<SecondaryInterfaceMock>(ecu_config);
590 auto storage = INvStorage::newStorage(conf.storage);
591 auto up = std_::make_unique<UptaneTestCommon::TestUptaneClient>(conf, storage, http);
592 up->addSecondary(sec);
593 EXPECT_NO_THROW(up->initialize());
595 EXPECT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
598 storage->loadLatestRoot(&meta.director_root, Uptane::RepositoryType::Director());
599 storage->loadNonRoot(&meta.director_targets, Uptane::RepositoryType::Director(), Uptane::Role::Targets());
600 storage->loadLatestRoot(&meta.image_root, Uptane::RepositoryType::Image());
601 storage->loadNonRoot(&meta.image_timestamp, Uptane::RepositoryType::Image(), Uptane::Role::Timestamp());
602 storage->loadNonRoot(&meta.image_snapshot, Uptane::RepositoryType::Image(), Uptane::Role::Snapshot());
603 storage->loadNonRoot(&meta.image_targets, Uptane::RepositoryType::Image(), Uptane::Role::Targets());
605 EXPECT_CALL(*sec, putMetadataMock(matchMeta(meta)));
606 result::Download download_result = up->downloadImages(update_result.updates);
607 EXPECT_EQ(download_result.status, result::DownloadStatus::kSuccess);
608 result::Install install_result = up->uptaneInstall(download_result.updates);
609 EXPECT_TRUE(install_result.dev_report.isSuccess());
610 EXPECT_EQ(install_result.dev_report.result_code, data::ResultCode::Numeric::kOk);
611 EXPECT_TRUE(EcuInstallationStartedReportGot);
615 TEST(
Uptane, UptaneSecondaryAdd) {
617 auto http = std::make_shared<HttpFake>(temp_dir.Path());
618 Config config = config_common();
619 boost::filesystem::copy_file(
"tests/test_data/cred.zip", temp_dir /
"cred.zip");
620 config.provision.provision_path = temp_dir /
"cred.zip";
621 config.provision.mode = ProvisionMode::kSharedCred;
622 config.uptane.director_server = http->tls_server +
"/director";
623 config.uptane.repo_server = http->tls_server +
"/repo";
624 config.tls.server = http->tls_server;
625 config.provision.primary_ecu_serial =
"testecuserial";
626 config.storage.path = temp_dir.Path();
627 config.pacman.type = PACKAGE_MANAGER_NONE;
628 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hardware");
630 auto storage = INvStorage::newStorage(config.storage);
631 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
632 EXPECT_NO_THROW(sota_client->initialize());
636 Json::Value ecu_data = Utils::parseJSONFile(temp_dir /
"post.json");
637 EXPECT_EQ(ecu_data[
"ecus"].size(), 2);
638 EXPECT_EQ(ecu_data[
"primary_ecu_serial"].asString(), config.provision.primary_ecu_serial);
639 EXPECT_EQ(ecu_data[
"ecus"][1][
"ecu_serial"].asString(),
"secondary_ecu_serial");
640 EXPECT_EQ(ecu_data[
"ecus"][1][
"hardware_identifier"].asString(),
"secondary_hardware");
641 EXPECT_EQ(ecu_data[
"ecus"][1][
"clientKey"][
"keytype"].asString(),
"RSA");
642 EXPECT_TRUE(ecu_data[
"ecus"][1][
"clientKey"][
"keyval"][
"public"].asString().size() > 0);
646 TEST(
Uptane, UptaneSecondaryAddSameSerial) {
648 auto http = std::make_shared<HttpFake>(temp_dir.Path());
649 boost::filesystem::copy_file(
"tests/test_data/cred.zip", temp_dir /
"cred.zip");
650 Config config = config_common();
651 config.provision.provision_path = temp_dir /
"cred.zip";
652 config.provision.mode = ProvisionMode::kSharedCred;
653 config.pacman.type = PACKAGE_MANAGER_NONE;
654 config.storage.path = temp_dir.Path();
656 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hardware");
658 auto storage = INvStorage::newStorage(config.storage);
659 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
660 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hardware_new");
661 EXPECT_THROW(sota_client->addSecondary(std::make_shared<Primary::VirtualSecondary>(
662 Primary::VirtualSecondaryConfig::create_from_file(config.uptane.secondary_config_file)[0])),
673 TEST(
Uptane, UptaneSecondaryMisconfigured) {
675 boost::filesystem::copy_file(
"tests/test_data/cred.zip", temp_dir /
"cred.zip");
676 auto http = std::make_shared<HttpFake>(temp_dir.Path());
678 Config config = config_common();
679 config.provision.provision_path = temp_dir /
"cred.zip";
680 config.provision.mode = ProvisionMode::kSharedCred;
681 config.pacman.type = PACKAGE_MANAGER_NONE;
682 config.storage.path = temp_dir.Path();
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());
689 std::vector<MisconfiguredEcu> ecus;
690 storage->loadMisconfiguredEcus(&ecus);
691 EXPECT_EQ(ecus.size(), 0);
694 Config config = config_common();
695 config.provision.provision_path = temp_dir /
"cred.zip";
696 config.provision.mode = ProvisionMode::kSharedCred;
697 config.pacman.type = PACKAGE_MANAGER_NONE;
698 config.storage.path = temp_dir.Path();
699 auto storage = INvStorage::newStorage(config.storage);
700 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"new_secondary_ecu_serial",
"new_secondary_hardware");
701 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
702 EXPECT_NO_THROW(sota_client->initialize());
704 std::vector<MisconfiguredEcu> ecus;
705 storage->loadMisconfiguredEcus(&ecus);
706 EXPECT_EQ(ecus.size(), 2);
707 if (ecus[0].serial.ToString() ==
"new_secondary_ecu_serial") {
708 EXPECT_EQ(ecus[0].state, EcuState::kNotRegistered);
709 EXPECT_EQ(ecus[1].serial.ToString(),
"secondary_ecu_serial");
710 EXPECT_EQ(ecus[1].state, EcuState::kOld);
711 }
else if (ecus[0].serial.ToString() ==
"secondary_ecu_serial") {
712 EXPECT_EQ(ecus[0].state, EcuState::kOld);
713 EXPECT_EQ(ecus[1].serial.ToString(),
"new_secondary_ecu_serial");
714 EXPECT_EQ(ecus[1].state, EcuState::kNotRegistered);
716 FAIL() <<
"Unexpected secondary serial in storage: " << ecus[0].serial.ToString();
720 Config config = config_common();
721 config.provision.provision_path = temp_dir /
"cred.zip";
722 config.provision.mode = ProvisionMode::kSharedCred;
723 config.pacman.type = PACKAGE_MANAGER_NONE;
724 config.storage.path = temp_dir.Path();
725 auto storage = INvStorage::newStorage(config.storage);
726 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hardware");
727 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
728 EXPECT_NO_THROW(sota_client->initialize());
730 std::vector<MisconfiguredEcu> ecus;
731 storage->loadMisconfiguredEcus(&ecus);
732 EXPECT_EQ(ecus.size(), 0);
746 HttpFakeProv(
const boost::filesystem::path &test_dir_in, std::string flavor =
"")
747 :
HttpFake(test_dir_in, std::move(flavor)) {}
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 <= 2) {
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 Json::Value hwinfo = Utils::getHardwareInfo();
894 EXPECT_EQ(hwinfo[
"id"].asString(),
data[
"id"].asString());
895 EXPECT_EQ(hwinfo[
"description"].asString(),
data[
"description"].asString());
896 EXPECT_EQ(hwinfo[
"class"].asString(),
data[
"class"].asString());
897 EXPECT_EQ(hwinfo[
"product"].asString(),
data[
"product"].asString());
899 EXPECT_EQ(0, 1) <<
"Unexpected put to URL: " << url;
902 return HttpFake::put(url,
data);
905 size_t events_seen{0};
906 int devices_count{0};
908 int manifest_count{0};
909 int installed_count{0};
910 int system_info_count{0};
911 int network_count{0};
914 int primary_download_start{0};
915 int primary_download_complete{0};
916 int secondary_download_start{0};
917 int secondary_download_complete{0};
925 TEST(
Uptane, ProvisionOnServer) {
926 RecordProperty(
"zephyr_key",
"OTA-984,TST-149");
928 Config config(
"tests/config/basic.toml");
929 auto http = std::make_shared<HttpFakeProv>(temp_dir.Path(),
"hasupdates");
930 const std::string &server = http->tls_server;
931 config.provision.server = server;
932 config.tls.server = server;
933 config.uptane.director_server = server +
"/director";
934 config.uptane.repo_server = server +
"/repo";
935 config.provision.ecu_registration_endpoint = server +
"/director/ecus";
936 config.provision.device_id =
"tst149_device_id";
937 config.provision.primary_ecu_serial =
"CA:FE:A6:D2:84:9D";
938 config.provision.primary_ecu_hardware_id =
"primary_hw";
939 config.storage.path = temp_dir.Path();
940 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hw");
942 auto storage = INvStorage::newStorage(config.storage);
943 auto events_channel = std::make_shared<event::Channel>();
944 auto up = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http, events_channel);
946 EXPECT_EQ(http->devices_count, 0);
947 EXPECT_EQ(http->ecus_count, 0);
948 EXPECT_EQ(http->manifest_count, 0);
949 EXPECT_EQ(http->installed_count, 0);
950 EXPECT_EQ(http->system_info_count, 0);
951 EXPECT_EQ(http->network_count, 0);
953 EXPECT_NO_THROW(up->initialize());
955 storage->loadEcuSerials(&serials);
956 EXPECT_EQ(serials[0].second.ToString(),
"primary_hw");
958 EXPECT_EQ(http->devices_count, 1);
959 EXPECT_EQ(http->ecus_count, 1);
961 EXPECT_NO_THROW(up->sendDeviceData());
962 EXPECT_EQ(http->manifest_count, 1);
963 EXPECT_EQ(http->installed_count, 1);
964 EXPECT_EQ(http->system_info_count, 1);
965 EXPECT_EQ(http->network_count, 1);
968 EXPECT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
969 EXPECT_EQ(http->manifest_count, 2);
972 result::Download download_result = up->downloadImages(update_result.updates);
973 EXPECT_EQ(download_result.status, result::DownloadStatus::kSuccess);
974 result::Install install_result = up->uptaneInstall(download_result.updates);
975 EXPECT_TRUE(install_result.dev_report.isSuccess());
976 EXPECT_EQ(install_result.dev_report.result_code, data::ResultCode::Numeric::kOk);
979 EXPECT_EQ(http->devices_count, 1);
980 EXPECT_EQ(http->ecus_count, 1);
981 EXPECT_EQ(http->manifest_count, 3);
982 EXPECT_EQ(http->installed_count, 1);
983 EXPECT_EQ(http->system_info_count, 1);
984 EXPECT_EQ(http->network_count, 1);
985 EXPECT_EQ(http->events_seen, 8);
989 TEST(
Uptane, FsToSqlFull) {
991 Utils::copyDir(
"tests/test_data/prov", temp_dir.Path());
992 ASSERT_GE(chmod(temp_dir.Path().c_str(), S_IRWXU), 0);
994 config.type = StorageType::kSqlite;
995 config.path = temp_dir.Path();
999 std::string public_key;
1000 std::string private_key;
1001 fs_storage.loadPrimaryKeys(&public_key, &private_key);
1006 fs_storage.loadTlsCreds(&ca, &cert, &pkey);
1008 std::string device_id;
1009 fs_storage.loadDeviceId(&device_id);
1012 fs_storage.loadEcuSerials(&serials);
1014 bool ecu_registered = fs_storage.loadEcuRegistered();
1016 std::vector<Uptane::Target> fs_installed_versions;
1017 std::vector<Uptane::Target> fixed_installed_versions;
1018 fs_storage.loadInstalledVersions(&fs_installed_versions,
nullptr);
1021 for (
auto &target : fs_installed_versions) {
1022 Json::Value dump = target.toDebugJson();
1023 dump[
"custom"][
"ecuIdentifiers"][serials[0].first.ToString()][
"hardwareId"] = serials[0].second.ToString();
1024 fixed_installed_versions.emplace_back(
Uptane::Target(target.filename(), dump));
1027 std::string director_root;
1028 std::string director_targets;
1029 std::string images_root;
1030 std::string images_targets;
1031 std::string images_timestamp;
1032 std::string images_snapshot;
1034 EXPECT_TRUE(fs_storage.loadLatestRoot(&director_root, Uptane::RepositoryType::Director()));
1035 EXPECT_TRUE(fs_storage.loadNonRoot(&director_targets, Uptane::RepositoryType::Director(), Uptane::Role::Targets()));
1036 EXPECT_TRUE(fs_storage.loadLatestRoot(&images_root, Uptane::RepositoryType::Image()));
1037 EXPECT_TRUE(fs_storage.loadNonRoot(&images_targets, Uptane::RepositoryType::Image(), Uptane::Role::Targets()));
1038 EXPECT_TRUE(fs_storage.loadNonRoot(&images_timestamp, Uptane::RepositoryType::Image(), Uptane::Role::Timestamp()));
1039 EXPECT_TRUE(fs_storage.loadNonRoot(&images_snapshot, Uptane::RepositoryType::Image(), Uptane::Role::Snapshot()));
1041 EXPECT_TRUE(boost::filesystem::exists(config.uptane_public_key_path.get(config.path)));
1042 EXPECT_TRUE(boost::filesystem::exists(config.uptane_private_key_path.get(config.path)));
1043 EXPECT_TRUE(boost::filesystem::exists(config.tls_cacert_path.get(config.path)));
1044 EXPECT_TRUE(boost::filesystem::exists(config.tls_clientcert_path.get(config.path)));
1045 EXPECT_TRUE(boost::filesystem::exists(config.tls_pkey_path.get(config.path)));
1047 boost::filesystem::path image_path = config.uptane_metadata_path.get(config.path) /
"repo";
1048 boost::filesystem::path director_path = config.uptane_metadata_path.get(config.path) /
"director";
1049 EXPECT_TRUE(boost::filesystem::exists(director_path /
"1.root.json"));
1050 EXPECT_TRUE(boost::filesystem::exists(director_path /
"targets.json"));
1051 EXPECT_TRUE(boost::filesystem::exists(image_path /
"1.root.json"));
1052 EXPECT_TRUE(boost::filesystem::exists(image_path /
"targets.json"));
1053 EXPECT_TRUE(boost::filesystem::exists(image_path /
"timestamp.json"));
1054 EXPECT_TRUE(boost::filesystem::exists(image_path /
"snapshot.json"));
1055 EXPECT_TRUE(boost::filesystem::exists(Utils::absolutePath(config.path,
"device_id")));
1056 EXPECT_TRUE(boost::filesystem::exists(Utils::absolutePath(config.path,
"is_registered")));
1057 EXPECT_TRUE(boost::filesystem::exists(Utils::absolutePath(config.path,
"primary_ecu_serial")));
1058 EXPECT_TRUE(boost::filesystem::exists(Utils::absolutePath(config.path,
"primary_ecu_hardware_id")));
1059 EXPECT_TRUE(boost::filesystem::exists(Utils::absolutePath(config.path,
"secondaries_list")));
1060 auto sql_storage = INvStorage::newStorage(config);
1062 EXPECT_FALSE(boost::filesystem::exists(config.uptane_public_key_path.get(config.path)));
1063 EXPECT_FALSE(boost::filesystem::exists(config.uptane_private_key_path.get(config.path)));
1064 EXPECT_FALSE(boost::filesystem::exists(config.tls_cacert_path.get(config.path)));
1065 EXPECT_FALSE(boost::filesystem::exists(config.tls_clientcert_path.get(config.path)));
1066 EXPECT_FALSE(boost::filesystem::exists(config.tls_pkey_path.get(config.path)));
1068 EXPECT_FALSE(boost::filesystem::exists(director_path /
"root.json"));
1069 EXPECT_FALSE(boost::filesystem::exists(director_path /
"targets.json"));
1070 EXPECT_FALSE(boost::filesystem::exists(director_path /
"root.json"));
1071 EXPECT_FALSE(boost::filesystem::exists(director_path /
"targets.json"));
1072 EXPECT_FALSE(boost::filesystem::exists(image_path /
"timestamp.json"));
1073 EXPECT_FALSE(boost::filesystem::exists(image_path /
"snapshot.json"));
1074 EXPECT_FALSE(boost::filesystem::exists(Utils::absolutePath(config.path,
"device_id")));
1075 EXPECT_FALSE(boost::filesystem::exists(Utils::absolutePath(config.path,
"is_registered")));
1076 EXPECT_FALSE(boost::filesystem::exists(Utils::absolutePath(config.path,
"primary_ecu_serial")));
1077 EXPECT_FALSE(boost::filesystem::exists(Utils::absolutePath(config.path,
"primary_ecu_hardware_id")));
1078 EXPECT_FALSE(boost::filesystem::exists(Utils::absolutePath(config.path,
"secondaries_list")));
1080 std::string sql_public_key;
1081 std::string sql_private_key;
1082 sql_storage->loadPrimaryKeys(&sql_public_key, &sql_private_key);
1085 std::string sql_cert;
1086 std::string sql_pkey;
1087 sql_storage->loadTlsCreds(&sql_ca, &sql_cert, &sql_pkey);
1089 std::string sql_device_id;
1090 sql_storage->loadDeviceId(&sql_device_id);
1092 EcuSerials sql_serials;
1093 sql_storage->loadEcuSerials(&sql_serials);
1095 bool sql_ecu_registered = sql_storage->loadEcuRegistered();
1097 std::vector<Uptane::Target> sql_installed_versions;
1098 sql_storage->loadPrimaryInstallationLog(&sql_installed_versions,
true);
1100 std::string sql_director_root;
1101 std::string sql_director_targets;
1102 std::string sql_images_root;
1103 std::string sql_images_targets;
1104 std::string sql_images_timestamp;
1105 std::string sql_images_snapshot;
1107 sql_storage->loadLatestRoot(&sql_director_root, Uptane::RepositoryType::Director());
1108 sql_storage->loadNonRoot(&sql_director_targets, Uptane::RepositoryType::Director(), Uptane::Role::Targets());
1109 sql_storage->loadLatestRoot(&sql_images_root, Uptane::RepositoryType::Image());
1110 sql_storage->loadNonRoot(&sql_images_targets, Uptane::RepositoryType::Image(), Uptane::Role::Targets());
1111 sql_storage->loadNonRoot(&sql_images_timestamp, Uptane::RepositoryType::Image(), Uptane::Role::Timestamp());
1112 sql_storage->loadNonRoot(&sql_images_snapshot, Uptane::RepositoryType::Image(), Uptane::Role::Snapshot());
1114 EXPECT_EQ(sql_public_key, public_key);
1115 EXPECT_EQ(sql_private_key, private_key);
1116 EXPECT_EQ(sql_ca, ca);
1117 EXPECT_EQ(sql_cert, cert);
1118 EXPECT_EQ(sql_pkey, pkey);
1119 EXPECT_EQ(sql_device_id, device_id);
1120 EXPECT_EQ(sql_serials, serials);
1121 EXPECT_EQ(sql_ecu_registered, ecu_registered);
1122 EXPECT_TRUE(Uptane::MatchTargetVector(sql_installed_versions, fixed_installed_versions));
1124 EXPECT_EQ(sql_director_root, director_root);
1125 EXPECT_EQ(sql_director_targets, director_targets);
1126 EXPECT_EQ(sql_images_root, images_root);
1127 EXPECT_EQ(sql_images_targets, images_targets);
1128 EXPECT_EQ(sql_images_timestamp, images_timestamp);
1129 EXPECT_EQ(sql_images_snapshot, images_snapshot);
1133 TEST(
Uptane, InstalledVersionImport) {
1134 Config config = config_common();
1137 Utils::createDirectories(temp_dir /
"import", S_IRWXU);
1138 config.storage.path = temp_dir.Path();
1139 config.import.base_path = temp_dir /
"import";
1140 config.postUpdateValues();
1142 boost::filesystem::copy_file(
"tests/test_data/prov/installed_versions",
1143 temp_dir.Path() /
"import/installed_versions");
1146 auto storage = INvStorage::newStorage(config.storage);
1147 storage->importData(config.import);
1149 boost::optional<Uptane::Target> current_version;
1150 storage->loadPrimaryInstalledVersions(¤t_version,
nullptr);
1151 EXPECT_TRUE(!!current_version);
1152 EXPECT_EQ(current_version->filename(),
"master-863de625f305413dc3be306afab7c3f39d8713045cfff812b3af83f9722851f0");
1156 Json::Value target_json;
1157 target_json[
"hashes"][
"sha256"] =
"a0fb2e119cf812f1aa9e993d01f5f07cb41679096cb4492f1265bff5ac901d0d";
1158 target_json[
"length"] = 123;
1160 storage->savePrimaryInstalledVersion(new_installed_version, InstalledVersionUpdateMode::kCurrent);
1162 auto new_storage = INvStorage::newStorage(config.storage);
1163 new_storage->importData(config.import);
1165 current_version = boost::none;
1166 new_storage->loadPrimaryInstalledVersions(¤t_version,
nullptr);
1167 EXPECT_TRUE(!!current_version);
1168 EXPECT_EQ(current_version->filename(),
"filename");
1172 TEST(
Uptane, SaveAndLoadVersion) {
1174 Config config = config_common();
1175 config.storage.path = temp_dir.Path();
1176 config.provision.device_id =
"device_id";
1177 config.postUpdateValues();
1178 auto storage = INvStorage::newStorage(config.storage);
1180 Json::Value target_json;
1181 target_json[
"hashes"][
"sha256"] =
"a0fb2e119cf812f1aa9e993d01f5f07cb41679096cb4492f1265bff5ac901d0d";
1182 target_json[
"length"] = 123;
1185 storage->savePrimaryInstalledVersion(t, InstalledVersionUpdateMode::kCurrent);
1187 boost::optional<Uptane::Target> current_version;
1188 storage->loadPrimaryInstalledVersions(¤t_version,
nullptr);
1190 EXPECT_TRUE(!!current_version);
1191 EXPECT_EQ(current_version->sha256Hash(),
"a0fb2e119cf812f1aa9e993d01f5f07cb41679096cb4492f1265bff5ac901d0d");
1192 EXPECT_EQ(current_version->length(), 123);
1193 EXPECT_TRUE(current_version->MatchTarget(t));
1199 HttpResponse get(
const std::string &url, int64_t maxsize)
override {
1200 if (unstable_valid_count >= unstable_valid_num) {
1205 if (url.find(
"director/root.json") == std::string::npos) {
1206 ++unstable_valid_count;
1208 return HttpFake::get(url, maxsize);
1212 void setUnstableValidNum(
int num) {
1213 unstable_valid_num = num;
1214 unstable_valid_count = 0;
1217 int unstable_valid_num{0};
1218 int unstable_valid_count{0};
1230 TEST(
Uptane, restoreVerify) {
1232 auto http = std::make_shared<HttpFakeUnstable>(temp_dir.Path());
1233 Config config(
"tests/config/basic.toml");
1234 config.storage.path = temp_dir.Path();
1235 config.pacman.type = PACKAGE_MANAGER_NONE;
1236 config.uptane.director_server = http->tls_server +
"director";
1237 config.uptane.repo_server = http->tls_server +
"repo";
1238 config.provision.primary_ecu_serial =
"CA:FE:A6:D2:84:9D";
1239 config.provision.primary_ecu_hardware_id =
"primary_hw";
1240 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hw");
1241 config.postUpdateValues();
1243 auto storage = INvStorage::newStorage(config.storage);
1244 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
1246 EXPECT_NO_THROW(sota_client->initialize());
1247 sota_client->AssembleManifest();
1249 EXPECT_FALSE(sota_client->uptaneIteration(
nullptr,
nullptr));
1250 EXPECT_FALSE(storage->loadLatestRoot(
nullptr, Uptane::RepositoryType::Director()));
1253 http->setUnstableValidNum(1);
1254 EXPECT_FALSE(sota_client->uptaneIteration(
nullptr,
nullptr));
1255 EXPECT_TRUE(storage->loadLatestRoot(
nullptr, Uptane::RepositoryType::Director()));
1256 EXPECT_FALSE(storage->loadNonRoot(
nullptr, Uptane::RepositoryType::Director(), Uptane::Role::Targets()));
1259 http->setUnstableValidNum(2);
1260 EXPECT_FALSE(sota_client->uptaneIteration(
nullptr,
nullptr));
1261 EXPECT_TRUE(storage->loadLatestRoot(
nullptr, Uptane::RepositoryType::Director()));
1262 EXPECT_TRUE(storage->loadNonRoot(
nullptr, Uptane::RepositoryType::Director(), Uptane::Role::Targets()));
1263 EXPECT_FALSE(storage->loadLatestRoot(
nullptr, Uptane::RepositoryType::Image()));
1266 http->setUnstableValidNum(3);
1267 EXPECT_FALSE(sota_client->uptaneIteration(
nullptr,
nullptr));
1268 EXPECT_TRUE(storage->loadLatestRoot(
nullptr, Uptane::RepositoryType::Image()));
1269 EXPECT_FALSE(storage->loadNonRoot(
nullptr, Uptane::RepositoryType::Image(), Uptane::Role::Timestamp()));
1272 http->setUnstableValidNum(4);
1273 EXPECT_FALSE(sota_client->uptaneIteration(
nullptr,
nullptr));
1274 EXPECT_TRUE(storage->loadNonRoot(
nullptr, Uptane::RepositoryType::Image(), Uptane::Role::Timestamp()));
1275 EXPECT_FALSE(storage->loadNonRoot(
nullptr, Uptane::RepositoryType::Image(), Uptane::Role::Snapshot()));
1278 http->setUnstableValidNum(5);
1279 EXPECT_FALSE(sota_client->uptaneIteration(
nullptr,
nullptr));
1280 EXPECT_TRUE(storage->loadNonRoot(
nullptr, Uptane::RepositoryType::Image(), Uptane::Role::Snapshot()));
1281 EXPECT_FALSE(storage->loadNonRoot(
nullptr, Uptane::RepositoryType::Image(), Uptane::Role::Targets()));
1284 http->setUnstableValidNum(6);
1285 EXPECT_TRUE(sota_client->uptaneIteration(
nullptr,
nullptr));
1286 EXPECT_TRUE(storage->loadNonRoot(
nullptr, Uptane::RepositoryType::Image(), Uptane::Role::Targets()));
1294 TEST(
Uptane, offlineIteration) {
1296 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates");
1297 Config config(
"tests/config/basic.toml");
1298 config.storage.path = temp_dir.Path();
1299 config.uptane.director_server = http->tls_server +
"director";
1300 config.uptane.repo_server = http->tls_server +
"repo";
1301 config.pacman.type = PACKAGE_MANAGER_NONE;
1302 config.provision.primary_ecu_serial =
"CA:FE:A6:D2:84:9D";
1303 config.provision.primary_ecu_hardware_id =
"primary_hw";
1304 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hw");
1305 config.postUpdateValues();
1307 auto storage = INvStorage::newStorage(config.storage);
1308 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
1309 EXPECT_NO_THROW(sota_client->initialize());
1311 std::vector<Uptane::Target> targets_online;
1312 EXPECT_TRUE(sota_client->uptaneIteration(&targets_online,
nullptr));
1314 std::vector<Uptane::Target> targets_offline;
1315 EXPECT_TRUE(sota_client->uptaneOfflineIteration(&targets_offline,
nullptr));
1316 EXPECT_TRUE(Uptane::MatchTargetVector(targets_online, targets_offline));
1323 TEST(
Uptane, IgnoreUnknownUpdate) {
1325 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates");
1326 Config config(
"tests/config/basic.toml");
1327 config.storage.path = temp_dir.Path();
1328 config.uptane.director_server = http->tls_server +
"director";
1329 config.uptane.repo_server = http->tls_server +
"repo";
1330 config.pacman.type = PACKAGE_MANAGER_NONE;
1331 config.provision.primary_ecu_serial =
"primary_ecu";
1332 config.provision.primary_ecu_hardware_id =
"primary_hw";
1333 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hw");
1334 config.postUpdateValues();
1336 auto storage = INvStorage::newStorage(config.storage);
1337 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
1339 EXPECT_NO_THROW(sota_client->initialize());
1340 auto result = sota_client->fetchMeta();
1341 EXPECT_EQ(
result.status, result::UpdateStatus::kError);
1342 EXPECT_STREQ(sota_client->getLastException().what(),
1343 "The target had an ECU ID that did not match the client's configured ECU id.");
1345 result = sota_client->checkUpdates();
1346 EXPECT_EQ(
result.status, result::UpdateStatus::kError);
1347 EXPECT_STREQ(sota_client->getLastException().what(),
1348 "The target had an ECU ID that did not match the client's configured ECU id.");
1349 std::vector<Uptane::Target> packages_to_install = UptaneTestCommon::makePackage(
"testecuserial",
"testecuhwid");
1351 auto report = sota_client->uptaneInstall(packages_to_install);
1352 EXPECT_STREQ(sota_client->getLastException().what(),
1353 "The target had an ECU ID that did not match the client's configured ECU id.");
1354 EXPECT_EQ(report.ecu_reports.size(), 0);
1358 TEST(
Uptane, Pkcs11Provision) {
1361 Utils::createDirectories(temp_dir /
"import", S_IRWXU);
1362 boost::filesystem::copy_file(
"tests/test_data/device_cred_prov/ca.pem", temp_dir /
"import/root.crt");
1363 config.tls.cert_source = CryptoSource::kPkcs11;
1364 config.tls.pkey_source = CryptoSource::kPkcs11;
1365 config.p11.module = TEST_PKCS11_MODULE_PATH;
1366 config.p11.pass =
"1234";
1367 config.p11.tls_clientcert_id =
"01";
1368 config.p11.tls_pkey_id =
"02";
1369 config.import.base_path = (temp_dir /
"import").
string();
1370 config.import.tls_cacert_path =
BasedPath(
"root.crt");
1372 config.storage.path = temp_dir.Path();
1373 config.postUpdateValues();
1375 auto storage = INvStorage::newStorage(config.storage);
1376 storage->importData(config.import);
1377 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates");
1378 KeyManager keys(storage, config.keymanagerConfig());
1379 Initializer initializer(config.provision, storage, http, keys, {});
1381 EXPECT_TRUE(initializer.isSuccessful());
1386 int main(
int argc,
char **argv) {
1387 ::testing::InitGoogleTest(&argc, argv);
1390 logger_set_threshold(boost::log::trivial::trace);
1392 return RUN_ALL_TESTS();