Skip to content

Commit cfd9abe

Browse files
committed
MCU8MASS-942 Initial template for MQTT provisioning sketch
1 parent a8ea618 commit cfd9abe

File tree

1 file changed

+367
-0
lines changed

1 file changed

+367
-0
lines changed
Lines changed: 367 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,367 @@
1+
/**
2+
* @brief This provisioning is for using MQTT with TLS and without the ECC. In
3+
* order to start the provisioning, just upload this sketch to the board.
4+
*/
5+
6+
#include "led_ctrl.h"
7+
#include "log.h"
8+
#include "sequans_controller.h"
9+
10+
#define MQTT_TLS (1)
11+
#define MQTT_TLS_PUBLIC_PRIVATE_KEY_PAIR (2)
12+
13+
#define TLS_VERSION_1 (1)
14+
#define TLS_VERSION_1_1 (2)
15+
#define TLS_VERSION_1_2 (3)
16+
#define TLS_VERSION_1_3 (4)
17+
18+
#define AT_SETUP_SECURITY_PROFILE "AT+SQNSPCFG=2,%u,\"%s\",%u,1,,,\"%s\",\"%s\""
19+
#define AT_SETUP_SECURITY_PROFILE_WITH_CERTIFICATES \
20+
"AT+SQNSPCFG=2,%u,\"%s\",%u,1,17,17,\"%s\",\"%s\""
21+
22+
#define AT_WRITE_CERTIFICATE "AT+SQNSVW=\"certificate\",17,%u"
23+
#define AT_WRITE_PRIVATE_KEY "AT+SQNSVW=\"certificate\",17,%u"
24+
25+
#define NUMBER_OF_CIPHERS (64)
26+
#define CIPHER_TEXT_MAX_LENGTH (50)
27+
28+
#define ASCII_ENTER (13)
29+
30+
const char cipher_values[NUMBER_OF_CIPHERS][8] = {
31+
"0x1301;", // TLS_AES_128_GCM_SHA256
32+
"0x1302;", // TLS_AES_256_GCM_SHA384
33+
"0x1303;", // TLS_CHACHA20_POLY1305_SHA256
34+
"0x1304;", // TLS_AES_128_CCM_SHA256
35+
"0x1305;", // TLS_AES_128_CCM_8_SHA256
36+
"0x000A;", // SSL_RSA_WITH_3DES_EDE_CBC_SHA
37+
"0x002F;", // TLS_RSA_WITH_AES_128_CBC_SHA
38+
"0x0035;", // TLS_RSA_WITH_AES_256_CBC_SHA
39+
"0x0033;", // TLS_DHE_RSA_WITH_AES_128_CBC_SHA
40+
"0x0039;", // TLS_DHE_RSA_WITH_AES_256_CBC_SHA
41+
"0x00AB;", // TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
42+
"0x00AA;", // TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
43+
"0x00A9;", // TLS_PSK_WITH_AES_256_GCM_SHA384
44+
"0x00A8;", // TLS_PSK_WITH_AES_128_GCM_SHA256
45+
"0x00B3;", // TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
46+
"0x00B2;", // TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
47+
"0x00AF;", // TLS_PSK_WITH_AES_256_CBC_SHA384
48+
"0x00AE;", // TLS_PSK_WITH_AES_128_CBC_SHA256
49+
"0x008C;", // TLS_PSK_WITH_AES_128_CBC_SHA
50+
"0x008D;", // TLS_PSK_WITH_AES_256_CBC_SHA
51+
"0xC0A6;", // TLS_DHE_PSK_WITH_AES_128_CCM
52+
"0xC0A7;", // TLS_DHE_PSK_WITH_AES_256_CCM
53+
"0xC0A4;", // TLS_PSK_WITH_AES_128_CCM
54+
"0xC0A5;", // TLS_PSK_WITH_AES_256_CCM
55+
"0xC0A8;", // TLS_PSK_WITH_AES_128_CCM_8
56+
"0xC0A9;", // TLS_PSK_WITH_AES_256_CCM_8
57+
"0xC0A0;", // TLS_RSA_WITH_AES_128_CCM_8
58+
"0xC0A1;", // TLS_RSA_WITH_AES_256_CCM_8
59+
"0xC0AC;", // TLS_ECDHE_ECDSA_WITH_AES_128_CCM
60+
"0xC0AE;", // TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
61+
"0xC0AF;", // TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
62+
"0xC014;", // TLS_EDHE_ECDSA_WITH_AES_256_CCM_8
63+
"0xC013;", // TLS_ECCDHE_RSA_WITH_AES_256_CBC_SHA
64+
"0xC009;", // TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
65+
"0xC00A;", // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
66+
"0xC012;", // TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
67+
"0xC008;", // TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
68+
"0x003C;", // TLS_RSA_WITH_AES_128_CBC_SHA256
69+
"0x003D;", // TLS_RSA_WITH_AES_256_CBC_SHA256
70+
"0x0067;", // TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
71+
"0x006B;", // TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
72+
"0x009C;", // TLS_RSA_WITH_AES_128_GCM_SHA256
73+
"0x009D;", // TLS_RSA_WITH_AES_256_GCM_SHA384
74+
"0x009E;", // TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
75+
"0x009F;", // TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
76+
"0xC02F;", // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
77+
"0xC030;", // TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
78+
"0xC02B;", // TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
79+
"0xC02C;", // TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
80+
"0xC027;", // TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
81+
"0xC023;", // TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
82+
"0xC028;", // TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
83+
"0xC024;", // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
84+
"0xCCA8;", // TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
85+
"0xCCA9;", // TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
86+
"0xCCAA;", // TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
87+
"0xCC13;", // TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
88+
"0xCC14;", // TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256
89+
"0xCC15;", // TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
90+
"0xC037;", // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
91+
"0xCCAB;", // TLS_PSK_WITH_CHACHA20_POLY1305_SHA256
92+
"0xCCAC;", // TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256
93+
"0xCCAD;", // TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256
94+
"0x0016;", // TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
95+
};
96+
97+
const char cipher_text_values[NUMBER_OF_CIPHERS][CIPHER_TEXT_MAX_LENGTH] = {
98+
"TLS_AES_128_GCM_SHA256",
99+
"TLS_AES_256_GCM_SHA384",
100+
"TLS_CHACHA20_POLY1305_SHA256",
101+
"TLS_AES_128_CCM_SHA256",
102+
"TLS_AES_128_CCM_8_SHA256",
103+
"SSL_RSA_WITH_3DES_EDE_CBC_SHA",
104+
"TLS_RSA_WITH_AES_128_CBC_SHA",
105+
"TLS_RSA_WITH_AES_256_CBC_SHA",
106+
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
107+
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
108+
"TLS_DHE_PSK_WITH_AES_256_GCM_SHA384",
109+
"TLS_DHE_PSK_WITH_AES_128_GCM_SHA256",
110+
"TLS_PSK_WITH_AES_256_GCM_SHA384",
111+
"TLS_PSK_WITH_AES_128_GCM_SHA256",
112+
"TLS_DHE_PSK_WITH_AES_256_CBC_SHA384",
113+
"TLS_DHE_PSK_WITH_AES_128_CBC_SHA256",
114+
"TLS_PSK_WITH_AES_256_CBC_SHA384",
115+
"TLS_PSK_WITH_AES_128_CBC_SHA256",
116+
"TLS_PSK_WITH_AES_128_CBC_SHA",
117+
"TLS_PSK_WITH_AES_256_CBC_SHA",
118+
"TLS_DHE_PSK_WITH_AES_128_CCM",
119+
"TLS_DHE_PSK_WITH_AES_256_CCM",
120+
"TLS_PSK_WITH_AES_128_CCM",
121+
"TLS_PSK_WITH_AES_256_CCM",
122+
"TLS_PSK_WITH_AES_128_CCM_8",
123+
"TLS_PSK_WITH_AES_256_CCM_8",
124+
"TLS_RSA_WITH_AES_128_CCM_8",
125+
"TLS_RSA_WITH_AES_256_CCM_8",
126+
"TLS_ECDHE_ECDSA_WITH_AES_128_CCM",
127+
"TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8",
128+
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
129+
"TLS_EDHE_ECDSA_WITH_AES_256_CCM_8",
130+
"TLS_ECCDHE_RSA_WITH_AES_256_CBC_SHA",
131+
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
132+
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
133+
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
134+
"TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
135+
"TLS_RSA_WITH_AES_128_CBC_SHA256",
136+
"TLS_RSA_WITH_AES_256_CBC_SHA256",
137+
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
138+
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
139+
"TLS_RSA_WITH_AES_128_GCM_SHA256",
140+
"TLS_RSA_WITH_AES_256_GCM_SHA384",
141+
"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
142+
"TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
143+
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
144+
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
145+
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
146+
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
147+
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
148+
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
149+
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
150+
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
151+
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
152+
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
153+
"TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
154+
"TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256",
155+
"TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256",
156+
"TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256",
157+
"TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256",
158+
"TLS_PSK_WITH_CHACHA20_POLY1305_SHA256",
159+
"TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256",
160+
"TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256",
161+
"TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA"};
162+
163+
// TODO: Would be nice to get this to work with the ECC as well...
164+
165+
/*
166+
* Flow
167+
*
168+
* 1. Choose authentication method
169+
* 2. Choose the TLS version
170+
* 3. Choose ciphers
171+
* -> If PSK cipher is used, ask about PSK and PSK identity
172+
* 4. Choose whether to verify the domain using a certificate authority (CA).
173+
* -> Ask if a custom CA should be loaded
174+
* 5. If public private key pair is utilized, fill in the certificates which
175+
* will be written to the device.
176+
*/
177+
178+
void setup() {
179+
LedCtrl.begin();
180+
LedCtrl.startupCycle();
181+
182+
Serial3.begin(115200);
183+
Serial3.setTimeout(120000);
184+
185+
SequansController.begin();
186+
187+
Serial3.println("=== MQTT provisioning for TLS ===");
188+
189+
uint8_t method = 0;
190+
191+
// Choosing authentication method
192+
while (true) {
193+
Serial3.println("\r\nWhich method do you want to use?");
194+
Serial3.println(
195+
"1: MQTT TLS unauthenticated or with username and password");
196+
Serial3.println(
197+
"2: MQTT TLS with public and private key pair certificates");
198+
Serial3.print("Please choose: ");
199+
200+
while (Serial3.available() == 0) {}
201+
202+
method = Serial3.read();
203+
Serial3.print((char)method);
204+
205+
// Convert to number
206+
method = method - '0';
207+
208+
if (method != MQTT_TLS && method != MQTT_TLS_PUBLIC_PRIVATE_KEY_PAIR) {
209+
Serial3.println("\r\nUnknown method chosen");
210+
} else {
211+
break;
212+
}
213+
}
214+
215+
Serial3.println();
216+
217+
bool has_chosen_ciphers = false;
218+
219+
// Choosing ciphers
220+
while (!has_chosen_ciphers) {
221+
Serial3.println(
222+
"\r\nWhich cipher(s) do you want to use? Leave blank for the "
223+
"cipher to be chosen automatically. Select "
224+
"multiple ciphers by comma between the indices (e.g. 1,2,3 for "
225+
"the first three ciphers)");
226+
227+
char line[164] = "";
228+
229+
for (uint8_t i = 0; i < NUMBER_OF_CIPHERS / 2; i++) {
230+
231+
sprintf(line,
232+
"%2d: %-52s %2d: %-52s",
233+
i + 1,
234+
cipher_text_values[i],
235+
NUMBER_OF_CIPHERS / 2 + i + 1,
236+
cipher_text_values[NUMBER_OF_CIPHERS / 2 + i]);
237+
238+
Serial3.println(line);
239+
}
240+
241+
Serial3.print("Please choose. Press enter when done: ");
242+
243+
char cipher_input[128] = "";
244+
size_t index = 0;
245+
246+
while (true) {
247+
if (Serial3.available()) {
248+
char input = Serial3.read();
249+
250+
if ((uint8_t)input == ASCII_ENTER) {
251+
break;
252+
}
253+
254+
cipher_input[index++] = input;
255+
256+
Serial3.print(input);
257+
}
258+
}
259+
260+
// Check input
261+
has_chosen_ciphers = true;
262+
263+
Serial3.println();
264+
265+
Serial3.print("Ciphers chosen: ");
266+
Serial3.println(cipher_input);
267+
}
268+
269+
while (1) {}
270+
271+
/*
272+
273+
// Constructing the ciphers from the ones uncommented (if any)
274+
char ciphers_used[576] = "";
275+
276+
// TODO: test with only one, two and all
277+
if (sizeof(ciphers) > 0) {
278+
char* cipher_used_ptr = ciphers_used;
279+
280+
for (size_t i = 0; i < sizeof(ciphers) / sizeof(ciphers[0]); i++) {
281+
282+
// Not all ciphers have equal length, so we calculate this here, but
283+
// each entry has the same amount of allocated space for it in the
284+
// ciphers array
285+
const size_t cipher_size = strlen(ciphers[i]);
286+
memcpy(cipher_used_ptr, ciphers[i], cipher_size);
287+
cipher_used_ptr += cipher_size;
288+
}
289+
290+
// Remove the last semi-colon
291+
*(cipher_used_ptr - 1) = '\0';
292+
}
293+
294+
char command_buffer[712] = "";
295+
296+
switch (AUTHENTICATION_METHOD) {
297+
298+
// Same provisioning for unauthenticated and username+password as the
299+
// username and password is provided when the MQTT client is configured
300+
case MQTT_TLS_UNAUTHENTICATED:
301+
case MQTT_TLS_USERNAME_PASSWORD:
302+
sprintf(command_buffer,
303+
AT_SETUP_SECURITY_PROFILE,
304+
TLS_VERSION,
305+
ciphers_used,
306+
USE_CA ? 1 : 0,
307+
pre_shared_key,
308+
pre_shared_key_identifier);
309+
310+
Log.infof("Sending command: %s\r\n", command_buffer);
311+
SequansController.writeBytes((uint8_t*)command_buffer,
312+
strlen(command_buffer),
313+
true);
314+
break;
315+
316+
case MQTT_TLS_PUBLIC_PRIVATE_KEY_PAIR:
317+
318+
// Write certificate and private key first before setting the security
319+
// profile
320+
char certificate_command[64] = "";
321+
322+
const size_t certificate_length = strlen(client_certificate);
323+
sprintf(certificate_command, AT_WRITE_CERTIFICATE, certificate_length);
324+
325+
SequansController.writeBytes((uint8_t*)certificate_command,
326+
strlen(certificate_command),
327+
true);
328+
329+
// TODO: figure out which slots to use
330+
sprintf(command_buffer,
331+
AT_SETUP_SECURITY_PROFILE_WITH_CERTIFICATES,
332+
TLS_VERSION,
333+
ciphers_used,
334+
USE_CA ? 1 : 0,
335+
pre_shared_key,
336+
pre_shared_key_identifier);
337+
338+
break;
339+
340+
default:
341+
342+
Log.error("Unknown authentication method provided! Choose one of the "
343+
"MQTT_TLS defines.");
344+
345+
while (1) {}
346+
break;
347+
}
348+
349+
char buffer[128] = "";
350+
351+
if (!SequansController.waitForURC("SQNSPCFG",
352+
buffer,
353+
sizeof(buffer),
354+
4000)) {
355+
Log.infof("Failed to set security profile\r\n");
356+
return;
357+
}
358+
359+
Log.infof("Result: %s\r\n", buffer);
360+
361+
Log.info("Done!");
362+
363+
SequansController.end();
364+
*/
365+
}
366+
367+
void loop() {}

0 commit comments

Comments
 (0)