1 #include "initializer.h"
5 #include <openssl/bio.h>
6 #include <boost/scoped_array.hpp>
8 #include "bootstrap/bootstrap.h"
9 #include "crypto/keymanager.h"
10 #include "logging/logging.h"
13 void Initializer::initDeviceId() {
15 std::string device_id;
16 if (storage_->loadDeviceId(&device_id)) {
21 device_id = config_.device_id;
22 if (device_id.empty()) {
25 device_id = keys_.getCN();
26 }
catch (
const std::exception& e) {
29 if (config_.mode == ProvisionMode::kSharedCred || config_.mode == ProvisionMode::kSharedCredReuse) {
30 device_id = Utils::genPrettyName();
31 }
else if (config_.mode == ProvisionMode::kDeviceCred) {
34 throw Error(
"Unknown provisioning method");
39 storage_->storeDeviceId(device_id);
42 void Initializer::resetDeviceId() { storage_->clearDeviceId(); }
45 void Initializer::initEcuSerials() {
46 EcuSerials stored_ecu_serials;
47 storage_->loadEcuSerials(&stored_ecu_serials);
49 std::string primary_ecu_serial_local = config_.primary_ecu_serial;
50 if (primary_ecu_serial_local.empty()) {
51 primary_ecu_serial_local = keys_.UptanePublicKey().KeyId();
54 std::string primary_ecu_hardware_id = config_.primary_ecu_hardware_id;
55 if (primary_ecu_hardware_id.empty()) {
56 primary_ecu_hardware_id = Utils::getHostname();
57 if (primary_ecu_hardware_id.empty()) {
58 throw Error(
"Could not get current host name, please configure an hardware ID explicitly");
64 for (
const auto& s : secondaries_) {
65 new_ecu_serials_.emplace_back(s.first, s.second->getHwId());
68 register_ecus_ = stored_ecu_serials.empty();
69 if (!stored_ecu_serials.empty()) {
72 std::vector<bool> found(stored_ecu_serials.size(),
false);
75 EcuSerials::const_iterator store_it;
76 store_it = std::find_if(stored_ecu_serials.cbegin(), stored_ecu_serials.cend(), primary_comp);
77 if (store_it == stored_ecu_serials.cend()) {
78 LOG_INFO <<
"Configured Primary ECU serial " << new_ecu_serials_[0].first <<
" with hardware ID "
79 << new_ecu_serials_[0].second <<
" not found in storage.";
80 register_ecus_ =
true;
82 found[
static_cast<size_t>(store_it - stored_ecu_serials.cbegin())] =
true;
86 for (
auto it = secondaries_.cbegin(); it != secondaries_.cend(); ++it) {
87 EcuCompare secondary_comp(std::make_pair(it->second->getSerial(), it->second->getHwId()));
88 store_it = std::find_if(stored_ecu_serials.cbegin(), stored_ecu_serials.cend(), secondary_comp);
89 if (store_it == stored_ecu_serials.cend()) {
90 LOG_INFO <<
"Configured Secondary ECU serial " << it->second->getSerial() <<
" with hardware ID "
91 << it->second->getHwId() <<
" not found in storage.";
92 register_ecus_ =
true;
94 found[
static_cast<size_t>(store_it - stored_ecu_serials.cbegin())] =
true;
100 std::vector<bool>::iterator found_it;
101 for (found_it = found.begin(); found_it != found.end(); ++found_it) {
103 auto not_registered = stored_ecu_serials[
static_cast<size_t>(found_it - found.begin())];
104 LOG_INFO <<
"ECU serial " << not_registered.first <<
" with hardware ID " << not_registered.second
105 <<
" in storage was not found in Secondary configuration.";
106 register_ecus_ =
true;
107 storage_->saveMisconfiguredEcu({not_registered.first, not_registered.second, EcuState::kOld});
114 void Initializer::initPrimaryEcuKeys() {
115 std::string key_pair;
117 key_pair = keys_.generateUptaneKeyPair();
118 }
catch (
const std::exception& e) {
119 throw KeyGenerationError(e.what());
122 if (key_pair.empty()) {
123 throw KeyGenerationError(
"Unknow error");
127 bool Initializer::loadSetTlsCreds() {
128 keys_.copyCertsToCurl(*http_client_);
133 void Initializer::initTlsCreds() {
134 if (loadSetTlsCreds()) {
138 if (config_.mode == ProvisionMode::kDeviceCred) {
139 throw StorageError(
"Device credentials expected but not found");
146 Bootstrap boot(config_.provision_path, config_.p12_password);
147 http_client_->setCerts(boot.getCa(), CryptoSource::kFile, boot.getCert(), CryptoSource::kFile, boot.getPkey(),
148 CryptoSource::kFile);
151 std::string device_id;
152 if (!storage_->loadDeviceId(&device_id)) {
153 throw StorageError(
"Unable to load device_id during shared credential provisioning");
155 data[
"deviceId"] = device_id;
156 data[
"ttl"] = config_.expiry_days;
157 HttpResponse response = http_client_->post(config_.server +
"/devices",
data);
158 if (!response.isOk()) {
159 Json::Value resp_code;
161 resp_code = response.getJson()[
"code"];
162 }
catch (
const std::exception& ex) {
163 LOG_ERROR <<
"Unable to parse reponse code from device registration: " << ex.what();
164 throw ServerError(ex.what());
166 if (resp_code.isString() && resp_code.asString() ==
"device_already_registered") {
167 LOG_ERROR <<
"Device ID " << device_id <<
" is already registered.";
168 throw ServerOccupied();
170 const auto err = std::string(
"Shared credential provisioning failed: ") +
171 std::to_string(response.http_status_code) +
" " + response.body;
172 throw ServerError(err);
178 StructGuard<BIO> device_p12(BIO_new_mem_buf(response.body.c_str(),
static_cast<int>(response.body.size())),
180 if (!Crypto::parseP12(device_p12.get(),
"", &pkey, &cert, &ca)) {
181 throw ServerError(
"Received malformed device credentials from the server");
183 storage_->storeTlsCreds(ca, cert, pkey);
186 if (!loadSetTlsCreds()) {
187 throw Error(
"Failed to configure HTTP client with device credentials.");
190 if (config_.mode != ProvisionMode::kSharedCredReuse) {
193 Utils::removeFileFromArchive(config_.provision_path,
"autoprov_credentials.p12");
197 Utils::removeFileFromArchive(config_.provision_path,
"treehub.json");
202 LOG_INFO <<
"Provisioned successfully on Device Gateway.";
205 void Initializer::resetTlsCreds() {
206 if (config_.mode != ProvisionMode::kDeviceCred) {
207 storage_->clearTlsCreds();
212 void Initializer::initEcuRegister() {
214 if (!register_ecus_) {
215 LOG_DEBUG <<
"All ECUs are already registered with the server.";
219 PublicKey uptane_public_key = keys_.UptanePublicKey();
221 if (uptane_public_key.Type() == KeyType::kUnknown) {
222 throw StorageError(
"Invalid key in storage");
225 Json::Value all_ecus;
226 all_ecus[
"primary_ecu_serial"] = new_ecu_serials_[0].first.ToString();
227 all_ecus[
"ecus"] = Json::arrayValue;
229 Json::Value primary_ecu;
230 primary_ecu[
"hardware_identifier"] = new_ecu_serials_[0].second.ToString();
231 primary_ecu[
"ecu_serial"] = new_ecu_serials_[0].first.ToString();
232 primary_ecu[
"clientKey"] = keys_.UptanePublicKey().
ToUptane();
233 all_ecus[
"ecus"].append(primary_ecu);
236 for (
const auto& info : sec_info_) {
238 ecu[
"hardware_identifier"] = info.hw_id.ToString();
239 ecu[
"ecu_serial"] = info.serial.ToString();
240 ecu[
"clientKey"] = info.pub_key.ToUptane();
241 all_ecus[
"ecus"].append(ecu);
244 HttpResponse response = http_client_->post(config_.ecu_registration_endpoint, all_ecus);
245 if (!response.isOk()) {
246 Json::Value resp_code = response.getJson()[
"code"];
247 if (resp_code.isString() &&
248 (resp_code.asString() ==
"ecu_already_registered" || resp_code.asString() ==
"device_already_registered")) {
249 throw ServerError(
"One or more ECUs are unexpectedly already registered");
252 std::string(
"Error registering device: ") + std::to_string(response.http_status_code) +
" " + response.body;
253 throw ServerError(err);
257 storage_->storeEcuSerials(new_ecu_serials_);
258 for (
const auto& info : sec_info_) {
259 storage_->saveSecondaryInfo(info.serial, info.type, info.pub_key);
261 storage_->storeEcuRegistered();
263 LOG_INFO <<
"ECUs have been successfully registered with the server.";
266 void Initializer::initSecondaryInfo() {
267 for (
const auto& s : secondaries_) {
276 if (!storage_->loadSecondaryInfo(serial, &info) || info.type.empty() || info.pub_key.Type() == KeyType::kUnknown) {
277 info.serial = serial;
278 info.hw_id = sec.getHwId();
279 info.type = sec.Type();
281 if (p.Type() != KeyType::kUnknown) {
286 if (!register_ecus_) {
287 storage_->saveSecondaryInfo(info.serial, info.type, info.pub_key);
291 sec_info_.push_back(std::move(info));
295 void Initializer::initEcuReportCounter() {
296 std::vector<std::pair<Uptane::EcuSerial, int64_t>> ecu_cnt;
298 if (storage_->loadEcuReportCounter(&ecu_cnt)) {
302 EcuSerials ecu_serials;
304 if (!storage_->loadEcuSerials(&ecu_serials) || ecu_serials.empty()) {
305 throw Error(
"Could not load ECU serials");
308 storage_->saveEcuReportCounter(
Uptane::EcuSerial(ecu_serials[0].first.ToString()), 0);
312 Initializer::Initializer(
const ProvisionConfig& config_in, std::shared_ptr<INvStorage> storage_in,
313 std::shared_ptr<HttpInterface> http_client_in,
KeyManager& keys_in,
314 const std::map<
Uptane::EcuSerial, std::shared_ptr<SecondaryInterface>>& secondaries_in)
315 : config_(config_in),
316 storage_(std::move(storage_in)),
317 http_client_(std::move(http_client_in)),
319 secondaries_(secondaries_in) {
320 for (
int i = 0; i < MaxInitializationAttempts; i++) {
325 }
catch (
const ServerOccupied& e) {
329 LOG_ERROR <<
"Device name is already registered. Retrying.";
333 initPrimaryEcuKeys();
341 initEcuReportCounter();
346 throw Error(std::string(
"Initialization failed after ") + std::to_string(MaxInitializationAttempts) +
" attempts");