luajitos

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

BLAKE2.c (6553B)


      1 /*
      2  * BLAKE2b Implementation
      3  * RFC 7693
      4  *
      5  * Fast cryptographic hash function, faster than SHA-2/SHA-3
      6  * Optimized for 64-bit platforms
      7  */
      8 
      9 #include <stdint.h>
     10 #include <string.h>
     11 #include <stdlib.h>
     12 
     13 /* BLAKE2b IV */
     14 static const uint64_t blake2b_iv[8] = {
     15     0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
     16     0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
     17     0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
     18     0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
     19 };
     20 
     21 /* BLAKE2b sigma (message schedule) */
     22 static const uint8_t blake2b_sigma[12][16] = {
     23     {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
     24     {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
     25     {11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4},
     26     {7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8},
     27     {9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13},
     28     {2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9},
     29     {12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11},
     30     {13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10},
     31     {6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5},
     32     {10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0},
     33     {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
     34     {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3}
     35 };
     36 
     37 #define ROR64(x, n) (((x) >> (n)) | ((x) << (64 - (n))))
     38 
     39 /* Load 64-bit little-endian */
     40 static inline uint64_t load64_le(const uint8_t *src) {
     41     return (uint64_t)src[0] |
     42            ((uint64_t)src[1] << 8) |
     43            ((uint64_t)src[2] << 16) |
     44            ((uint64_t)src[3] << 24) |
     45            ((uint64_t)src[4] << 32) |
     46            ((uint64_t)src[5] << 40) |
     47            ((uint64_t)src[6] << 48) |
     48            ((uint64_t)src[7] << 56);
     49 }
     50 
     51 /* Store 64-bit little-endian */
     52 static inline void store64_le(uint8_t *dst, uint64_t w) {
     53     dst[0] = (uint8_t)w;
     54     dst[1] = (uint8_t)(w >> 8);
     55     dst[2] = (uint8_t)(w >> 16);
     56     dst[3] = (uint8_t)(w >> 24);
     57     dst[4] = (uint8_t)(w >> 32);
     58     dst[5] = (uint8_t)(w >> 40);
     59     dst[6] = (uint8_t)(w >> 48);
     60     dst[7] = (uint8_t)(w >> 56);
     61 }
     62 
     63 /* BLAKE2b mixing function G */
     64 #define G(r, i, a, b, c, d, m)                           \
     65     do {                                                  \
     66         a = a + b + m[blake2b_sigma[r][2 * i]];         \
     67         d = ROR64(d ^ a, 32);                            \
     68         c = c + d;                                       \
     69         b = ROR64(b ^ c, 24);                            \
     70         a = a + b + m[blake2b_sigma[r][2 * i + 1]];     \
     71         d = ROR64(d ^ a, 16);                            \
     72         c = c + d;                                       \
     73         b = ROR64(b ^ c, 63);                            \
     74     } while (0)
     75 
     76 /* BLAKE2b compression function */
     77 static void blake2b_compress(uint64_t h[8], const uint8_t block[128],
     78                              uint64_t t0, uint64_t t1, int last) {
     79     uint64_t v[16], m[16];
     80 
     81     /* Initialize work vector */
     82     for (int i = 0; i < 8; i++) {
     83         v[i] = h[i];
     84         v[i + 8] = blake2b_iv[i];
     85     }
     86 
     87     v[12] ^= t0;
     88     v[13] ^= t1;
     89 
     90     if (last) {
     91         v[14] = ~v[14];
     92     }
     93 
     94     /* Load message */
     95     for (int i = 0; i < 16; i++) {
     96         m[i] = load64_le(block + i * 8);
     97     }
     98 
     99     /* 12 rounds */
    100     for (int r = 0; r < 12; r++) {
    101         G(r, 0, v[0], v[4], v[8], v[12], m);
    102         G(r, 1, v[1], v[5], v[9], v[13], m);
    103         G(r, 2, v[2], v[6], v[10], v[14], m);
    104         G(r, 3, v[3], v[7], v[11], v[15], m);
    105         G(r, 4, v[0], v[5], v[10], v[15], m);
    106         G(r, 5, v[1], v[6], v[11], v[12], m);
    107         G(r, 6, v[2], v[7], v[8], v[13], m);
    108         G(r, 7, v[3], v[4], v[9], v[14], m);
    109     }
    110 
    111     /* Update hash */
    112     for (int i = 0; i < 8; i++) {
    113         h[i] ^= v[i] ^ v[i + 8];
    114     }
    115 }
    116 
    117 /* BLAKE2b context */
    118 typedef struct {
    119     uint64_t h[8];
    120     uint64_t t[2];
    121     uint8_t buf[128];
    122     size_t buflen;
    123     size_t outlen;
    124 } blake2b_context;
    125 
    126 /* Initialize BLAKE2b */
    127 static void blake2b_init(blake2b_context *ctx, size_t outlen, const uint8_t *key, size_t keylen) {
    128     memset(ctx, 0, sizeof(blake2b_context));
    129 
    130     ctx->outlen = outlen;
    131 
    132     /* Initialize hash state */
    133     for (int i = 0; i < 8; i++) {
    134         ctx->h[i] = blake2b_iv[i];
    135     }
    136 
    137     /* Parameter block */
    138     ctx->h[0] ^= 0x01010000 ^ (keylen << 8) ^ outlen;
    139 
    140     /* Process key if present */
    141     if (keylen > 0) {
    142         memcpy(ctx->buf, key, keylen);
    143         ctx->buflen = 128;
    144     }
    145 }
    146 
    147 /* Update BLAKE2b */
    148 static void blake2b_update(blake2b_context *ctx, const uint8_t *data, size_t len) {
    149     while (len > 0) {
    150         size_t take = 128 - ctx->buflen;
    151         if (take > len) take = len;
    152 
    153         memcpy(ctx->buf + ctx->buflen, data, take);
    154         ctx->buflen += take;
    155         data += take;
    156         len -= take;
    157 
    158         if (ctx->buflen == 128) {
    159             ctx->t[0] += 128;
    160             if (ctx->t[0] < 128) ctx->t[1]++;
    161 
    162             blake2b_compress(ctx->h, ctx->buf, ctx->t[0], ctx->t[1], 0);
    163             ctx->buflen = 0;
    164         }
    165     }
    166 }
    167 
    168 /* Finalize BLAKE2b */
    169 static void blake2b_final(blake2b_context *ctx, uint8_t *out) {
    170     ctx->t[0] += ctx->buflen;
    171     if (ctx->t[0] < ctx->buflen) ctx->t[1]++;
    172 
    173     /* Pad with zeros */
    174     memset(ctx->buf + ctx->buflen, 0, 128 - ctx->buflen);
    175 
    176     blake2b_compress(ctx->h, ctx->buf, ctx->t[0], ctx->t[1], 1);
    177 
    178     /* Output hash */
    179     for (size_t i = 0; i < ctx->outlen / 8; i++) {
    180         store64_le(out + i * 8, ctx->h[i]);
    181     }
    182 
    183     /* Handle partial word */
    184     if (ctx->outlen % 8) {
    185         uint8_t temp[8];
    186         store64_le(temp, ctx->h[ctx->outlen / 8]);
    187         memcpy(out + (ctx->outlen / 8) * 8, temp, ctx->outlen % 8);
    188     }
    189 }
    190 
    191 /* BLAKE2b hash function (simple interface) */
    192 void blake2b(const uint8_t *data, size_t len, uint8_t *out, size_t outlen) {
    193     blake2b_context ctx;
    194     blake2b_init(&ctx, outlen, NULL, 0);
    195     blake2b_update(&ctx, data, len);
    196     blake2b_final(&ctx, out);
    197     memset(&ctx, 0, sizeof(ctx));
    198 }
    199 
    200 /* BLAKE2b-256 (32 bytes) */
    201 void blake2b_256(const uint8_t *data, size_t len, uint8_t digest[32]) {
    202     blake2b(data, len, digest, 32);
    203 }
    204 
    205 /* BLAKE2b-512 (64 bytes) */
    206 void blake2b_512(const uint8_t *data, size_t len, uint8_t digest[64]) {
    207     blake2b(data, len, digest, 64);
    208 }
    209 
    210 /* BLAKE2b with key (MAC) */
    211 void blake2b_mac(const uint8_t *key, size_t keylen,
    212                  const uint8_t *data, size_t len,
    213                  uint8_t *out, size_t outlen) {
    214     blake2b_context ctx;
    215     blake2b_init(&ctx, outlen, key, keylen);
    216     blake2b_update(&ctx, data, len);
    217     blake2b_final(&ctx, out);
    218     memset(&ctx, 0, sizeof(ctx));
    219 }