Skip to content

Commit 5289da7

Browse files
authored
Merge pull request #522 from pennam/a-ca-rebuild
Allow device certificate update
2 parents c28ca7a + 88aedae commit 5289da7

7 files changed

+265
-269
lines changed

src/ArduinoIoTCloudTCP.cpp

+97-24
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP()
5959
#ifdef BOARD_HAS_SECRET_KEY
6060
, _password("")
6161
#endif
62+
#if defined(BOARD_HAS_SECURE_ELEMENT)
63+
, _writeCertOnConnect(false)
64+
#endif
6265
, _mqttClient{nullptr}
6366
, _messageTopicOut("")
6467
, _messageTopicIn("")
@@ -80,11 +83,6 @@ int ArduinoIoTCloudTCP::begin(ConnectionHandler & connection, bool const enable_
8083
{
8184
_connection = &connection;
8285
_brokerAddress = brokerAddress;
83-
#ifdef BOARD_HAS_SECRET_KEY
84-
_brokerPort = _password.length() ? DEFAULT_BROKER_PORT_USER_PASS_AUTH : brokerPort;
85-
#else
86-
_brokerPort = brokerPort;
87-
#endif
8886

8987
/* Setup broker TLS client */
9088
_brokerClient.begin(connection);
@@ -94,20 +92,7 @@ int ArduinoIoTCloudTCP::begin(ConnectionHandler & connection, bool const enable_
9492
_otaClient.begin(connection);
9593
#endif
9694

97-
/* Setup TimeService */
98-
_time_service.begin(_connection);
99-
100-
/* Setup retry timers */
101-
_connection_attempt.begin(AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms, AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms);
102-
return begin(enable_watchdog, _brokerAddress, _brokerPort);
103-
}
104-
105-
int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, uint16_t brokerPort)
106-
{
107-
_brokerAddress = brokerAddress;
108-
_brokerPort = brokerPort;
109-
110-
#if defined(BOARD_HAS_SECRET_KEY)
95+
#if defined (BOARD_HAS_SECRET_KEY)
11196
/* If board is not configured for username and password login */
11297
if(!_password.length())
11398
{
@@ -129,23 +114,44 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress,
129114
DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not read device id.", __FUNCTION__);
130115
return 0;
131116
}
132-
#if !defined(BOARD_HAS_OFFLOADED_ECCX08)
133-
if (!SElementArduinoCloudCertificate::read(_selement, _cert, SElementArduinoCloudSlot::CompressedCertificate))
134-
{
135-
DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not read device certificate.", __FUNCTION__);
136-
return 0;
117+
if (!_writeCertOnConnect) {
118+
/* No update pending read certificate stored in secure element */
119+
if (!SElementArduinoCloudCertificate::read(_selement, _cert, SElementArduinoCloudSlot::CompressedCertificate))
120+
{
121+
DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not read device certificate.", __FUNCTION__);
122+
return 0;
123+
}
137124
}
125+
#if !defined(BOARD_HAS_OFFLOADED_ECCX08)
138126
_brokerClient.setEccSlot(static_cast<int>(SElementArduinoCloudSlot::Key), _cert.bytes(), _cert.length());
139127
#if OTA_ENABLED
140128
_otaClient.setEccSlot(static_cast<int>(SElementArduinoCloudSlot::Key), _cert.bytes(), _cert.length());
141129
#endif
142130
#endif
131+
_brokerPort = (brokerPort == DEFAULT_BROKER_PORT_AUTO) ? mqttPort() : brokerPort;
143132
#endif
144133

145134
#if defined(BOARD_HAS_SECRET_KEY)
146135
}
136+
else
137+
{
138+
_brokerPort = (brokerPort == DEFAULT_BROKER_PORT_AUTO) ? DEFAULT_BROKER_PORT_USER_PASS_AUTH : brokerPort;
139+
}
147140
#endif
148141

142+
/* Setup TimeService */
143+
_time_service.begin(_connection);
144+
145+
/* Setup retry timers */
146+
_connection_attempt.begin(AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms, AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms);
147+
return begin(enable_watchdog, _brokerAddress, _brokerPort);
148+
}
149+
150+
int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, uint16_t brokerPort)
151+
{
152+
_brokerAddress = brokerAddress;
153+
_brokerPort = brokerPort;
154+
149155
_mqttClient.setClient(_brokerClient);
150156

151157
#ifdef BOARD_HAS_SECRET_KEY
@@ -281,6 +287,17 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker()
281287
/* Subscribe to message topic to receive commands */
282288
_mqttClient.subscribe(_messageTopicIn);
283289

290+
#if defined(BOARD_HAS_SECURE_ELEMENT)
291+
/* A device certificate update was pending */
292+
if (_writeCertOnConnect)
293+
{
294+
if (SElementArduinoCloudCertificate::write(_selement, _cert, SElementArduinoCloudSlot::CompressedCertificate))
295+
{
296+
DEBUG_INFO("ArduinoIoTCloudTCP::%s device certificate update done.", __FUNCTION__);
297+
_writeCertOnConnect = false;
298+
}
299+
}
300+
#endif
284301
DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s connected to %s:%d", __FUNCTION__, _brokerAddress.c_str(), _brokerPort);
285302
return State::Connected;
286303
}
@@ -558,6 +575,62 @@ int ArduinoIoTCloudTCP::write(String const topic, byte const data[], int const l
558575
return 0;
559576
}
560577

578+
#if defined(BOARD_HAS_SECURE_ELEMENT)
579+
int ArduinoIoTCloudTCP::mqttPort()
580+
{
581+
if (memcmp(DEPRECATED_BROKER_AUTHORITY_KEY_IDENTIFIER, _cert.authorityKeyIdentifierBytes() , ECP256_CERT_AUTHORITY_KEY_ID_LENGTH) == 0) {
582+
return DEPRECATED_BROKER_PORT_SECURE_AUTH;
583+
} else {
584+
return DEFAULT_BROKER_PORT_SECURE_AUTH;
585+
}
586+
}
587+
588+
int ArduinoIoTCloudTCP::updateCertificate(String authorityKeyIdentifier, String serialNumber, String notBefore, String notAfter, String signature)
589+
{
590+
if (!_selement.begin())
591+
{
592+
DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not initialize secure element.", __FUNCTION__);
593+
#if defined(ARDUINO_UNOWIFIR4)
594+
if (String(WiFi.firmwareVersion()) < String("0.4.1")) {
595+
DEBUG_ERROR("ArduinoIoTCloudTCP::%s In order to read device certificate, WiFi firmware needs to be >= 0.4.1, current %s", __FUNCTION__, WiFi.firmwareVersion());
596+
}
597+
#endif
598+
return 0;
599+
}
600+
if (!SElementArduinoCloudDeviceId::read(_selement, getDeviceId(), SElementArduinoCloudSlot::DeviceId))
601+
{
602+
DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not read device id.", __FUNCTION__);
603+
return 0;
604+
}
605+
/* read certificate stored in secure element to compare AUTHORITY_KEY_ID */
606+
if (!SElementArduinoCloudCertificate::read(_selement, _cert, SElementArduinoCloudSlot::CompressedCertificate))
607+
{
608+
DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not read device certificate.", __FUNCTION__);
609+
return 0;
610+
}
611+
/* check if we need to update 0 = equal <0 = error skip rebuild */
612+
if(SElementArduinoCloudCertificate::signatureCompare(_cert.signatureBytes(), signature) <= 0) {
613+
DEBUG_INFO("ArduinoIoTCloudTCP::%s request skipped.", __FUNCTION__);
614+
return 0;
615+
}
616+
/* rebuild device certificate */
617+
if (SElementArduinoCloudCertificate::rebuild(_selement, _cert, getDeviceId(), notBefore, notAfter, serialNumber, authorityKeyIdentifier, signature))
618+
{
619+
DEBUG_INFO("ArduinoIoTCloudTCP::%s request started.", __FUNCTION__);
620+
#if defined(BOARD_HAS_OFFLOADED_ECCX08)
621+
if (SElementArduinoCloudCertificate::write(_selement, _cert, SElementArduinoCloudSlot::CompressedCertificate))
622+
{
623+
DEBUG_INFO("ArduinoIoTCloudTCP::%s update done.", __FUNCTION__);
624+
}
625+
#else
626+
_writeCertOnConnect = true;
627+
#endif
628+
return 1;
629+
}
630+
return 0;
631+
}
632+
#endif
633+
561634
/******************************************************************************
562635
* EXTERN DEFINITION
563636
******************************************************************************/

src/ArduinoIoTCloudTCP.h

+24-13
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,14 @@
3131
#if defined(BOARD_HAS_SECURE_ELEMENT)
3232
#include <Arduino_SecureElement.h>
3333
#include <utility/SElementArduinoCloudDeviceId.h>
34-
#if !defined(BOARD_HAS_OFFLOADED_ECCX08)
35-
#include <utility/SElementArduinoCloudCertificate.h>
36-
#endif
34+
#include <utility/SElementArduinoCloudCertificate.h>
3735
#endif
3836

3937
#include <tls/utility/TLSClientMqtt.h>
4038
#include <tls/utility/TLSClientOta.h>
4139

4240
#if OTA_ENABLED
43-
#include <ota/OTA.h>
41+
#include <ota/OTA.h>
4442
#endif
4543

4644
#include "cbor/MessageDecoder.h"
@@ -49,9 +47,14 @@
4947
/******************************************************************************
5048
CONSTANTS
5149
******************************************************************************/
52-
static char const DEFAULT_BROKER_ADDRESS_SECURE_AUTH[] = "iot.arduino.cc";
53-
static uint16_t const DEFAULT_BROKER_PORT_SECURE_AUTH = 8883;
54-
static uint16_t const DEFAULT_BROKER_PORT_USER_PASS_AUTH = 8884;
50+
static constexpr char DEFAULT_BROKER_ADDRESS[] = "iot.arduino.cc";
51+
static constexpr uint16_t DEFAULT_BROKER_PORT_SECURE_AUTH = 8885;
52+
static constexpr uint16_t DEPRECATED_BROKER_PORT_SECURE_AUTH = 8883;
53+
static constexpr uint8_t DEPRECATED_BROKER_AUTHORITY_KEY_IDENTIFIER[] = {
54+
0x5b, 0x3e, 0x2a, 0x6b, 0x8e, 0xc9, 0xb0, 0x1a, 0xa8, 0x54,
55+
0xe6, 0x36, 0x9b, 0x8c, 0x09, 0xf9, 0xfc, 0xe1, 0xb9, 0x80 };
56+
static constexpr uint16_t DEFAULT_BROKER_PORT_USER_PASS_AUTH = 8884;
57+
static constexpr uint16_t DEFAULT_BROKER_PORT_AUTO = 0;
5558

5659
/******************************************************************************
5760
* TYPEDEF
@@ -74,13 +77,17 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass
7477
virtual int connected () override;
7578
virtual void printDebugInfo() override;
7679

77-
int begin(ConnectionHandler & connection, bool const enable_watchdog = true, String brokerAddress = DEFAULT_BROKER_ADDRESS_SECURE_AUTH, uint16_t brokerPort = DEFAULT_BROKER_PORT_SECURE_AUTH);
78-
int begin(bool const enable_watchdog = true, String brokerAddress = DEFAULT_BROKER_ADDRESS_SECURE_AUTH, uint16_t brokerPort = DEFAULT_BROKER_PORT_SECURE_AUTH);
80+
int begin(ConnectionHandler & connection, bool const enable_watchdog = true, String brokerAddress = DEFAULT_BROKER_ADDRESS, uint16_t brokerPort = DEFAULT_BROKER_PORT_AUTO);
81+
int begin(bool const enable_watchdog = true, String brokerAddress = DEFAULT_BROKER_ADDRESS, uint16_t brokerPort = DEFAULT_BROKER_PORT_AUTO);
7982

80-
#ifdef BOARD_HAS_SECRET_KEY
83+
#if defined(BOARD_HAS_SECURE_ELEMENT)
84+
int updateCertificate(String authorityKeyIdentifier, String serialNumber, String notBefore, String notAfter, String signature);
85+
#endif
86+
87+
#ifdef BOARD_HAS_SECRET_KEY
8188
inline void setBoardId (String const device_id) { setDeviceId(device_id); }
8289
inline void setSecretDeviceKey(String const password) { _password = password; }
83-
#endif
90+
#endif
8491

8592
inline String getBrokerAddress() const { return _brokerAddress; }
8693
inline uint16_t getBrokerPort () const { return _brokerPort; }
@@ -142,9 +149,9 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass
142149

143150
#if defined(BOARD_HAS_SECURE_ELEMENT)
144151
SecureElement _selement;
145-
#if !defined(BOARD_HAS_OFFLOADED_ECCX08)
146152
ECP256Certificate _cert;
147-
#endif
153+
/* Flag used to store updated device certificate after broker connection has succeeded */
154+
bool _writeCertOnConnect;
148155
#endif
149156

150157
TLSClientMqtt _brokerClient;
@@ -183,6 +190,10 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass
183190
void detachThing();
184191
int write(String const topic, byte const data[], int const length);
185192

193+
#if defined(BOARD_HAS_SECURE_ELEMENT)
194+
int mqttPort();
195+
#endif
196+
186197
};
187198

188199
/******************************************************************************

src/tls/AIoTCSSCert.h

+27
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
* CONSTANTS
3131
******************************************************************************/
3232
static const char AIoTSSCert[] =
33+
/* https://iot.arduino.cc:8883 */
3334
"-----BEGIN CERTIFICATE-----\n"
3435
"MIIBzzCCAXSgAwIBAgIUHxAd66fhJecnwaOR4+wNF03tSlkwCgYIKoZIzj0EAwIw\n"
3536
"RTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkFyZHVpbm8gTExDIFVTMQswCQYDVQQL\n"
@@ -41,6 +42,32 @@ static const char AIoTSSCert[] =
4142
"VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUWz4qa47JsBqoVOY2m4wJ+fzhuYAwCgYI\n"
4243
"KoZIzj0EAwIDSQAwRgIhAL/T3CNmaLUK3D8NDsNz4grH92CqEA3TIL/hApabawXY\n"
4344
"AiEA6tnZ2lrNElKXCajtZg/hjWRE/+giFzBP8riar8qOz2w=\n"
45+
"-----END CERTIFICATE-----\n"
46+
/* https://iot.arduino.cc:8885 */
47+
"-----BEGIN CERTIFICATE-----\n"
48+
"MIIB0DCCAXagAwIBAgIUb62eK/Vv1baaPAaY5DADBUbxB1owCgYIKoZIzj0EAwIw\n"
49+
"RTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkFyZHVpbm8gTExDIFVTMQswCQYDVQQL\n"
50+
"EwJJVDEQMA4GA1UEAxMHQXJkdWlubzAgFw0yNTAxMTAxMDUzMjJaGA8yMDU1MDEw\n"
51+
"MzEwNTMyMlowRTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkFyZHVpbm8gTExDIFVT\n"
52+
"MQswCQYDVQQLEwJJVDEQMA4GA1UEAxMHQXJkdWlubzBZMBMGByqGSM49AgEGCCqG\n"
53+
"SM49AwEHA0IABKHhU2w1UhozDegrrFsSwY9QN7M+ZJug7icCNceNWhBF0Mr1UuyX\n"
54+
"8pr/gcbieZc/0znG16HMa2GFcPY7rmIdccijQjBAMA8GA1UdEwEB/wQFMAMBAf8w\n"
55+
"DgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRCZSmE0ASI0cYD9AmzeOM7EijgPjAK\n"
56+
"BggqhkjOPQQDAgNIADBFAiEAz6TLYP9eiVOr/cVU/11zwGofe/FoNe4p1BlzMl7G\n"
57+
"VVACIG8tL3Ta2WbIOaUVpBL2gfLuI9WSW1sR++zXP+zFhmen\n"
58+
"-----END CERTIFICATE-----\n"
59+
/* https://iot.oniudra.cc:8885 */
60+
"-----BEGIN CERTIFICATE-----\n"
61+
"MIIBzzCCAXagAwIBAgIUI5fEitwlnwujc/mU0d8LnDiDXBIwCgYIKoZIzj0EAwIw\n"
62+
"RTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkFyZHVpbm8gTExDIFVTMQswCQYDVQQL\n"
63+
"EwJJVDEQMA4GA1UEAxMHQXJkdWlubzAgFw0yNTAxMDgxMTA4MzdaGA8yMDU1MDEw\n"
64+
"MTExMDgzN1owRTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkFyZHVpbm8gTExDIFVT\n"
65+
"MQswCQYDVQQLEwJJVDEQMA4GA1UEAxMHQXJkdWlubzBZMBMGByqGSM49AgEGCCqG\n"
66+
"SM49AwEHA0IABBFwNODDPgC9C1kDmKBbawtQ31FmTudAXVpGSOUwcDX582z820cD\n"
67+
"eIaCwOxghmI+p/CpOH63f5F6h23ErqZMBkijQjBAMA8GA1UdEwEB/wQFMAMBAf8w\n"
68+
"DgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBQdnBmQGLB7ls/r1Tetdp+MVMqxfTAK\n"
69+
"BggqhkjOPQQDAgNHADBEAiBPSZ9HpF7MuFoK4Jsz//PHILQuHM4WmRopQR9ysSs0\n"
70+
"HAIgNadMPgxv01dy59kCgzehgKzmKdTF0rG1SniYqnkLqPA=\n"
4471
"-----END CERTIFICATE-----\n";
4572

4673
#endif /* #if defined(BOARD_HAS_SE050) || defined(BOARD_HAS_SOFTSE) */

0 commit comments

Comments
 (0)