1 #include "initializer.h" 5 #include <openssl/x509.h> 6 #include <boost/scoped_array.hpp> 8 #include "bootstrap/bootstrap.h" 9 #include "crypto/keymanager.h" 10 #include "logging/logging.h" 13 bool 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::kAutomatic) {
24 device_id = Utils::genPrettyName();
25 }
else if (config_.mode == ProvisionMode::kImplicit) {
26 device_id = keys_.getCN();
28 LOG_ERROR <<
"Unknown provisioning method";
33 storage_->storeDeviceId(device_id);
36 void Initializer::resetDeviceId() { storage_->clearDeviceId(); }
39 bool Initializer::initEcuSerials() {
40 EcuSerials ecu_serials;
44 if (storage_->loadEcuSerials(&ecu_serials)) {
48 std::string primary_ecu_serial_local = config_.primary_ecu_serial;
49 if (primary_ecu_serial_local.empty()) {
50 primary_ecu_serial_local = keys_.UptanePublicKey().KeyId();
53 std::string primary_ecu_hardware_id = config_.primary_ecu_hardware_id;
54 if (primary_ecu_hardware_id.empty()) {
55 primary_ecu_hardware_id = Utils::getHostname();
56 if (primary_ecu_hardware_id ==
"") {
64 for (
auto it = secondary_info_.begin(); it != secondary_info_.end(); ++it) {
65 ecu_serials.emplace_back(it->second->getSerial(), it->second->getHwId());
68 storage_->storeEcuSerials(ecu_serials);
72 void Initializer::resetEcuSerials() { storage_->clearEcuSerials(); }
75 bool Initializer::initPrimaryEcuKeys() {
return keys_.generateUptaneKeyPair().size() != 0u; }
77 void Initializer::resetEcuKeys() { storage_->clearPrimaryKeys(); }
79 bool Initializer::loadSetTlsCreds() {
80 keys_.copyCertsToCurl(http_client_);
85 InitRetCode Initializer::initTlsCreds() {
86 if (loadSetTlsCreds()) {
87 return InitRetCode::kOk;
90 if (config_.mode != ProvisionMode::kAutomatic) {
91 LOG_ERROR <<
"Credentials not found";
92 return InitRetCode::kStorageFailure;
98 Bootstrap boot(config_.provision_path, config_.p12_password);
99 http_client_->setCerts(boot.getCa(), CryptoSource::kFile, boot.getCert(), CryptoSource::kFile, boot.getPkey(),
100 CryptoSource::kFile);
103 std::string device_id;
104 if (!storage_->loadDeviceId(&device_id)) {
105 LOG_ERROR <<
"device_id unknown during autoprovisioning process";
106 return InitRetCode::kStorageFailure;
108 data[
"deviceId"] = device_id;
109 data[
"ttl"] = config_.expiry_days;
110 HttpResponse response = http_client_->post(config_.server +
"/devices",
data);
111 if (!response.isOk()) {
112 Json::Value resp_code = response.getJson()[
"code"];
113 if (resp_code.isString() && resp_code.asString() ==
"device_already_registered") {
114 LOG_ERROR <<
"Device id" << device_id <<
"is occupied";
115 return InitRetCode::kOccupied;
117 LOG_ERROR <<
"Autoprovisioning failed, response: " << response.body;
118 return InitRetCode::kServerFailure;
124 StructGuard<BIO> device_p12(BIO_new_mem_buf(response.body.c_str(),
static_cast<int>(response.body.size())),
126 if (!Crypto::parseP12(device_p12.get(),
"", &pkey, &cert, &ca)) {
127 LOG_ERROR <<
"Received a malformed P12 package from the server";
128 return InitRetCode::kBadP12;
130 storage_->storeTlsCreds(ca, cert, pkey);
133 if (!loadSetTlsCreds()) {
134 LOG_ERROR <<
"Failed to set provisioned credentials";
135 return InitRetCode::kStorageFailure;
138 LOG_INFO <<
"Provisioned successfully on Device Gateway";
139 return InitRetCode::kOk;
142 void Initializer::resetTlsCreds() {
143 if (config_.mode != ProvisionMode::kImplicit) {
144 storage_->clearTlsCreds();
149 InitRetCode Initializer::initEcuRegister() {
150 if (storage_->loadEcuRegistered()) {
151 return InitRetCode::kOk;
154 PublicKey uptane_public_key = keys_.UptanePublicKey();
156 if (uptane_public_key.Type() == KeyType::kUnknown) {
157 return InitRetCode::kStorageFailure;
160 EcuSerials ecu_serials;
162 if (!storage_->loadEcuSerials(&ecu_serials) || ecu_serials.size() < 1) {
163 return InitRetCode::kStorageFailure;
166 Json::Value all_ecus;
167 all_ecus[
"primary_ecu_serial"] = ecu_serials[0].first.ToString();
168 all_ecus[
"ecus"] = Json::arrayValue;
170 Json::Value primary_ecu;
171 primary_ecu[
"hardware_identifier"] = ecu_serials[0].second.ToString();
172 primary_ecu[
"ecu_serial"] = ecu_serials[0].first.ToString();
173 primary_ecu[
"clientKey"] = keys_.UptanePublicKey().
ToUptane();
174 all_ecus[
"ecus"].append(primary_ecu);
177 for (
auto it = secondary_info_.cbegin(); it != secondary_info_.cend(); it++) {
179 auto public_key = it->second->getPublicKey();
180 ecu[
"hardware_identifier"] = it->second->getHwId().ToString();
181 ecu[
"ecu_serial"] = it->second->getSerial().ToString();
182 ecu[
"clientKey"] = public_key.ToUptane();
183 all_ecus[
"ecus"].append(ecu);
186 HttpResponse response = http_client_->post(config_.ecu_registration_endpoint, all_ecus);
187 if (!response.isOk()) {
188 Json::Value resp_code = response.getJson()[
"code"];
189 if (resp_code.isString() &&
190 (resp_code.asString() ==
"ecu_already_registered" || resp_code.asString() ==
"device_already_registered")) {
191 LOG_ERROR <<
"Some ECU is already registered";
192 return InitRetCode::kOccupied;
194 LOG_ERROR <<
"Error registering device on Uptane, response: " << response.body;
195 return InitRetCode::kServerFailure;
199 LOG_INFO <<
"ECUs have been successfully registered to the server";
200 return InitRetCode::kOk;
204 Initializer::Initializer(
205 const ProvisionConfig& config_in, std::shared_ptr<INvStorage> storage_in,
206 std::shared_ptr<HttpInterface> http_client_in,
KeyManager& keys_in,
207 const std::map<
Uptane::EcuSerial, std::shared_ptr<Uptane::SecondaryInterface> >& secondary_info_in)
208 : config_(config_in),
209 storage_(
std::move(storage_in)),
210 http_client_(
std::move(http_client_in)),
212 secondary_info_(secondary_info_in) {
214 for (
int i = 0; i < MaxInitializationAttempts; i++) {
215 if (!initDeviceId()) {
216 LOG_ERROR <<
"Device ID generation failed, abort initialization";
220 InitRetCode ret_code = initTlsCreds();
223 if (ret_code == InitRetCode::kOccupied) {
225 LOG_INFO <<
"Device name is already registered, restart";
227 }
else if (ret_code == InitRetCode::kStorageFailure) {
228 LOG_ERROR <<
"Error reading existing provisioning data from storage";
230 }
else if (ret_code != InitRetCode::kOk) {
231 LOG_ERROR <<
"Autoprovisioning failed, abort initialization";
235 if (!initPrimaryEcuKeys()) {
236 LOG_ERROR <<
"ECU key generation failed, abort initialization";
239 if (!initEcuSerials()) {
240 LOG_ERROR <<
"ECU serial generation failed, abort initialization";
244 ret_code = initEcuRegister();
247 if (ret_code == InitRetCode::kOccupied) {
248 LOG_INFO <<
"ECU serial is already registered";
249 }
else if (ret_code != InitRetCode::kOk) {
250 LOG_ERROR <<
"ECU registration failed, abort initialization";
255 storage_->storeEcuRegistered();
259 LOG_ERROR <<
"Initialization failed after " << MaxInitializationAttempts <<
" attempts";
Json::Value ToUptane() const
Uptane Json representation of this public key.