ESP32 after a few days starts returning error Certificate is expired or not yet valid
goseese opened this issue ยท 15 comments
I have a sketch that runs on many ESP32 devices with a W5500.
All devices have been running fine for approx 1 month with no issues.
Recently all the devices have started reporting the following error when attempting to connect to my server.
20:53:51.515 -> (SSLClient)(SSL_WARN)(connect): Arduino client is already connected? Continuing anyway...
20:53:51.515 -> (SSLClient)(SSL_WARN)(m_run_until): Terminating because the ssl engine closed
20:53:51.515 -> (SSLClient)(SSL_ERROR)(m_start_ssl): Failed to initlalize the SSL layer
20:53:51.515 -> (SSLClient)(SSL_ERROR)(m_print_br_error): Certificate is expired or not yet valid.
The server ssl certificate is a letsencrypt certificate and is working properly. Double checking the certificate expire data is about 90 days from the current date. The certificates have recently renewed.
First I forced the certificate to renew again, and rebooted the devices, no change.
Then I re-uploaded firmware to one of the devices. No changes were made to the firmware. The trust anchor was not changed. - The device started working.
I then forced the certificate to renew again. This did not cause the problem to come back for that device and all other devices were un-changed.
As a check I exported the trust anchor again and compared to the existing trust anchor. The trust anchor content did not change.
So my problem is I have many devices that are failing with the stated error "Certificate is expired or not yet valid". The only fix seems to be re-uploading unchanged firmware to the device.
Perhaps there is something with timestamp that validates the certificate at compile time and I need some way to update that time stamp?
The devices do not have an RTC and I do not set the time on them. I Can make a code change to do that, however uploading new code temporarily solves the issue so it would be hard for me to verify that is a fix.
Perhaps there is something with timestamp that validates the certificate at compile time and I need some way to update that time stamp?
The timestamp is fixed at the last compile time, and that's probably what is causing the issue. SSLClient uses the compilation timestamp as the "current time" in leu of a real time clock, which is why re-uploading fixed the error but restarting didn't:
SSLClient/src/TLS12_only_profile.c
Lines 410 to 426 in 32d1c55
Given this, I would say that your issue is expected behavior, at least for the moment. Are you looking for a function to change the fixed timestamp? I did notice that the documentation doesn't mention this behavior anywhere, so I can go ahead and fix that.
So if I write a function that pulls in an epoch time stamp and sets the ESP32 current time to that value and then passes that timestamp to the validation function that should solve this issue?
I think so. I went ahead and added a setVerificationTime
function on master which you can use to get the timestamp into SSLClient. It accepts the weird time format that BearSSL uses, which unfortunately isn't epoch but is pretty close. The UNIX_TIMESTAMP_UTX
macro is an epoch value in the code I linked above, so you can use the same math to convert your epoch timestamp into BearSSL's format. Give that a shot and tell me what you think.
Hi - I've got self-signed certificates with an extremely long expiration date set. Will I be running into this issue after devices have been in the field a few months as well?
Hi - I've got self-signed certificates with an extremely long expiration date set. Will I be running into this issue after devices have been in the field a few months as well?
No, this issue will only occur if a certificate expires or is replaced while the device is operating. Since you control the certificate chain, so long as you never replace the certificates without re-flashing the devices you should be fine.
Thanks.
Once again thanks for monumental job. I have tried too many alternative libraries, but only given library's performance got just fine.
I got worked it with TinyGSM library. For timing subject, it would be perfect to get implemented one line command that will use the result of beneath command from TinyGSM:
String timefromNet = modem.getGSMDateTime(DATE_FULL); SerialMon.println("Current Network Time: " + timefromNet);
Which returns a string type variable, like this (Copy/Pasted from terminal window):
Current Network Time: 21/04/19,12:19:36+16
Sorry for the silly questions but I'm newbie and I'm having the same problem of @goseese.
Should I call void setVerificationTime (uint32_t days, uint32_t seconds); function before (!client.connect(host, httpsPort)) ?
Hi,
I am also using TinyGSM. Is there an easy way to get the days for current date calculated if full date is available?
Best regards
Holger
So I added the following to when I connection to the WIFI module is established.
unsigned long WIFITime = WiFi.getTime(); sslClient.setVerificationTime((uint32_t)((WIFITime / (SECS_PER_DAY)) + 719528UL), (uint32_t)(WIFITime % (SECS_PER_DAY)));
Now I get the following messages:
Connect failed(SSLClient)(SSL_WARN)(connect): Arduino client is already connected? Continuing anyway...
(SSLClient)(SSL_WARN)(m_run_until): Terminating because the ssl engine closed
(SSLClient)(SSL_ERROR)(m_start_ssl): Failed to initlalize the SSL layer
(SSLClient)(SSL_ERROR)(m_print_br_error): Certificate is expired or not yet valid.
When does "setVerficationTime" need to be called? I am effectively using the conversion for day to 1/1/0 from the BEARSSL calc. When I use compile time there is no issue but when I set the time in the code with the same calc it says the Cerficate is expired.
What am I doing wrong?
Thanks
Bruce
I think so. I went ahead and added a
setVerificationTime
function on master which you can use to get the timestamp into SSLClient. It accepts the weird time format that BearSSL uses, which unfortunately isn't epoch but is pretty close. TheUNIX_TIMESTAMP_UTX
macro is an epoch value in the code I linked above, so you can use the same math to convert your epoch timestamp into BearSSL's format. Give that a shot and tell me what you think.
...
unsigned long epoch = TWiFiStuff::getEpochTime();
const static unsigned long sec_per_day = 60 * 60 * 24;
p_ssl_cli->setVerificationTime(
// days since 1970 + days from 1970 to year 0
epoch / sec_per_day + 719528UL,
// seconds over start of day
epoch % sec_per_day
);
if(p_mqtt_cli->connect(server.c_str(), port))
{
...
I have exactly the same problem you have. Did you find a solution?
I find epoch from UTP server and convert it via the following command:
// days since 1970 + days from 1970 to year 0
//(unsigned long) (epoch / sec_per_day ),
(uint32_t) (epoch / sec_per_day + 719528UL),
// seconds over start of day
(uint32_t) epoch % sec_per_day
);
If someone has a solution, please share it :)
So I added the following to when I connection to the WIFI module is established.
unsigned long WIFITime = WiFi.getTime(); sslClient.setVerificationTime((uint32_t)((WIFITime / (SECS_PER_DAY)) + 719528UL), (uint32_t)(WIFITime % (SECS_PER_DAY)));
Now I get the following messages: Connect failed(SSLClient)(SSL_WARN)(connect): Arduino client is already connected? Continuing anyway... (SSLClient)(SSL_WARN)(m_run_until): Terminating because the ssl engine closed (SSLClient)(SSL_ERROR)(m_start_ssl): Failed to initlalize the SSL layer (SSLClient)(SSL_ERROR)(m_print_br_error): Certificate is expired or not yet valid.
When does "setVerficationTime" need to be called? I am effectively using the conversion for day to 1/1/0 from the BEARSSL calc. When I use compile time there is no issue but when I set the time in the code with the same calc it says the Cerficate is expired.
What am I doing wrong?
Thanks
Bruce
Despite possessing a valid certificate, I'm encountering an ongoing issue. Previously, everything operated smoothly, but after a span of 67 days, all my devices unexpectedly disconnected. I rely on an AWS IoT Core auto-signed certificate, depicted below, yet the outcome remains the same as shown in the logs bellow. After re-flashing the devices, without any code changes, back to work again.
Certificate
Logs
I had the same problem as in the previous comment (#27 (comment)), also on AWS IoT Core, with authenticated certificates. In my case, rewriting does not solve the problem either.
I also suffered frome the same problem. But I've solved this problem, and I'll talk about how I've solved it.
First, the problem is solved by changing the contents of the file TLS12_only_profile.c under the SSLClient/src document so that the compiler can understand it anew. For example, adding a space key to the empty space of the file.
But, This method is not a fundamental problem-solving method.
As mentioned in "StefanoPierini commented on May 16, 2023", it was resolved using setVerificationTime.
The location of the function I used was executed before "mqtt server connect".
To reveal a bit of the sauce
**
if (!wclient.connected())
{
wclient.clearWriteError();
Serial.print("$0,Attempting MQTT connection...;");
// Serial.printf(" %d \n",maintainFlag);
clientStateFlag = wclient.state();
wifiClientSSL.setVerificationTime(getDayValue() + 719528UL, 0);
if (wclient.connect(NetworkClientId.c_str()))
{
**
My development environment uses "VSCode PlatformIO IDE". I am using the libraries of "SSLClient" and "subclient".
I hope this comment from me will be helpful.