DeterministicESPAsyncWebServer 1.2.0
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
sha1.cpp
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file sha1.cpp
6 * @brief SHA-1 implementation.
7 *
8 * On Arduino (ESP32) targets, delegates to mbedtls_sha1() which uses the
9 * hardware SHA accelerator in the ESP32 and is significantly faster than the
10 * software implementation.
11 *
12 * On native (x86) test targets, uses a portable software implementation so
13 * unit tests run without mbedTLS installed.
14 */
15
16#include "sha1.h"
17
18#ifdef ARDUINO
19
20// --- ESP32 / Arduino: use mbedTLS (hardware-accelerated on ESP32) ----------
21#include "mbedtls/sha1.h"
22#include <string.h>
23
24void sha1(const uint8_t *data, size_t len, uint8_t digest[SHA1_DIGEST_LEN])
25{
26 (void)mbedtls_sha1(data, len, digest);
27}
28
29#else
30
31// --- Native / test: software SHA-1, no external dependencies ---------------
32#include <string.h>
33
34// ---------------------------------------------------------------------------
35// Helpers
36// ---------------------------------------------------------------------------
37
38static inline uint32_t rot32(uint32_t x, int n)
39{
40 return (x << n) | (x >> (32 - n));
41}
42
43static inline uint32_t load_be32(const uint8_t *p)
44{
45 return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) | ((uint32_t)p[2] << 8) | (uint32_t)p[3];
46}
47
48static inline void store_be32(uint8_t *p, uint32_t v)
49{
50 p[0] = (uint8_t)(v >> 24);
51 p[1] = (uint8_t)(v >> 16);
52 p[2] = (uint8_t)(v >> 8);
53 p[3] = (uint8_t)(v);
54}
55
56// ---------------------------------------------------------------------------
57// SHA-1 block compression (processes one 64-byte block)
58// ---------------------------------------------------------------------------
59
60static void sha1_block(uint32_t h[5], const uint8_t block[64])
61{
62 uint32_t w[80];
63 for (int i = 0; i < 16; i++)
64 w[i] = load_be32(block + i * 4);
65 for (int i = 16; i < 80; i++)
66 w[i] = rot32(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1);
67
68 uint32_t a = h[0], b = h[1], c = h[2], d = h[3], e = h[4];
69
70 for (int i = 0; i < 80; i++)
71 {
72 uint32_t f, k;
73 if (i < 20)
74 {
75 f = (b & c) | (~b & d);
76 k = 0x5A827999u;
77 }
78 else if (i < 40)
79 {
80 f = b ^ c ^ d;
81 k = 0x6ED9EBA1u;
82 }
83 else if (i < 60)
84 {
85 f = (b & c) | (b & d) | (c & d);
86 k = 0x8F1BBCDCu;
87 }
88 else
89 {
90 f = b ^ c ^ d;
91 k = 0xCA62C1D6u;
92 }
93
94 uint32_t tmp = rot32(a, 5) + f + e + k + w[i];
95 e = d;
96 d = c;
97 c = rot32(b, 30);
98 b = a;
99 a = tmp;
100 }
101
102 h[0] += a;
103 h[1] += b;
104 h[2] += c;
105 h[3] += d;
106 h[4] += e;
107}
108
109// ---------------------------------------------------------------------------
110// Public API
111// ---------------------------------------------------------------------------
112
113void sha1(const uint8_t *data, size_t len, uint8_t digest[SHA1_DIGEST_LEN])
114{
115 uint32_t h[5] = {0x67452301u, 0xEFCDAB89u, 0x98BADCFEu, 0x10325476u, 0xC3D2E1F0u};
116
117 // Process full 64-byte blocks
118 size_t blocks = len / 64;
119 for (size_t i = 0; i < blocks; i++)
120 sha1_block(h, data + i * 64);
121
122 // Build the padded final block(s)
123 uint8_t pad[128] = {};
124 size_t tail = len - blocks * 64;
125 memcpy(pad, data + blocks * 64, tail);
126 pad[tail] = 0x80;
127
128 // Bit-length goes in the last 8 bytes of the final block
129 uint64_t bit_len = (uint64_t)len * 8;
130 uint8_t *bl = (tail < 56) ? pad + 56 : pad + 120;
131 for (int i = 7; i >= 0; i--, bit_len >>= 8)
132 bl[i] = (uint8_t)bit_len;
133
134 sha1_block(h, pad);
135 if (tail >= 56)
136 sha1_block(h, pad + 64);
137
138 for (int i = 0; i < 5; i++)
139 store_be32(digest + i * 4, h[i]);
140}
141
142#endif // ARDUINO
void sha1(const uint8_t *data, size_t len, uint8_t digest[SHA1_DIGEST_LEN])
Compute a SHA-1 digest over an arbitrary byte buffer.
Definition sha1.cpp:24
Software SHA-1 implementation — no platform dependencies.
#define SHA1_DIGEST_LEN
SHA-1 digest length in bytes.
Definition sha1.h:22