commit fda402b

Michael Forney  ·  2026-05-15 19:46:50 +0000 UTC
parent 744b378
bearssl: Add SHA-512/256 implementation
2 files changed,  +235, -1
+234, -0
  1@@ -0,0 +1,234 @@
  2+From 4f6c794c471789bed5e078bb0330ff08bb5936ac Mon Sep 17 00:00:00 2001
  3+From: Michael Forney <mforney@mforney.org>
  4+Date: Fri, 15 May 2026 02:59:18 -0700
  5+Subject: [PATCH] Add br_sha512_256
  6+
  7+---
  8+ inc/bearssl_hash.h | 132 +++++++++++++++++++++++++++++++++++++++++----
  9+ src/hash/sha2big.c |  42 +++++++++++++++
 10+ 2 files changed, 164 insertions(+), 10 deletions(-)
 11+
 12+diff --git a/inc/bearssl_hash.h b/inc/bearssl_hash.h
 13+index ca4fa26..769e7ac 100644
 14+--- a/inc/bearssl_hash.h
 15++++ b/inc/bearssl_hash.h
 16+@@ -156,15 +156,16 @@ extern "C" {
 17+  *
 18+  * Implemented hash functions are:
 19+  *
 20+- * | Function  | Name    | Output length | State length |
 21+- * | :-------- | :------ | :-----------: | :----------: |
 22+- * | MD5       | md5     |     16        |     16       |
 23+- * | SHA-1     | sha1    |     20        |     20       |
 24+- * | SHA-224   | sha224  |     28        |     32       |
 25+- * | SHA-256   | sha256  |     32        |     32       |
 26+- * | SHA-384   | sha384  |     48        |     64       |
 27+- * | SHA-512   | sha512  |     64        |     64       |
 28+- * | MD5+SHA-1 | md5sha1 |     36        |     36       |
 29++ * | Function    | Name       | Output length | State length |
 30++ * | :---------- | :--------- | :-----------: | :----------: |
 31++ * | MD5         | md5        |     16        |     16       |
 32++ * | SHA-1       | sha1       |     20        |     20       |
 33++ * | SHA-224     | sha224     |     28        |     32       |
 34++ * | SHA-256     | sha256     |     32        |     32       |
 35++ * | SHA-384     | sha384     |     48        |     64       |
 36++ * | SHA-512     | sha512     |     64        |     64       |
 37++ * | SHA-512/256 | sha512_256 |     32        |     64       |
 38++ * | MD5+SHA-1   | md5sha1    |     36        |     36       |
 39+  *
 40+  * (MD5+SHA-1 is the concatenation of MD5 and SHA-1 computed over the
 41+  * same input; in the implementation, the internal data buffer is
 42+@@ -359,7 +360,7 @@ struct br_hash_class_ {
 43+  * -- First field is called 'vtable' and is a pointer to a
 44+  *    const-qualified br_hash_class instance (pointer is set by init()).
 45+  * -- SHA-224 and SHA-256 contexts are identical.
 46+- * -- SHA-384 and SHA-512 contexts are identical.
 47++ * -- SHA-384, SHA-512, and SHA-512/256 contexts are identical.
 48+  *
 49+  * Thus, contexts can be moved and cloned to capture the hash function
 50+  * current state; and there is no need for any explicit "release" function.
 51+@@ -961,6 +962,117 @@ void br_sha512_set_state(br_sha512_context *ctx,
 52+ #define br_sha512_set_state   br_sha384_set_state
 53+ #endif
 54+ 
 55++/**
 56++ * \brief Symbolic identifier for SHA-512/256.
 57++ *
 58++ * SHA-512/256 is the truncation of SHA-512 to 32 bytes with a
 59++ * special IV. It is not one of the functions identified in TLS,
 60++ * so we give it a symbolic identifier of value 0.
 61++ */
 62++#define br_sha512_256_ID     0
 63++
 64++/**
 65++ * \brief SHA-512 output size (in bytes).
 66++ */
 67++#define br_sha512_256_SIZE   32
 68++
 69++/**
 70++ * \brief Constant vtable for SHA-512/256.
 71++ */
 72++extern const br_hash_class br_sha512_256_vtable;
 73++
 74++#ifdef BR_DOXYGEN_IGNORE
 75++/**
 76++ * \brief SHA-512/256 context.
 77++ *
 78++ * First field is a pointer to the vtable; it is set by the initialisation
 79++ * function. Other fields are not supposed to be accessed by user code.
 80++ */
 81++typedef struct {
 82++	/**
 83++	 * \brief Pointer to vtable for this context.
 84++	 */
 85++	const br_hash_class *vtable;
 86++} br_sha512_256_context;
 87++#else
 88++typedef br_sha384_context br_sha512_256_context;
 89++#endif
 90++
 91++/**
 92++ * \brief SHA-512/256 context initialisation.
 93++ *
 94++ * This function initialises or resets a context for a new SHA-512/256
 95++ * computation. It also sets the vtable pointer.
 96++ *
 97++ * \param ctx   pointer to the context structure.
 98++ */
 99++void br_sha512_256_init(br_sha512_256_context *ctx);
100++
101++#ifdef BR_DOXYGEN_IGNORE
102++/**
103++ * \brief Inject some data bytes in a running SHA-512/256 computation.
104++ *
105++ * The provided context is updated with some data bytes. If the number
106++ * of bytes (`len`) is zero, then the data pointer (`data`) is ignored
107++ * and may be `NULL`, and this function does nothing.
108++ *
109++ * \param ctx    pointer to the context structure.
110++ * \param data   pointer to the injected data.
111++ * \param len    injected data length (in bytes).
112++ */
113++void br_sha512_256_update(br_sha512_256_context *ctx, const void *data, size_t len);
114++#else
115++#define br_sha512_256_update   br_sha384_update
116++#endif
117++
118++/**
119++ * \brief Compute SHA-512/256 output.
120++ *
121++ * The SHA-512/256 output for the concatenation of all bytes injected
122++ * in the provided context since the last initialisation or reset
123++ * call, is computed and written in the buffer pointed to by `out`.
124++ * The context itself is not modified, so extra bytes may be injected
125++ * afterwards to continue that computation.
126++ *
127++ * \param ctx   pointer to the context structure.
128++ * \param out   destination buffer for the hash output.
129++ */
130++void br_sha512_256_out(const br_sha512_256_context *ctx, void *out);
131++
132++#ifdef BR_DOXYGEN_IGNORE
133++/**
134++ * \brief Save SHA-512/256 running state.
135++ *
136++ * The running state for SHA-512/256 (output of the last internal
137++ * block processing) is written in the buffer pointed to by `out`.
138++ * The number of bytes injected since the last initialisation or
139++ * reset call is returned. The context is not modified.
140++ *
141++ * \param ctx   pointer to the context structure.
142++ * \param out   destination buffer for the running state.
143++ * \return  the injected total byte length.
144++ */
145++uint64_t br_sha512_256_state(const br_sha512_256_context *ctx, void *out);
146++#else
147++#define br_sha512_256_state   br_sha384_state
148++#endif
149++
150++#ifdef BR_DOXYGEN_IGNORE
151++/**
152++ * \brief Restore SHA-512/256 running state.
153++ *
154++ * The running state for SHA-512/256 is set to the provided values.
155++ *
156++ * \param ctx     pointer to the context structure.
157++ * \param stb     source buffer for the running state.
158++ * \param count   the injected total byte length.
159++ */
160++void br_sha512_256_set_state(br_sha512_256_context *ctx,
161++	const void *stb, uint64_t count);
162++#else
163++#define br_sha512_256_set_state   br_sha384_set_state
164++#endif
165++
166+ /*
167+  * "md5sha1" is a special hash function that computes both MD5 and SHA-1
168+  * on the same input, and produces a 36-byte output (MD5 and SHA-1
169+diff --git a/src/hash/sha2big.c b/src/hash/sha2big.c
170+index 5be92ed..a8b930c 100644
171+--- a/src/hash/sha2big.c
172++++ b/src/hash/sha2big.c
173+@@ -48,6 +48,13 @@ static const uint64_t IV512[8] = {
174+ 	0x1F83D9ABFB41BD6B, 0x5BE0CD19137E2179
175+ };
176+ 
177++static const uint64_t IV512_256[8] = {
178++	0x22312194FC2BF72C, 0x9F555FA3C84C64C2,
179++	0x2393B86B6F53B151, 0x963877195940EABD,
180++	0x96283EE2A88EFFE3, 0xBE5E1E2553863992,
181++	0x2B0199FC2C85B8AA, 0x0EB72DDC81C52CA2
182++};
183++
184+ static const uint64_t K[80] = {
185+ 	0x428A2F98D728AE22, 0x7137449123EF65CD,
186+ 	0xB5C0FBCFEC4D3B2F, 0xE9B5DBA58189DBBC,
187+@@ -246,6 +253,22 @@ br_sha512_out(const br_sha512_context *cc, void *dst)
188+ 	sha2big_out(cc, dst, 8);
189+ }
190+ 
191++/* see bearssl.h */
192++void
193++br_sha512_256_init(br_sha512_context *cc)
194++{
195++	cc->vtable = &br_sha512_256_vtable;
196++	memcpy(cc->val, IV512_256, sizeof IV512_256);
197++	cc->count = 0;
198++}
199++
200++/* see bearssl.h */
201++void
202++br_sha512_256_out(const br_sha512_context *cc, void *dst)
203++{
204++	sha2big_out(cc, dst, 4);
205++}
206++
207+ /* see bearssl.h */
208+ const br_hash_class br_sha384_vtable = {
209+ 	sizeof(br_sha384_context),
210+@@ -283,3 +306,22 @@ const br_hash_class br_sha512_vtable = {
211+ 	(void (*)(const br_hash_class **, const void *, uint64_t))
212+ 		&br_sha512_set_state
213+ };
214++
215++/* see bearssl.h */
216++const br_hash_class br_sha512_256_vtable = {
217++	sizeof(br_sha512_256_context),
218++	BR_HASHDESC_ID(br_sha512_ID)
219++		| BR_HASHDESC_OUT(32)
220++		| BR_HASHDESC_STATE(64)
221++		| BR_HASHDESC_LBLEN(7)
222++		| BR_HASHDESC_MD_PADDING
223++		| BR_HASHDESC_MD_PADDING_BE
224++		| BR_HASHDESC_MD_PADDING_128,
225++	(void (*)(const br_hash_class **))&br_sha512_256_init,
226++	(void (*)(const br_hash_class **, const void *, size_t))
227++		&br_sha512_256_update,
228++	(void (*)(const br_hash_class *const *, void *))&br_sha512_256_out,
229++	(uint64_t (*)(const br_hash_class *const *, void *))&br_sha512_256_state,
230++	(void (*)(const br_hash_class **, const void *, uint64_t))
231++		&br_sha512_256_set_state
232++};
233+-- 
234+2.54.0
235+
+1, -1
1@@ -1 +1 @@
2-0.6-39-g7bea48e r1
3+0.6-39-g7bea48e r2