From ea4b7d415c3a6096ce953e99c968900cff5d2046 Mon Sep 17 00:00:00 2001 From: Pablo2048 Date: Thu, 6 Jun 2024 10:17:05 +0200 Subject: [PATCH] Aktualizace na verzi 2.10.5 --- README.md | 39 +++--- docs/index.md | 39 +++--- examples/Draft/Draft.ino | 37 +++++ library.json_ | 2 +- library.properties | 2 +- platformio.ini | 9 +- src/AsyncWebSocket.cpp | 25 ++-- src/ESPAsyncWebServer.h | 4 +- src/WebAuthentication.cpp | 32 ++--- src/port/SHA1Builder.cpp | 284 ++++++++++++++++++++++++++++++++++++++ src/port/SHA1Builder.h | 39 ++++++ 11 files changed, 435 insertions(+), 77 deletions(-) create mode 100644 examples/Draft/Draft.ino create mode 100644 src/port/SHA1Builder.cpp create mode 100644 src/port/SHA1Builder.h diff --git a/README.md b/README.md index b10865c..8c56e7a 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,8 @@ This fork is based on [yubox-node-org/ESPAsyncWebServer](https://github.com/yubo Usage and API stays the same as the original library. Please look at the original libraries for more examples and documentation. -[https://github.com/yubox-node-org/ESPAsyncWebServer](https://github.com/yubox-node-org/ESPAsyncWebServer) +- [https://github.com/me-no-dev/ESPAsyncWebServer](https://github.com/me-no-dev/ESPAsyncWebServer) (original library) +- [https://github.com/yubox-node-org/ESPAsyncWebServer](https://github.com/yubox-node-org/ESPAsyncWebServer) (fork of the original library) ## `AsyncWebSocketMessageBuffer` and `makeBuffer()` @@ -44,9 +45,8 @@ The fork from `yubox-node-org` introduces some breaking API changes compared to This fork is compatible with the original library from `me-no-dev` regarding WebSocket, and wraps the optimizations done by `yubox-node-org` in the `AsyncWebSocketMessageBuffer` class. So you have the choice of which API to use. -I strongly suggest to use the optimized API from `yubox-node-org` as it is much more efficient. -Here is an example for serializing a Json document in a websocket message buffer. This code is compatible with any forks, but not optimized: +Here are examples for serializing a Json document in a websocket message buffer: ```cpp void send(JsonDocument& doc) { @@ -60,28 +60,31 @@ void send(JsonDocument& doc) { } ``` -Here is an example for serializing a Json document in a more optimized way, and compatible with both forks: - ```cpp void send(JsonDocument& doc) { const size_t len = measureJson(doc); -#if defined(ASYNCWEBSERVER_FORK_mathieucarbou) - - // this fork (originally from yubox-node-org), uses another API with shared pointer that better support concurrent use cases then the original project + // this fork (originally from yubox-node-org), uses another API with shared pointer auto buffer = std::make_shared>(len); assert(buffer); // up to you to keep or remove this serializeJson(doc, buffer->data(), len); _ws->textAll(std::move(buffer)); - -#else - - // original API from me-no-dev - AsyncWebSocketMessageBuffer* buffer = _ws->makeBuffer(len); - assert(buffer); // up to you to keep or remove this - serializeJson(doc, buffer->get(), len); - _ws->textAll(buffer); - -#endif } ``` + +I recommend to use the official API `AsyncWebSocketMessageBuffer` to retain further compatibility. + +## Stack size and queues + +Here are some important flags to tweak depending on your needs: + +```cpp + // Async TCP queue size + -D CONFIG_ASYNC_TCP_QUEUE_SIZE=128 + // Async TCP async task core + -D CONFIG_ASYNC_TCP_RUNNING_CORE=1 + // Async TCP async stac ksize + -D CONFIG_ASYNC_TCP_STACK_SIZE=8096 + // WebSocket queue size + -D WS_MAX_QUEUED_MESSAGES=64 +``` diff --git a/docs/index.md b/docs/index.md index b10865c..8c56e7a 100644 --- a/docs/index.md +++ b/docs/index.md @@ -36,7 +36,8 @@ This fork is based on [yubox-node-org/ESPAsyncWebServer](https://github.com/yubo Usage and API stays the same as the original library. Please look at the original libraries for more examples and documentation. -[https://github.com/yubox-node-org/ESPAsyncWebServer](https://github.com/yubox-node-org/ESPAsyncWebServer) +- [https://github.com/me-no-dev/ESPAsyncWebServer](https://github.com/me-no-dev/ESPAsyncWebServer) (original library) +- [https://github.com/yubox-node-org/ESPAsyncWebServer](https://github.com/yubox-node-org/ESPAsyncWebServer) (fork of the original library) ## `AsyncWebSocketMessageBuffer` and `makeBuffer()` @@ -44,9 +45,8 @@ The fork from `yubox-node-org` introduces some breaking API changes compared to This fork is compatible with the original library from `me-no-dev` regarding WebSocket, and wraps the optimizations done by `yubox-node-org` in the `AsyncWebSocketMessageBuffer` class. So you have the choice of which API to use. -I strongly suggest to use the optimized API from `yubox-node-org` as it is much more efficient. -Here is an example for serializing a Json document in a websocket message buffer. This code is compatible with any forks, but not optimized: +Here are examples for serializing a Json document in a websocket message buffer: ```cpp void send(JsonDocument& doc) { @@ -60,28 +60,31 @@ void send(JsonDocument& doc) { } ``` -Here is an example for serializing a Json document in a more optimized way, and compatible with both forks: - ```cpp void send(JsonDocument& doc) { const size_t len = measureJson(doc); -#if defined(ASYNCWEBSERVER_FORK_mathieucarbou) - - // this fork (originally from yubox-node-org), uses another API with shared pointer that better support concurrent use cases then the original project + // this fork (originally from yubox-node-org), uses another API with shared pointer auto buffer = std::make_shared>(len); assert(buffer); // up to you to keep or remove this serializeJson(doc, buffer->data(), len); _ws->textAll(std::move(buffer)); - -#else - - // original API from me-no-dev - AsyncWebSocketMessageBuffer* buffer = _ws->makeBuffer(len); - assert(buffer); // up to you to keep or remove this - serializeJson(doc, buffer->get(), len); - _ws->textAll(buffer); - -#endif } ``` + +I recommend to use the official API `AsyncWebSocketMessageBuffer` to retain further compatibility. + +## Stack size and queues + +Here are some important flags to tweak depending on your needs: + +```cpp + // Async TCP queue size + -D CONFIG_ASYNC_TCP_QUEUE_SIZE=128 + // Async TCP async task core + -D CONFIG_ASYNC_TCP_RUNNING_CORE=1 + // Async TCP async stac ksize + -D CONFIG_ASYNC_TCP_STACK_SIZE=8096 + // WebSocket queue size + -D WS_MAX_QUEUED_MESSAGES=64 +``` diff --git a/examples/Draft/Draft.ino b/examples/Draft/Draft.ino new file mode 100644 index 0000000..0a1cb1f --- /dev/null +++ b/examples/Draft/Draft.ino @@ -0,0 +1,37 @@ +#include +#include +#include "mbedtls/md5.h" + +void setup() { + Serial.begin(115200); + delay(2000); + + const char* data = "Hello World"; + + { + uint8_t md5[16]; + mbedtls_md5_context _ctx; + mbedtls_md5_init(&_ctx); + mbedtls_md5_starts(&_ctx); + mbedtls_md5_update(&_ctx, (const unsigned char*)data, strlen(data)); + mbedtls_md5_finish(&_ctx, md5); + char output[33]; + for (int i = 0; i < 16; i++) { + sprintf_P(output + (i * 2), PSTR("%02x"), md5[i]); + } + Serial.println(String(output)); + } + + { + MD5Builder md5; + md5.begin(); + md5.add(data, strlen(data); + md5.calculate(); + char output[33]; + md5.getChars(output); + Serial.println(String(output)); + } +} + +void loop() { +} diff --git a/library.json_ b/library.json_ index 539ff5d..df9d36a 100644 --- a/library.json_ +++ b/library.json_ @@ -1,6 +1,6 @@ { "name": "ESP Async WebServer", - "version": "2.10.4", + "version": "2.10.5", "description": "Asynchronous HTTP and WebSocket Server Library for ESP32. Supports: WebSocket, SSE, Authentication, Arduino Json 7, File Upload, Static File serving, URL Rewrite, URL Redirect, etc.", "keywords": "http,async,websocket,webserver", "homepage": "https://github.com/mathieucarbou/ESPAsyncWebServer", diff --git a/library.properties b/library.properties index fc68a1c..b6e35d0 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ESP Async WebServer -version=2.10.4 +version=2.10.5 author=Me-No-Dev maintainer=Mathieu Carbou sentence=Asynchronous HTTP and WebSocket Server Library for ESP32 diff --git a/platformio.ini b/platformio.ini index eff6677..1f19720 100644 --- a/platformio.ini +++ b/platformio.ini @@ -16,10 +16,11 @@ monitor_filters = esp32_exception_decoder, log2file [platformio] lib_dir = . -; src_dir = examples/CaptivePortal +src_dir = examples/CaptivePortal ; src_dir = examples/SimpleServer -src_dir = examples/StreamFiles +; src_dir = examples/StreamFiles ; src_dir = examples/Filters +; src_dir = examples/Draft [env:arduino] platform = espressif32 @@ -32,8 +33,8 @@ board = esp32dev [env:arduino-3] platform = espressif32 platform_packages= - platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.0 - platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.0/esp32-arduino-libs-3.0.0.zip + platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.1 + platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.1/esp32-arduino-libs-3.0.1.zip board = esp32dev [env:esp8266] diff --git a/src/AsyncWebSocket.cpp b/src/AsyncWebSocket.cpp index f231d23..9a07d1e 100644 --- a/src/AsyncWebSocket.cpp +++ b/src/AsyncWebSocket.cpp @@ -26,7 +26,11 @@ #include #ifndef ESP8266 -#include "mbedtls/sha1.h" +#if ESP_IDF_VERSION_MAJOR < 5 +#include "./port/SHA1Builder.h" +#else +#include +#endif #include #else #include @@ -1305,19 +1309,12 @@ AsyncWebSocketResponse::AsyncWebSocketResponse(const String& key, AsyncWebSocket #ifdef ESP8266 sha1(key + WS_STR_UUID, hash); #else - (String&)key += WS_STR_UUID; - mbedtls_sha1_context ctx; - mbedtls_sha1_init(&ctx); -#if ESP_IDF_VERSION_MAJOR == 5 - mbedtls_sha1_starts(&ctx); - mbedtls_sha1_update(&ctx, (const unsigned char*)key.c_str(), key.length()); - mbedtls_sha1_finish(&ctx, hash); -#else - mbedtls_sha1_starts_ret(&ctx); - mbedtls_sha1_update_ret(&ctx, (const unsigned char*)key.c_str(), key.length()); - mbedtls_sha1_finish_ret(&ctx, hash); -#endif - mbedtls_sha1_free(&ctx); + String k = key + WS_STR_UUID; + SHA1Builder sha1; + sha1.begin(); + sha1.add((const uint8_t*)k.c_str(), k.length()); + sha1.calculate(); + sha1.getBytes(hash); #endif base64_encodestate _state; base64_init_encodestate(&_state); diff --git a/src/ESPAsyncWebServer.h b/src/ESPAsyncWebServer.h index 8533df6..3865333 100644 --- a/src/ESPAsyncWebServer.h +++ b/src/ESPAsyncWebServer.h @@ -40,10 +40,10 @@ #error Platform not supported #endif -#define ASYNCWEBSERVER_VERSION "2.10.4" +#define ASYNCWEBSERVER_VERSION "2.10.5" #define ASYNCWEBSERVER_VERSION_MAJOR 2 #define ASYNCWEBSERVER_VERSION_MINOR 10 -#define ASYNCWEBSERVER_VERSION_REVISION 4 +#define ASYNCWEBSERVER_VERSION_REVISION 5 #define ASYNCWEBSERVER_FORK_mathieucarbou #ifdef ASYNCWEBSERVER_REGEX diff --git a/src/WebAuthentication.cpp b/src/WebAuthentication.cpp index 2f122d7..8396795 100644 --- a/src/WebAuthentication.cpp +++ b/src/WebAuthentication.cpp @@ -21,7 +21,7 @@ #include "WebAuthentication.h" #include #ifdef ESP32 -#include "mbedtls/md5.h" +#include #else #include "md5.h" #endif @@ -66,35 +66,29 @@ bool checkBasicAuthentication(const char * hash, const char * username, const ch static bool getMD5(uint8_t * data, uint16_t len, char * output){//33 bytes or more #ifdef ESP32 - mbedtls_md5_context _ctx; + MD5Builder md5; + md5.begin(); + md5.add(data, len); + md5.calculate(); + md5.getChars(output); #else - md5_context_t _ctx; -#endif - uint8_t i; + md5_context_t _ctx; + uint8_t * _buf = (uint8_t*)malloc(16); if(_buf == NULL) return false; memset(_buf, 0x00, 16); -#ifdef ESP32 - mbedtls_md5_init(&_ctx); -#if ESP_IDF_VERSION_MAJOR == 5 - mbedtls_md5_starts(&_ctx); - mbedtls_md5_update(&_ctx, data, len); - mbedtls_md5_finish(&_ctx, _buf); -#else - mbedtls_md5_starts_ret(&_ctx); - mbedtls_md5_update_ret(&_ctx, data, len); - mbedtls_md5_finish_ret(&_ctx, _buf); -#endif -#else + MD5Init(&_ctx); MD5Update(&_ctx, data, len); MD5Final(_buf, &_ctx); -#endif - for(i = 0; i < 16; i++) { + + for(uint8_t i = 0; i < 16; i++) { sprintf_P(output + (i * 2), PSTR("%02x"), _buf[i]); } + free(_buf); +#endif return true; } diff --git a/src/port/SHA1Builder.cpp b/src/port/SHA1Builder.cpp new file mode 100644 index 0000000..901fb80 --- /dev/null +++ b/src/port/SHA1Builder.cpp @@ -0,0 +1,284 @@ +/* + * FIPS-180-1 compliant SHA-1 implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + * Modified for esp32 by Lucas Saavedra Vaz on 11 Jan 2024 + */ + +#include +#if ESP_IDF_VERSION_MAJOR < 5 + +#include "SHA1Builder.h" + +// 32-bit integer manipulation macros (big endian) + +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n, b, i) \ + { (n) = ((uint32_t)(b)[(i)] << 24) | ((uint32_t)(b)[(i) + 1] << 16) | ((uint32_t)(b)[(i) + 2] << 8) | ((uint32_t)(b)[(i) + 3]); } +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n, b, i) \ + { \ + (b)[(i)] = (uint8_t)((n) >> 24); \ + (b)[(i) + 1] = (uint8_t)((n) >> 16); \ + (b)[(i) + 2] = (uint8_t)((n) >> 8); \ + (b)[(i) + 3] = (uint8_t)((n)); \ + } +#endif + +// Constants + +static const uint8_t sha1_padding[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +// Private methods + +void SHA1Builder::process(const uint8_t *data) { + uint32_t temp, W[16], A, B, C, D, E; + + GET_UINT32_BE(W[0], data, 0); + GET_UINT32_BE(W[1], data, 4); + GET_UINT32_BE(W[2], data, 8); + GET_UINT32_BE(W[3], data, 12); + GET_UINT32_BE(W[4], data, 16); + GET_UINT32_BE(W[5], data, 20); + GET_UINT32_BE(W[6], data, 24); + GET_UINT32_BE(W[7], data, 28); + GET_UINT32_BE(W[8], data, 32); + GET_UINT32_BE(W[9], data, 36); + GET_UINT32_BE(W[10], data, 40); + GET_UINT32_BE(W[11], data, 44); + GET_UINT32_BE(W[12], data, 48); + GET_UINT32_BE(W[13], data, 52); + GET_UINT32_BE(W[14], data, 56); + GET_UINT32_BE(W[15], data, 60); + +#define sha1_S(x, n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + +#define sha1_R(t) (temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ W[(t - 14) & 0x0F] ^ W[t & 0x0F], (W[t & 0x0F] = sha1_S(temp, 1))) + +#define sha1_P(a, b, c, d, e, x) \ + { \ + e += sha1_S(a, 5) + sha1_F(b, c, d) + sha1_K + x; \ + b = sha1_S(b, 30); \ + } + + A = state[0]; + B = state[1]; + C = state[2]; + D = state[3]; + E = state[4]; + +#define sha1_F(x, y, z) (z ^ (x & (y ^ z))) +#define sha1_K 0x5A827999 + + sha1_P(A, B, C, D, E, W[0]); + sha1_P(E, A, B, C, D, W[1]); + sha1_P(D, E, A, B, C, W[2]); + sha1_P(C, D, E, A, B, W[3]); + sha1_P(B, C, D, E, A, W[4]); + sha1_P(A, B, C, D, E, W[5]); + sha1_P(E, A, B, C, D, W[6]); + sha1_P(D, E, A, B, C, W[7]); + sha1_P(C, D, E, A, B, W[8]); + sha1_P(B, C, D, E, A, W[9]); + sha1_P(A, B, C, D, E, W[10]); + sha1_P(E, A, B, C, D, W[11]); + sha1_P(D, E, A, B, C, W[12]); + sha1_P(C, D, E, A, B, W[13]); + sha1_P(B, C, D, E, A, W[14]); + sha1_P(A, B, C, D, E, W[15]); + sha1_P(E, A, B, C, D, sha1_R(16)); + sha1_P(D, E, A, B, C, sha1_R(17)); + sha1_P(C, D, E, A, B, sha1_R(18)); + sha1_P(B, C, D, E, A, sha1_R(19)); + +#undef sha1_K +#undef sha1_F + +#define sha1_F(x, y, z) (x ^ y ^ z) +#define sha1_K 0x6ED9EBA1 + + sha1_P(A, B, C, D, E, sha1_R(20)); + sha1_P(E, A, B, C, D, sha1_R(21)); + sha1_P(D, E, A, B, C, sha1_R(22)); + sha1_P(C, D, E, A, B, sha1_R(23)); + sha1_P(B, C, D, E, A, sha1_R(24)); + sha1_P(A, B, C, D, E, sha1_R(25)); + sha1_P(E, A, B, C, D, sha1_R(26)); + sha1_P(D, E, A, B, C, sha1_R(27)); + sha1_P(C, D, E, A, B, sha1_R(28)); + sha1_P(B, C, D, E, A, sha1_R(29)); + sha1_P(A, B, C, D, E, sha1_R(30)); + sha1_P(E, A, B, C, D, sha1_R(31)); + sha1_P(D, E, A, B, C, sha1_R(32)); + sha1_P(C, D, E, A, B, sha1_R(33)); + sha1_P(B, C, D, E, A, sha1_R(34)); + sha1_P(A, B, C, D, E, sha1_R(35)); + sha1_P(E, A, B, C, D, sha1_R(36)); + sha1_P(D, E, A, B, C, sha1_R(37)); + sha1_P(C, D, E, A, B, sha1_R(38)); + sha1_P(B, C, D, E, A, sha1_R(39)); + +#undef sha1_K +#undef sha1_F + +#define sha1_F(x, y, z) ((x & y) | (z & (x | y))) +#define sha1_K 0x8F1BBCDC + + sha1_P(A, B, C, D, E, sha1_R(40)); + sha1_P(E, A, B, C, D, sha1_R(41)); + sha1_P(D, E, A, B, C, sha1_R(42)); + sha1_P(C, D, E, A, B, sha1_R(43)); + sha1_P(B, C, D, E, A, sha1_R(44)); + sha1_P(A, B, C, D, E, sha1_R(45)); + sha1_P(E, A, B, C, D, sha1_R(46)); + sha1_P(D, E, A, B, C, sha1_R(47)); + sha1_P(C, D, E, A, B, sha1_R(48)); + sha1_P(B, C, D, E, A, sha1_R(49)); + sha1_P(A, B, C, D, E, sha1_R(50)); + sha1_P(E, A, B, C, D, sha1_R(51)); + sha1_P(D, E, A, B, C, sha1_R(52)); + sha1_P(C, D, E, A, B, sha1_R(53)); + sha1_P(B, C, D, E, A, sha1_R(54)); + sha1_P(A, B, C, D, E, sha1_R(55)); + sha1_P(E, A, B, C, D, sha1_R(56)); + sha1_P(D, E, A, B, C, sha1_R(57)); + sha1_P(C, D, E, A, B, sha1_R(58)); + sha1_P(B, C, D, E, A, sha1_R(59)); + +#undef sha1_K +#undef sha1_F + +#define sha1_F(x, y, z) (x ^ y ^ z) +#define sha1_K 0xCA62C1D6 + + sha1_P(A, B, C, D, E, sha1_R(60)); + sha1_P(E, A, B, C, D, sha1_R(61)); + sha1_P(D, E, A, B, C, sha1_R(62)); + sha1_P(C, D, E, A, B, sha1_R(63)); + sha1_P(B, C, D, E, A, sha1_R(64)); + sha1_P(A, B, C, D, E, sha1_R(65)); + sha1_P(E, A, B, C, D, sha1_R(66)); + sha1_P(D, E, A, B, C, sha1_R(67)); + sha1_P(C, D, E, A, B, sha1_R(68)); + sha1_P(B, C, D, E, A, sha1_R(69)); + sha1_P(A, B, C, D, E, sha1_R(70)); + sha1_P(E, A, B, C, D, sha1_R(71)); + sha1_P(D, E, A, B, C, sha1_R(72)); + sha1_P(C, D, E, A, B, sha1_R(73)); + sha1_P(B, C, D, E, A, sha1_R(74)); + sha1_P(A, B, C, D, E, sha1_R(75)); + sha1_P(E, A, B, C, D, sha1_R(76)); + sha1_P(D, E, A, B, C, sha1_R(77)); + sha1_P(C, D, E, A, B, sha1_R(78)); + sha1_P(B, C, D, E, A, sha1_R(79)); + +#undef sha1_K +#undef sha1_F + + state[0] += A; + state[1] += B; + state[2] += C; + state[3] += D; + state[4] += E; +} + +// Public methods + +void SHA1Builder::begin(void) { + total[0] = 0; + total[1] = 0; + + state[0] = 0x67452301; + state[1] = 0xEFCDAB89; + state[2] = 0x98BADCFE; + state[3] = 0x10325476; + state[4] = 0xC3D2E1F0; + + memset(buffer, 0x00, sizeof(buffer)); + memset(hash, 0x00, sizeof(hash)); +} + +void SHA1Builder::add(const uint8_t *data, size_t len) { + size_t fill; + uint32_t left; + + if (len == 0) { + return; + } + + left = total[0] & 0x3F; + fill = 64 - left; + + total[0] += (uint32_t)len; + total[0] &= 0xFFFFFFFF; + + if (total[0] < (uint32_t)len) { + total[1]++; + } + + if (left && len >= fill) { + memcpy((void *)(buffer + left), data, fill); + process(buffer); + data += fill; + len -= fill; + left = 0; + } + + while (len >= 64) { + process(data); + data += 64; + len -= 64; + } + + if (len > 0) { + memcpy((void *)(buffer + left), data, len); + } +} + +void SHA1Builder::calculate(void) { + uint32_t last, padn; + uint32_t high, low; + uint8_t msglen[8]; + + high = (total[0] >> 29) | (total[1] << 3); + low = (total[0] << 3); + + PUT_UINT32_BE(high, msglen, 0); + PUT_UINT32_BE(low, msglen, 4); + + last = total[0] & 0x3F; + padn = (last < 56) ? (56 - last) : (120 - last); + + add((uint8_t *)sha1_padding, padn); + add(msglen, 8); + + PUT_UINT32_BE(state[0], hash, 0); + PUT_UINT32_BE(state[1], hash, 4); + PUT_UINT32_BE(state[2], hash, 8); + PUT_UINT32_BE(state[3], hash, 12); + PUT_UINT32_BE(state[4], hash, 16); +} + +void SHA1Builder::getBytes(uint8_t *output) { + memcpy(output, hash, SHA1_HASH_SIZE); +} + +#endif // ESP_IDF_VERSION_MAJOR < 5 diff --git a/src/port/SHA1Builder.h b/src/port/SHA1Builder.h new file mode 100644 index 0000000..da9a77a --- /dev/null +++ b/src/port/SHA1Builder.h @@ -0,0 +1,39 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SHA1Builder_h +#define SHA1Builder_h + +#include +#include + +#define SHA1_HASH_SIZE 20 + +class SHA1Builder { + private: + uint32_t total[2]; /* number of bytes processed */ + uint32_t state[5]; /* intermediate digest state */ + unsigned char buffer[64]; /* data block being processed */ + uint8_t hash[SHA1_HASH_SIZE]; /* SHA-1 result */ + + void process(const uint8_t* data); + + public: + void begin(); + void add(const uint8_t* data, size_t len); + void calculate(); + void getBytes(uint8_t* output); +}; + +#endif // SHA1Builder_h