skip to content
[readonly]
==> src/sha256_stream.c <==
1/* Buffering bytes into 64-byte blocks, the FIPS 180-4 padding, the digest. */
2#include "sha256_stream.h"
3#include "sha256_compress.h"
4
5static void block(sha256_stream *s) {
6    uint32_t w[16];
7    for (int i = 0; i < 16; i++)
8        w[i] = (uint32_t)s->block[4 * i] << 24 | (uint32_t)s->block[4 * i + 1] << 16 | (uint32_t)s->block[4 * i + 2] << 8 | s->block[4 * i + 3];
9    sha256_compress(s->h, w);
10    s->used = 0;
11}
12
13void sha256_stream_init(sha256_stream *s) {
14    for (int i = 0; i < 8; i++) s->h[i] = SHA256_H0[i];
15    s->bytes = 0;
16    s->used = 0;
17}
18
19void sha256_stream_update(sha256_stream *s, const void *data, size_t n) {
20    const uint8_t *p = data;
21    s->bytes += n;
22    while (n > 0) {
23        size_t k = 64 - s->used < n ? 64 - s->used : n;
24        for (size_t i = 0; i < k; i++) s->block[s->used + i] = p[i];
25        s->used += k;
26        p += k;
27        n -= k;
28        if (s->used == 64) block(s);
29    }
30}
31
32void sha256_stream_final(sha256_stream *s, uint8_t out[32]) {
33    uint64_t bits = s->bytes * 8;
34    s->block[s->used++] = 0x80;
35    if (s->used > 56) {
36        while (s->used < 64) s->block[s->used++] = 0;
37        block(s);
38    }
39    while (s->used < 56) s->block[s->used++] = 0;
40    for (int i = 0; i < 8; i++) s->block[56 + i] = (uint8_t)(bits >> (56 - 8 * i));
41    block(s);
42    for (int i = 0; i < 8; i++)
43        for (int k = 0; k < 4; k++) out[4 * i + k] = (uint8_t)(s->h[i] >> (24 - 8 * k));
44}
45
46void sha256_stream_hex(const uint8_t digest[32], char out[65]) {
47    static const char hex[] = "0123456789abcdef";
48    for (int i = 0; i < 32; i++) {
49        out[2 * i] = hex[digest[i] >> 4];
50        out[2 * i + 1] = hex[digest[i] & 15];
51    }
52    out[64] = 0;
53}