Skip to content

Commit e38e9f8

Browse files
authored
add more build switches for TLS (#292)
* add cmake switch MO_BUILD_UNIT_MBEDTLS * fix memory leaks * add MO_ENABLE_CERT_MGMT switch * add .gitignore * update changelog * update changelog * enable Cert Mgmt by default for v2.0.1
1 parent b99f1c2 commit e38e9f8

27 files changed

+242
-88
lines changed

.github/workflows/tests.yml

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ jobs:
1515
steps:
1616
- name: Check out repository code
1717
uses: actions/checkout@v3
18+
- name: Check out MbedTLS
19+
uses: actions/checkout@v3
20+
with:
21+
repository: Mbed-TLS/mbedtls
22+
ref: v2.28.1
23+
path: lib/mbedtls
1824
- name: Get build tools
1925
run: |
2026
sudo apt update
@@ -25,23 +31,21 @@ jobs:
2531
- name: Get ArduinoJson
2632
run: wget -Uri https://github.com/bblanchon/ArduinoJson/releases/download/v6.21.3/ArduinoJson-v6.21.3.h -O ./src/ArduinoJson.h
2733
- name: Generate CMake build files
28-
run: cmake -S . -B ./build
34+
run: cmake -S . -B ./build -DMO_BUILD_UNIT_MBEDTLS=True
2935
- name: Compile
30-
run: cmake --build ./build -j 16 --target mo_unit_tests
36+
run: cmake --build ./build -j 32 --target mo_unit_tests
3137
- name: Configure FS
3238
run: mkdir mo_store
33-
- name: Run tests
34-
run: ./build/mo_unit_tests
3539
- name: Run tests (valgrind)
36-
run: valgrind --error-exitcode=1 --leak-check=full ./build/mo_unit_tests
40+
run: valgrind --error-exitcode=1 --leak-check=full ./build/mo_unit_tests --abort
3741
- name: Generate CMake build files (AddressSanitizer, UndefinedBehaviorSanitizer)
3842
run: |
3943
rm -r ./build
40-
cmake -S . -B ./build -DCMAKE_CXX_FLAGS="-fsanitize=address -fsanitize=undefined" -DCMAKE_EXE_LINKER_FLAGS="-fsanitize=address -fsanitize=undefined"
44+
cmake -S . -B ./build -DCMAKE_CXX_FLAGS="-fsanitize=address -fsanitize=undefined" -DCMAKE_EXE_LINKER_FLAGS="-fsanitize=address -fsanitize=undefined" -DMO_BUILD_UNIT_MBEDTLS=True
4145
- name: Compile (ASan, UBSan)
42-
run: cmake --build ./build -j 16 --target mo_unit_tests
46+
run: cmake --build ./build -j 32 --target mo_unit_tests
4347
- name: Run tests (ASan, UBSan)
44-
run: ./build/mo_unit_tests
48+
run: ./build/mo_unit_tests --abort
4549
- name: Create coverage report
4650
run: |
4751
lcov --directory . --capture --output-file coverage.info

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.pio
2+
build
3+
lib
4+
mo_store
5+
src/ArduinoJson*
6+
src/main.cpp
7+
coverage.info

CHANGELOG.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,22 @@
44

55
### Changed
66

7-
- Replace `PollResult<bool>` with enum `UnlockConnectorResult`
7+
- Replace `PollResult<bool>` with enum `UnlockConnectorResult` ([#271](https://github.com/matth-x/MicroOcpp/pull/271))
88
- Rename master branch into main
99
- Tx logic directly checks if WebSocket is offline ([#282](https://github.com/matth-x/MicroOcpp/pull/282))
10+
- `ocppPermitsCharge` ignores Faulted state ([#279](https://github.com/matth-x/MicroOcpp/pull/279))
1011

1112
### Added
1213

1314
- File index ([#270](https://github.com/matth-x/MicroOcpp/pull/270))
14-
- Config `Cst_TxStartOnPowerPathClosed` to put back TxStartPoint
15+
- Config `Cst_TxStartOnPowerPathClosed` to put back TxStartPoint ([#271](https://github.com/matth-x/MicroOcpp/pull/271))
1516
- Function `bool isConnected()` in `Connection` interface ([#282](https://github.com/matth-x/MicroOcpp/pull/282))
16-
- Build flags for customizing memory limits of SmartCharging
17+
- Build flags for customizing memory limits of SmartCharging ([#260](https://github.com/matth-x/MicroOcpp/pull/260))
1718
- SConscript ([#287](https://github.com/matth-x/MicroOcpp/pull/287))
18-
- Operation GetInstalledCertificateIds, UC M03 ([#262](https://github.com/matth-x/MicroOcpp/pull/262))
19-
- Operation DeleteCertificate, UC M04 ([#262](https://github.com/matth-x/MicroOcpp/pull/262))
20-
- Operation InstallCertificate, UC M05 ([#262](https://github.com/matth-x/MicroOcpp/pull/262))
19+
- Certificate Management, UCs M03 - M05 ([#262](https://github.com/matth-x/MicroOcpp/pull/262), [#274](https://github.com/matth-x/MicroOcpp/pull/274), [#292](https://github.com/matth-x/MicroOcpp/pull/292))
20+
- FTP Client ([#291](https://github.com/matth-x/MicroOcpp/pull/291))
2121
- `ProtocolVersion` selects v1.6 or v2.0.1 ([#247](https://github.com/matth-x/MicroOcpp/pull/247))
22-
- Build flag `MO_ENABLE_V201` set to 1 enables OCPP 2.0.1 features ([#247](https://github.com/matth-x/MicroOcpp/pull/247))
22+
- Build flag `MO_ENABLE_V201=1` enables OCPP 2.0.1 features ([#247](https://github.com/matth-x/MicroOcpp/pull/247))
2323
- Variables (non-persistent), UCs B05 - B07 ([#247](https://github.com/matth-x/MicroOcpp/pull/247), [#284](https://github.com/matth-x/MicroOcpp/pull/284))
2424
- Transactions (preview only), UCs E01 - E12 ([#247](https://github.com/matth-x/MicroOcpp/pull/247))
2525
- StatusNotification compatibility ([#247](https://github.com/matth-x/MicroOcpp/pull/247))
@@ -29,15 +29,15 @@
2929

3030
### Fixed
3131

32-
- Fix defect idTag check in `endTransaction`
32+
- Fix defect idTag check in `endTransaction` ([#275](https://github.com/matth-x/MicroOcpp/pull/275))
3333
- Make field localAuthorizationList in SendLocalList optional
3434
- Update charging profiles when flash disabled (relates to [#260](https://github.com/matth-x/MicroOcpp/pull/260))
35-
- Ignore UnlockConnector when handler not set
36-
- Reject ChargingProfile if unit not supported
35+
- Ignore UnlockConnector when handler not set ([#271](https://github.com/matth-x/MicroOcpp/pull/271))
36+
- Reject ChargingProfile if unit not supported ([#271](https://github.com/matth-x/MicroOcpp/pull/271))
3737
- Fix building with debug level warn and error
3838
- Fix transaction freeze in offline mode ([#279](https://github.com/matth-x/MicroOcpp/pull/279), [#287](https://github.com/matth-x/MicroOcpp/pull/287))
3939
- Fix compilation error caused by `PRId32` ([#279](https://github.com/matth-x/MicroOcpp/pull/279))
40-
- Don't load FW-mngt. module when no handlers set
40+
- Don't load FW-mngt. module when no handlers set ([#271](https://github.com/matth-x/MicroOcpp/pull/271))
4141
- Avoid creating conf when operation fails ([#290](https://github.com/matth-x/MicroOcpp/pull/290))
4242

4343
## [1.0.3] - 2024-04-06

CMakeLists.txt

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ set(MO_SRC_UNIT
147147
tests/LocalAuthList.cpp
148148
tests/Variables.cpp
149149
tests/Transactions.cpp
150-
#tests/Certificates.cpp # add if MbedTLS is available
150+
tests/Certificates.cpp
151151
)
152152

153153
add_executable(mo_unit_tests
@@ -156,13 +156,18 @@ add_executable(mo_unit_tests
156156
./tests/catch2/catchMain.cpp
157157
)
158158

159-
# add MbedTLS for testing (TODO integrate properly into build system)
160-
#add_subdirectory(lib/mbedtls)
161-
#target_link_libraries(mo_unit_tests PUBLIC
162-
# mbedtls
163-
# mbedcrypto
164-
# mbedx509
165-
#)
159+
if (MO_BUILD_UNIT_MBEDTLS)
160+
add_subdirectory(lib/mbedtls)
161+
target_link_libraries(mo_unit_tests PUBLIC
162+
mbedtls
163+
mbedcrypto
164+
mbedx509
165+
)
166+
167+
target_compile_definitions(mo_unit_tests PUBLIC
168+
MO_ENABLE_MBEDTLS=1
169+
)
170+
endif()
166171

167172
target_include_directories(mo_unit_tests PUBLIC
168173
"./tests/catch2"
@@ -181,10 +186,10 @@ target_compile_definitions(mo_unit_tests PUBLIC
181186
MO_LocalAuthListMaxLength=8
182187
MO_SendLocalListMaxLength=4
183188
MO_ENABLE_FILE_INDEX=1
184-
#MO_ENABLE_MBEDTLS=1
185189
MO_ChargeProfileMaxStackLevel=2
186190
MO_ChargingScheduleMaxPeriods=4
187191
MO_MaxChargingProfilesInstalled=3
192+
MO_ENABLE_CERT_MGMT=1
188193
)
189194

190195
target_compile_options(mo_unit_tests PUBLIC

src/MicroOcpp.cpp

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#include <MicroOcpp/Model/Variables/VariableService.h>
2121
#include <MicroOcpp/Model/Transactions/TransactionService.h>
2222
#include <MicroOcpp/Model/Certificates/CertificateService.h>
23-
#include <MicroOcpp/Model/Certificates/CertificateMbedTLS.h> //default CertStore implementation depends on MbedTLS
23+
#include <MicroOcpp/Model/Certificates/CertificateMbedTLS.h>
2424
#include <MicroOcpp/Core/SimpleRequestFactory.h>
2525
#include <MicroOcpp/Core/OperationRegistry.h>
2626
#include <MicroOcpp/Core/FilesystemAdapter.h>
@@ -234,7 +234,7 @@ ChargerCredentials ChargerCredentials::v201(const char *cpModel, const char *cpV
234234
return res;
235235
}
236236

237-
void mocpp_initialize(Connection& connection, const char *bootNotificationCredentials, std::shared_ptr<FilesystemAdapter> fs, bool autoRecover, MicroOcpp::ProtocolVersion version, std::unique_ptr<CertificateStore> certStore) {
237+
void mocpp_initialize(Connection& connection, const char *bootNotificationCredentials, std::shared_ptr<FilesystemAdapter> fs, bool autoRecover, MicroOcpp::ProtocolVersion version) {
238238
if (context) {
239239
MO_DBG_WARN("already initialized. To reinit, call mocpp_deinitialize() before");
240240
return;
@@ -297,6 +297,17 @@ void mocpp_initialize(Connection& connection, const char *bootNotificationCreden
297297
new TransactionService(*context)));
298298
#endif
299299

300+
#if MO_ENABLE_CERT_MGMT && MO_ENABLE_CERT_STORE_MBEDTLS
301+
std::unique_ptr<CertificateStore> certStore = makeCertificateStoreMbedTLS(filesystem);
302+
if (certStore) {
303+
model.setCertificateService(std::unique_ptr<CertificateService>(
304+
new CertificateService(*context)));
305+
}
306+
if (certStore && model.getCertificateService()) {
307+
model.getCertificateService()->setCertificateStore(std::move(certStore));
308+
}
309+
#endif
310+
300311
#if MO_ENABLE_V201
301312
if (version.major == 2) {
302313
//depends on VariableService
@@ -309,21 +320,6 @@ void mocpp_initialize(Connection& connection, const char *bootNotificationCreden
309320
new ResetService(*context)));
310321
}
311322

312-
std::unique_ptr<CertificateStore> certStoreUse;
313-
if (certStore) {
314-
certStoreUse = std::move(certStore);
315-
}
316-
#if MO_ENABLE_MBEDTLS && MO_ENABLE_CERT_STORE_MBEDTLS
317-
else {
318-
certStoreUse = makeCertificateStoreMbedTLS(filesystem);
319-
}
320-
#endif
321-
322-
if (certStoreUse) {
323-
model.setCertificateService(std::unique_ptr<CertificateService>(
324-
new CertificateService(*context, std::move(certStoreUse))));
325-
}
326-
327323
#if MO_PLATFORM == MO_PLATFORM_ARDUINO && !defined(MO_CUSTOM_UPDATER)
328324
#if defined(ESP32) || defined(ESP8266)
329325
model.setFirmwareService(std::unique_ptr<FirmwareService>(
@@ -956,6 +952,28 @@ DiagnosticsService *getDiagnosticsService() {
956952
return model.getDiagnosticsService();
957953
}
958954

955+
#if MO_ENABLE_CERT_MGMT
956+
957+
void setCertificateStore(std::unique_ptr<MicroOcpp::CertificateStore> certStore) {
958+
if (!context) {
959+
MO_DBG_ERR("OCPP uninitialized"); //need to call mocpp_initialize before
960+
return;
961+
}
962+
963+
auto& model = context->getModel();
964+
if (!model.getCertificateService()) {
965+
model.setCertificateService(std::unique_ptr<CertificateService>(
966+
new CertificateService(*context)));
967+
}
968+
if (auto certService = model.getCertificateService()) {
969+
certService->setCertificateStore(std::move(certStore));
970+
} else {
971+
MO_DBG_ERR("OOM");
972+
(void)0;
973+
}
974+
}
975+
#endif //MO_ENABLE_CERT_MGMT
976+
959977
Context *getOcppContext() {
960978
return context;
961979
}

src/MicroOcpp.h

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,7 @@ void mocpp_initialize(
110110
std::shared_ptr<MicroOcpp::FilesystemAdapter> filesystem =
111111
MicroOcpp::makeDefaultFilesystemAdapter(MicroOcpp::FilesystemOpt::Use_Mount_FormatOnFail), //If this library should format the flash if necessary. Find further options in ConfigurationOptions.h
112112
bool autoRecover = false, //automatically sanitize the local data store when the lib detects recurring crashes. Not recommended during development
113-
MicroOcpp::ProtocolVersion version = MicroOcpp::ProtocolVersion(1,6),
114-
std::unique_ptr<MicroOcpp::CertificateStore> certStore = nullptr); //optionally use custom Cert Store (default depends on MbedTLS)
113+
MicroOcpp::ProtocolVersion version = MicroOcpp::ProtocolVersion(1,6));
115114

116115
/*
117116
* Stop the OCPP library and release allocated resources.
@@ -356,6 +355,22 @@ MicroOcpp::FirmwareService *getFirmwareService();
356355
*/
357356
MicroOcpp::DiagnosticsService *getDiagnosticsService();
358357

358+
#if MO_ENABLE_CERT_MGMT
359+
/*
360+
* Set a custom Certificate Store which implements certificate updates on the host system.
361+
* MicroOcpp will forward OCPP-side update requests to the certificate store, as well as
362+
* query the certificate store upon server request.
363+
*
364+
* To enable OCPP-side certificate updates (UCs M03 - M05), set the build flag
365+
* MO_ENABLE_CERT_MGMT=1 so that this function becomes accessible.
366+
*
367+
* To use the built-in certificate store (depends on MbedTLS), set the build flag
368+
* MO_ENABLE_MBEDTLS=1. To not use the built-in implementation, but still enable MbedTLS,
369+
* additionally set MO_ENABLE_CERT_STORE_MBEDTLS=0.
370+
*/
371+
void setCertificateStore(std::unique_ptr<MicroOcpp::CertificateStore> certStore);
372+
#endif //MO_ENABLE_CERT_MGMT
373+
359374
/*
360375
* Add features and customize the behavior of the OCPP client
361376
*/

src/MicroOcpp/Core/FtpMbedTLS.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#if MO_ENABLE_MBEDTLS
88

99
#include <string>
10+
#include <string.h>
1011
#include <functional>
1112

1213
#include "mbedtls/net_sockets.h"

src/MicroOcpp/Model/Certificates/Certificate.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
#include <MicroOcpp/Model/Certificates/Certificate.h>
66

7+
#if MO_ENABLE_CERT_MGMT
8+
79
#include <string.h>
810
#include <stdio.h>
911

@@ -161,3 +163,5 @@ int ocpp_cert_set_serialNumber(ocpp_cert_hash *dst, const char *hex_src) {
161163

162164
return ret;
163165
}
166+
167+
#endif //MO_ENABLE_CERT_MGMT

src/MicroOcpp/Model/Certificates/Certificate.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
#ifndef MO_CERTIFICATE_H
66
#define MO_CERTIFICATE_H
77

8+
#include <MicroOcpp/Version.h>
9+
10+
#if MO_ENABLE_CERT_MGMT
11+
812
#include <stddef.h>
913

1014
#ifdef __cplusplus
@@ -144,6 +148,8 @@ struct CertificateChainHash {
144148
*/
145149
class CertificateStore {
146150
public:
151+
virtual ~CertificateStore() = default;
152+
147153
virtual GetInstalledCertificateStatus getCertificateIds(const std::vector<GetCertificateIdType>& certificateType, std::vector<CertificateChainHash>& out) = 0;
148154
virtual DeleteCertificateStatus deleteCertificate(const CertificateHash& hash) = 0;
149155
virtual InstallCertificateStatus installCertificate(InstallCertificateType certificateType, const char *certificate) = 0;
@@ -152,5 +158,5 @@ class CertificateStore {
152158
} //namespace MicroOcpp
153159

154160
#endif //__cplusplus
155-
161+
#endif //MO_ENABLE_CERT_MGMT
156162
#endif

src/MicroOcpp/Model/Certificates/CertificateMbedTLS.cpp

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
#include <MicroOcpp/Model/Certificates/CertificateMbedTLS.h>
66

7-
#if MO_ENABLE_MBEDTLS && MO_ENABLE_CERT_STORE_MBEDTLS
7+
#if MO_ENABLE_CERT_MGMT && MO_ENABLE_CERT_STORE_MBEDTLS
88

99
#include <string.h>
1010

@@ -15,19 +15,7 @@
1515

1616
#include <MicroOcpp/Debug.h>
1717

18-
bool ocpp_get_cert_hash(const unsigned char *buf, size_t len, HashAlgorithmType hashAlg, ocpp_cert_hash *out) {
19-
20-
mbedtls_x509_crt cacert;
21-
mbedtls_x509_crt_init(&cacert);
22-
23-
int ret;
24-
25-
if((ret = mbedtls_x509_crt_parse(&cacert, buf, len + 1)) < 0) {
26-
char err [100];
27-
mbedtls_strerror(ret, err, 100);
28-
MO_DBG_ERR("mbedtls_x509_crt_parse: %i -- %s", ret, err);
29-
return false;
30-
}
18+
bool ocpp_get_cert_hash(mbedtls_x509_crt& cacert, HashAlgorithmType hashAlg, ocpp_cert_hash *out) {
3119

3220
if (cacert.next) {
3321
MO_DBG_ERR("only sole root certs supported");
@@ -72,6 +60,8 @@ bool ocpp_get_cert_hash(const unsigned char *buf, size_t len, HashAlgorithmType
7260
return false;
7361
}
7462

63+
int ret;
64+
7565
if ((ret = mbedtls_md(md_info, cacert.issuer_raw.p, cacert.issuer_raw.len, out->issuerNameHash))) {
7666
MO_DBG_ERR("mbedtls_md: %i", ret);
7767
return false;
@@ -122,6 +112,26 @@ bool ocpp_get_cert_hash(const unsigned char *buf, size_t len, HashAlgorithmType
122112
return true;
123113
}
124114

115+
bool ocpp_get_cert_hash(const unsigned char *buf, size_t len, HashAlgorithmType hashAlg, ocpp_cert_hash *out) {
116+
117+
mbedtls_x509_crt cacert;
118+
mbedtls_x509_crt_init(&cacert);
119+
120+
bool success = false;
121+
int ret;
122+
123+
if((ret = mbedtls_x509_crt_parse(&cacert, buf, len + 1)) >= 0) {
124+
success = ocpp_get_cert_hash(cacert, hashAlg, out);
125+
} else {
126+
char err [100];
127+
mbedtls_strerror(ret, err, 100);
128+
MO_DBG_ERR("mbedtls_x509_crt_parse: %i -- %s", ret, err);
129+
}
130+
131+
mbedtls_x509_crt_free(&cacert);
132+
return success;
133+
}
134+
125135
namespace MicroOcpp {
126136

127137
class CertificateStoreMbedTLS : public CertificateStore {
@@ -402,4 +412,4 @@ bool printCertFn(const char *certType, size_t index, char *buf, size_t bufsize)
402412

403413
} //namespace MicroOcpp
404414

405-
#endif //MO_ENABLE_MBEDTLS && MO_ENABLE_CERT_STORE_MBEDTLS
415+
#endif //MO_ENABLE_CERT_MGMT && MO_ENABLE_CERT_STORE_MBEDTLS

0 commit comments

Comments
 (0)