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"
11 #include "storage/invstorage.h"
14 bool Initializer::initDeviceId() {
16 std::string device_id;
17 if (storage_->loadDeviceId(&device_id)) {
22 device_id = config_.device_id;
23 if (device_id.empty()) {
24 if (config_.mode == ProvisionMode::kSharedCred) {
25 device_id = Utils::genPrettyName();
26 }
else if (config_.mode == ProvisionMode::kDeviceCred) {
27 device_id = keys_.getCN();
29 LOG_ERROR <<
"Unknown provisioning method";
34 storage_->storeDeviceId(device_id);
37 void Initializer::resetDeviceId() { storage_->clearDeviceId(); }
40 bool Initializer::initEcuSerials() {
41 EcuSerials ecu_serials;
45 if (storage_->loadEcuSerials(&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 ==
"") {
65 for (
auto it = secondary_info_.begin(); it != secondary_info_.end(); ++it) {
66 ecu_serials.emplace_back(it->second->getSerial(), it->second->getHwId());
69 storage_->storeEcuSerials(ecu_serials);
73 void Initializer::resetEcuSerials() { storage_->clearEcuSerials(); }
76 bool Initializer::initPrimaryEcuKeys() {
return keys_.generateUptaneKeyPair().size() != 0u; }
78 void Initializer::resetEcuKeys() { storage_->clearPrimaryKeys(); }
80 bool Initializer::loadSetTlsCreds() {
81 keys_.copyCertsToCurl(*http_client_);
86 InitRetCode Initializer::initTlsCreds() {
87 if (loadSetTlsCreds()) {
88 return InitRetCode::kOk;
91 if (config_.mode != ProvisionMode::kSharedCred) {
92 LOG_ERROR <<
"Credentials not found";
93 return InitRetCode::kStorageFailure;
100 Bootstrap boot(config_.provision_path, config_.p12_password);
101 http_client_->setCerts(boot.getCa(), CryptoSource::kFile, boot.getCert(), CryptoSource::kFile, boot.getPkey(),
102 CryptoSource::kFile);
105 std::string device_id;
106 if (!storage_->loadDeviceId(&device_id)) {
107 LOG_ERROR <<
"Unknown device_id during shared credential provisioning.";
108 return InitRetCode::kStorageFailure;
110 data[
"deviceId"] = device_id;
111 data[
"ttl"] = config_.expiry_days;
112 HttpResponse response = http_client_->post(config_.server +
"/devices",
data);
113 if (!response.isOk()) {
114 Json::Value resp_code = response.getJson()[
"code"];
115 if (resp_code.isString() && resp_code.asString() ==
"device_already_registered") {
116 LOG_ERROR <<
"Device id" << device_id <<
"is occupied";
117 return InitRetCode::kOccupied;
119 LOG_ERROR <<
"Shared credential provisioning failed, response: " << response.body;
120 return InitRetCode::kServerFailure;
126 StructGuard<BIO> device_p12(BIO_new_mem_buf(response.body.c_str(), static_cast<int>(response.body.size())),
128 if (!Crypto::parseP12(device_p12.get(),
"", &pkey, &cert, &ca)) {
129 LOG_ERROR <<
"Received a malformed P12 package from the server";
130 return InitRetCode::kBadP12;
132 storage_->storeTlsCreds(ca, cert, pkey);
135 if (!loadSetTlsCreds()) {
136 LOG_ERROR <<
"Failed to set provisioned credentials";
137 return InitRetCode::kStorageFailure;
140 LOG_INFO <<
"Provisioned successfully on Device Gateway";
141 return InitRetCode::kOk;
144 void Initializer::resetTlsCreds() {
145 if (config_.mode != ProvisionMode::kDeviceCred) {
146 storage_->clearTlsCreds();
151 InitRetCode Initializer::initEcuRegister() {
152 if (storage_->loadEcuRegistered()) {
153 return InitRetCode::kOk;
156 PublicKey uptane_public_key = keys_.UptanePublicKey();
158 if (uptane_public_key.Type() == KeyType::kUnknown) {
159 return InitRetCode::kStorageFailure;
162 EcuSerials ecu_serials;
164 if (!storage_->loadEcuSerials(&ecu_serials) || ecu_serials.size() < 1) {
165 return InitRetCode::kStorageFailure;
168 Json::Value all_ecus;
169 all_ecus[
"primary_ecu_serial"] = ecu_serials[0].first.ToString();
170 all_ecus[
"ecus"] = Json::arrayValue;
172 Json::Value primary_ecu;
173 primary_ecu[
"hardware_identifier"] = ecu_serials[0].second.ToString();
174 primary_ecu[
"ecu_serial"] = ecu_serials[0].first.ToString();
175 primary_ecu[
"clientKey"] = keys_.UptanePublicKey().
ToUptane();
176 all_ecus[
"ecus"].append(primary_ecu);
179 for (
auto it = secondary_info_.cbegin(); it != secondary_info_.cend(); it++) {
181 auto public_key = it->second->getPublicKey();
182 ecu[
"hardware_identifier"] = it->second->getHwId().ToString();
183 ecu[
"ecu_serial"] = it->second->getSerial().ToString();
184 ecu[
"clientKey"] = public_key.ToUptane();
185 all_ecus[
"ecus"].append(ecu);
188 HttpResponse response = http_client_->post(config_.ecu_registration_endpoint, all_ecus);
189 if (!response.isOk()) {
190 Json::Value resp_code = response.getJson()[
"code"];
191 if (resp_code.isString() &&
192 (resp_code.asString() ==
"ecu_already_registered" || resp_code.asString() ==
"device_already_registered")) {
193 LOG_ERROR <<
"One or more ECUs are unexpectedly already registered.";
194 return InitRetCode::kOccupied;
196 LOG_ERROR <<
"Error registering device on Uptane, response: " << response.body;
197 return InitRetCode::kServerFailure;
201 LOG_INFO <<
"ECUs have been successfully registered to the server.";
202 return InitRetCode::kOk;
205 bool Initializer::initEcuReportCounter() {
206 std::vector<std::pair<Uptane::EcuSerial, int64_t>> ecu_cnt;
208 if (storage_->loadEcuReportCounter(&ecu_cnt)) {
212 EcuSerials ecu_serials;
214 if (!storage_->loadEcuSerials(&ecu_serials) || (ecu_serials.size() == 0)) {
218 storage_->saveEcuReportCounter(
Uptane::EcuSerial(ecu_serials[0].first.ToString()), 0);
223 Initializer::Initializer(
224 const ProvisionConfig& config_in, std::shared_ptr<INvStorage> storage_in,
225 std::shared_ptr<HttpInterface> http_client_in,
KeyManager& keys_in,
226 const std::map<
Uptane::EcuSerial, std::shared_ptr<Uptane::SecondaryInterface>>& secondary_info_in)
227 : config_(config_in),
228 storage_(std::move(storage_in)),
229 http_client_(std::move(http_client_in)),
231 secondary_info_(secondary_info_in) {
233 for (
int i = 0; i < MaxInitializationAttempts; i++) {
234 if (!initDeviceId()) {
235 LOG_ERROR <<
"Device ID generation failed. Aborting initialization.";
239 InitRetCode ret_code = initTlsCreds();
242 if (ret_code == InitRetCode::kOccupied) {
244 LOG_INFO <<
"Device name is already registered. Restarting.";
246 }
else if (ret_code == InitRetCode::kStorageFailure) {
247 LOG_ERROR <<
"Error reading existing provisioning data from storage.";
249 }
else if (ret_code != InitRetCode::kOk) {
250 LOG_ERROR <<
"Shared credential provisioning failed. Aborting initialization.";
254 if (!initPrimaryEcuKeys()) {
255 LOG_ERROR <<
"ECU key generation failed. Aborting initialization.";
258 if (!initEcuSerials()) {
259 LOG_ERROR <<
"ECU serial generation failed. Aborting initialization.";
262 if (!initEcuReportCounter()) {
263 LOG_ERROR <<
"ECU report counter init failed. Aborting initialization.";
267 ret_code = initEcuRegister();
270 if (ret_code == InitRetCode::kOccupied) {
271 LOG_INFO <<
"ECU serial is already registered.";
272 }
else if (ret_code != InitRetCode::kOk) {
273 LOG_ERROR <<
"ECU registration failed. Aborting initialization.";
278 storage_->storeEcuRegistered();
282 LOG_ERROR <<
"Initialization failed after " << MaxInitializationAttempts <<
" attempts.";