1
1
#ifdef COMPILE_L_BAND
2
2
3
+ #include " mbedtls/ssl.h" // Needed for certificate validation
4
+
3
5
// ----------------------------------------
4
6
// Locals - compiled out
5
7
// ----------------------------------------
@@ -12,7 +14,7 @@ static SFE_UBLOX_GNSS_SUPER i2cLBand; // NEO-D9S
12
14
#ifndef POINTPERFECT_TOKEN
13
15
#define POINTPERFECT_TOKEN \
14
16
0xAA , 0xBB , 0xCC , 0xDD , 0x00 , 0x11 , 0x22 , 0x33 , 0x0A , 0x0B , 0x0C , 0x0D , 0x00 , 0x01 , 0x02 , 0x03
15
- #endif // POINTPERFECT_TOKEN
17
+ #endif // POINTPERFECT_TOKEN
16
18
17
19
static uint8_t pointPerfectTokenArray[16 ] = {POINTPERFECT_TOKEN}; // Token in HEX form
18
20
@@ -196,7 +198,7 @@ bool pointperfectProvisionDevice()
196
198
// Override ID with testing ID
197
199
snprintf (hardwareID, sizeof (hardwareID), " %02X%02X%02X%02X%02X%02X" , whitelistID[0 ], whitelistID[1 ],
198
200
whitelistID[2 ], whitelistID[3 ], whitelistID[4 ], whitelistID[5 ]);
199
- #endif // WHITELISTED_ID
201
+ #endif // WHITELISTED_ID
200
202
201
203
char givenName[100 ];
202
204
snprintf (givenName, sizeof (givenName), " SparkFun RTK %s v%d.%d - %s" , platformPrefix, FIRMWARE_VERSION_MAJOR,
@@ -317,9 +319,94 @@ bool pointperfectProvisionDevice()
317
319
bluetoothStart ();
318
320
319
321
return (retVal);
320
- #else // COMPILE_WIFI
322
+ #else // COMPILE_WIFI
321
323
return (false );
322
- #endif // COMPILE_WIFI
324
+ #endif // COMPILE_WIFI
325
+ }
326
+
327
+ // Check certificate and privatekey for valid formatting
328
+ // Return false if improperly formatted
329
+ bool checkCertificates ()
330
+ {
331
+ bool validCertificates = true ;
332
+ char *certificateContents = nullptr ; // Holds the contents of the keys prior to MQTT connection
333
+ char *keyContents = nullptr ;
334
+
335
+ // Allocate the buffers
336
+ certificateContents = (char *)malloc (MQTT_CERT_SIZE);
337
+ keyContents = (char *)malloc (MQTT_CERT_SIZE);
338
+ if ((!certificateContents) || (!keyContents))
339
+ {
340
+ systemPrintln (" Failed to allocate content buffers!" );
341
+ return (false );
342
+ }
343
+
344
+ // Load the certificate
345
+ memset (certificateContents, 0 , MQTT_CERT_SIZE);
346
+ loadFile (" certificate" , certificateContents);
347
+
348
+ if (checkCertificateValidity (certificateContents, strlen (certificateContents)) == false )
349
+ {
350
+ log_d (" Certificate is corrupt." );
351
+ validCertificates = false ;
352
+ }
353
+
354
+ // Load the private key
355
+ memset (keyContents, 0 , MQTT_CERT_SIZE);
356
+ loadFile (" privateKey" , keyContents);
357
+
358
+ if (checkCertificateValidity (keyContents, strlen (keyContents)) == false )
359
+ {
360
+ log_d (" PrivateKey is corrupt." );
361
+ validCertificates = false ;
362
+ }
363
+
364
+ // Free the content buffers
365
+ if (certificateContents)
366
+ free (certificateContents);
367
+ if (keyContents)
368
+ free (keyContents);
369
+
370
+ return (validCertificates);
371
+ }
372
+
373
+ // Check if a given certificate is in a valid format
374
+ // This was created to detect corrupt or invalid certificates caused by bugs in v3.0 to and including v3.3.
375
+ bool checkCertificateValidity (char *certificateContent, int certificateContentSize)
376
+ {
377
+ // Check for valid format of certificate
378
+ // From ssl_client.cpp
379
+ // https://stackoverflow.com/questions/70670070/mbedtls-cannot-parse-valid-x509-certificate
380
+ mbedtls_x509_crt certificate;
381
+ mbedtls_x509_crt_init (&certificate);
382
+
383
+ int result_code =
384
+ mbedtls_x509_crt_parse (&certificate, (unsigned char *)certificateContent, certificateContentSize + 1 );
385
+
386
+ mbedtls_x509_crt_free (&certificate);
387
+
388
+ if (result_code < 0 )
389
+ {
390
+ log_d (" Cert formatting invalid" );
391
+ return (false );
392
+ }
393
+
394
+ return (true );
395
+ }
396
+
397
+ // When called, removes the files used for SSL to PointPerfect obtained during provisioning
398
+ // Also deletes keys so the user can immediately re-provision
399
+ void erasePointperfectCredentials ()
400
+ {
401
+ char fileName[80 ];
402
+
403
+ snprintf (fileName, sizeof (fileName), " /%s_%s_%d.txt" , platformFilePrefix, " certificate" , profileNumber);
404
+ LittleFS.remove (fileName);
405
+
406
+ snprintf (fileName, sizeof (fileName), " /%s_%s_%d.txt" , platformFilePrefix, " privateKey" , profileNumber);
407
+ LittleFS.remove (fileName);
408
+ strcpy (settings.pointPerfectCurrentKey , " " ); // Clear contents
409
+ strcpy (settings.pointPerfectNextKey , " " ); // Clear contents
323
410
}
324
411
325
412
// Subscribe to MQTT channel, grab keys, then stop
@@ -445,9 +532,9 @@ bool pointperfectUpdateKeys()
445
532
446
533
// Return the key status
447
534
return (gotKeys);
448
- #else // COMPILE_WIFI
535
+ #else // COMPILE_WIFI
449
536
return (false );
450
- #endif // COMPILE_WIFI
537
+ #endif // COMPILE_WIFI
451
538
}
452
539
453
540
char *ltrim (char *s)
@@ -565,6 +652,13 @@ int daysFromEpoch(long long endEpoch)
565
652
{
566
653
endEpoch /= 1000 ; // Convert PointPerfect ms Epoch to s
567
654
655
+ if (online.rtc == false )
656
+ {
657
+ // If we don't have RTC we can't calculate days to expire
658
+ log_d (" No RTC available" );
659
+ return (0 );
660
+ }
661
+
568
662
long localEpoch = rtc.getEpoch ();
569
663
570
664
long delta = endEpoch - localEpoch; // number of s between dates
@@ -954,13 +1048,22 @@ void menuPointPerfect()
954
1048
systemPrint (" Days until keys expire: " );
955
1049
if (strlen (settings.pointPerfectCurrentKey ) > 0 )
956
1050
{
957
- int daysRemaining =
958
- daysFromEpoch (settings. pointPerfectNextKeyStart + settings. pointPerfectNextKeyDuration + 1 );
959
-
960
- if (daysRemaining < 0 )
961
- systemPrintln ( " Expired " );
1051
+ if (online. rtc == false )
1052
+ {
1053
+ // If we don't have RTC we can't calculate days to expire
1054
+ systemPrintln ( " No RTC " );
1055
+ }
962
1056
else
963
- systemPrintln (daysRemaining);
1057
+ {
1058
+
1059
+ int daysRemaining =
1060
+ daysFromEpoch (settings.pointPerfectNextKeyStart + settings.pointPerfectNextKeyDuration + 1 );
1061
+
1062
+ if (daysRemaining < 0 )
1063
+ systemPrintln (" Expired" );
1064
+ else
1065
+ systemPrintln (daysRemaining);
1066
+ }
964
1067
}
965
1068
else
966
1069
systemPrintln (" No keys" );
@@ -1021,8 +1124,23 @@ void menuPointPerfect()
1021
1124
{
1022
1125
pointperfectProvisionDevice (); // Connect to ThingStream API and get keys
1023
1126
}
1024
- else
1025
- pointperfectUpdateKeys ();
1127
+ else // We have certs and keys
1128
+ {
1129
+ // Check that the certs are valid
1130
+ if (checkCertificates () == true )
1131
+ {
1132
+ // Update the keys
1133
+ pointperfectUpdateKeys ();
1134
+ }
1135
+ else
1136
+ {
1137
+ // Erase keys
1138
+ erasePointperfectCredentials ();
1139
+
1140
+ // Provision device
1141
+ pointperfectProvisionDevice (); // Connect to ThingStream API and get keys
1142
+ }
1143
+ }
1026
1144
}
1027
1145
else
1028
1146
{
0 commit comments