Skip to content

Instantly share code, notes, and snippets.

@igrr
Last active October 30, 2022 14:18
Show Gist options
  • Star 18 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save igrr/24dd2138e9c8a7daa1b4 to your computer and use it in GitHub Desktop.
Save igrr/24dd2138e9c8a7daa1b4 to your computer and use it in GitHub Desktop.
ESP8266 ota over HTTPS
/*
OTA update over HTTPS
As an example, we download and install ESP8266Basic firmware from github.
Requires latest git version of the core (November 17, 2015)
Created by Ivan Grokhotkov, 2015.
This example is in public domain.
*/
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <FS.h>
#include "ESP8266httpUpdate.h"
const char* ssid = "..............";
const char* password = "..............";
const char* host = "raw.githubusercontent.com";
const int httpsPort = 443;
// Use web browser to view and copy
// SHA1 fingerprint of the certificate
const char* fingerprint = "B0 74 BB EF 10 C2 DD 70 89 C8 EA 58 A2 F9 E1 41 00 D3 38 82";
const char* url = "/esp8266/Basic/master/Flasher/Build/4M/ESP8266Basic.cpp.bin";
void setup() {
Serial.begin(115200);
Serial.setDebugOutput(true);
WiFi.mode(WIFI_STA);
delay(5000);
Serial.println();
Serial.print("connecting to ");
Serial.println(ssid);
if (WiFi.SSID() != ssid) {
WiFi.begin(ssid, password);
}
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
// configure time
configTime(3 * 3600, 0, "pool.ntp.org");
// Use WiFiClientSecure class to create TLS connection
WiFiClientSecure client;
Serial.print("connecting to ");
Serial.println(host);
if (!client.connect(host, httpsPort)) {
Serial.println("connection failed");
return;
}
if (client.verify(fingerprint, host)) {
Serial.println("certificate matches");
} else {
Serial.println("certificate doesn't match");
return;
}
Serial.print("Starting OTA from: ");
Serial.println(url);
auto ret = ESPhttpUpdate.update(client, host, url);
// if successful, ESP will restart
Serial.println("update failed");
Serial.println((int) ret);
}
void loop() {
}
@roccomuso
Copy link

This is a pull example am I right?

@neuhaus
Copy link

neuhaus commented May 25, 2016

The current certificate has the SHA1 fingerprint 21:99:13:84:63:72:17:13:B9:ED:0E:8F:00:A5:9B:73:0D:D0:56:58

@teopost
Copy link

teopost commented Sep 3, 2016

This code don't work.
Return an error on arguments of line 72

@bmidgley
Copy link

bmidgley commented Jul 28, 2017

I'm updating my comment below. It appears I misread the way the secure client is passed into the update function. It shouldn't be susceptible to the attack I described. Does the client use the same connection that it had verified when it downloads the image? There is still a potential problem if it closes and reopens a connection to the host.

If you just check the SSL endpoint and then request the plaintext, a man in the middle could be orchestrated.

  1. Force the esp onto an access point on which you hijack dns to point to a man-in-the-middle server
  2. Forward port 443 from the middleman to the real server so the SSL request passes
  3. Intercept port 80 requests and send the bad firmware

@marcelstoer
Copy link

I'm wondering how that is supposed to work when ESP8266httpUpdate.h doesn't even have a public function that accepts a client. No doubt it does work, just wondering how.

@apicquot
Copy link

apicquot commented May 9, 2018

replace line 72 with ESPhttpUpdate.update(String(host),httpsPort,String(url),String(""),String(fingerprint));

@akhtarusafzai
Copy link

How will I get the SHA1 fingerprint of the certificate?

@akhtarusafzai
Copy link

I am trying to download the bin file from GitHub, but unfortunately, The WiFiClientSecure is not connecting to github over port 443, 80 and even 8080. Every time I try to achieve it, it says Connection Failed. Any one who can help me on this.
`/*
OTA update over HTTPS

As an example, we download and install ESP8266Basic firmware from github.

Requires latest git version of the core (November 17, 2015)

Created by Ivan Grokhotkov, 2015.
This example is in public domain.

*/

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <FS.h>
#include "ESP8266httpUpdate.h"

const char* ssid = "TI_DEV";
const char* password = "TechDeve";

const char* host = "github.com";
const int httpsPort = 443;

// Use web browser to view and copy
// SHA1 fingerprint of the certificate
const char* fingerprint = "7F 91 47 43 E0 CA 8E 04 E7 F4 33 80 2F E6 E4 55 53 84 F0 A8";

const char* url = "/akhtarusafzai/office/raw/master/Blink.bin";

void setup() {

Serial.begin(115200);
Serial.setDebugOutput(true);
WiFi.mode(WIFI_STA);
delay(5000);
Serial.println();
Serial.print("connecting to ");
Serial.println(ssid);

if (WiFi.SSID() != ssid) {
WiFi.begin(ssid, password);
}
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());

// configure time
configTime(3 * 3600, 0, "pool.ntp.org");

// Use WiFiClientSecure class to create TLS connection
WiFiClientSecure client;
Serial.print("connecting to ");
client.connect (host,httpsPort);
Serial.println(host);
if (!client.connect(host, httpsPort)) {
Serial.println("connection failed");
return;
}

if (client.verify(fingerprint, host)) {
Serial.println("certificate matches");
} else {
Serial.println("certificate doesn't match");
return;
}

Serial.print("Starting OTA from: ");
Serial.println(url);

auto ret = ESPhttpUpdate.update(client, host, url);
// if successful, ESP will restart
Serial.println("update failed");
Serial.println((int) ret);
}

void loop() {
}`

err

@dknop97
Copy link

dknop97 commented Aug 26, 2019

Hi! I want to know if have a software way to collect the SHA1 of an ENDPOINT in the esp8266 nodemcu. I do it manually, but I need to make it automatically with a code in Arduino IDE.
If I made some mistakes, take my apologies about my English. I'm still improving it.

@psatya111
Copy link

psatya111 commented Sep 12, 2019

I have successfully download the bin file from server but unfortunately in between the download,the esp crashes with the exception :esp8266 fatal exception 29(storeprohibited cause).
Need help for this issue.

@bmidgley
Copy link

bmidgley commented Oct 4, 2019

I would think this approach requires a cert you don't rotate. So eventually browsers will say it's expired but you keep it around because the fingerprint has to match what is in the code. Is that how you use it?

@dknop97
Copy link

dknop97 commented Oct 15, 2019

Hi! I want to know if have a software way to collect the SHA1 of an ENDPOINT in the esp8266 nodemcu. I do it manually, but I need to make it automatically with a code in Arduino IDE.
If I made some mistakes, take my apologies about my English. I'm still improving it.

Currently I put in my endpoint server a .txt file with the fingerprints, and every day it's actualized. So, in ESP, I made some functions and a rotine to in case of fail, go to the endpoint and make a GET request in the .txt file, analyze the data and push the fingerprints in the variables in my code. It is working very well.

Anyway, I'm still searching for solutions in the ESP code to collect the fingerprints automatically and accepting suggestions/help.
Again, ignore some English errors in my text, I'm improving it yet.

@bmidgley
Copy link

David -- @dknop97 -- You could save the fingerprint in nonvolatile ram.

There is a security problem if you ever get your txt file using http or untrusted https. It could be faked that way. I think a workaround is to have two servers and ask the trusted one to tell you the fingerprint of the other one so you can trust it.

Will we ever be able to verify SSL via signing authorities like browsers do?

@dknop97
Copy link

dknop97 commented Oct 16, 2019

David -- @dknop97 -- You could save the fingerprint in nonvolatile ram.
Will we ever be able to verify SSL via signing authorities like browsers do?

I understood your argument about the txt file, but this file is pushed in the endpoint (Amazon Lambda) by the admin of the Database, so I think about the possibilities and don't see the change of the txt file or of your data like a real possibilitie, but I'm justing thinking without any experience in this area, it's another sector of the project, with other people.

Well, I don't know about this possibilities of SSL verification. I'm a noob programmer in this area, so I don't have some experience, just have the desire for learn kkkkkk.
If you - and others - have ideas, let's talk a bit more, but I'm just a young Padawan here.

@shrimantpatel
Copy link

shrimantpatel commented Oct 18, 2019

I have successfully download the bin file from server but unfortunately in between the download,the esp crashes with the exception :esp8266 fatal exception 29(storeprohibited cause).
Need help for this issue.

I was getting the exact same error .... then I humped into an old post from @igrr (Ivan Grokhotkov) ... Ex 29 basically means its getting out of memory, so finish all your download/Update activities before you do any other activity meaning creating new instances of any CLASS. So the best place to do it would be in the first part of setup() or the first statement in the Loop() putting a flag to identify that its the first loop. If you have Global class instances , switch to pointers meaning just assign a pointer variable and later create the actual instance post your download/update activity. This shall ensure nothing is loaded to the memory before the download/Update activity runs....below is an example on what exactly I wanted to say.

Example:

//************OLD CODE EXAMPLE*******************
//______________________________________
WiFiServer server(8080);
void setup() {
//.
//
//.
     server.begin();
//Your Download /Update code HERE    
//.
//.
}
//_________________________________________
//***************/NEW CODE corresponding would be as below*************
WiFiServer *server = NULL;
void setup() {
//.
//.
//.
//Your Download /Update code HERE    
//.
//.
//.
server = new WiFiServer(8080);
 server.begin();
}

@hkarthik97
Copy link

@btruden
Copy link

btruden commented Feb 25, 2020

Hi @hkarthik97, I've tried with that and functioned perfectly. It updates from an HTTPS URL. Well, at least I insert an HTTPS URL when calling the ESPhttpUpdate.update() method and it seems to be working.

But in that code, before attempting to connect the WifiClientSecure object, it calls the method client.setInsecure().

What exactly does the setInsecure() method do? Does it keep using HTTPS protocol or it automatically switches to HTTP?

Thanks in advance!

@programmer131
Copy link

here is my code that so far works for both esp8266 and esp32
https://github.com/programmer131/ESP8266_ESP32_SelfUpdate

@bangnguyendev
Copy link

here is my code that so far works for both esp8266 and esp32 https://github.com/programmer131/ESP8266_ESP32_SelfUpdate
Thank @programmer131

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment