Skip to content

Commit 9e5e8d8

Browse files
committed
firmware-update: Add custom HTTPS certificate support
1 parent 47686dc commit 9e5e8d8

File tree

6 files changed

+45
-11
lines changed

6 files changed

+45
-11
lines changed

software/src/modules/firmware_update/firmware_update.cpp

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,15 @@ extern "C" esp_err_t esp_crt_bundle_attach(void *conf);
3737
#define FIRMWARE_INFO_OFFSET (0xd000 - 0x1000)
3838
#define FIRMWARE_INFO_LENGTH 0x1000
3939

40+
#if !MODULE_CERTS_AVAILABLE()
41+
#define MAX_CERT_ID -1
42+
#endif
43+
4044
void FirmwareUpdate::pre_setup()
4145
{
4246
config = Config::Object({
4347
{"update_url", Config::Str("", 0, 128)},
48+
{"cert_id", Config::Int(-1, -1, MAX_CERT_ID)},
4449
}); // FIXME: add validator to only accept https:// update URLs
4550

4651
available_updates = Config::Object({
@@ -69,6 +74,7 @@ void FirmwareUpdate::setup()
6974
update_url += "_firmware.txt";
7075
}
7176

77+
cert_id = config.get("cert_id")->asInt();
7278
initialized = true;
7379
}
7480

@@ -444,21 +450,42 @@ void FirmwareUpdate::check_for_updates()
444450
update_complete = false;
445451
last_non_beta_timestamp = time(nullptr);
446452

447-
esp_http_client_config_t config;
448-
memset(&config, 0, sizeof(config));
453+
esp_http_client_config_t http_config = {};
454+
455+
http_config.url = update_url.c_str();
456+
http_config.event_handler = update_event_handler;
457+
http_config.user_data = this;
458+
http_config.is_async = true;
459+
460+
size_t cert_len = 0;
461+
462+
if (cert_id < 0) {
463+
http_config.crt_bundle_attach = esp_crt_bundle_attach;
464+
}
465+
else {
466+
#if MODULE_CERTS_AVAILABLE()
467+
cert = certs.get_cert(static_cast<uint8_t>(cert_id), &cert_len);
449468

450-
config.url = update_url.c_str();
451-
// FIXME: allow custom certificate
452-
config.crt_bundle_attach = esp_crt_bundle_attach;
453-
config.transport_type = HTTP_TRANSPORT_OVER_SSL;
454-
config.event_handler = update_event_handler;
455-
config.user_data = this;
456-
config.is_async = true;
469+
if (cert == nullptr) {
470+
logger.printfln("Certificate with ID %d is not available", cert_id);
471+
available_updates.get("error")->updateString("no_cert");
472+
return;
473+
}
474+
475+
http_config.cert_pem = (const char *)cert.get();
476+
#else
477+
// defense in depth: it should not be possible to arrive here because in case
478+
// that the certs module is not available the cert_id should always be -1
479+
logger.printfln("Can't use custom certitifate: certs module is not built into this firmware!");
480+
return;
481+
#endif
482+
}
457483

458-
http_client = esp_http_client_init(&config);
484+
http_client = esp_http_client_init(&http_config);
459485

460486
if (http_client == nullptr) {
461487
logger.printfln("Error while creating HTTP client");
488+
cert.reset();
462489
return;
463490
}
464491

@@ -502,6 +529,7 @@ void FirmwareUpdate::check_for_updates()
502529

503530
esp_http_client_cleanup(http_client);
504531
http_client = nullptr;
532+
cert.reset();
505533

506534
task_scheduler.cancel(task_scheduler.currentTaskId());
507535
}, 100, 100);

software/src/modules/firmware_update/firmware_update.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ class FirmwareUpdate final : public IModule
7575
bool info_found = false;
7676

7777
String update_url;
78+
int cert_id = -1;
79+
std::unique_ptr<unsigned char[]> cert = nullptr;
7880
esp_http_client_handle_t http_client = nullptr;
7981
char update_buf[64 + 1];
8082
size_t update_buf_used;
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
[Dependencies]
2-
Optional = Energy Manager
2+
Optional = Certs
3+
Energy Manager
34
Evse Common

software/web/src/modules/firmware_update/api.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export interface config {
22
update_url: string,
3+
cert_id: number,
34
}
45

56
export interface available_updates {

software/web/src/modules/firmware_update/translation_de.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ let x = {
3535
"wrong_firmware_type": null,
3636
"downgrade": "Firmware-Datei beinhaltet ein Downgrade auf Version %firmware%. Installiert ist Version %installed%.",
3737
"no_update_url": "Kein Aktualisierungs-URL konfiguriert",
38+
"no_cert": "HTTPS-Zertifikat nicht vorhanden",
3839
"download_error": "Fehler beim Download aufgetreten",
3940
"list_malformed": "Aktualisierungsliste ist beschädigt",
4041
"build_time": /*SFN*/ (build_time: string) => ` (erstellt ${build_time})`/*NF*/

software/web/src/modules/firmware_update/translation_en.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ let x = {
3535
"wrong_firmware_type": null,
3636
"downgrade": "Firmware file contains a downgrade to version %firmware%. Installed is version %installed%.",
3737
"no_update_url": "No update URL configured",
38+
"no_cert": "HTTPS certificate not available",
3839
"download_error": "Error occurred during download",
3940
"list_malformed": "Update list is malformed",
4041
"build_time": /*SFN*/ (build_time: string) => ` (created ${build_time})`/*NF*/

0 commit comments

Comments
 (0)