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()) {
23 if (config_.mode == ProvisionMode::kSharedCred) {
24 device_id = Utils::genPrettyName();
25 }
else if (config_.mode == ProvisionMode::kDeviceCred) {
26 device_id = keys_.getCN();
28 throw Error(
"Unknown provisioning method");
32 storage_->storeDeviceId(device_id);
35 void Initializer::resetDeviceId() { storage_->clearDeviceId(); }
38 void Initializer::initEcuSerials() {
39 EcuSerials ecu_serials;
43 if (storage_->loadEcuSerials(&ecu_serials)) {
47 std::string primary_ecu_serial_local = config_.primary_ecu_serial;
48 if (primary_ecu_serial_local.empty()) {
49 primary_ecu_serial_local = keys_.UptanePublicKey().KeyId();
52 std::string primary_ecu_hardware_id = config_.primary_ecu_hardware_id;
53 if (primary_ecu_hardware_id.empty()) {
54 primary_ecu_hardware_id = Utils::getHostname();
55 if (primary_ecu_hardware_id ==
"") {
56 throw Error(
"Could not get current host name, please configure an hardware ID explicitely");
63 for (
const auto& s : secondaries_) {
64 ecu_serials.emplace_back(s.first, s.second->getHwId());
67 storage_->storeEcuSerials(ecu_serials);
70 void Initializer::resetEcuSerials() { storage_->clearEcuSerials(); }
73 void Initializer::initPrimaryEcuKeys() {
76 key_pair = keys_.generateUptaneKeyPair();
77 }
catch (
const std::exception& e) {
78 throw KeyGenerationError(e.what());
81 if (key_pair.size() == 0U) {
82 throw KeyGenerationError(
"Unknow error");
86 void Initializer::resetEcuKeys() { storage_->clearPrimaryKeys(); }
88 bool Initializer::loadSetTlsCreds() {
89 keys_.copyCertsToCurl(*http_client_);
94 void Initializer::initTlsCreds() {
95 if (loadSetTlsCreds()) {
99 if (config_.mode != ProvisionMode::kSharedCred) {
100 throw StorageError(
"Shared credentials expected but not found");
107 Bootstrap boot(config_.provision_path, config_.p12_password);
108 http_client_->setCerts(boot.getCa(), CryptoSource::kFile, boot.getCert(), CryptoSource::kFile, boot.getPkey(),
109 CryptoSource::kFile);
112 std::string device_id;
113 if (!storage_->loadDeviceId(&device_id)) {
114 throw StorageError(
"Unable to load device_id during shared credential provisioning");
116 data[
"deviceId"] = device_id;
117 data[
"ttl"] = config_.expiry_days;
118 HttpResponse response = http_client_->post(config_.server +
"/devices", data);
119 if (!response.isOk()) {
120 Json::Value resp_code = response.getJson()[
"code"];
121 if (resp_code.isString() && resp_code.asString() ==
"device_already_registered") {
122 LOG_ERROR <<
"Device ID " << device_id <<
" is already registered.";
123 throw ServerOccupied();
125 const auto err = std::string(
"Shared credential provisioning failed: ") +
126 std::to_string(response.http_status_code) +
" " + response.body;
127 throw ServerError(err);
133 StructGuard<BIO> device_p12(BIO_new_mem_buf(response.body.c_str(),
static_cast<int>(response.body.size())),
135 if (!Crypto::parseP12(device_p12.get(),
"", &pkey, &cert, &ca)) {
136 throw ServerError(
"Received malformed device credentials from the server");
138 storage_->storeTlsCreds(ca, cert, pkey);
141 if (!loadSetTlsCreds()) {
142 throw Error(
"Failed to configure HTTP client with device credentials.");
145 LOG_INFO <<
"Provisioned successfully on Device Gateway.";
148 void Initializer::resetTlsCreds() {
149 if (config_.mode != ProvisionMode::kDeviceCred) {
150 storage_->clearTlsCreds();
155 void Initializer::initEcuRegister() {
156 if (storage_->loadEcuRegistered()) {
160 PublicKey uptane_public_key = keys_.UptanePublicKey();
162 if (uptane_public_key.Type() == KeyType::kUnknown) {
163 throw StorageError(
"Invalid key in storage");
166 EcuSerials ecu_serials;
168 if (!storage_->loadEcuSerials(&ecu_serials) || ecu_serials.size() < 1) {
169 throw StorageError(
"Could not load ECUs from storage");
172 Json::Value all_ecus;
173 all_ecus[
"primary_ecu_serial"] = ecu_serials[0].first.ToString();
174 all_ecus[
"ecus"] = Json::arrayValue;
176 Json::Value primary_ecu;
177 primary_ecu[
"hardware_identifier"] = ecu_serials[0].second.ToString();
178 primary_ecu[
"ecu_serial"] = ecu_serials[0].first.ToString();
179 primary_ecu[
"clientKey"] = keys_.UptanePublicKey().
ToUptane();
180 all_ecus[
"ecus"].append(primary_ecu);
183 for (
const auto& info : sec_info_) {
185 ecu[
"hardware_identifier"] = info.hw_id.ToString();
186 ecu[
"ecu_serial"] = info.serial.ToString();
187 ecu[
"clientKey"] = info.pub_key.ToUptane();
188 all_ecus[
"ecus"].append(ecu);
191 HttpResponse response = http_client_->post(config_.ecu_registration_endpoint, all_ecus);
192 if (!response.isOk()) {
193 Json::Value resp_code = response.getJson()[
"code"];
194 if (resp_code.isString() &&
195 (resp_code.asString() ==
"ecu_already_registered" || resp_code.asString() ==
"device_already_registered")) {
196 throw ServerError(
"One or more ECUs are unexpectedly already registered");
199 std::string(
"Error registering device: ") + std::to_string(response.http_status_code) +
" " + response.body;
200 throw ServerError(err);
203 storage_->storeEcuRegistered();
205 LOG_INFO <<
"ECUs have been successfully registered with the server.";
208 void Initializer::initSecondaryInfo() {
209 for (
const auto& s : secondaries_) {
218 if (!storage_->loadSecondaryInfo(serial, &info) || info.type ==
"" || info.pub_key.Type() == KeyType::kUnknown) {
219 info.serial = serial;
220 info.hw_id = sec.getHwId();
221 info.type = sec.Type();
223 if (p.Type() != KeyType::kUnknown) {
226 storage_->saveSecondaryInfo(info.serial, info.type, info.pub_key);
229 sec_info_.push_back(std::move(info));
233 void Initializer::initEcuReportCounter() {
234 std::vector<std::pair<Uptane::EcuSerial, int64_t>> ecu_cnt;
236 if (storage_->loadEcuReportCounter(&ecu_cnt)) {
240 EcuSerials ecu_serials;
242 if (!storage_->loadEcuSerials(&ecu_serials) || (ecu_serials.size() == 0)) {
243 throw Error(
"Could not load ECU serials");
246 storage_->saveEcuReportCounter(
Uptane::EcuSerial(ecu_serials[0].first.ToString()), 0);
250 Initializer::Initializer(
const ProvisionConfig& config_in, std::shared_ptr<INvStorage> storage_in,
251 std::shared_ptr<HttpInterface> http_client_in,
KeyManager& keys_in,
252 const std::map<
Uptane::EcuSerial, std::shared_ptr<Uptane::SecondaryInterface>>& secondaries_in)
253 : config_(config_in),
254 storage_(
std::move(storage_in)),
255 http_client_(
std::move(http_client_in)),
257 secondaries_(secondaries_in) {
258 for (
int i = 0; i < MaxInitializationAttempts; i++) {
263 }
catch (
const ServerOccupied& e) {
267 LOG_ERROR <<
"Device name is already registered. Retrying.";
271 initPrimaryEcuKeys();
275 initEcuReportCounter();
284 throw Error(std::string(
"Initialization failed after ") + std::to_string(MaxInitializationAttempts) +
" attempts");
Json::Value ToUptane() const
Uptane Json representation of this public key.