Aktualizr
C++ SOTA Client
uptane_key_test.cc
1 #include <gtest/gtest.h>
2 
3 #include <map>
4 #include <memory>
5 #include <string>
6 #include <vector>
7 
8 #include <boost/filesystem.hpp>
9 #include <boost/polymorphic_pointer_cast.hpp>
10 
11 #include "httpfake.h"
12 #include "logging/logging.h"
13 #include "managedsecondary.h"
14 #include "primary/reportqueue.h"
15 #include "primary/sotauptaneclient.h"
16 #include "storage/invstorage.h"
17 #include "uptane/uptanerepository.h"
18 #include "uptane_test_common.h"
19 
20 void initKeyTests(Config& config, Primary::VirtualSecondaryConfig& ecu_config1,
22  const std::string& tls_server) {
23  boost::filesystem::copy_file("tests/test_data/cred.zip", temp_dir / "cred.zip");
24  config.provision.primary_ecu_serial = "testecuserial";
25  config.provision.provision_path = temp_dir / "cred.zip";
26  config.provision.mode = ProvisionMode::kSharedCredReuse;
27  config.tls.server = tls_server;
28  config.uptane.director_server = tls_server + "/director";
29  config.uptane.repo_server = tls_server + "/repo";
30  config.storage.path = temp_dir.Path();
31  config.pacman.type = PACKAGE_MANAGER_NONE;
32 
33  ecu_config1.partial_verifying = false;
34  ecu_config1.full_client_dir = temp_dir.Path();
35  ecu_config1.ecu_serial = "secondary_ecu_serial1";
36  ecu_config1.ecu_hardware_id = "secondary_hardware1";
37  ecu_config1.ecu_private_key = "sec1.priv";
38  ecu_config1.ecu_public_key = "sec1.pub";
39  ecu_config1.firmware_path = temp_dir / "firmware1.txt";
40  ecu_config1.target_name_path = temp_dir / "firmware1_name.txt";
41  ecu_config1.metadata_path = temp_dir / "secondary1_metadata";
42 
43  ecu_config2.partial_verifying = false;
44  ecu_config2.full_client_dir = temp_dir.Path();
45  ecu_config2.ecu_serial = "secondary_ecu_serial2";
46  ecu_config2.ecu_hardware_id = "secondary_hardware2";
47  ecu_config2.ecu_private_key = "sec2.priv";
48  ecu_config2.ecu_public_key = "sec2.pub";
49  ecu_config2.firmware_path = temp_dir / "firmware2.txt";
50  ecu_config2.target_name_path = temp_dir / "firmware2_name.txt";
51  ecu_config2.metadata_path = temp_dir / "secondary2_metadata";
52 }
53 
54 // This is a class solely for the purpose of being a FRIEND_TEST to
55 // SotaUptaneClient. The name is carefully constructed for this purpose.
57  public:
58  static void checkKeyTests(std::shared_ptr<INvStorage>& storage, const SotaUptaneClient& sota_client) {
59  // Verify that TLS credentials are valid.
60  std::string ca;
61  std::string cert;
62  std::string pkey;
63  EXPECT_TRUE(storage->loadTlsCreds(&ca, &cert, &pkey));
64  EXPECT_GT(ca.size(), 0);
65  EXPECT_GT(cert.size(), 0);
66  EXPECT_GT(pkey.size(), 0);
67 
68  // Verify that Primary keys are valid.
69  std::string primary_public;
70  std::string primary_private;
71  EXPECT_TRUE(storage->loadPrimaryKeys(&primary_public, &primary_private));
72  EXPECT_GT(primary_public.size(), 0);
73  EXPECT_GT(primary_private.size(), 0);
74 
75  EcuSerials ecu_serials;
76  EXPECT_TRUE(storage->loadEcuSerials(&ecu_serials));
77  EXPECT_EQ(ecu_serials.size(), 3);
78 
79  std::vector<std::string> public_keys;
80  std::vector<std::string> private_keys;
81  public_keys.push_back(primary_public);
82  private_keys.push_back(primary_private);
83 
84  // Verify that each Secondary has valid keys.
85  for (auto it = sota_client.secondaries.begin(); it != sota_client.secondaries.end(); it++) {
86  std::shared_ptr<Primary::ManagedSecondary> managed =
87  boost::polymorphic_pointer_downcast<Primary::ManagedSecondary>(it->second);
88  std::string public_key;
89  std::string private_key;
90  EXPECT_TRUE(managed->loadKeys(&public_key, &private_key));
91  EXPECT_GT(public_key.size(), 0);
92  EXPECT_GT(private_key.size(), 0);
93  EXPECT_NE(public_key, private_key);
94  public_keys.push_back(public_key);
95  private_keys.push_back(private_key);
96  }
97 
98  // Verify that none of the ECUs have matching keys.
99  std::sort(public_keys.begin(), public_keys.end());
100  EXPECT_EQ(adjacent_find(public_keys.begin(), public_keys.end()), public_keys.end());
101  std::sort(private_keys.begin(), private_keys.end());
102  EXPECT_EQ(adjacent_find(private_keys.begin(), private_keys.end()), private_keys.end());
103  }
104 };
105 
106 /**
107  * Check that all keys are present after successful provisioning.
108  */
109 TEST(UptaneKey, CheckAllKeys) {
110  RecordProperty("zephyr_key", "OTA-987,TST-159");
111  TemporaryDirectory temp_dir;
112  auto http = std::make_shared<HttpFake>(temp_dir.Path());
113  Config config;
116  initKeyTests(config, ecu_config1, ecu_config2, temp_dir, http->tls_server);
117  auto storage = INvStorage::newStorage(config.storage);
118  auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
119  sota_client->addSecondary(std::make_shared<Primary::VirtualSecondary>(ecu_config1));
120  sota_client->addSecondary(std::make_shared<Primary::VirtualSecondary>(ecu_config2));
121  EXPECT_NO_THROW(sota_client->initialize());
122  UptaneKey_Check_Test::checkKeyTests(storage, *sota_client);
123 }
124 
125 /**
126  * Check that aktualizr can recover from a half done device registration.
127  */
128 TEST(UptaneKey, RecoverWithoutKeys) {
129  RecordProperty("zephyr_key", "OTA-987,TST-160");
130  TemporaryDirectory temp_dir;
131  auto http = std::make_shared<HttpFake>(temp_dir.Path());
132  Config config;
135 
136  initKeyTests(config, ecu_config1, ecu_config2, temp_dir, http->tls_server);
137 
138  // Initialize.
139  {
140  auto storage = INvStorage::newStorage(config.storage);
141  auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
142  sota_client->addSecondary(std::make_shared<Primary::VirtualSecondary>(ecu_config1));
143  sota_client->addSecondary(std::make_shared<Primary::VirtualSecondary>(ecu_config2));
144  EXPECT_NO_THROW(sota_client->initialize());
145  UptaneKey_Check_Test::checkKeyTests(storage, *sota_client);
146 
147  // Remove TLS keys but keep ECU keys and try to initialize again.
148  storage->clearTlsCreds();
149  }
150 
151  {
152  auto storage = INvStorage::newStorage(config.storage);
153  auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
154  sota_client->addSecondary(std::make_shared<Primary::VirtualSecondary>(ecu_config1));
155  sota_client->addSecondary(std::make_shared<Primary::VirtualSecondary>(ecu_config2));
156  EXPECT_NO_THROW(sota_client->initialize());
157  UptaneKey_Check_Test::checkKeyTests(storage, *sota_client);
158 
159  // Remove ECU keys but keep TLS keys and try to initialize again.
160  storage->clearPrimaryKeys();
161  }
162 
163  boost::filesystem::remove(ecu_config1.full_client_dir / ecu_config1.ecu_public_key);
164  boost::filesystem::remove(ecu_config1.full_client_dir / ecu_config1.ecu_private_key);
165  boost::filesystem::remove(ecu_config2.full_client_dir / ecu_config2.ecu_public_key);
166  boost::filesystem::remove(ecu_config2.full_client_dir / ecu_config2.ecu_private_key);
167 
168  {
169  auto storage = INvStorage::newStorage(config.storage);
170  auto sota_client = std_::make_unique<UptaneTestCommon::TestUptaneClient>(config, storage, http);
171  sota_client->addSecondary(std::make_shared<Primary::VirtualSecondary>(ecu_config1));
172  sota_client->addSecondary(std::make_shared<Primary::VirtualSecondary>(ecu_config2));
173  EXPECT_NO_THROW(sota_client->initialize());
174  UptaneKey_Check_Test::checkKeyTests(storage, *sota_client);
175  }
176 }
177 
178 #ifndef __NO_MAIN__
179 int main(int argc, char** argv) {
180  ::testing::InitGoogleTest(&argc, argv);
181  logger_set_threshold(boost::log::trivial::trace);
182  return RUN_ALL_TESTS();
183 }
184 #endif
SotaUptaneClient
Definition: sotauptaneclient.h:35
Config
Configuration object for an aktualizr instance running on a Primary ECU.
Definition: config.h:208
Primary::VirtualSecondaryConfig
Definition: virtualsecondary.h:11
TemporaryDirectory
Definition: utils.h:82
UptaneKey_Check_Test
Definition: uptane_key_test.cc:56