Skip to content

Commit a8976a0

Browse files
author
Me No Dev
committed
Add MD5 to core, Fix OTA examples and Digest Authentication to OTA and espota.py
1 parent e613e42 commit a8976a0

File tree

13 files changed

+501
-230
lines changed

13 files changed

+501
-230
lines changed

cores/esp8266/MD5Builder.cpp

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#include "Arduino.h"
2+
#include "md5.h"
3+
#include "MD5Builder.h"
4+
5+
#define hex_char_to_byte(c) (((c)>='a'&&(c)<='f')?((c)-87):((c)>='A'&&(c)<='F')?((c)-55):((c)>='0'&&(c)<='9')?((c)-48):0)
6+
7+
void MD5Builder::begin(void){
8+
memset(_buf, 0x00, 16);
9+
MD5Init(&_ctx);
10+
}
11+
12+
void MD5Builder::add(uint8_t * data, uint16_t len){
13+
MD5Update(&_ctx, data, len);
14+
}
15+
16+
void MD5Builder::addHexString(const char * data){
17+
uint16_t i, len = strlen(data);
18+
uint8_t * tmp = (uint8_t*)malloc(len/2);
19+
if(tmp == NULL)
20+
return;
21+
for(i=0; i<len; i+=2) tmp[i/2] = (hex_char_to_byte(data[i]) & 0x0F) << 4 | (hex_char_to_byte(data[i+1]) & 0x0F);
22+
add(tmp, len/2);
23+
free(tmp);
24+
}
25+
26+
void MD5Builder::calculate(void){
27+
MD5Final(_buf, &_ctx);
28+
}
29+
30+
void MD5Builder::getBytes(uint8_t * output){
31+
memcpy(output, _buf, 16);
32+
}
33+
34+
void MD5Builder::getChars(char * output){
35+
for(uint8_t i = 0; i < 16; i++)
36+
sprintf(output + (i * 2), "%02x", _buf[i]);
37+
}
38+
39+
String MD5Builder::toString(void){
40+
char out[32];
41+
getChars(out);
42+
return String(out);
43+
}

cores/esp8266/MD5Builder.h

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
md5.h - exposed md5 ROM functions for esp8266
3+
4+
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
5+
This file is part of the esp8266 core for Arduino environment.
6+
7+
This library is free software; you can redistribute it and/or
8+
modify it under the terms of the GNU Lesser General Public
9+
License as published by the Free Software Foundation; either
10+
version 2.1 of the License, or (at your option) any later version.
11+
12+
This library is distributed in the hope that it will be useful,
13+
but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+
Lesser General Public License for more details.
16+
17+
You should have received a copy of the GNU Lesser General Public
18+
License along with this library; if not, write to the Free Software
19+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20+
*/
21+
#ifndef __ESP8266_MD5_BUILDER__
22+
#define __ESP8266_MD5_BUILDER__
23+
24+
#include "Arduino.h"
25+
#include "md5.h"
26+
27+
class MD5Builder {
28+
private:
29+
md5_context_t _ctx;
30+
uint8_t _buf[16];
31+
public:
32+
void begin(void);
33+
void add(uint8_t * data, uint16_t len);
34+
void add(const char * data){ add((uint8_t*)data, strlen(data)); }
35+
void add(char * data){ add((const char*)data); }
36+
void add(String data){ add(data.c_str()); }
37+
void addHexString(const char * data);
38+
void addHexString(char * data){ addHexString((const char*)data); }
39+
void addHexString(String data){ addHexString(data.c_str()); }
40+
void calculate(void);
41+
void getBytes(uint8_t * output);
42+
void getChars(char * output);
43+
String toString(void);
44+
};
45+
46+
47+
#endif

cores/esp8266/Updater.cpp

+27-2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ void UpdaterClass::_reset() {
3232
_currentAddress = 0;
3333
_size = 0;
3434
_command = U_FLASH;
35+
_target_md5 = 0;
3536
}
3637

3738
bool UpdaterClass::begin(size_t size, int command) {
@@ -96,10 +97,17 @@ bool UpdaterClass::begin(size_t size, int command) {
9697
_size = size;
9798
_buffer = new uint8_t[FLASH_SECTOR_SIZE];
9899
_command = command;
99-
100+
101+
_target_md5 = new char[64];
102+
_md5.begin();
100103
return true;
101104
}
102105

106+
void UpdaterClass::setMD5(const char * expected_md5){
107+
if(strlen(expected_md5) != 32) return;
108+
strcpy(_target_md5, expected_md5);
109+
}
110+
103111
bool UpdaterClass::end(bool evenIfRemaining){
104112
if(_size == 0){
105113
#ifdef DEBUG_UPDATER
@@ -123,7 +131,21 @@ bool UpdaterClass::end(bool evenIfRemaining){
123131
}
124132
_size = progress();
125133
}
126-
134+
135+
_md5.calculate();
136+
if(_target_md5 && strlen(_target_md5) == 32){
137+
if(strcmp(_target_md5, _md5.toString().c_str()) != 0){
138+
_error = UPDATE_ERROR_MD5;
139+
#ifdef DEBUG_UPDATER
140+
DEBUG_UPDATER.printf("MD5 Failed: expected:%s, calculated:%s\n", _target_md5, _md5.toString().c_str());
141+
#endif
142+
return false;
143+
}
144+
#ifdef DEBUG_UPDATER
145+
else DEBUG_UPDATER.printf("MD5 Success: %s\n", _md5.toString().c_str());
146+
#endif
147+
}
148+
127149
if (_command == U_FLASH) {
128150
eboot_command ebcmd;
129151
ebcmd.action = ACTION_COPY_RAW;
@@ -157,6 +179,7 @@ bool UpdaterClass::_writeBuffer(){
157179
#endif
158180
return false;
159181
}
182+
_md5.add(_buffer, _bufferLen);
160183
_currentAddress += _bufferLen;
161184
_bufferLen = 0;
162185
return true;
@@ -232,6 +255,8 @@ void UpdaterClass::printError(Stream &out){
232255
out.println("Bad Size Given");
233256
} else if(_error == UPDATE_ERROR_STREAM){
234257
out.println("Stream Read Timeout");
258+
} else if(_error == UPDATE_ERROR_MD5){
259+
out.println("MD5 Check Failed");
235260
} else {
236261
out.println("UNKNOWN");
237262
}

cores/esp8266/Updater.h

+21-1
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,20 @@
33

44
#include "Arduino.h"
55
#include "flash_utils.h"
6+
#include "MD5Builder.h"
67

78
#define UPDATE_ERROR_OK 0
89
#define UPDATE_ERROR_WRITE 1
910
#define UPDATE_ERROR_ERASE 2
1011
#define UPDATE_ERROR_SPACE 3
1112
#define UPDATE_ERROR_SIZE 4
1213
#define UPDATE_ERROR_STREAM 5
14+
#define UPDATE_ERROR_MD5 6
1315

1416
#define U_FLASH 0
1517
#define U_SPIFFS 100
1618

17-
//#define DEBUG_UPDATER Serial1
19+
//#define DEBUG_UPDATER Serial
1820

1921
class UpdaterClass {
2022
public:
@@ -56,7 +58,22 @@ class UpdaterClass {
5658
Prints the last error to an output stream
5759
*/
5860
void printError(Stream &out);
61+
62+
/*
63+
sets the expected MD5 for the firmware (hexString)
64+
*/
65+
void setMD5(const char * expected_md5);
5966

67+
/*
68+
returns the MD5 String of the sucessfully ended firmware
69+
*/
70+
String md5String(void){ return _md5.toString(); }
71+
72+
/*
73+
populated the result with the md5 bytes of the sucessfully ended firmware
74+
*/
75+
void md5(uint8_t * result){ return _md5.getBytes(result); }
76+
6077
//Helpers
6178
uint8_t getError(){ return _error; }
6279
void clearError(){ _error = UPDATE_ERROR_OK; }
@@ -120,6 +137,9 @@ class UpdaterClass {
120137
uint32_t _startAddress;
121138
uint32_t _currentAddress;
122139
uint32_t _command;
140+
141+
char *_target_md5;
142+
MD5Builder _md5;
123143
};
124144

125145
extern UpdaterClass Update;

cores/esp8266/md5.h

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
md5.h - exposed md5 ROM functions for esp8266
3+
4+
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
5+
This file is part of the esp8266 core for Arduino environment.
6+
7+
original C source from https://github.com/morrissinger/ESP8266-Websocket/raw/master/MD5.h
8+
9+
This library is free software; you can redistribute it and/or
10+
modify it under the terms of the GNU Lesser General Public
11+
License as published by the Free Software Foundation; either
12+
version 2.1 of the License, or (at your option) any later version.
13+
14+
This library is distributed in the hope that it will be useful,
15+
but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17+
Lesser General Public License for more details.
18+
19+
You should have received a copy of the GNU Lesser General Public
20+
License along with this library; if not, write to the Free Software
21+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22+
*/
23+
#ifndef __ESP8266_MD5__
24+
#define __ESP8266_MD5__
25+
26+
#ifdef __cplusplus
27+
extern "C" {
28+
#endif
29+
30+
typedef struct {
31+
uint32_t state[4];
32+
uint32_t count[2];
33+
uint8_t buffer[64];
34+
} md5_context_t;
35+
36+
extern void MD5Init (md5_context_t *);
37+
extern void MD5Update (md5_context_t *, uint8_t *, uint16_t);
38+
extern void MD5Final (uint8_t [16], md5_context_t *);
39+
40+
#ifdef __cplusplus
41+
} // extern "C"
42+
#endif
43+
44+
#endif

0 commit comments

Comments
 (0)