11#ifdef  COMPILE_L_BAND
22
3+ #include  " mbedtls/ssl.h"   // Needed for certificate validation
4+ 
35// ----------------------------------------
46//  Locals - compiled out
57// ----------------------------------------
@@ -12,7 +14,7 @@ static SFE_UBLOX_GNSS_SUPER i2cLBand; // NEO-D9S
1214#ifndef  POINTPERFECT_TOKEN
1315#define  POINTPERFECT_TOKEN                                                                                              \
1416    0xAA , 0xBB , 0xCC , 0xDD , 0x00 , 0x11 , 0x22 , 0x33 , 0x0A , 0x0B , 0x0C , 0x0D , 0x00 , 0x01 , 0x02 , 0x03 
15- #endif    //  POINTPERFECT_TOKEN
17+ #endif  //  POINTPERFECT_TOKEN
1618
1719static  uint8_t  pointPerfectTokenArray[16 ] = {POINTPERFECT_TOKEN}; //  Token in HEX form
1820
@@ -196,7 +198,7 @@ bool pointperfectProvisionDevice()
196198        //  Override ID with testing ID
197199        snprintf (hardwareID, sizeof (hardwareID), " %02X%02X%02X%02X%02X%02X"  , whitelistID[0 ], whitelistID[1 ],
198200                 whitelistID[2 ], whitelistID[3 ], whitelistID[4 ], whitelistID[5 ]);
199- #endif    //  WHITELISTED_ID
201+ #endif  //  WHITELISTED_ID
200202
201203        char  givenName[100 ];
202204        snprintf (givenName, sizeof (givenName), " SparkFun RTK %s v%d.%d - %s"  , platformPrefix, FIRMWARE_VERSION_MAJOR,
@@ -317,9 +319,94 @@ bool pointperfectProvisionDevice()
317319    bluetoothStart ();
318320
319321    return  (retVal);
320- #else     //  COMPILE_WIFI
322+ #else   //  COMPILE_WIFI
321323    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
323410}
324411
325412//  Subscribe to MQTT channel, grab keys, then stop
@@ -445,9 +532,9 @@ bool pointperfectUpdateKeys()
445532
446533    //  Return the key status
447534    return  (gotKeys);
448- #else     //  COMPILE_WIFI
535+ #else   //  COMPILE_WIFI
449536    return  (false );
450- #endif    //  COMPILE_WIFI
537+ #endif  //  COMPILE_WIFI
451538}
452539
453540char  *ltrim (char  *s)
@@ -565,6 +652,13 @@ int daysFromEpoch(long long endEpoch)
565652{
566653    endEpoch /= 1000 ; //  Convert PointPerfect ms Epoch to s
567654
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+ 
568662    long  localEpoch = rtc.getEpoch ();
569663
570664    long  delta = endEpoch - localEpoch; //  number of s between dates
@@ -954,13 +1048,22 @@ void menuPointPerfect()
9541048        systemPrint (" Days until keys expire: "  );
9551049        if  (strlen (settings.pointPerfectCurrentKey ) > 0 )
9561050        {
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+             } 
9621056            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+             }
9641067        }
9651068        else 
9661069            systemPrintln (" No keys"  );
@@ -1021,8 +1124,23 @@ void menuPointPerfect()
10211124                    {
10221125                        pointperfectProvisionDevice (); //  Connect to ThingStream API and get keys
10231126                    }
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+                     }
10261144                }
10271145                else 
10281146                {
0 commit comments