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\n Which 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\n Unknown 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\n Which 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