diff options
Diffstat (limited to 'src/sha256.c')
-rw-r--r-- | src/sha256.c | 158 |
1 files changed, 111 insertions, 47 deletions
diff --git a/src/sha256.c b/src/sha256.c index 61faae7..68c1025 100644 --- a/src/sha256.c +++ b/src/sha256.c @@ -36,7 +36,29 @@ static inline uint32_t rotr(uint32_t x, int r) { return (x >> r) | (x << (32-r)); } -static void sha256_blocks_va(uint32_t out[FASTD_SHA256_HASH_WORDS], const uint32_t *in1, const uint32_t *in2, va_list ap) { +static inline void copy_words(uint32_t w[8], const uint32_t *in, ssize_t *left) { + unsigned i; + for (i = 0; i < 8; i++) { + if (*left >= 4) { + w[i] = ntohl(in[i]); + } + else if (*left > 0) { + uint32_t tmp = 0; + memcpy(&tmp, &in[i], *left); + w[i] = ntohl(tmp) | (0x80000000 >> (*left * 8)); + } + else if (*left == 0) { + w[i] = 0x80000000; + } + else { + w[i] = 0; + } + + *left -= 4; + } +} + +static void sha256_list(uint32_t out[FASTD_SHA256_HASH_WORDS], const uint32_t *const *in, size_t len) { static const uint32_t k[64] = { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, @@ -58,29 +80,17 @@ static void sha256_blocks_va(uint32_t out[FASTD_SHA256_HASH_WORDS], const uint32 0x1f83d9ab, 0x5be0cd19 }; - unsigned count = in2 ? 2 : in1 ? 1 : 0, i; + ssize_t left = len; + unsigned i; - while (true) { + while (left >= -8) { uint32_t w[64], v[8]; - if (in1) { - for (i = 0; i < 8; i++) - w[i] = ntohl(in1[i]); - } - else { - w[0] = 0x80000000; - memset(w+1, 0, 7*sizeof(uint32_t)); - } + copy_words(w, *(in++), &left); + copy_words(w+8, *(in++), &left); - if (in2) { - for (i = 0; i < 8; i++) - w[i+8] = ntohl(in2[i]); - } - else { - w[8] = in1 ? 0x80000000 : 0; - memset(w+9, 0, 6*sizeof(uint32_t)); - w[15] = count << 8; - } + if (left < -8) + w[15] = len << 3; for (i = 16; i < 64; i++) { uint32_t s0 = rotr(w[i-15], 7) ^ rotr(w[i-15], 18) ^ (w[i-15] >> 3); @@ -110,30 +120,51 @@ static void sha256_blocks_va(uint32_t out[FASTD_SHA256_HASH_WORDS], const uint32 for (i = 0; i < 8; i++) h[i] += v[i]; + } + for (i = 0; i < 8; i++) + out[i] = htonl(h[i]); +} - if (!in2) - break; +static void sha256_blocks_va(uint32_t out[FASTD_SHA256_HASH_WORDS], va_list ap) { + size_t count = 0; + va_list ap2; + va_copy(ap2, ap); + while (va_arg(ap2, const uint32_t*)) + count++; + va_end(ap2); - in1 = va_arg(ap, const uint32_t*); - if (in1) { - count++; - in2 = va_arg(ap, const uint32_t*); + const uint32_t *blocks[count]; - if (in2) - count++; - } - else { - in2 = NULL; - } - } + size_t i = 0; + const uint32_t *block; + while ((block = va_arg(ap, const uint32_t*)) != NULL) + blocks[i++] = block; - for (i = 0; i < 8; i++) - out[i] = htonl(h[i]); + sha256_list(out, blocks, count*FASTD_SHA256_BLOCK_BYTES); } -static void hmacsha256_blocks_va(fastd_sha256_t *out, const uint32_t key[FASTD_HMACSHA256_KEY_WORDS], va_list ap) { +void fastd_sha256_blocks(fastd_sha256_t *out, ...) { + va_list ap; + + va_start(ap, out); + sha256_blocks_va(out->w, ap); + va_end(ap); +} + +void fastd_sha256(fastd_sha256_t *out, const uint32_t *in, size_t len) { + size_t count = (len+FASTD_SHA256_BLOCK_BYTES-1) / FASTD_SHA256_BLOCK_BYTES; + const uint32_t *blocks[count]; + unsigned i; + + for (i = 0; i < count; i++) + blocks[i] = in + i*FASTD_SHA256_BLOCK_WORDS; + + sha256_list(out->w, blocks, len); +} + +static void hmacsha256_list(fastd_sha256_t *out, const uint32_t key[FASTD_HMACSHA256_KEY_WORDS], const uint32_t *const *in, size_t len) { static const uint32_t ipad2[8] = { 0x36363636, 0x36363636, @@ -142,7 +173,7 @@ static void hmacsha256_blocks_va(fastd_sha256_t *out, const uint32_t key[FASTD_H 0x36363636, 0x36363636, 0x36363636, - 0x36363636 + 0x36363636, }; static const uint32_t opad2[8] = { 0x5c5c5c5c, @@ -152,9 +183,11 @@ static void hmacsha256_blocks_va(fastd_sha256_t *out, const uint32_t key[FASTD_H 0x5c5c5c5c, 0x5c5c5c5c, 0x5c5c5c5c, - 0x5c5c5c5c + 0x5c5c5c5c, }; + size_t count = (len+FASTD_SHA256_BLOCK_BYTES-1) / FASTD_SHA256_BLOCK_BYTES; + const uint32_t *blocks[count+2]; uint32_t ipad[8], opad[8]; unsigned i; @@ -163,21 +196,34 @@ static void hmacsha256_blocks_va(fastd_sha256_t *out, const uint32_t key[FASTD_H opad[i] = key[i] ^ 0x5c5c5c5c; } - uint32_t temp[8]; - sha256_blocks_va(temp, ipad, ipad2, ap); + blocks[0] = ipad; + blocks[1] = ipad2; + for (i = 0; i < count; i++) + blocks[i+2] = in[i]; + + uint32_t temp[8]; + sha256_list(temp, blocks, len + 2*FASTD_SHA256_BLOCK_BYTES); fastd_sha256_blocks(out, opad, opad2, temp, NULL); } +static void hmacsha256_blocks_va(fastd_sha256_t *out, const uint32_t key[FASTD_HMACSHA256_KEY_WORDS], va_list ap) { + size_t count = 0; + va_list ap2; -void fastd_sha256_blocks(fastd_sha256_t *out, ...) { - va_list ap; + va_copy(ap2, ap); + while (va_arg(ap2, const uint32_t*)) + count++; + va_end(ap2); - va_start(ap, out); - const uint32_t *in1 = va_arg(ap, const uint32_t*); - const uint32_t *in2 = in1 ? va_arg(ap, const uint32_t*) : NULL; - sha256_blocks_va(out->w, in1, in2, ap); - va_end(ap); + const uint32_t *blocks[count]; + + size_t i = 0; + const uint32_t *block; + while ((block = va_arg(ap, const uint32_t*)) != NULL) + blocks[i++] = block; + + hmacsha256_list(out, key, blocks, count*FASTD_SHA256_BLOCK_BYTES); } void fastd_hmacsha256_blocks(fastd_sha256_t *out, const uint32_t key[FASTD_HMACSHA256_KEY_WORDS], ...) { @@ -198,3 +244,21 @@ bool fastd_hmacsha256_blocks_verify(const uint8_t mac[FASTD_SHA256_HASH_BYTES], return !memcmp(out.b, mac, FASTD_SHA256_HASH_BYTES); } + +void fastd_hmacsha256(fastd_sha256_t *out, const uint32_t key[FASTD_HMACSHA256_KEY_WORDS], const uint32_t *in, size_t len) { + size_t count = (len+FASTD_SHA256_BLOCK_BYTES-1) / FASTD_SHA256_BLOCK_BYTES; + const uint32_t *blocks[count]; + unsigned i; + + for (i = 0; i < count; i++) + blocks[i] = in + i*FASTD_SHA256_BLOCK_WORDS; + + hmacsha256_list(out, key, blocks, len); +} + +bool fastd_hmacsha256_verify(const uint8_t mac[FASTD_SHA256_HASH_BYTES], const uint32_t key[FASTD_HMACSHA256_KEY_WORDS], const uint32_t *in, size_t len) { + fastd_sha256_t out; + + fastd_hmacsha256(&out, key, in, len); + return !memcmp(out.b, mac, FASTD_SHA256_HASH_BYTES); +} |