commit 55f8e8949b162f512e35ceb72c305641e468ed64
parent ee9242b65847d58d08b93abb9ce4cd5e51413d78
Author: vaplv <vaplv@free.fr>
Date: Wed, 12 Oct 2022 09:08:55 +0200
Merge remote-tracking branch 'origin/develop' into feature_posix_make
Diffstat:
3 files changed, 230 insertions(+), 156 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -38,8 +38,8 @@ include(rcmake)
# Configure and define targets
################################################################################
set(VERSION_MAJOR 0)
-set(VERSION_MINOR 12)
-set(VERSION_PATCH 1)
+set(VERSION_MINOR 13)
+set(VERSION_PATCH 0)
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
set(RSYS_FILES_SRC
diff --git a/src/hash.c b/src/hash.c
@@ -43,177 +43,234 @@ static const uint32_t k[64] = {
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
-/*******************************************************************************
- * Helper functions
- ******************************************************************************/
-/* Right rotation */
-static FINLINE uint32_t
-rrot(const uint32_t ui, const unsigned int count)
-{
- ASSERT(count <= 32);
- return ui >> count | ui << (32 - count);
-}
-
+/* Most of this code comes from GnuPG's cipher/sha1.c */
static void
-get_chunk512(char dst[64], const size_t ichunk512, void* ctx)
+sha256_process_chunk(struct sha256_ctx* ctx, const char chunk[64])
{
- struct buffer* buf = ctx;
- const char* chunk = NULL;
- size_t chunk_sz = 0;
- const size_t offset = ichunk512*(sizeof(char[64]));
- ASSERT(buf && offset < buf->len);
-
- chunk = buf->mem + offset;
- chunk_sz = MMIN(buf->len - offset, sizeof(char[64]));
- memcpy(dst, chunk, chunk_sz);
+ uint32_t w[16];
+ uint32_t a, b, c, d, e, f, g, h;
+ uint32_t i;
+
+ uint32_t tm;
+ uint32_t t0, t1;
+
+ ASSERT(ctx);
+
+ FOR_EACH(i, 0, 16) {
+ w[i] = big_endian_32(((uint32_t*)chunk)[i]);
+ }
+
+ a = ctx->state[0];
+ b = ctx->state[1];
+ c = ctx->state[2];
+ d = ctx->state[3];
+ e = ctx->state[4];
+ f = ctx->state[5];
+ g = ctx->state[6];
+ h = ctx->state[7];
+
+ #define ROL(X, N) (((X) << (N)) | ((X) >> (32 - (N))))
+ #define S0(X) (ROL(X,25)^ROL(X,14)^(X>>3))
+ #define S1(X) (ROL(X,15)^ROL(X,13)^(X>>10))
+ #define SS0(X) (ROL(X,30)^ROL(X,19)^ROL(X,10))
+ #define SS1(X) (ROL(X,26)^ROL(X,21)^ROL(X,7))
+ #define M(I) (tm = S1(w[(I- 2)&0x0f]) + w[(I-7)&0x0f] \
+ + S0(w[(I-15)&0x0f]) + w[I&0x0f], w[I&0x0f] = tm)
+ #define F2(A, B, C) (( A & B ) | (C & (A | B)))
+ #define F1(E, F, G) (G ^ (E & (F ^ G)))
+ #define R(A, B, C, D, E, F, G, H, K, M) { \
+ t0 = SS0(A) + F2(A, B, C); \
+ t1 = H + SS1(E) + F1(E, F, G) + K + M; \
+ D += t1; \
+ H = t0 + t1; \
+ } (void)0
+
+ R( a, b, c, d, e, f, g, h, k[ 0], w[ 0] );
+ R( h, a, b, c, d, e, f, g, k[ 1], w[ 1] );
+ R( g, h, a, b, c, d, e, f, k[ 2], w[ 2] );
+ R( f, g, h, a, b, c, d, e, k[ 3], w[ 3] );
+ R( e, f, g, h, a, b, c, d, k[ 4], w[ 4] );
+ R( d, e, f, g, h, a, b, c, k[ 5], w[ 5] );
+ R( c, d, e, f, g, h, a, b, k[ 6], w[ 6] );
+ R( b, c, d, e, f, g, h, a, k[ 7], w[ 7] );
+ R( a, b, c, d, e, f, g, h, k[ 8], w[ 8] );
+ R( h, a, b, c, d, e, f, g, k[ 9], w[ 9] );
+ R( g, h, a, b, c, d, e, f, k[10], w[10] );
+ R( f, g, h, a, b, c, d, e, k[11], w[11] );
+ R( e, f, g, h, a, b, c, d, k[12], w[12] );
+ R( d, e, f, g, h, a, b, c, k[13], w[13] );
+ R( c, d, e, f, g, h, a, b, k[14], w[14] );
+ R( b, c, d, e, f, g, h, a, k[15], w[15] );
+ R( a, b, c, d, e, f, g, h, k[16], M(16) );
+ R( h, a, b, c, d, e, f, g, k[17], M(17) );
+ R( g, h, a, b, c, d, e, f, k[18], M(18) );
+ R( f, g, h, a, b, c, d, e, k[19], M(19) );
+ R( e, f, g, h, a, b, c, d, k[20], M(20) );
+ R( d, e, f, g, h, a, b, c, k[21], M(21) );
+ R( c, d, e, f, g, h, a, b, k[22], M(22) );
+ R( b, c, d, e, f, g, h, a, k[23], M(23) );
+ R( a, b, c, d, e, f, g, h, k[24], M(24) );
+ R( h, a, b, c, d, e, f, g, k[25], M(25) );
+ R( g, h, a, b, c, d, e, f, k[26], M(26) );
+ R( f, g, h, a, b, c, d, e, k[27], M(27) );
+ R( e, f, g, h, a, b, c, d, k[28], M(28) );
+ R( d, e, f, g, h, a, b, c, k[29], M(29) );
+ R( c, d, e, f, g, h, a, b, k[30], M(30) );
+ R( b, c, d, e, f, g, h, a, k[31], M(31) );
+ R( a, b, c, d, e, f, g, h, k[32], M(32) );
+ R( h, a, b, c, d, e, f, g, k[33], M(33) );
+ R( g, h, a, b, c, d, e, f, k[34], M(34) );
+ R( f, g, h, a, b, c, d, e, k[35], M(35) );
+ R( e, f, g, h, a, b, c, d, k[36], M(36) );
+ R( d, e, f, g, h, a, b, c, k[37], M(37) );
+ R( c, d, e, f, g, h, a, b, k[38], M(38) );
+ R( b, c, d, e, f, g, h, a, k[39], M(39) );
+ R( a, b, c, d, e, f, g, h, k[40], M(40) );
+ R( h, a, b, c, d, e, f, g, k[41], M(41) );
+ R( g, h, a, b, c, d, e, f, k[42], M(42) );
+ R( f, g, h, a, b, c, d, e, k[43], M(43) );
+ R( e, f, g, h, a, b, c, d, k[44], M(44) );
+ R( d, e, f, g, h, a, b, c, k[45], M(45) );
+ R( c, d, e, f, g, h, a, b, k[46], M(46) );
+ R( b, c, d, e, f, g, h, a, k[47], M(47) );
+ R( a, b, c, d, e, f, g, h, k[48], M(48) );
+ R( h, a, b, c, d, e, f, g, k[49], M(49) );
+ R( g, h, a, b, c, d, e, f, k[50], M(50) );
+ R( f, g, h, a, b, c, d, e, k[51], M(51) );
+ R( e, f, g, h, a, b, c, d, k[52], M(52) );
+ R( d, e, f, g, h, a, b, c, k[53], M(53) );
+ R( c, d, e, f, g, h, a, b, k[54], M(54) );
+ R( b, c, d, e, f, g, h, a, k[55], M(55) );
+ R( a, b, c, d, e, f, g, h, k[56], M(56) );
+ R( h, a, b, c, d, e, f, g, k[57], M(57) );
+ R( g, h, a, b, c, d, e, f, k[58], M(58) );
+ R( f, g, h, a, b, c, d, e, k[59], M(59) );
+ R( e, f, g, h, a, b, c, d, k[60], M(60) );
+ R( d, e, f, g, h, a, b, c, k[61], M(61) );
+ R( c, d, e, f, g, h, a, b, k[62], M(62) );
+ R( b, c, d, e, f, g, h, a, k[63], M(63) );
+
+ ctx->state[0] += a;
+ ctx->state[1] += b;
+ ctx->state[2] += c;
+ ctx->state[3] += d;
+ ctx->state[4] += e;
+ ctx->state[5] += f;
+ ctx->state[6] += g;
+ ctx->state[7] += h;
}
/*******************************************************************************
* Exported functions
******************************************************************************/
void
-hash_sha256
- (const void* data,
- const size_t len,
- hash256_T hash)
+sha256_ctx_init(struct sha256_ctx* ctx)
{
- struct chunked_data_desc desc = CHUNKED_DATA_DESC_NULL;
- struct buffer buf;
+ /* Initial hash values: first 32 bits of the fractional parts of the square
+ * roots of the first 8 primes 2..19 */
+ ctx->state[0] = 0x6a09e667;
+ ctx->state[1] = 0xbb67ae85;
+ ctx->state[2] = 0x3c6ef372;
+ ctx->state[3] = 0xa54ff53a;
+ ctx->state[4] = 0x510e527f;
+ ctx->state[5] = 0x9b05688c;
+ ctx->state[6] = 0x1f83d9ab;
+ ctx->state[7] = 0x5be0cd19;
+ ctx->len = 0;
+ ctx->nbits = 0;
+}
- buf.mem = data;
- buf.len = len;
+void
+sha256_ctx_update
+ (struct sha256_ctx* ctx,
+ const char* bytes,
+ size_t len)
+{
+ size_t n;
+ uint32_t i;
+ ASSERT(ctx);
+ ASSERT(bytes || !len);
+
+ if(ctx->len) {
+ n = MMIN(64 - ctx->len, len);
+ memcpy(ctx->chunk + ctx->len, bytes, n);
+ ctx->len += (uint32_t)n;
+ bytes += n;
+ len -= n;
+
+ if(ctx->len == 64) {
+ sha256_process_chunk(ctx, ctx->chunk);
+ ctx->nbits += 512;
+ ctx->len = 0;
+ }
+ }
- desc.get_chunk512 = get_chunk512;
- desc.size = len;
- desc.context = &buf;
+ if(len >= 64) {
+ n = len / 64;
+ FOR_EACH(i, 0, n) {
+ sha256_process_chunk(ctx, bytes);
+ bytes += 64;
+ }
+ ctx->nbits += n * 512;
+ len -= n * 64;
+ }
- hash_sha256_chunked_data(&desc, hash);
+ if(len) {
+ memcpy(ctx->chunk, bytes, len);
+ ctx->len = (uint32_t)len;
+ }
}
void
-hash_sha256_chunked_data
- (struct chunked_data_desc* data,
- hash256_T hash)
+sha256_ctx_finalize(struct sha256_ctx* ctx, hash256_T hash)
{
- /* Actually, the size of one chunk is 64 bytes. Anyway, note that after the
- * last byte of the data to digest, one has to store 9 additionnal bytes: 1
- * to mark the end of the data and 8 used to save the effective data length.
- * Such tailing bytes can exceed the 64 bytes length of the chunk. Since the
- * overall message length must be aligned on 64 bytes we thus pre-allocate an
- * array whose size is 2 times the chunk size */
- char buffer[64*2];
-
- size_t msg_sz = 0;
- size_t ichunk = 0;
- size_t nchunks = 0;
- size_t ichunk_last_byte = 0; /* Chunk id the last data byte */
- size_t remaining_data_sz = 0;
+ uint32_t i;
- /* Initial hash values: first 32 bits of the fractional parts of the square
- * roots of the first 8 primes 2..19 */
- uint32_t h0 = 0x6a09e667;
- uint32_t h1 = 0xbb67ae85;
- uint32_t h2 = 0x3c6ef372;
- uint32_t h3 = 0xa54ff53a;
- uint32_t h4 = 0x510e527f;
- uint32_t h5 = 0x9b05688c;
- uint32_t h6 = 0x1f83d9ab;
- uint32_t h7 = 0x5be0cd19;
- ASSERT(data && hash);
-
- remaining_data_sz = data->size;
-
- /* Compute the overall size of the message */
- msg_sz = ALIGN_SIZE
- (data->size + 1/*Byte of the '1' bit*/ + 8/*message len*/, 64u);
-
- ASSERT((msg_sz % 64) == 0);
- nchunks = msg_sz / 64; /* #chunks of 512 bits */
-
- /* Index of the chunk containing the last data byte */
- ichunk_last_byte = data->size / 64;
-
- FOR_EACH(ichunk, 0, nchunks) {
- char* chunk = NULL;
- uint32_t w[64] = {0};
- uint32_t a=h0, b=h1, c=h2, d=h3, e=h4, f=h5, g=h6, h=h7;
- int i;
-
- if(ichunk > ichunk_last_byte) {
- chunk = buffer + 64;
- } else {
- chunk = buffer;
-
- /* Fetch the user data if any */
- if(remaining_data_sz) {
- ASSERT(data->get_chunk512);
- data->get_chunk512(buffer, ichunk, data->context);
- remaining_data_sz = remaining_data_sz > 64
- ? remaining_data_sz - 64 : 0;
- }
-
- /* Setup the tailing bytes of the message */
- if(ichunk == ichunk_last_byte) {
- char* remaining_msg = buffer;
- const size_t remaining_msg_sz = ichunk_last_byte==nchunks-1 ? 64 : 128;
-
- /* Id after the last data byte */
- const size_t ibyte_len = data->size % 64;
-
- /* Setup the '1' bit that marks the end of the data */
- remaining_msg[ibyte_len] = (char)0x80u;
-
- /* Clean up the bytes after the data up to the last 8 bytes */
- memset(remaining_msg + ibyte_len + 1, 0,
- remaining_msg_sz - ibyte_len - 1 - 8);
-
- /* Store the message 8*len in big endian */
- *(uint64_t*)(remaining_msg + remaining_msg_sz-8) =
- big_endian_64(data->size*8);
- }
- }
+ ASSERT(ctx && hash);
- FOR_EACH(i, 0, 16) {
- w[i] = big_endian_32(((uint32_t*)chunk)[i]);
- }
- FOR_EACH(i, 16, 64) {
- const uint32_t s0 = rrot(w[i-15],7) ^ rrot(w[i-15],18) ^ (w[i-15] >> 3);
- const uint32_t s1 = rrot(w[i-2],17) ^ rrot(w[i-2], 19) ^ (w[i-2] >> 10);
- w[i] = w[i-16] + s0 + w[i-7] + s1;
- }
+ ctx->nbits += ctx->len * 8; /* Update the message's length */
+ i = ctx->len;
- /* Compress the chunk */
- FOR_EACH(i, 0, 64) {
- const uint32_t s1 = rrot(e, 6) ^ rrot(e, 11) ^ rrot(e, 25);
- const uint32_t ch = (e & f) ^ ((~e) & g);
- const uint32_t tmp1 = h + s1 + ch + k[i] + w[i];
- const uint32_t s0 = rrot(a, 2) ^ rrot(a, 13) ^ rrot(a, 22);
- const uint32_t maj = (a & b) ^ (a & c) ^ (b & c);
- const uint32_t tmp2 = s0 + maj;
-
- h = g;
- g = f;
- f = e;
- e = d + tmp1;
- d = c;
- c = b;
- b = a;
- a = tmp1 + tmp2;
- }
+ /* Setup the '1' bit that marks the end of the data */
+ ctx->chunk[i++] = (char)0x80;
- /* Update hash with the current compressed chunk */
- h0+=a; h1+=b; h2+=c; h3+=d; h4+=e; h5+=f; h6+=g; h7+=h;
+ /* Clean up the bytes after the data up to the last 8 bytes */
+ if(ctx->len < 56) {
+ memset(ctx->chunk+i, 0, 56-i);
+ } else {
+ memset(ctx->chunk+i, 0, 64-i);
+ sha256_process_chunk(ctx, ctx->chunk);
+ memset(ctx->chunk, 0, 56);
}
- /* Write the results */
- ((uint32_t*)hash)[0] = big_endian_32(h0);
- ((uint32_t*)hash)[1] = big_endian_32(h1);
- ((uint32_t*)hash)[2] = big_endian_32(h2);
- ((uint32_t*)hash)[3] = big_endian_32(h3);
- ((uint32_t*)hash)[4] = big_endian_32(h4);
- ((uint32_t*)hash)[5] = big_endian_32(h5);
- ((uint32_t*)hash)[6] = big_endian_32(h6);
- ((uint32_t*)hash)[7] = big_endian_32(h7);
+ /* Store the message's length in bits */
+ *((uint64_t*)(ctx->chunk + 56)) = big_endian_64(ctx->nbits);
+ sha256_process_chunk(ctx, ctx->chunk);
+
+ /* Store result the result */
+ ((uint32_t*)hash)[0] = big_endian_32(ctx->state[0]);
+ ((uint32_t*)hash)[1] = big_endian_32(ctx->state[1]);
+ ((uint32_t*)hash)[2] = big_endian_32(ctx->state[2]);
+ ((uint32_t*)hash)[3] = big_endian_32(ctx->state[3]);
+ ((uint32_t*)hash)[4] = big_endian_32(ctx->state[4]);
+ ((uint32_t*)hash)[5] = big_endian_32(ctx->state[5]);
+ ((uint32_t*)hash)[6] = big_endian_32(ctx->state[6]);
+ ((uint32_t*)hash)[7] = big_endian_32(ctx->state[7]);
+}
+
+void
+hash_sha256
+ (const void* data,
+ const size_t len,
+ hash256_T hash)
+{
+ struct sha256_ctx ctx;
+ ASSERT(hash);
+ ASSERT(data || !len);
+
+ sha256_ctx_init(&ctx);
+ sha256_ctx_update(&ctx, data, len);
+ sha256_ctx_finalize(&ctx, hash);
}
void
diff --git a/src/hash.h b/src/hash.h
@@ -20,6 +20,13 @@
struct mem_allocator;
+struct sha256_ctx {
+ char chunk[64];
+ uint32_t len; /* #bytes registered in chunk */
+ uint32_t state[8]; /* Current hash state */
+ uint64_t nbits; /* Overall size of the message in bits */
+};
+
typedef char hash256_T[32];
struct chunked_data_desc {
@@ -77,14 +84,24 @@ hash_fnv64(const void* data, const size_t len)
BEGIN_DECLS
RSYS_API void
-hash_sha256
- (const void* data,
- const size_t len,
+sha256_ctx_init
+ (struct sha256_ctx* ctx);
+
+RSYS_API void
+sha256_ctx_update
+ (struct sha256_ctx* ctx,
+ const char* bytes,
+ const size_t len); /* #bytes */
+
+RSYS_API void
+sha256_ctx_finalize
+ (struct sha256_ctx* ctx,
hash256_T hash);
RSYS_API void
-hash_sha256_chunked_data
- (struct chunked_data_desc* data,
+hash_sha256
+ (const void* data,
+ const size_t len,
hash256_T hash);
RSYS_API void