Files
earlephilhower_arduino-pico/libraries/MD5Builder/src/MD5Builder.cpp
T
Earle F. Philhower, III da86a8942b Add OTA update support (#711)
Adds a 12K OTA stub 3rd stage bootloader, which reads new firmware
from the LittleFS filesystem and flashes on reboot.

By storing the OTA commands in a file in flash, it is possible to
recover from a power failure during OTA programming.  On power
resume, the OTA block will simply re-program from the beginning.

Support cryptographic signed OTA updates, if desired.  Includes
host-side signing logic via openssl.

Add PicoOTA library which encapsulates the file format for
the updater, including CRC32 checking.

Add LEAmDNS support to allow Arduino IDE discovery

Add ArduinoOTA class for IDE uploads

Add MD5Builder class

Add Updater class which supports writing and validating
cryptographically signed binaries from any source (http,
Ethernet, WiFi, Serial, etc.)

Add documentation and readmes.
2022-08-12 00:26:51 -07:00

118 lines
3.4 KiB
C++

/*
MD5Builder - Simple MD5 hash calculations
Updated for the Pico by Earle F. Philhower, III
Modified from the ESP8266 version which is
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
This file is part of the esp8266 core for Arduino environment.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <Arduino.h>
#include <MD5Builder.h>
#include <memory>
static uint8_t hex_char_to_byte(uint8_t c) {
return (c >= 'a' && c <= 'f') ? (c - ((uint8_t)'a' - 0xa)) :
(c >= 'A' && c <= 'F') ? (c - ((uint8_t)'A' - 0xA)) :
(c >= '0' && c <= '9') ? (c - (uint8_t)'0') : 0;
}
void MD5Builder::begin(void) {
memset(_buf, 0x00, 16);
br_md5_init(&_ctx);
}
void MD5Builder::add(const uint8_t * data, const uint16_t len) {
br_md5_update(&_ctx, data, len);
}
void MD5Builder::addHexString(const char * data) {
uint16_t i, len = strlen(data);
auto tmp = std::unique_ptr<uint8_t[]> {new (std::nothrow) uint8_t[len / 2]};
if (!tmp) {
return;
}
for (i = 0; i < len; i += 2) {
uint8_t high = hex_char_to_byte(data[i]);
uint8_t low = hex_char_to_byte(data[i + 1]);
tmp[i / 2] = (high & 0x0F) << 4 | (low & 0x0F);
}
add(tmp.get(), len / 2);
}
bool MD5Builder::addStream(Stream &stream, const size_t maxLen) {
const int buf_size = 512;
int maxLengthLeft = maxLen;
auto buf = std::unique_ptr<uint8_t[]> {new (std::nothrow) uint8_t[buf_size]};
if (!buf) {
return false;
}
int bytesAvailable = stream.available();
while ((bytesAvailable > 0) && (maxLengthLeft > 0)) {
// determine number of bytes to read
int readBytes = bytesAvailable;
if (readBytes > maxLengthLeft) {
readBytes = maxLengthLeft; // read only until max_len
}
if (readBytes > buf_size) {
readBytes = buf_size; // not read more the buffer can handle
}
// read data and check if we got something
int numBytesRead = stream.readBytes(buf.get(), readBytes);
if (numBytesRead < 1) {
return false;
}
// Update MD5 with buffer payload
br_md5_update(&_ctx, buf.get(), numBytesRead);
// update available number of bytes
maxLengthLeft -= numBytesRead;
bytesAvailable = stream.available();
}
return true;
}
void MD5Builder::calculate(void) {
br_md5_out(&_ctx, _buf);
}
void MD5Builder::getBytes(uint8_t * output) const {
memcpy(output, _buf, 16);
}
void MD5Builder::getChars(char * output) const {
for (uint8_t i = 0; i < 16; i++) {
sprintf(output + (i * 2), "%02x", _buf[i]);
}
}
String MD5Builder::toString(void) const {
char out[33];
getChars(out);
return String(out);
}