rsys

Basic data structures and low-level features
git clone git://git.meso-star.fr/rsys.git
Log | Files | Refs | README | LICENSE

hash.c (9369B)


      1 /* Copyright (C) 2013-2023, 2025 Vincent Forest (vaplv@free.fr)
      2  *
      3  * The RSys library is free software: you can redistribute it and/or modify
      4  * it under the terms of the GNU General Public License as published
      5  * by the Free Software Foundation, either version 3 of the License, or
      6  * (at your option) any later version.
      7  *
      8  * The RSys library is distributed in the hope that it will be useful,
      9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     11  * GNU General Public License for more details.
     12  *
     13  * You should have received a copy of the GNU General Public License
     14  * along with the RSys library. If not, see <http://www.gnu.org/licenses/>. */
     15 
     16 #define _POSIX_C_SOURCE 200112L
     17 
     18 #include "endianness.h"
     19 #include "hash.h"
     20 #include "math.h"
     21 #include "mem_allocator.h"
     22 
     23 #include <string.h>
     24 
     25 struct buffer {
     26   const char* mem;
     27   size_t len;
     28 };
     29 
     30 /* Array of round constants: first 32 bits of the fractional parts of the cube
     31  * roots of the first 64 primes 2..311 */
     32 static const uint32_t k[64] = {
     33   0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
     34   0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
     35   0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
     36   0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
     37   0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
     38   0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
     39   0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
     40   0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
     41   0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
     42   0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
     43   0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
     44 };
     45 
     46 /* Most of this code comes from GnuPG's cipher/sha1.c */
     47 static void
     48 sha256_process_chunk(struct sha256_ctx* ctx, const char chunk[64])
     49 {
     50   uint32_t w[16];
     51   uint32_t a, b, c, d, e, f, g, h;
     52   uint32_t i;
     53 
     54   uint32_t tm;
     55   uint32_t t0, t1;
     56 
     57   ASSERT(ctx);
     58 
     59   FOR_EACH(i, 0, 16) {
     60     w[i] = big_endian_32(((uint32_t*)chunk)[i]);
     61   }
     62 
     63   a = ctx->state[0];
     64   b = ctx->state[1];
     65   c = ctx->state[2];
     66   d = ctx->state[3];
     67   e = ctx->state[4];
     68   f = ctx->state[5];
     69   g = ctx->state[6];
     70   h = ctx->state[7];
     71 
     72   #define ROL(X, N) (((X) << (N)) | ((X) >> (32 - (N))))
     73   #define S0(X) (ROL(X,25)^ROL(X,14)^(X>>3))
     74   #define S1(X) (ROL(X,15)^ROL(X,13)^(X>>10))
     75   #define SS0(X) (ROL(X,30)^ROL(X,19)^ROL(X,10))
     76   #define SS1(X) (ROL(X,26)^ROL(X,21)^ROL(X,7))
     77   #define M(I) (tm = S1(w[(I- 2)&0x0f]) + w[(I-7)&0x0f]                        \
     78                    + S0(w[(I-15)&0x0f]) + w[I&0x0f], w[I&0x0f] = tm)
     79   #define F2(A, B, C) (( A & B ) | (C & (A | B)))
     80   #define F1(E, F, G) (G ^ (E & (F ^ G)))
     81   #define R(A, B, C, D, E, F, G, H, K, M) {                                    \
     82     t0 = SS0(A) + F2(A, B, C);                                                 \
     83     t1 = H + SS1(E) + F1(E, F, G) + K + M;                                     \
     84     D += t1;                                                                   \
     85     H = t0 + t1;                                                               \
     86   } (void)0
     87 
     88   R( a, b, c, d, e, f, g, h, k[ 0], w[ 0] );
     89   R( h, a, b, c, d, e, f, g, k[ 1], w[ 1] );
     90   R( g, h, a, b, c, d, e, f, k[ 2], w[ 2] );
     91   R( f, g, h, a, b, c, d, e, k[ 3], w[ 3] );
     92   R( e, f, g, h, a, b, c, d, k[ 4], w[ 4] );
     93   R( d, e, f, g, h, a, b, c, k[ 5], w[ 5] );
     94   R( c, d, e, f, g, h, a, b, k[ 6], w[ 6] );
     95   R( b, c, d, e, f, g, h, a, k[ 7], w[ 7] );
     96   R( a, b, c, d, e, f, g, h, k[ 8], w[ 8] );
     97   R( h, a, b, c, d, e, f, g, k[ 9], w[ 9] );
     98   R( g, h, a, b, c, d, e, f, k[10], w[10] );
     99   R( f, g, h, a, b, c, d, e, k[11], w[11] );
    100   R( e, f, g, h, a, b, c, d, k[12], w[12] );
    101   R( d, e, f, g, h, a, b, c, k[13], w[13] );
    102   R( c, d, e, f, g, h, a, b, k[14], w[14] );
    103   R( b, c, d, e, f, g, h, a, k[15], w[15] );
    104   R( a, b, c, d, e, f, g, h, k[16], M(16) );
    105   R( h, a, b, c, d, e, f, g, k[17], M(17) );
    106   R( g, h, a, b, c, d, e, f, k[18], M(18) );
    107   R( f, g, h, a, b, c, d, e, k[19], M(19) );
    108   R( e, f, g, h, a, b, c, d, k[20], M(20) );
    109   R( d, e, f, g, h, a, b, c, k[21], M(21) );
    110   R( c, d, e, f, g, h, a, b, k[22], M(22) );
    111   R( b, c, d, e, f, g, h, a, k[23], M(23) );
    112   R( a, b, c, d, e, f, g, h, k[24], M(24) );
    113   R( h, a, b, c, d, e, f, g, k[25], M(25) );
    114   R( g, h, a, b, c, d, e, f, k[26], M(26) );
    115   R( f, g, h, a, b, c, d, e, k[27], M(27) );
    116   R( e, f, g, h, a, b, c, d, k[28], M(28) );
    117   R( d, e, f, g, h, a, b, c, k[29], M(29) );
    118   R( c, d, e, f, g, h, a, b, k[30], M(30) );
    119   R( b, c, d, e, f, g, h, a, k[31], M(31) );
    120   R( a, b, c, d, e, f, g, h, k[32], M(32) );
    121   R( h, a, b, c, d, e, f, g, k[33], M(33) );
    122   R( g, h, a, b, c, d, e, f, k[34], M(34) );
    123   R( f, g, h, a, b, c, d, e, k[35], M(35) );
    124   R( e, f, g, h, a, b, c, d, k[36], M(36) );
    125   R( d, e, f, g, h, a, b, c, k[37], M(37) );
    126   R( c, d, e, f, g, h, a, b, k[38], M(38) );
    127   R( b, c, d, e, f, g, h, a, k[39], M(39) );
    128   R( a, b, c, d, e, f, g, h, k[40], M(40) );
    129   R( h, a, b, c, d, e, f, g, k[41], M(41) );
    130   R( g, h, a, b, c, d, e, f, k[42], M(42) );
    131   R( f, g, h, a, b, c, d, e, k[43], M(43) );
    132   R( e, f, g, h, a, b, c, d, k[44], M(44) );
    133   R( d, e, f, g, h, a, b, c, k[45], M(45) );
    134   R( c, d, e, f, g, h, a, b, k[46], M(46) );
    135   R( b, c, d, e, f, g, h, a, k[47], M(47) );
    136   R( a, b, c, d, e, f, g, h, k[48], M(48) );
    137   R( h, a, b, c, d, e, f, g, k[49], M(49) );
    138   R( g, h, a, b, c, d, e, f, k[50], M(50) );
    139   R( f, g, h, a, b, c, d, e, k[51], M(51) );
    140   R( e, f, g, h, a, b, c, d, k[52], M(52) );
    141   R( d, e, f, g, h, a, b, c, k[53], M(53) );
    142   R( c, d, e, f, g, h, a, b, k[54], M(54) );
    143   R( b, c, d, e, f, g, h, a, k[55], M(55) );
    144   R( a, b, c, d, e, f, g, h, k[56], M(56) );
    145   R( h, a, b, c, d, e, f, g, k[57], M(57) );
    146   R( g, h, a, b, c, d, e, f, k[58], M(58) );
    147   R( f, g, h, a, b, c, d, e, k[59], M(59) );
    148   R( e, f, g, h, a, b, c, d, k[60], M(60) );
    149   R( d, e, f, g, h, a, b, c, k[61], M(61) );
    150   R( c, d, e, f, g, h, a, b, k[62], M(62) );
    151   R( b, c, d, e, f, g, h, a, k[63], M(63) );
    152 
    153   ctx->state[0] += a;
    154   ctx->state[1] += b;
    155   ctx->state[2] += c;
    156   ctx->state[3] += d;
    157   ctx->state[4] += e;
    158   ctx->state[5] += f;
    159   ctx->state[6] += g;
    160   ctx->state[7] += h;
    161 }
    162 
    163 /*******************************************************************************
    164  * Exported functions
    165  ******************************************************************************/
    166 void
    167 sha256_ctx_init(struct sha256_ctx* ctx)
    168 {
    169   /* Initial hash values: first 32 bits of the fractional parts of the square
    170    * roots of the first 8 primes 2..19 */
    171   ctx->state[0] = 0x6a09e667;
    172   ctx->state[1] = 0xbb67ae85;
    173   ctx->state[2] = 0x3c6ef372;
    174   ctx->state[3] = 0xa54ff53a;
    175   ctx->state[4] = 0x510e527f;
    176   ctx->state[5] = 0x9b05688c;
    177   ctx->state[6] = 0x1f83d9ab;
    178   ctx->state[7] = 0x5be0cd19;
    179   ctx->len = 0;
    180   ctx->nbits = 0;
    181 }
    182 
    183 void
    184 sha256_ctx_update
    185   (struct sha256_ctx* ctx,
    186    const char* bytes,
    187    size_t len)
    188 {
    189   size_t n;
    190   uint32_t i;
    191   ASSERT(ctx);
    192   ASSERT(bytes || !len);
    193 
    194   if(ctx->len) {
    195     n = MMIN(64 - ctx->len, len);
    196     memcpy(ctx->chunk + ctx->len, bytes, n);
    197     ctx->len += (uint32_t)n;
    198     bytes += n;
    199     len -= n;
    200 
    201     if(ctx->len == 64) {
    202       sha256_process_chunk(ctx,  ctx->chunk);
    203       ctx->nbits += 512;
    204       ctx->len = 0;
    205     }
    206   }
    207 
    208   if(len >= 64) {
    209     n = len / 64;
    210     FOR_EACH(i, 0, n) {
    211       sha256_process_chunk(ctx,  bytes);
    212       bytes += 64;
    213     }
    214     ctx->nbits += n * 512;
    215     len -= n * 64;
    216   }
    217 
    218   if(len) {
    219     memcpy(ctx->chunk, bytes, len);
    220     ctx->len = (uint32_t)len;
    221   }
    222 }
    223 
    224 void
    225 sha256_ctx_finalize(struct sha256_ctx* ctx, hash256_T hash)
    226 {
    227   uint32_t i;
    228 
    229   ASSERT(ctx && hash);
    230 
    231   ctx->nbits += ctx->len * 8; /* Update the message's length */
    232   i = ctx->len;
    233 
    234   /* Setup the '1' bit that marks the end of the data */
    235   ctx->chunk[i++] = (char)0x80;
    236 
    237   /* Clean up the bytes after the data up to the last 8 bytes */
    238   if(ctx->len < 56) {
    239     memset(ctx->chunk+i, 0, 56-i);
    240   } else {
    241     memset(ctx->chunk+i, 0, 64-i);
    242     sha256_process_chunk(ctx, ctx->chunk);
    243     memset(ctx->chunk, 0, 56);
    244   }
    245 
    246   /* Store the message's length in bits */
    247   *((uint64_t*)(ctx->chunk + 56)) = big_endian_64(ctx->nbits);
    248   sha256_process_chunk(ctx, ctx->chunk);
    249 
    250   /* Store result the result */
    251   ((uint32_t*)hash)[0] = big_endian_32(ctx->state[0]);
    252   ((uint32_t*)hash)[1] = big_endian_32(ctx->state[1]);
    253   ((uint32_t*)hash)[2] = big_endian_32(ctx->state[2]);
    254   ((uint32_t*)hash)[3] = big_endian_32(ctx->state[3]);
    255   ((uint32_t*)hash)[4] = big_endian_32(ctx->state[4]);
    256   ((uint32_t*)hash)[5] = big_endian_32(ctx->state[5]);
    257   ((uint32_t*)hash)[6] = big_endian_32(ctx->state[6]);
    258   ((uint32_t*)hash)[7] = big_endian_32(ctx->state[7]);
    259 }
    260 
    261 void
    262 hash_sha256
    263   (const void* data,
    264    const size_t len,
    265    hash256_T hash)
    266 {
    267   struct sha256_ctx ctx;
    268   ASSERT(hash);
    269   ASSERT(data || !len);
    270 
    271   sha256_ctx_init(&ctx);
    272   sha256_ctx_update(&ctx, data, len);
    273   sha256_ctx_finalize(&ctx, hash);
    274 }
    275 
    276 void
    277 hash256_to_cstr(const hash256_T hash, char cstr[65])
    278 {
    279   size_t i;
    280   ASSERT(hash && cstr);
    281   FOR_EACH(i, 0, sizeof(hash256_T)) {
    282     sprintf(cstr+i*2, "%02x", (uint8_t)hash[i]);
    283   }
    284 }
    285 
    286 int
    287 hash256_eq(const hash256_T hash0, const hash256_T hash1)
    288 {
    289   return memcmp(hash0, hash1, sizeof(hash256_T)) == 0;
    290 }