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 = PackageManager::kNone;
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 = PackageManager::kNone;
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 = PackageManager::kNone;
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 = PackageManager::kNone;
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 = PackageManager::kNone;
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(
false, 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(
false, 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(
false, 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(
false, 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(
false, 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 PublicKey getPublicKey()
const override {
return public_key_; }
533 if (!sconfig.ecu_serial.empty()) {
540 MOCK_CONST_METHOD1(getRootVersionMock, int32_t(
bool));
542 bool putMetadata(
const Uptane::RawMetaPack &meta_pack)
override {
return putMetadataMock(meta_pack); }
543 int32_t getRootVersion(
bool director)
const override {
return getRootVersionMock(director); }
545 bool putRoot(
const std::string &,
bool)
override {
return true; }
546 bool sendFirmware(
const std::string &)
override {
return true; }
550 Json::Value manifest_;
555 MATCHER_P(matchMeta, meta,
"") {
556 return (arg.director_root == meta.director_root) && (arg.image_root == meta.image_root) &&
557 (arg.director_targets == meta.director_targets) && (arg.image_timestamp == meta.image_timestamp) &&
558 (arg.image_snapshot == meta.image_snapshot) && (arg.image_targets == meta.image_targets);
565 TEST(
Uptane, SendMetadataToSeconadry) {
566 Config conf(
"tests/config/basic.toml");
568 auto http = std::make_shared<HttpFakeEvents>(temp_dir.Path(),
"hasupdates");
569 conf.provision.primary_ecu_serial =
"CA:FE:A6:D2:84:9D";
570 conf.provision.primary_ecu_hardware_id =
"primary_hw";
571 conf.uptane.director_server = http->tls_server +
"/director";
572 conf.uptane.repo_server = http->tls_server +
"/repo";
573 conf.storage.path = temp_dir.Path();
574 conf.tls.server = http->tls_server;
577 ecu_config.partial_verifying =
false;
578 ecu_config.full_client_dir = temp_dir.Path();
579 ecu_config.ecu_serial =
"secondary_ecu_serial";
580 ecu_config.ecu_hardware_id =
"secondary_hw";
581 ecu_config.ecu_private_key =
"sec.priv";
582 ecu_config.ecu_public_key =
"sec.pub";
583 ecu_config.firmware_path = temp_dir /
"firmware.txt";
584 ecu_config.target_name_path = temp_dir /
"firmware_name.txt";
585 ecu_config.metadata_path = temp_dir /
"secondary_metadata";
587 auto sec = std::make_shared<SecondaryInterfaceMock>(ecu_config);
588 auto storage = INvStorage::newStorage(conf.storage);
589 auto up = std_::make_unique<UptaneTestCommon::TestUptaneClient>(conf, storage, http);
590 up->addNewSecondary(sec);
591 EXPECT_NO_THROW(up->initialize());
593 EXPECT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
596 storage->loadLatestRoot(&meta.director_root, Uptane::RepositoryType::Director());
597 storage->loadNonRoot(&meta.director_targets, Uptane::RepositoryType::Director(), Uptane::Role::Targets());
598 storage->loadLatestRoot(&meta.image_root, Uptane::RepositoryType::Image());
599 storage->loadNonRoot(&meta.image_timestamp, Uptane::RepositoryType::Image(), Uptane::Role::Timestamp());
600 storage->loadNonRoot(&meta.image_snapshot, Uptane::RepositoryType::Image(), Uptane::Role::Snapshot());
601 storage->loadNonRoot(&meta.image_targets, Uptane::RepositoryType::Image(), Uptane::Role::Targets());
603 EXPECT_CALL(*sec, putMetadataMock(matchMeta(meta)));
604 result::Download download_result = up->downloadImages(update_result.updates);
605 EXPECT_EQ(download_result.status, result::DownloadStatus::kSuccess);
606 result::Install install_result = up->uptaneInstall(download_result.updates);
607 EXPECT_TRUE(install_result.dev_report.isSuccess());
608 EXPECT_EQ(install_result.dev_report.result_code, data::ResultCode::Numeric::kOk);
609 EXPECT_TRUE(EcuInstallationStartedReportGot);
613 TEST(
Uptane, UptaneSecondaryAdd) {
615 auto http = std::make_shared<HttpFake>(temp_dir.Path());
616 Config config = config_common();
617 boost::filesystem::copy_file(
"tests/test_data/cred.zip", temp_dir /
"cred.zip");
618 config.provision.provision_path = temp_dir /
"cred.zip";
619 config.provision.mode = ProvisionMode::kSharedCred;
620 config.uptane.director_server = http->tls_server +
"/director";
621 config.uptane.repo_server = http->tls_server +
"/repo";
622 config.tls.server = http->tls_server;
623 config.provision.primary_ecu_serial =
"testecuserial";
624 config.storage.path = temp_dir.Path();
625 config.pacman.type = PackageManager::kNone;
626 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hardware");
628 auto storage = INvStorage::newStorage(config.storage);
629 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
630 EXPECT_NO_THROW(sota_client->initialize());
634 Json::Value ecu_data = Utils::parseJSONFile(temp_dir /
"post.json");
635 EXPECT_EQ(ecu_data[
"ecus"].size(), 2);
636 EXPECT_EQ(ecu_data[
"primary_ecu_serial"].asString(), config.provision.primary_ecu_serial);
637 EXPECT_EQ(ecu_data[
"ecus"][1][
"ecu_serial"].asString(),
"secondary_ecu_serial");
638 EXPECT_EQ(ecu_data[
"ecus"][1][
"hardware_identifier"].asString(),
"secondary_hardware");
639 EXPECT_EQ(ecu_data[
"ecus"][1][
"clientKey"][
"keytype"].asString(),
"RSA");
640 EXPECT_TRUE(ecu_data[
"ecus"][1][
"clientKey"][
"keyval"][
"public"].asString().size() > 0);
644 TEST(
Uptane, UptaneSecondaryAddSameSerial) {
646 auto http = std::make_shared<HttpFake>(temp_dir.Path());
647 boost::filesystem::copy_file(
"tests/test_data/cred.zip", temp_dir /
"cred.zip");
648 Config config = config_common();
649 config.provision.provision_path = temp_dir /
"cred.zip";
650 config.provision.mode = ProvisionMode::kSharedCred;
651 config.pacman.type = PackageManager::kNone;
652 config.storage.path = temp_dir.Path();
654 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hardware");
656 auto storage = INvStorage::newStorage(config.storage);
657 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
658 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hardware_new");
659 EXPECT_THROW(sota_client->addNewSecondary(std::make_shared<Primary::VirtualSecondary>(
660 Primary::VirtualSecondaryConfig::create_from_file(config.uptane.secondary_config_file)[0])),
668 TEST(
Uptane, UptaneSecondaryMisconfigured) {
670 boost::filesystem::copy_file(
"tests/test_data/cred.zip", temp_dir /
"cred.zip");
671 auto http = std::make_shared<HttpFake>(temp_dir.Path());
673 Config config = config_common();
674 config.provision.provision_path = temp_dir /
"cred.zip";
675 config.provision.mode = ProvisionMode::kSharedCred;
676 config.pacman.type = PackageManager::kNone;
677 config.storage.path = temp_dir.Path();
678 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hardware");
680 auto storage = INvStorage::newStorage(config.storage);
681 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
682 EXPECT_NO_THROW(sota_client->initialize());
684 std::vector<MisconfiguredEcu> ecus;
685 storage->loadMisconfiguredEcus(&ecus);
686 EXPECT_EQ(ecus.size(), 0);
689 Config config = config_common();
690 config.provision.provision_path = temp_dir /
"cred.zip";
691 config.provision.mode = ProvisionMode::kSharedCred;
692 config.pacman.type = PackageManager::kNone;
693 config.storage.path = temp_dir.Path();
694 auto storage = INvStorage::newStorage(config.storage);
695 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"new_secondary_ecu_serial",
"new_secondary_hardware");
696 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
697 EXPECT_NO_THROW(sota_client->initialize());
699 std::vector<MisconfiguredEcu> ecus;
700 storage->loadMisconfiguredEcus(&ecus);
701 EXPECT_EQ(ecus.size(), 2);
702 if (ecus[0].serial.ToString() ==
"new_secondary_ecu_serial") {
703 EXPECT_EQ(ecus[0].state, EcuState::kNotRegistered);
704 EXPECT_EQ(ecus[1].serial.ToString(),
"secondary_ecu_serial");
705 EXPECT_EQ(ecus[1].state, EcuState::kOld);
706 }
else if (ecus[0].serial.ToString() ==
"secondary_ecu_serial") {
707 EXPECT_EQ(ecus[0].state, EcuState::kOld);
708 EXPECT_EQ(ecus[1].serial.ToString(),
"new_secondary_ecu_serial");
709 EXPECT_EQ(ecus[1].state, EcuState::kNotRegistered);
711 FAIL() <<
"Unexpected secondary serial in storage: " << ecus[0].serial.ToString();
715 Config config = config_common();
716 config.provision.provision_path = temp_dir /
"cred.zip";
717 config.provision.mode = ProvisionMode::kSharedCred;
718 config.pacman.type = PackageManager::kNone;
719 config.storage.path = temp_dir.Path();
720 auto storage = INvStorage::newStorage(config.storage);
721 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hardware");
722 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
723 EXPECT_NO_THROW(sota_client->initialize());
725 std::vector<MisconfiguredEcu> ecus;
726 storage->loadMisconfiguredEcus(&ecus);
727 EXPECT_EQ(ecus.size(), 0);
740 HttpFakeProv(
const boost::filesystem::path &test_dir_in, std::string flavor =
"")
741 :
HttpFake(test_dir_in, std::move(flavor)) {}
743 HttpResponse post(
const std::string &url,
const Json::Value &
data)
override {
744 std::cout <<
"post " << url <<
"\n";
746 if (url.find(
"/devices") != std::string::npos) {
748 EXPECT_EQ(
data[
"deviceId"].asString(),
"tst149_device_id");
749 return HttpResponse(Utils::readFile(
"tests/test_data/cred.p12"), 200, CURLE_OK,
"");
750 }
else if (url.find(
"/director/ecus") != std::string::npos) {
753 EXPECT_EQ(
data[
"primary_ecu_serial"].asString(),
"CA:FE:A6:D2:84:9D");
754 EXPECT_EQ(
data[
"ecus"][0][
"hardware_identifier"].asString(),
"primary_hw");
755 EXPECT_EQ(
data[
"ecus"][0][
"ecu_serial"].asString(),
"CA:FE:A6:D2:84:9D");
756 if (ecus_count == 1) {
759 return HttpResponse(R
"({"code":"ecu_already_registered"})", 409, CURLE_OK, "");
761 }
else if (url.find(
"/events") != std::string::npos) {
762 return handle_event(url,
data);
764 EXPECT_EQ(0, 1) <<
"Unexpected post to URL: " << url;
769 if (
event[
"eventType"][
"id"] ==
"DownloadProgressReport") {
772 const std::string event_type =
event[
"eventType"][
"id"].asString();
773 const std::string serial =
event[
"event"][
"ecu"].asString();
774 std::cout <<
"Got " << event_type <<
" event\n";
776 switch (events_seen) {
778 EXPECT_EQ(event_type,
"SendDeviceDataComplete");
784 if (event_type ==
"EcuDownloadStarted") {
785 if (serial ==
"CA:FE:A6:D2:84:9D") {
786 ++primary_download_start;
787 }
else if (serial ==
"secondary_ecu_serial") {
788 ++secondary_download_start;
790 }
else if (event_type ==
"EcuDownloadCompleted") {
791 if (serial ==
"CA:FE:A6:D2:84:9D") {
792 ++primary_download_complete;
793 }
else if (serial ==
"secondary_ecu_serial") {
794 ++secondary_download_complete;
797 if (events_seen == 4) {
798 EXPECT_EQ(primary_download_start, 1);
799 EXPECT_EQ(primary_download_complete, 1);
800 EXPECT_EQ(secondary_download_start, 1);
801 EXPECT_EQ(secondary_download_complete, 1);
806 EXPECT_EQ(event_type,
"EcuInstallationStarted");
807 EXPECT_EQ(serial,
"CA:FE:A6:D2:84:9D");
811 EXPECT_EQ(event_type,
"EcuInstallationCompleted");
812 EXPECT_EQ(serial,
"CA:FE:A6:D2:84:9D");
816 EXPECT_EQ(event_type,
"EcuInstallationStarted");
817 EXPECT_EQ(serial,
"secondary_ecu_serial");
821 EXPECT_EQ(event_type,
"EcuInstallationCompleted");
822 EXPECT_EQ(serial,
"secondary_ecu_serial");
825 std::cout <<
"Unexpected event: " << event_type;
831 HttpResponse handle_event(
const std::string &url,
const Json::Value &
data)
override {
833 for (
const Json::Value &ev :
data) {
834 handle_event_single(ev);
839 HttpResponse put(
const std::string &url,
const Json::Value &
data)
override {
840 std::cout <<
"put " << url <<
"\n";
841 if (url.find(
"core/installed") != std::string::npos) {
844 EXPECT_EQ(
data.size(), 1);
845 EXPECT_EQ(
data[0][
"name"].asString(),
"fake-package");
846 EXPECT_EQ(
data[0][
"version"].asString(),
"1.0");
847 }
else if (url.find(
"/director/manifest") != std::string::npos) {
852 std::string file_primary;
853 std::string file_secondary;
854 std::string hash_primary;
855 std::string hash_secondary;
856 if (manifest_count <= 2) {
857 file_primary =
"unknown";
858 file_secondary =
"noimage";
860 hash_primary = boost::algorithm::to_lower_copy(boost::algorithm::hex(Crypto::sha256digest(
"")));
861 hash_secondary = boost::algorithm::to_lower_copy(boost::algorithm::hex(Crypto::sha256digest(
"")));
863 file_primary =
"primary_firmware.txt";
864 file_secondary =
"secondary_firmware.txt";
865 const Json::Value json = Utils::parseJSON(Utils::readFile(meta_dir /
"director/targets_hasupdates.json"));
866 const Json::Value targets_list = json[
"signed"][
"targets"];
867 hash_primary = targets_list[
"primary_firmware.txt"][
"hashes"][
"sha256"].asString();
868 hash_secondary = targets_list[
"secondary_firmware.txt"][
"hashes"][
"sha256"].asString();
870 const Json::Value manifest =
data[
"signed"][
"ecu_version_manifests"];
871 const Json::Value manifest_primary = manifest[
"CA:FE:A6:D2:84:9D"][
"signed"][
"installed_image"];
872 const Json::Value manifest_secondary = manifest[
"secondary_ecu_serial"][
"signed"][
"installed_image"];
873 EXPECT_EQ(file_primary, manifest_primary[
"filepath"].asString());
874 EXPECT_EQ(file_secondary, manifest_secondary[
"filepath"].asString());
875 EXPECT_EQ(manifest_primary[
"fileinfo"][
"hashes"][
"sha256"].asString(), hash_primary);
876 EXPECT_EQ(manifest_secondary[
"fileinfo"][
"hashes"][
"sha256"].asString(), hash_secondary);
877 }
else if (url.find(
"/system_info/network") != std::string::npos) {
880 Json::Value nwinfo = Utils::getNetworkInfo();
881 EXPECT_EQ(nwinfo[
"local_ipv4"].asString(),
data[
"local_ipv4"].asString());
882 EXPECT_EQ(nwinfo[
"mac"].asString(),
data[
"mac"].asString());
883 EXPECT_EQ(nwinfo[
"hostname"].asString(),
data[
"hostname"].asString());
884 }
else if (url.find(
"/system_info") != std::string::npos) {
887 Json::Value hwinfo = Utils::getHardwareInfo();
888 EXPECT_EQ(hwinfo[
"id"].asString(),
data[
"id"].asString());
889 EXPECT_EQ(hwinfo[
"description"].asString(),
data[
"description"].asString());
890 EXPECT_EQ(hwinfo[
"class"].asString(),
data[
"class"].asString());
891 EXPECT_EQ(hwinfo[
"product"].asString(),
data[
"product"].asString());
893 EXPECT_EQ(0, 1) <<
"Unexpected put to URL: " << url;
896 return HttpFake::put(url,
data);
899 size_t events_seen{0};
900 int devices_count{0};
902 int manifest_count{0};
903 int installed_count{0};
904 int system_info_count{0};
905 int network_count{0};
908 int primary_download_start{0};
909 int primary_download_complete{0};
910 int secondary_download_start{0};
911 int secondary_download_complete{0};
919 TEST(
Uptane, ProvisionOnServer) {
920 RecordProperty(
"zephyr_key",
"OTA-984,TST-149");
922 Config config(
"tests/config/basic.toml");
923 auto http = std::make_shared<HttpFakeProv>(temp_dir.Path(),
"hasupdates");
924 const std::string &server = http->tls_server;
925 config.provision.server = server;
926 config.tls.server = server;
927 config.uptane.director_server = server +
"/director";
928 config.uptane.repo_server = server +
"/repo";
929 config.provision.ecu_registration_endpoint = server +
"/director/ecus";
930 config.provision.device_id =
"tst149_device_id";
931 config.provision.primary_ecu_serial =
"CA:FE:A6:D2:84:9D";
932 config.provision.primary_ecu_hardware_id =
"primary_hw";
933 config.storage.path = temp_dir.Path();
934 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hw");
936 auto storage = INvStorage::newStorage(config.storage);
937 auto events_channel = std::make_shared<event::Channel>();
938 auto up = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http, events_channel);
940 EXPECT_EQ(http->devices_count, 0);
941 EXPECT_EQ(http->ecus_count, 0);
942 EXPECT_EQ(http->manifest_count, 0);
943 EXPECT_EQ(http->installed_count, 0);
944 EXPECT_EQ(http->system_info_count, 0);
945 EXPECT_EQ(http->network_count, 0);
947 EXPECT_NO_THROW(up->initialize());
949 storage->loadEcuSerials(&serials);
950 EXPECT_EQ(serials[0].second.ToString(),
"primary_hw");
952 EXPECT_EQ(http->devices_count, 1);
953 EXPECT_EQ(http->ecus_count, 1);
955 EXPECT_NO_THROW(up->sendDeviceData());
956 EXPECT_EQ(http->manifest_count, 1);
957 EXPECT_EQ(http->installed_count, 1);
958 EXPECT_EQ(http->system_info_count, 1);
959 EXPECT_EQ(http->network_count, 1);
962 EXPECT_EQ(update_result.status, result::UpdateStatus::kUpdatesAvailable);
963 EXPECT_EQ(http->manifest_count, 2);
966 result::Download download_result = up->downloadImages(update_result.updates);
967 EXPECT_EQ(download_result.status, result::DownloadStatus::kSuccess);
968 result::Install install_result = up->uptaneInstall(download_result.updates);
969 EXPECT_TRUE(install_result.dev_report.isSuccess());
970 EXPECT_EQ(install_result.dev_report.result_code, data::ResultCode::Numeric::kOk);
973 EXPECT_EQ(http->devices_count, 1);
974 EXPECT_EQ(http->ecus_count, 1);
975 EXPECT_EQ(http->manifest_count, 3);
976 EXPECT_EQ(http->installed_count, 1);
977 EXPECT_EQ(http->system_info_count, 1);
978 EXPECT_EQ(http->network_count, 1);
979 EXPECT_EQ(http->events_seen, 8);
983 TEST(
Uptane, FsToSqlFull) {
985 Utils::copyDir(
"tests/test_data/prov", temp_dir.Path());
986 ASSERT_GE(chmod(temp_dir.Path().c_str(), S_IRWXU), 0);
988 config.type = StorageType::kSqlite;
989 config.path = temp_dir.Path();
993 std::string public_key;
994 std::string private_key;
995 fs_storage.loadPrimaryKeys(&public_key, &private_key);
1000 fs_storage.loadTlsCreds(&ca, &cert, &pkey);
1002 std::string device_id;
1003 fs_storage.loadDeviceId(&device_id);
1006 fs_storage.loadEcuSerials(&serials);
1008 bool ecu_registered = fs_storage.loadEcuRegistered();
1010 std::vector<Uptane::Target> fs_installed_versions;
1011 std::vector<Uptane::Target> fixed_installed_versions;
1012 fs_storage.loadInstalledVersions(&fs_installed_versions,
nullptr);
1015 for (
auto &target : fs_installed_versions) {
1016 Json::Value dump = target.toDebugJson();
1017 dump[
"custom"][
"ecuIdentifiers"][serials[0].first.ToString()][
"hardwareId"] = serials[0].second.ToString();
1018 fixed_installed_versions.emplace_back(
Uptane::Target(target.filename(), dump));
1021 std::string director_root;
1022 std::string director_targets;
1023 std::string images_root;
1024 std::string images_targets;
1025 std::string images_timestamp;
1026 std::string images_snapshot;
1028 EXPECT_TRUE(fs_storage.loadLatestRoot(&director_root, Uptane::RepositoryType::Director()));
1029 EXPECT_TRUE(fs_storage.loadNonRoot(&director_targets, Uptane::RepositoryType::Director(), Uptane::Role::Targets()));
1030 EXPECT_TRUE(fs_storage.loadLatestRoot(&images_root, Uptane::RepositoryType::Image()));
1031 EXPECT_TRUE(fs_storage.loadNonRoot(&images_targets, Uptane::RepositoryType::Image(), Uptane::Role::Targets()));
1032 EXPECT_TRUE(fs_storage.loadNonRoot(&images_timestamp, Uptane::RepositoryType::Image(), Uptane::Role::Timestamp()));
1033 EXPECT_TRUE(fs_storage.loadNonRoot(&images_snapshot, Uptane::RepositoryType::Image(), Uptane::Role::Snapshot()));
1035 EXPECT_TRUE(boost::filesystem::exists(config.uptane_public_key_path.get(config.path)));
1036 EXPECT_TRUE(boost::filesystem::exists(config.uptane_private_key_path.get(config.path)));
1037 EXPECT_TRUE(boost::filesystem::exists(config.tls_cacert_path.get(config.path)));
1038 EXPECT_TRUE(boost::filesystem::exists(config.tls_clientcert_path.get(config.path)));
1039 EXPECT_TRUE(boost::filesystem::exists(config.tls_pkey_path.get(config.path)));
1041 boost::filesystem::path image_path = config.uptane_metadata_path.get(config.path) /
"repo";
1042 boost::filesystem::path director_path = config.uptane_metadata_path.get(config.path) /
"director";
1043 EXPECT_TRUE(boost::filesystem::exists(director_path /
"1.root.json"));
1044 EXPECT_TRUE(boost::filesystem::exists(director_path /
"targets.json"));
1045 EXPECT_TRUE(boost::filesystem::exists(image_path /
"1.root.json"));
1046 EXPECT_TRUE(boost::filesystem::exists(image_path /
"targets.json"));
1047 EXPECT_TRUE(boost::filesystem::exists(image_path /
"timestamp.json"));
1048 EXPECT_TRUE(boost::filesystem::exists(image_path /
"snapshot.json"));
1049 EXPECT_TRUE(boost::filesystem::exists(Utils::absolutePath(config.path,
"device_id")));
1050 EXPECT_TRUE(boost::filesystem::exists(Utils::absolutePath(config.path,
"is_registered")));
1051 EXPECT_TRUE(boost::filesystem::exists(Utils::absolutePath(config.path,
"primary_ecu_serial")));
1052 EXPECT_TRUE(boost::filesystem::exists(Utils::absolutePath(config.path,
"primary_ecu_hardware_id")));
1053 EXPECT_TRUE(boost::filesystem::exists(Utils::absolutePath(config.path,
"secondaries_list")));
1054 auto sql_storage = INvStorage::newStorage(config);
1056 EXPECT_FALSE(boost::filesystem::exists(config.uptane_public_key_path.get(config.path)));
1057 EXPECT_FALSE(boost::filesystem::exists(config.uptane_private_key_path.get(config.path)));
1058 EXPECT_FALSE(boost::filesystem::exists(config.tls_cacert_path.get(config.path)));
1059 EXPECT_FALSE(boost::filesystem::exists(config.tls_clientcert_path.get(config.path)));
1060 EXPECT_FALSE(boost::filesystem::exists(config.tls_pkey_path.get(config.path)));
1062 EXPECT_FALSE(boost::filesystem::exists(director_path /
"root.json"));
1063 EXPECT_FALSE(boost::filesystem::exists(director_path /
"targets.json"));
1064 EXPECT_FALSE(boost::filesystem::exists(director_path /
"root.json"));
1065 EXPECT_FALSE(boost::filesystem::exists(director_path /
"targets.json"));
1066 EXPECT_FALSE(boost::filesystem::exists(image_path /
"timestamp.json"));
1067 EXPECT_FALSE(boost::filesystem::exists(image_path /
"snapshot.json"));
1068 EXPECT_FALSE(boost::filesystem::exists(Utils::absolutePath(config.path,
"device_id")));
1069 EXPECT_FALSE(boost::filesystem::exists(Utils::absolutePath(config.path,
"is_registered")));
1070 EXPECT_FALSE(boost::filesystem::exists(Utils::absolutePath(config.path,
"primary_ecu_serial")));
1071 EXPECT_FALSE(boost::filesystem::exists(Utils::absolutePath(config.path,
"primary_ecu_hardware_id")));
1072 EXPECT_FALSE(boost::filesystem::exists(Utils::absolutePath(config.path,
"secondaries_list")));
1074 std::string sql_public_key;
1075 std::string sql_private_key;
1076 sql_storage->loadPrimaryKeys(&sql_public_key, &sql_private_key);
1079 std::string sql_cert;
1080 std::string sql_pkey;
1081 sql_storage->loadTlsCreds(&sql_ca, &sql_cert, &sql_pkey);
1083 std::string sql_device_id;
1084 sql_storage->loadDeviceId(&sql_device_id);
1086 EcuSerials sql_serials;
1087 sql_storage->loadEcuSerials(&sql_serials);
1089 bool sql_ecu_registered = sql_storage->loadEcuRegistered();
1091 std::vector<Uptane::Target> sql_installed_versions;
1092 sql_storage->loadPrimaryInstallationLog(&sql_installed_versions,
true);
1094 std::string sql_director_root;
1095 std::string sql_director_targets;
1096 std::string sql_images_root;
1097 std::string sql_images_targets;
1098 std::string sql_images_timestamp;
1099 std::string sql_images_snapshot;
1101 sql_storage->loadLatestRoot(&sql_director_root, Uptane::RepositoryType::Director());
1102 sql_storage->loadNonRoot(&sql_director_targets, Uptane::RepositoryType::Director(), Uptane::Role::Targets());
1103 sql_storage->loadLatestRoot(&sql_images_root, Uptane::RepositoryType::Image());
1104 sql_storage->loadNonRoot(&sql_images_targets, Uptane::RepositoryType::Image(), Uptane::Role::Targets());
1105 sql_storage->loadNonRoot(&sql_images_timestamp, Uptane::RepositoryType::Image(), Uptane::Role::Timestamp());
1106 sql_storage->loadNonRoot(&sql_images_snapshot, Uptane::RepositoryType::Image(), Uptane::Role::Snapshot());
1108 EXPECT_EQ(sql_public_key, public_key);
1109 EXPECT_EQ(sql_private_key, private_key);
1110 EXPECT_EQ(sql_ca, ca);
1111 EXPECT_EQ(sql_cert, cert);
1112 EXPECT_EQ(sql_pkey, pkey);
1113 EXPECT_EQ(sql_device_id, device_id);
1114 EXPECT_EQ(sql_serials, serials);
1115 EXPECT_EQ(sql_ecu_registered, ecu_registered);
1116 EXPECT_TRUE(Uptane::MatchTargetVector(sql_installed_versions, fixed_installed_versions));
1118 EXPECT_EQ(sql_director_root, director_root);
1119 EXPECT_EQ(sql_director_targets, director_targets);
1120 EXPECT_EQ(sql_images_root, images_root);
1121 EXPECT_EQ(sql_images_targets, images_targets);
1122 EXPECT_EQ(sql_images_timestamp, images_timestamp);
1123 EXPECT_EQ(sql_images_snapshot, images_snapshot);
1127 TEST(
Uptane, InstalledVersionImport) {
1128 Config config = config_common();
1131 Utils::createDirectories(temp_dir /
"import", S_IRWXU);
1132 config.storage.path = temp_dir.Path();
1133 config.import.base_path = temp_dir /
"import";
1134 config.postUpdateValues();
1136 boost::filesystem::copy_file(
"tests/test_data/prov/installed_versions",
1137 temp_dir.Path() /
"import/installed_versions");
1140 auto storage = INvStorage::newStorage(config.storage);
1141 storage->importData(config.import);
1143 boost::optional<Uptane::Target> current_version;
1144 storage->loadPrimaryInstalledVersions(¤t_version,
nullptr);
1145 EXPECT_TRUE(!!current_version);
1146 EXPECT_EQ(current_version->filename(),
"master-863de625f305413dc3be306afab7c3f39d8713045cfff812b3af83f9722851f0");
1150 Json::Value target_json;
1151 target_json[
"hashes"][
"sha256"] =
"a0fb2e119cf812f1aa9e993d01f5f07cb41679096cb4492f1265bff5ac901d0d";
1152 target_json[
"length"] = 123;
1154 storage->savePrimaryInstalledVersion(new_installed_version, InstalledVersionUpdateMode::kCurrent);
1156 auto new_storage = INvStorage::newStorage(config.storage);
1157 new_storage->importData(config.import);
1159 current_version = boost::none;
1160 new_storage->loadPrimaryInstalledVersions(¤t_version,
nullptr);
1161 EXPECT_TRUE(!!current_version);
1162 EXPECT_EQ(current_version->filename(),
"filename");
1166 TEST(
Uptane, SaveAndLoadVersion) {
1168 Config config = config_common();
1169 config.storage.path = temp_dir.Path();
1170 config.provision.device_id =
"device_id";
1171 config.postUpdateValues();
1172 auto storage = INvStorage::newStorage(config.storage);
1174 Json::Value target_json;
1175 target_json[
"hashes"][
"sha256"] =
"a0fb2e119cf812f1aa9e993d01f5f07cb41679096cb4492f1265bff5ac901d0d";
1176 target_json[
"length"] = 123;
1179 storage->savePrimaryInstalledVersion(t, InstalledVersionUpdateMode::kCurrent);
1181 boost::optional<Uptane::Target> current_version;
1182 storage->loadPrimaryInstalledVersions(¤t_version,
nullptr);
1184 EXPECT_TRUE(!!current_version);
1185 EXPECT_EQ(current_version->sha256Hash(),
"a0fb2e119cf812f1aa9e993d01f5f07cb41679096cb4492f1265bff5ac901d0d");
1186 EXPECT_EQ(current_version->length(), 123);
1187 EXPECT_TRUE(current_version->MatchTarget(t));
1193 HttpResponse get(
const std::string &url, int64_t maxsize)
override {
1194 if (unstable_valid_count >= unstable_valid_num) {
1199 if (url.find(
"director/root.json") == std::string::npos) {
1200 ++unstable_valid_count;
1202 return HttpFake::get(url, maxsize);
1206 void setUnstableValidNum(
int num) {
1207 unstable_valid_num = num;
1208 unstable_valid_count = 0;
1211 int unstable_valid_num{0};
1212 int unstable_valid_count{0};
1224 TEST(
Uptane, restoreVerify) {
1226 auto http = std::make_shared<HttpFakeUnstable>(temp_dir.Path());
1227 Config config(
"tests/config/basic.toml");
1228 config.storage.path = temp_dir.Path();
1229 config.pacman.type = PackageManager::kNone;
1230 config.uptane.director_server = http->tls_server +
"director";
1231 config.uptane.repo_server = http->tls_server +
"repo";
1232 config.provision.primary_ecu_serial =
"CA:FE:A6:D2:84:9D";
1233 config.provision.primary_ecu_hardware_id =
"primary_hw";
1234 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hw");
1235 config.postUpdateValues();
1237 auto storage = INvStorage::newStorage(config.storage);
1238 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
1240 EXPECT_NO_THROW(sota_client->initialize());
1241 sota_client->AssembleManifest();
1243 EXPECT_FALSE(sota_client->uptaneIteration(
nullptr,
nullptr));
1244 EXPECT_FALSE(storage->loadLatestRoot(
nullptr, Uptane::RepositoryType::Director()));
1247 http->setUnstableValidNum(1);
1248 EXPECT_FALSE(sota_client->uptaneIteration(
nullptr,
nullptr));
1249 EXPECT_TRUE(storage->loadLatestRoot(
nullptr, Uptane::RepositoryType::Director()));
1250 EXPECT_FALSE(storage->loadNonRoot(
nullptr, Uptane::RepositoryType::Director(), Uptane::Role::Targets()));
1253 http->setUnstableValidNum(2);
1254 EXPECT_FALSE(sota_client->uptaneIteration(
nullptr,
nullptr));
1255 EXPECT_TRUE(storage->loadLatestRoot(
nullptr, Uptane::RepositoryType::Director()));
1256 EXPECT_TRUE(storage->loadNonRoot(
nullptr, Uptane::RepositoryType::Director(), Uptane::Role::Targets()));
1257 EXPECT_FALSE(storage->loadLatestRoot(
nullptr, Uptane::RepositoryType::Image()));
1260 http->setUnstableValidNum(3);
1261 EXPECT_FALSE(sota_client->uptaneIteration(
nullptr,
nullptr));
1262 EXPECT_TRUE(storage->loadLatestRoot(
nullptr, Uptane::RepositoryType::Image()));
1263 EXPECT_FALSE(storage->loadNonRoot(
nullptr, Uptane::RepositoryType::Image(), Uptane::Role::Timestamp()));
1266 http->setUnstableValidNum(4);
1267 EXPECT_FALSE(sota_client->uptaneIteration(
nullptr,
nullptr));
1268 EXPECT_TRUE(storage->loadNonRoot(
nullptr, Uptane::RepositoryType::Image(), Uptane::Role::Timestamp()));
1269 EXPECT_FALSE(storage->loadNonRoot(
nullptr, Uptane::RepositoryType::Image(), Uptane::Role::Snapshot()));
1272 http->setUnstableValidNum(5);
1273 EXPECT_FALSE(sota_client->uptaneIteration(
nullptr,
nullptr));
1274 EXPECT_TRUE(storage->loadNonRoot(
nullptr, Uptane::RepositoryType::Image(), Uptane::Role::Snapshot()));
1275 EXPECT_FALSE(storage->loadNonRoot(
nullptr, Uptane::RepositoryType::Image(), Uptane::Role::Targets()));
1278 http->setUnstableValidNum(6);
1279 EXPECT_TRUE(sota_client->uptaneIteration(
nullptr,
nullptr));
1280 EXPECT_TRUE(storage->loadNonRoot(
nullptr, Uptane::RepositoryType::Image(), Uptane::Role::Targets()));
1288 TEST(
Uptane, offlineIteration) {
1290 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates");
1291 Config config(
"tests/config/basic.toml");
1292 config.storage.path = temp_dir.Path();
1293 config.uptane.director_server = http->tls_server +
"director";
1294 config.uptane.repo_server = http->tls_server +
"repo";
1295 config.pacman.type = PackageManager::kNone;
1296 config.provision.primary_ecu_serial =
"CA:FE:A6:D2:84:9D";
1297 config.provision.primary_ecu_hardware_id =
"primary_hw";
1298 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hw");
1299 config.postUpdateValues();
1301 auto storage = INvStorage::newStorage(config.storage);
1302 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
1303 EXPECT_NO_THROW(sota_client->initialize());
1305 std::vector<Uptane::Target> targets_online;
1306 EXPECT_TRUE(sota_client->uptaneIteration(&targets_online,
nullptr));
1308 std::vector<Uptane::Target> targets_offline;
1309 EXPECT_TRUE(sota_client->uptaneOfflineIteration(&targets_offline,
nullptr));
1310 EXPECT_TRUE(Uptane::MatchTargetVector(targets_online, targets_offline));
1317 TEST(
Uptane, IgnoreUnknownUpdate) {
1319 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates");
1320 Config config(
"tests/config/basic.toml");
1321 config.storage.path = temp_dir.Path();
1322 config.uptane.director_server = http->tls_server +
"director";
1323 config.uptane.repo_server = http->tls_server +
"repo";
1324 config.pacman.type = PackageManager::kNone;
1325 config.provision.primary_ecu_serial =
"primary_ecu";
1326 config.provision.primary_ecu_hardware_id =
"primary_hw";
1327 UptaneTestCommon::addDefaultSecondary(config, temp_dir,
"secondary_ecu_serial",
"secondary_hw");
1328 config.postUpdateValues();
1330 auto storage = INvStorage::newStorage(config.storage);
1331 auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
1333 EXPECT_NO_THROW(sota_client->initialize());
1334 auto result = sota_client->fetchMeta();
1335 EXPECT_EQ(
result.status, result::UpdateStatus::kError);
1336 EXPECT_STREQ(sota_client->getLastException().what(),
1337 "The target had an ECU ID that did not match the client's configured ECU id.");
1339 result = sota_client->checkUpdates();
1340 EXPECT_EQ(
result.status, result::UpdateStatus::kError);
1341 EXPECT_STREQ(sota_client->getLastException().what(),
1342 "The target had an ECU ID that did not match the client's configured ECU id.");
1343 std::vector<Uptane::Target> packages_to_install = UptaneTestCommon::makePackage(
"testecuserial",
"testecuhwid");
1345 auto report = sota_client->uptaneInstall(packages_to_install);
1346 EXPECT_STREQ(sota_client->getLastException().what(),
1347 "The target had an ECU ID that did not match the client's configured ECU id.");
1348 EXPECT_EQ(report.ecu_reports.size(), 0);
1352 TEST(
Uptane, Pkcs11Provision) {
1355 Utils::createDirectories(temp_dir /
"import", S_IRWXU);
1356 boost::filesystem::copy_file(
"tests/test_data/device_cred_prov/ca.pem", temp_dir /
"import/root.crt");
1357 config.tls.cert_source = CryptoSource::kPkcs11;
1358 config.tls.pkey_source = CryptoSource::kPkcs11;
1359 config.p11.module = TEST_PKCS11_MODULE_PATH;
1360 config.p11.pass =
"1234";
1361 config.p11.tls_clientcert_id =
"01";
1362 config.p11.tls_pkey_id =
"02";
1363 config.import.base_path = (temp_dir /
"import").
string();
1364 config.import.tls_cacert_path =
BasedPath(
"root.crt");
1366 config.storage.path = temp_dir.Path();
1367 config.postUpdateValues();
1369 auto storage = INvStorage::newStorage(config.storage);
1370 storage->importData(config.import);
1371 auto http = std::make_shared<HttpFake>(temp_dir.Path(),
"hasupdates");
1372 KeyManager keys(storage, config.keymanagerConfig());
1373 Initializer initializer(config.provision, storage, http, keys, {});
1375 EXPECT_TRUE(initializer.isSuccessful());
1380 int main(
int argc,
char **argv) {
1381 ::testing::InitGoogleTest(&argc, argv);
1384 logger_set_threshold(boost::log::trivial::trace);
1386 return RUN_ALL_TESTS();