core: add support for lots of different hash algorithms
This commit is contained in:
18
core/hash.c
18
core/hash.c
@@ -1,18 +0,0 @@
|
|||||||
#include <blue/core/hash.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#define FNV1_OFFSET_BASIS 0xcbf29ce484222325
|
|
||||||
#define FNV1_PRIME 0x100000001b3
|
|
||||||
|
|
||||||
uint64_t b_hash_string(const char *s)
|
|
||||||
{
|
|
||||||
uint64_t hash = FNV1_OFFSET_BASIS;
|
|
||||||
|
|
||||||
for (size_t i = 0; s[i]; i++) {
|
|
||||||
hash ^= s[i];
|
|
||||||
hash *= FNV1_PRIME;
|
|
||||||
}
|
|
||||||
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
139
core/hash/hash.c
Normal file
139
core/hash/hash.c
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
#include "hash.h"
|
||||||
|
|
||||||
|
#include <blue/core/hash.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define FNV1_OFFSET_BASIS 0xcbf29ce484222325
|
||||||
|
#define FNV1_PRIME 0x100000001b3
|
||||||
|
|
||||||
|
extern struct b_hash_function_ops z__b_md4_ops;
|
||||||
|
extern struct b_hash_function_ops z__b_md5_ops;
|
||||||
|
extern struct b_hash_function_ops z__b_sha1_ops;
|
||||||
|
extern struct b_hash_function_ops z__b_sha2_224_ops;
|
||||||
|
extern struct b_hash_function_ops z__b_sha2_256_ops;
|
||||||
|
extern struct b_hash_function_ops z__b_sha2_384_ops;
|
||||||
|
extern struct b_hash_function_ops z__b_sha2_512_ops;
|
||||||
|
extern struct b_hash_function_ops z__b_sha3_224_ops;
|
||||||
|
extern struct b_hash_function_ops z__b_sha3_256_ops;
|
||||||
|
extern struct b_hash_function_ops z__b_sha3_384_ops;
|
||||||
|
extern struct b_hash_function_ops z__b_sha3_512_ops;
|
||||||
|
extern struct b_hash_function_ops z__b_shake128_ops;
|
||||||
|
extern struct b_hash_function_ops z__b_shake256_ops;
|
||||||
|
|
||||||
|
static const struct b_hash_function_ops *hash_functions[] = {
|
||||||
|
[B_HASH_NONE] = NULL,
|
||||||
|
[B_HASH_MD4] = &z__b_md4_ops,
|
||||||
|
[B_HASH_MD5] = &z__b_md5_ops,
|
||||||
|
[B_HASH_SHA1] = &z__b_sha1_ops,
|
||||||
|
[B_HASH_SHA2_224] = &z__b_sha2_224_ops,
|
||||||
|
[B_HASH_SHA2_256] = &z__b_sha2_256_ops,
|
||||||
|
[B_HASH_SHA2_384] = &z__b_sha2_384_ops,
|
||||||
|
[B_HASH_SHA2_512] = &z__b_sha2_512_ops,
|
||||||
|
[B_HASH_SHA3_224] = &z__b_sha3_224_ops,
|
||||||
|
[B_HASH_SHA3_256] = &z__b_sha3_256_ops,
|
||||||
|
[B_HASH_SHA3_384] = &z__b_sha3_384_ops,
|
||||||
|
[B_HASH_SHA3_512] = &z__b_sha3_512_ops,
|
||||||
|
[B_HASH_SHAKE128] = &z__b_shake128_ops,
|
||||||
|
[B_HASH_SHAKE256] = &z__b_shake256_ops,
|
||||||
|
};
|
||||||
|
static const size_t nr_hash_functions
|
||||||
|
= sizeof hash_functions / sizeof hash_functions[0];
|
||||||
|
|
||||||
|
uint64_t b_hash_string(const char *s)
|
||||||
|
{
|
||||||
|
size_t x = 0;
|
||||||
|
return b_hash_string_ex(s, &x);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t b_hash_string_ex(const char *s, size_t *len)
|
||||||
|
{
|
||||||
|
uint64_t hash = FNV1_OFFSET_BASIS;
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
|
for (i = 0; s[i]; i++) {
|
||||||
|
hash ^= s[i];
|
||||||
|
hash *= FNV1_PRIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len) {
|
||||||
|
*len = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum b_status b_hash_ctx_init(struct b_hash_ctx *ctx, enum b_hash_function func)
|
||||||
|
{
|
||||||
|
if (func < 0 || func >= nr_hash_functions) {
|
||||||
|
return B_ERR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct b_hash_function_ops *hash_function = hash_functions[func];
|
||||||
|
if (!hash_function) {
|
||||||
|
return B_ERR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(ctx, 0x0, sizeof *ctx);
|
||||||
|
|
||||||
|
ctx->ctx_func = func;
|
||||||
|
ctx->ctx_ops = hash_function;
|
||||||
|
|
||||||
|
if (hash_function->hash_init) {
|
||||||
|
hash_function->hash_init(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum b_status b_hash_ctx_reset(struct b_hash_ctx *ctx)
|
||||||
|
{
|
||||||
|
if (ctx->ctx_func == B_HASH_NONE || !ctx->ctx_ops) {
|
||||||
|
return B_ERR_BAD_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&ctx->ctx_state, 0x0, sizeof ctx->ctx_state);
|
||||||
|
|
||||||
|
if (ctx->ctx_ops->hash_init) {
|
||||||
|
ctx->ctx_ops->hash_init(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum b_status b_hash_ctx_update(struct b_hash_ctx *ctx, const void *p, size_t len)
|
||||||
|
{
|
||||||
|
if (!ctx->ctx_ops) {
|
||||||
|
return B_ERR_BAD_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ctx->ctx_ops->hash_update) {
|
||||||
|
return B_ERR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->ctx_ops->hash_update(ctx, p, len);
|
||||||
|
return B_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum b_status b_hash_ctx_finish(
|
||||||
|
struct b_hash_ctx *ctx, void *out_digest, size_t out_max)
|
||||||
|
{
|
||||||
|
if (!ctx->ctx_ops) {
|
||||||
|
return B_ERR_BAD_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ctx->ctx_ops->hash_finish) {
|
||||||
|
return B_ERR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->ctx_ops->hash_finish(ctx, out_digest, out_max);
|
||||||
|
|
||||||
|
memset(&ctx->ctx_state, 0x0, sizeof ctx->ctx_state);
|
||||||
|
|
||||||
|
if (ctx->ctx_ops->hash_init) {
|
||||||
|
ctx->ctx_ops->hash_init(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_SUCCESS;
|
||||||
|
}
|
||||||
14
core/hash/hash.h
Normal file
14
core/hash/hash.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#ifndef _HASH_H_
|
||||||
|
#define _HASH_H_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
struct b_hash_ctx;
|
||||||
|
|
||||||
|
struct b_hash_function_ops {
|
||||||
|
void (*hash_init)(struct b_hash_ctx *);
|
||||||
|
void (*hash_update)(struct b_hash_ctx *, const void *, size_t);
|
||||||
|
void (*hash_finish)(struct b_hash_ctx *, void *, size_t);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
270
core/hash/md4.c
Normal file
270
core/hash/md4.c
Normal file
@@ -0,0 +1,270 @@
|
|||||||
|
/*
|
||||||
|
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
|
||||||
|
* MD4 Message-Digest Algorithm (RFC 1320).
|
||||||
|
*
|
||||||
|
* Homepage:
|
||||||
|
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md4
|
||||||
|
*
|
||||||
|
* Author:
|
||||||
|
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
|
||||||
|
*
|
||||||
|
* This software was written by Alexander Peslyak in 2001. No copyright is
|
||||||
|
* claimed, and the software is hereby placed in the public domain.
|
||||||
|
* In case this attempt to disclaim copyright and place the software in the
|
||||||
|
* public domain is deemed null and void, then the software is
|
||||||
|
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
|
||||||
|
* general public under the following terms:
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted.
|
||||||
|
*
|
||||||
|
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
||||||
|
*
|
||||||
|
* (This is a heavily cut-down "BSD license".)
|
||||||
|
*
|
||||||
|
* This differs from Colin Plumb's older public domain implementation in that
|
||||||
|
* no exactly 32-bit integer data type is required (any 32-bit or wider
|
||||||
|
* unsigned integer data type will do), there's no compile-time endianness
|
||||||
|
* configuration, and the function prototypes match OpenSSL's. No code from
|
||||||
|
* Colin Plumb's implementation has been reused; this comment merely compares
|
||||||
|
* the properties of the two independent implementations.
|
||||||
|
*
|
||||||
|
* The primary goals of this implementation are portability and ease of use.
|
||||||
|
* It is meant to be fast, but not as fast as possible. Some known
|
||||||
|
* optimizations are not included to reduce source code size and avoid
|
||||||
|
* compile-time configuration.
|
||||||
|
*/
|
||||||
|
#include "hash.h"
|
||||||
|
|
||||||
|
#include <blue/core/hash.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The basic MD4 functions.
|
||||||
|
*
|
||||||
|
* F and G are optimized compared to their RFC 1320 definitions, with the
|
||||||
|
* optimization for F borrowed from Colin Plumb's MD5 implementation.
|
||||||
|
*/
|
||||||
|
#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
|
||||||
|
#define G(x, y, z) (((x) & ((y) | (z))) | ((y) & (z)))
|
||||||
|
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The MD4 transformation for all three rounds.
|
||||||
|
*/
|
||||||
|
#define STEP(f, a, b, c, d, x, s) \
|
||||||
|
(a) += f((b), (c), (d)) + (x); \
|
||||||
|
(a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s))));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SET reads 4 input bytes in little-endian byte order and stores them in a
|
||||||
|
* properly aligned word in host byte order.
|
||||||
|
*
|
||||||
|
* The check for little-endian architectures that tolerate unaligned memory
|
||||||
|
* accesses is just an optimization. Nothing will break if it fails to detect
|
||||||
|
* a suitable architecture.
|
||||||
|
*
|
||||||
|
* Unfortunately, this optimization may be a C strict aliasing rules violation
|
||||||
|
* if the caller's data buffer has effective type that cannot be aliased by
|
||||||
|
* uint32_t. In practice, this problem may occur if these MD4 routines are
|
||||||
|
* inlined into a calling function, or with future and dangerously advanced
|
||||||
|
* link-time optimizations. For the time being, keeping these MD4 routines in
|
||||||
|
* their own translation unit avoids the problem.
|
||||||
|
*/
|
||||||
|
#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
|
||||||
|
#define SET(n) (*(uint32_t *)&ptr[(n) * 4])
|
||||||
|
#define GET(n) SET(n)
|
||||||
|
#else
|
||||||
|
#define SET(n) \
|
||||||
|
(ctx->ctx_state.md4.block[(n)] = (uint32_t)ptr[(n) * 4] \
|
||||||
|
| ((uint32_t)ptr[(n) * 4 + 1] << 8) \
|
||||||
|
| ((uint32_t)ptr[(n) * 4 + 2] << 16) \
|
||||||
|
| ((uint32_t)ptr[(n) * 4 + 3] << 24))
|
||||||
|
#define GET(n) (ctx->ctx_state.md4.block[(n)])
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This processes one or more 64-byte data blocks, but does NOT update the bit
|
||||||
|
* counters. There are no alignment requirements.
|
||||||
|
*/
|
||||||
|
static const void *body(struct b_hash_ctx *ctx, const void *data, unsigned long size)
|
||||||
|
{
|
||||||
|
const unsigned char *ptr;
|
||||||
|
uint32_t a, b, c, d;
|
||||||
|
uint32_t saved_a, saved_b, saved_c, saved_d;
|
||||||
|
const uint32_t ac1 = 0x5a827999, ac2 = 0x6ed9eba1;
|
||||||
|
|
||||||
|
ptr = (const unsigned char *)data;
|
||||||
|
|
||||||
|
a = ctx->ctx_state.md4.a;
|
||||||
|
b = ctx->ctx_state.md4.b;
|
||||||
|
c = ctx->ctx_state.md4.c;
|
||||||
|
d = ctx->ctx_state.md4.d;
|
||||||
|
|
||||||
|
do {
|
||||||
|
saved_a = a;
|
||||||
|
saved_b = b;
|
||||||
|
saved_c = c;
|
||||||
|
saved_d = d;
|
||||||
|
|
||||||
|
/* Round 1 */
|
||||||
|
STEP(F, a, b, c, d, SET(0), 3)
|
||||||
|
STEP(F, d, a, b, c, SET(1), 7)
|
||||||
|
STEP(F, c, d, a, b, SET(2), 11)
|
||||||
|
STEP(F, b, c, d, a, SET(3), 19)
|
||||||
|
STEP(F, a, b, c, d, SET(4), 3)
|
||||||
|
STEP(F, d, a, b, c, SET(5), 7)
|
||||||
|
STEP(F, c, d, a, b, SET(6), 11)
|
||||||
|
STEP(F, b, c, d, a, SET(7), 19)
|
||||||
|
STEP(F, a, b, c, d, SET(8), 3)
|
||||||
|
STEP(F, d, a, b, c, SET(9), 7)
|
||||||
|
STEP(F, c, d, a, b, SET(10), 11)
|
||||||
|
STEP(F, b, c, d, a, SET(11), 19)
|
||||||
|
STEP(F, a, b, c, d, SET(12), 3)
|
||||||
|
STEP(F, d, a, b, c, SET(13), 7)
|
||||||
|
STEP(F, c, d, a, b, SET(14), 11)
|
||||||
|
STEP(F, b, c, d, a, SET(15), 19)
|
||||||
|
|
||||||
|
/* Round 2 */
|
||||||
|
STEP(G, a, b, c, d, GET(0) + ac1, 3)
|
||||||
|
STEP(G, d, a, b, c, GET(4) + ac1, 5)
|
||||||
|
STEP(G, c, d, a, b, GET(8) + ac1, 9)
|
||||||
|
STEP(G, b, c, d, a, GET(12) + ac1, 13)
|
||||||
|
STEP(G, a, b, c, d, GET(1) + ac1, 3)
|
||||||
|
STEP(G, d, a, b, c, GET(5) + ac1, 5)
|
||||||
|
STEP(G, c, d, a, b, GET(9) + ac1, 9)
|
||||||
|
STEP(G, b, c, d, a, GET(13) + ac1, 13)
|
||||||
|
STEP(G, a, b, c, d, GET(2) + ac1, 3)
|
||||||
|
STEP(G, d, a, b, c, GET(6) + ac1, 5)
|
||||||
|
STEP(G, c, d, a, b, GET(10) + ac1, 9)
|
||||||
|
STEP(G, b, c, d, a, GET(14) + ac1, 13)
|
||||||
|
STEP(G, a, b, c, d, GET(3) + ac1, 3)
|
||||||
|
STEP(G, d, a, b, c, GET(7) + ac1, 5)
|
||||||
|
STEP(G, c, d, a, b, GET(11) + ac1, 9)
|
||||||
|
STEP(G, b, c, d, a, GET(15) + ac1, 13)
|
||||||
|
|
||||||
|
/* Round 3 */
|
||||||
|
STEP(H, a, b, c, d, GET(0) + ac2, 3)
|
||||||
|
STEP(H, d, a, b, c, GET(8) + ac2, 9)
|
||||||
|
STEP(H, c, d, a, b, GET(4) + ac2, 11)
|
||||||
|
STEP(H, b, c, d, a, GET(12) + ac2, 15)
|
||||||
|
STEP(H, a, b, c, d, GET(2) + ac2, 3)
|
||||||
|
STEP(H, d, a, b, c, GET(10) + ac2, 9)
|
||||||
|
STEP(H, c, d, a, b, GET(6) + ac2, 11)
|
||||||
|
STEP(H, b, c, d, a, GET(14) + ac2, 15)
|
||||||
|
STEP(H, a, b, c, d, GET(1) + ac2, 3)
|
||||||
|
STEP(H, d, a, b, c, GET(9) + ac2, 9)
|
||||||
|
STEP(H, c, d, a, b, GET(5) + ac2, 11)
|
||||||
|
STEP(H, b, c, d, a, GET(13) + ac2, 15)
|
||||||
|
STEP(H, a, b, c, d, GET(3) + ac2, 3)
|
||||||
|
STEP(H, d, a, b, c, GET(11) + ac2, 9)
|
||||||
|
STEP(H, c, d, a, b, GET(7) + ac2, 11)
|
||||||
|
STEP(H, b, c, d, a, GET(15) + ac2, 15)
|
||||||
|
|
||||||
|
a += saved_a;
|
||||||
|
b += saved_b;
|
||||||
|
c += saved_c;
|
||||||
|
d += saved_d;
|
||||||
|
|
||||||
|
ptr += 64;
|
||||||
|
} while (size -= 64);
|
||||||
|
|
||||||
|
ctx->ctx_state.md4.a = a;
|
||||||
|
ctx->ctx_state.md4.b = b;
|
||||||
|
ctx->ctx_state.md4.c = c;
|
||||||
|
ctx->ctx_state.md4.d = d;
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void md4_init(struct b_hash_ctx *ctx)
|
||||||
|
{
|
||||||
|
ctx->ctx_state.md4.a = 0x67452301;
|
||||||
|
ctx->ctx_state.md4.b = 0xefcdab89;
|
||||||
|
ctx->ctx_state.md4.c = 0x98badcfe;
|
||||||
|
ctx->ctx_state.md4.d = 0x10325476;
|
||||||
|
|
||||||
|
ctx->ctx_state.md4.lo = 0;
|
||||||
|
ctx->ctx_state.md4.hi = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void md4_update(struct b_hash_ctx *ctx, const void *data, unsigned long size)
|
||||||
|
{
|
||||||
|
uint32_t saved_lo;
|
||||||
|
unsigned long used, available;
|
||||||
|
|
||||||
|
saved_lo = ctx->ctx_state.md4.lo;
|
||||||
|
if ((ctx->ctx_state.md4.lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
|
||||||
|
ctx->ctx_state.md4.hi++;
|
||||||
|
ctx->ctx_state.md4.hi += size >> 29;
|
||||||
|
|
||||||
|
used = saved_lo & 0x3f;
|
||||||
|
|
||||||
|
if (used) {
|
||||||
|
available = 64 - used;
|
||||||
|
|
||||||
|
if (size < available) {
|
||||||
|
memcpy(&ctx->ctx_state.md4.buffer[used], data, size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&ctx->ctx_state.md4.buffer[used], data, available);
|
||||||
|
data = (const unsigned char *)data + available;
|
||||||
|
size -= available;
|
||||||
|
body(ctx, ctx->ctx_state.md4.buffer, 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size >= 64) {
|
||||||
|
data = body(ctx, data, size & ~(unsigned long)0x3f);
|
||||||
|
size &= 0x3f;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(ctx->ctx_state.md4.buffer, data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define OUT(dst, src) \
|
||||||
|
(dst)[0] = (unsigned char)(src); \
|
||||||
|
(dst)[1] = (unsigned char)((src) >> 8); \
|
||||||
|
(dst)[2] = (unsigned char)((src) >> 16); \
|
||||||
|
(dst)[3] = (unsigned char)((src) >> 24);
|
||||||
|
|
||||||
|
void md4_finish(struct b_hash_ctx *ctx, void *out, size_t max)
|
||||||
|
{
|
||||||
|
unsigned char *result = out;
|
||||||
|
unsigned long used, available;
|
||||||
|
|
||||||
|
used = ctx->ctx_state.md4.lo & 0x3f;
|
||||||
|
|
||||||
|
ctx->ctx_state.md4.buffer[used++] = 0x80;
|
||||||
|
|
||||||
|
available = 64 - used;
|
||||||
|
|
||||||
|
if (available < 8) {
|
||||||
|
memset(&ctx->ctx_state.md4.buffer[used], 0, available);
|
||||||
|
body(ctx, ctx->ctx_state.md4.buffer, 64);
|
||||||
|
used = 0;
|
||||||
|
available = 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&ctx->ctx_state.md4.buffer[used], 0, available - 8);
|
||||||
|
|
||||||
|
ctx->ctx_state.md4.lo <<= 3;
|
||||||
|
OUT(&ctx->ctx_state.md4.buffer[56], ctx->ctx_state.md4.lo)
|
||||||
|
OUT(&ctx->ctx_state.md4.buffer[60], ctx->ctx_state.md4.hi)
|
||||||
|
|
||||||
|
body(ctx, ctx->ctx_state.md4.buffer, 64);
|
||||||
|
|
||||||
|
OUT(&result[0], ctx->ctx_state.md4.a)
|
||||||
|
OUT(&result[4], ctx->ctx_state.md4.b)
|
||||||
|
OUT(&result[8], ctx->ctx_state.md4.c)
|
||||||
|
OUT(&result[12], ctx->ctx_state.md4.d)
|
||||||
|
|
||||||
|
memset(ctx, 0, sizeof(*ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct b_hash_function_ops z__b_md4_ops = {
|
||||||
|
.hash_init = md4_init,
|
||||||
|
.hash_update = md4_update,
|
||||||
|
.hash_finish = md4_finish,
|
||||||
|
};
|
||||||
238
core/hash/md5.c
Normal file
238
core/hash/md5.c
Normal file
@@ -0,0 +1,238 @@
|
|||||||
|
/* This implementation was sourced from
|
||||||
|
* https://github.com/galenguyer/md5
|
||||||
|
* and is in the public domain. */
|
||||||
|
#include "hash.h"
|
||||||
|
|
||||||
|
#include <blue/core/hash.h>
|
||||||
|
#include <memory.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define F(x, y, z) (z ^ (x & (y ^ z)))
|
||||||
|
#define G(x, y, z) (y ^ (z & (x ^ y)))
|
||||||
|
#define H(x, y, z) (x ^ y ^ z)
|
||||||
|
#define I(x, y, z) (y ^ (x | ~z))
|
||||||
|
|
||||||
|
#define ROTATE_LEFT(x, s) (x << s | x >> (32 - s))
|
||||||
|
|
||||||
|
#define STEP(f, a, b, c, d, x, t, s) \
|
||||||
|
(a += f(b, c, d) + x + t, a = ROTATE_LEFT(a, s), a += b)
|
||||||
|
|
||||||
|
void md5_init(struct b_hash_ctx *ctx)
|
||||||
|
{
|
||||||
|
ctx->ctx_state.md5.a = 0x67452301;
|
||||||
|
ctx->ctx_state.md5.b = 0xefcdab89;
|
||||||
|
ctx->ctx_state.md5.c = 0x98badcfe;
|
||||||
|
ctx->ctx_state.md5.d = 0x10325476;
|
||||||
|
|
||||||
|
ctx->ctx_state.md5.count[0] = 0;
|
||||||
|
ctx->ctx_state.md5.count[1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *md5_transform(struct b_hash_ctx *ctx, const void *data, uintmax_t size)
|
||||||
|
{
|
||||||
|
uint8_t *ptr = (uint8_t *)data;
|
||||||
|
uint32_t a, b, c, d, aa, bb, cc, dd;
|
||||||
|
|
||||||
|
#define GET(n) (ctx->ctx_state.md5.block[(n)])
|
||||||
|
#define SET(n) \
|
||||||
|
(ctx->ctx_state.md5.block[(n)] = ((uint32_t)ptr[(n) * 4 + 0] << 0) \
|
||||||
|
| ((uint32_t)ptr[(n) * 4 + 1] << 8) \
|
||||||
|
| ((uint32_t)ptr[(n) * 4 + 2] << 16) \
|
||||||
|
| ((uint32_t)ptr[(n) * 4 + 3] << 24))
|
||||||
|
|
||||||
|
a = ctx->ctx_state.md5.a;
|
||||||
|
b = ctx->ctx_state.md5.b;
|
||||||
|
c = ctx->ctx_state.md5.c;
|
||||||
|
d = ctx->ctx_state.md5.d;
|
||||||
|
|
||||||
|
do {
|
||||||
|
aa = a;
|
||||||
|
bb = b;
|
||||||
|
cc = c;
|
||||||
|
dd = d;
|
||||||
|
|
||||||
|
STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7);
|
||||||
|
STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12);
|
||||||
|
STEP(F, c, d, a, b, SET(2), 0x242070db, 17);
|
||||||
|
STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22);
|
||||||
|
STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7);
|
||||||
|
STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12);
|
||||||
|
STEP(F, c, d, a, b, SET(6), 0xa8304613, 17);
|
||||||
|
STEP(F, b, c, d, a, SET(7), 0xfd469501, 22);
|
||||||
|
STEP(F, a, b, c, d, SET(8), 0x698098d8, 7);
|
||||||
|
STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12);
|
||||||
|
STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17);
|
||||||
|
STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22);
|
||||||
|
STEP(F, a, b, c, d, SET(12), 0x6b901122, 7);
|
||||||
|
STEP(F, d, a, b, c, SET(13), 0xfd987193, 12);
|
||||||
|
STEP(F, c, d, a, b, SET(14), 0xa679438e, 17);
|
||||||
|
STEP(F, b, c, d, a, SET(15), 0x49b40821, 22);
|
||||||
|
|
||||||
|
STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5);
|
||||||
|
STEP(G, d, a, b, c, GET(6), 0xc040b340, 9);
|
||||||
|
STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14);
|
||||||
|
STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20);
|
||||||
|
STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5);
|
||||||
|
STEP(G, d, a, b, c, GET(10), 0x02441453, 9);
|
||||||
|
STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14);
|
||||||
|
STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20);
|
||||||
|
STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5);
|
||||||
|
STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9);
|
||||||
|
STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14);
|
||||||
|
STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20);
|
||||||
|
STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5);
|
||||||
|
STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9);
|
||||||
|
STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14);
|
||||||
|
STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20);
|
||||||
|
|
||||||
|
STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4);
|
||||||
|
STEP(H, d, a, b, c, GET(8), 0x8771f681, 11);
|
||||||
|
STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16);
|
||||||
|
STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23);
|
||||||
|
STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4);
|
||||||
|
STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11);
|
||||||
|
STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16);
|
||||||
|
STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23);
|
||||||
|
STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4);
|
||||||
|
STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11);
|
||||||
|
STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16);
|
||||||
|
STEP(H, b, c, d, a, GET(6), 0x04881d05, 23);
|
||||||
|
STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4);
|
||||||
|
STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11);
|
||||||
|
STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16);
|
||||||
|
STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23);
|
||||||
|
|
||||||
|
STEP(I, a, b, c, d, GET(0), 0xf4292244, 6);
|
||||||
|
STEP(I, d, a, b, c, GET(7), 0x432aff97, 10);
|
||||||
|
STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15);
|
||||||
|
STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21);
|
||||||
|
STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6);
|
||||||
|
STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10);
|
||||||
|
STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15);
|
||||||
|
STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21);
|
||||||
|
STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6);
|
||||||
|
STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10);
|
||||||
|
STEP(I, c, d, a, b, GET(6), 0xa3014314, 15);
|
||||||
|
STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21);
|
||||||
|
STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6);
|
||||||
|
STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10);
|
||||||
|
STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15);
|
||||||
|
STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21);
|
||||||
|
|
||||||
|
a += aa;
|
||||||
|
b += bb;
|
||||||
|
c += cc;
|
||||||
|
d += dd;
|
||||||
|
|
||||||
|
ptr += 64;
|
||||||
|
} while (size -= 64);
|
||||||
|
|
||||||
|
ctx->ctx_state.md5.a = a;
|
||||||
|
ctx->ctx_state.md5.b = b;
|
||||||
|
ctx->ctx_state.md5.c = c;
|
||||||
|
ctx->ctx_state.md5.d = d;
|
||||||
|
|
||||||
|
#undef GET
|
||||||
|
#undef SET
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void md5_update(struct b_hash_ctx *ctx, const void *buffer, size_t buffer_size)
|
||||||
|
{
|
||||||
|
uint32_t saved_low = ctx->ctx_state.md5.count[0];
|
||||||
|
uint32_t used;
|
||||||
|
uint32_t free;
|
||||||
|
|
||||||
|
if ((ctx->ctx_state.md5.count[0] = ((saved_low + buffer_size) & 0x1fffffff))
|
||||||
|
< saved_low) {
|
||||||
|
ctx->ctx_state.md5.count[1]++;
|
||||||
|
}
|
||||||
|
ctx->ctx_state.md5.count[1] += (uint32_t)(buffer_size >> 29);
|
||||||
|
|
||||||
|
used = saved_low & 0x3f;
|
||||||
|
|
||||||
|
if (used) {
|
||||||
|
free = 64 - used;
|
||||||
|
|
||||||
|
if (buffer_size < free) {
|
||||||
|
memcpy(&ctx->ctx_state.md5.input[used], buffer,
|
||||||
|
buffer_size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&ctx->ctx_state.md5.input[used], buffer, free);
|
||||||
|
buffer = (uint8_t *)buffer + free;
|
||||||
|
buffer_size -= free;
|
||||||
|
md5_transform(ctx, ctx->ctx_state.md5.input, 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer_size >= 64) {
|
||||||
|
buffer = md5_transform(
|
||||||
|
ctx, buffer, buffer_size & ~(unsigned long)0x3f);
|
||||||
|
buffer_size = buffer_size % 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(ctx->ctx_state.md5.input, buffer, buffer_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void md5_finish(struct b_hash_ctx *ctx, void *out, size_t max)
|
||||||
|
{
|
||||||
|
uint32_t used = ctx->ctx_state.md5.count[0] & 0x3f;
|
||||||
|
ctx->ctx_state.md5.input[used++] = 0x80;
|
||||||
|
uint32_t free = 64 - used;
|
||||||
|
|
||||||
|
if (free < 8) {
|
||||||
|
memset(&ctx->ctx_state.md5.input[used], 0, free);
|
||||||
|
md5_transform(ctx, ctx->ctx_state.md5.input, 64);
|
||||||
|
used = 0;
|
||||||
|
free = 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&ctx->ctx_state.md5.input[used], 0, free - 8);
|
||||||
|
|
||||||
|
unsigned char digest[B_DIGEST_LENGTH_MD5];
|
||||||
|
|
||||||
|
ctx->ctx_state.md5.count[0] <<= 3;
|
||||||
|
ctx->ctx_state.md5.input[56] = (uint8_t)(ctx->ctx_state.md5.count[0]);
|
||||||
|
ctx->ctx_state.md5.input[57] = (uint8_t)(ctx->ctx_state.md5.count[0] >> 8);
|
||||||
|
ctx->ctx_state.md5.input[58]
|
||||||
|
= (uint8_t)(ctx->ctx_state.md5.count[0] >> 16);
|
||||||
|
ctx->ctx_state.md5.input[59]
|
||||||
|
= (uint8_t)(ctx->ctx_state.md5.count[0] >> 24);
|
||||||
|
ctx->ctx_state.md5.input[60] = (uint8_t)(ctx->ctx_state.md5.count[1]);
|
||||||
|
ctx->ctx_state.md5.input[61] = (uint8_t)(ctx->ctx_state.md5.count[1] >> 8);
|
||||||
|
ctx->ctx_state.md5.input[62]
|
||||||
|
= (uint8_t)(ctx->ctx_state.md5.count[1] >> 16);
|
||||||
|
ctx->ctx_state.md5.input[63]
|
||||||
|
= (uint8_t)(ctx->ctx_state.md5.count[1] >> 24);
|
||||||
|
|
||||||
|
md5_transform(ctx, ctx->ctx_state.md5.input, 64);
|
||||||
|
|
||||||
|
digest[0] = (uint8_t)(ctx->ctx_state.md5.a);
|
||||||
|
digest[1] = (uint8_t)(ctx->ctx_state.md5.a >> 8);
|
||||||
|
digest[2] = (uint8_t)(ctx->ctx_state.md5.a >> 16);
|
||||||
|
digest[3] = (uint8_t)(ctx->ctx_state.md5.a >> 24);
|
||||||
|
digest[4] = (uint8_t)(ctx->ctx_state.md5.b);
|
||||||
|
digest[5] = (uint8_t)(ctx->ctx_state.md5.b >> 8);
|
||||||
|
digest[6] = (uint8_t)(ctx->ctx_state.md5.b >> 16);
|
||||||
|
digest[7] = (uint8_t)(ctx->ctx_state.md5.b >> 24);
|
||||||
|
digest[8] = (uint8_t)(ctx->ctx_state.md5.c);
|
||||||
|
digest[9] = (uint8_t)(ctx->ctx_state.md5.c >> 8);
|
||||||
|
digest[10] = (uint8_t)(ctx->ctx_state.md5.c >> 16);
|
||||||
|
digest[11] = (uint8_t)(ctx->ctx_state.md5.c >> 24);
|
||||||
|
digest[12] = (uint8_t)(ctx->ctx_state.md5.d);
|
||||||
|
digest[13] = (uint8_t)(ctx->ctx_state.md5.d >> 8);
|
||||||
|
digest[14] = (uint8_t)(ctx->ctx_state.md5.d >> 16);
|
||||||
|
digest[15] = (uint8_t)(ctx->ctx_state.md5.d >> 24);
|
||||||
|
|
||||||
|
memcpy(out, digest, b_min(size_t, sizeof digest, max));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct b_hash_function_ops z__b_md5_ops = {
|
||||||
|
.hash_init = md5_init,
|
||||||
|
.hash_update = md5_update,
|
||||||
|
.hash_finish = md5_finish,
|
||||||
|
};
|
||||||
268
core/hash/sha1.c
Normal file
268
core/hash/sha1.c
Normal file
@@ -0,0 +1,268 @@
|
|||||||
|
/*
|
||||||
|
SHA-1 in C
|
||||||
|
By Steve Reid <steve@edmweb.com>
|
||||||
|
100% Public Domain
|
||||||
|
|
||||||
|
Test Vectors (from FIPS PUB 180-1)
|
||||||
|
"abc"
|
||||||
|
A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
|
||||||
|
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
|
||||||
|
84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
|
||||||
|
A million repetitions of "a"
|
||||||
|
34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */
|
||||||
|
/* #define SHA1HANDSOFF * Copies data before messing with it. */
|
||||||
|
|
||||||
|
#define SHA1HANDSOFF
|
||||||
|
|
||||||
|
#include "hash.h"
|
||||||
|
|
||||||
|
#include <blue/core/hash.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* for uint32_t */
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
|
||||||
|
|
||||||
|
/* blk0() and blk() perform the initial expand. */
|
||||||
|
/* I got the idea of expanding during the round function from SSLeay */
|
||||||
|
#if defined(LITTLE_ENDIAN)
|
||||||
|
#define blk0(i) \
|
||||||
|
(block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) \
|
||||||
|
| (rol(block->l[i], 8) & 0x00FF00FF))
|
||||||
|
#elif defined(BIG_ENDIAN)
|
||||||
|
#define blk0(i) block->l[i]
|
||||||
|
#else
|
||||||
|
#error "Endianness not defined!"
|
||||||
|
#endif
|
||||||
|
#define blk(i) \
|
||||||
|
(block->l[i & 15] \
|
||||||
|
= rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] \
|
||||||
|
^ block->l[(i + 2) & 15] ^ block->l[i & 15], \
|
||||||
|
1))
|
||||||
|
|
||||||
|
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
|
||||||
|
#define R0(v, w, x, y, z, i) \
|
||||||
|
z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \
|
||||||
|
w = rol(w, 30);
|
||||||
|
#define R1(v, w, x, y, z, i) \
|
||||||
|
z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
|
||||||
|
w = rol(w, 30);
|
||||||
|
#define R2(v, w, x, y, z, i) \
|
||||||
|
z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \
|
||||||
|
w = rol(w, 30);
|
||||||
|
#define R3(v, w, x, y, z, i) \
|
||||||
|
z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
|
||||||
|
w = rol(w, 30);
|
||||||
|
#define R4(v, w, x, y, z, i) \
|
||||||
|
z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
|
||||||
|
w = rol(w, 30);
|
||||||
|
|
||||||
|
/* Hash a single 512-bit block. This is the core of the algorithm. */
|
||||||
|
|
||||||
|
void SHA1Transform(uint32_t state[5], const unsigned char buffer[64])
|
||||||
|
{
|
||||||
|
uint32_t a, b, c, d, e;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
unsigned char c[64];
|
||||||
|
uint32_t l[16];
|
||||||
|
} CHAR64LONG16;
|
||||||
|
|
||||||
|
#ifdef SHA1HANDSOFF
|
||||||
|
CHAR64LONG16 block[1]; /* use array to appear as a pointer */
|
||||||
|
|
||||||
|
memcpy(block, buffer, 64);
|
||||||
|
#else
|
||||||
|
/* The following had better never be used because it causes the
|
||||||
|
* pointer-to-const buffer to be cast into a pointer to non-const.
|
||||||
|
* And the result is written through. I threw a "const" in, hoping
|
||||||
|
* this will cause a diagnostic.
|
||||||
|
*/
|
||||||
|
CHAR64LONG16 *block = (const CHAR64LONG16 *)buffer;
|
||||||
|
#endif
|
||||||
|
/* Copy context->ctx_state.sha1.state[] to working vars */
|
||||||
|
a = state[0];
|
||||||
|
b = state[1];
|
||||||
|
c = state[2];
|
||||||
|
d = state[3];
|
||||||
|
e = state[4];
|
||||||
|
/* 4 rounds of 20 operations each. Loop unrolled. */
|
||||||
|
R0(a, b, c, d, e, 0);
|
||||||
|
R0(e, a, b, c, d, 1);
|
||||||
|
R0(d, e, a, b, c, 2);
|
||||||
|
R0(c, d, e, a, b, 3);
|
||||||
|
R0(b, c, d, e, a, 4);
|
||||||
|
R0(a, b, c, d, e, 5);
|
||||||
|
R0(e, a, b, c, d, 6);
|
||||||
|
R0(d, e, a, b, c, 7);
|
||||||
|
R0(c, d, e, a, b, 8);
|
||||||
|
R0(b, c, d, e, a, 9);
|
||||||
|
R0(a, b, c, d, e, 10);
|
||||||
|
R0(e, a, b, c, d, 11);
|
||||||
|
R0(d, e, a, b, c, 12);
|
||||||
|
R0(c, d, e, a, b, 13);
|
||||||
|
R0(b, c, d, e, a, 14);
|
||||||
|
R0(a, b, c, d, e, 15);
|
||||||
|
R1(e, a, b, c, d, 16);
|
||||||
|
R1(d, e, a, b, c, 17);
|
||||||
|
R1(c, d, e, a, b, 18);
|
||||||
|
R1(b, c, d, e, a, 19);
|
||||||
|
R2(a, b, c, d, e, 20);
|
||||||
|
R2(e, a, b, c, d, 21);
|
||||||
|
R2(d, e, a, b, c, 22);
|
||||||
|
R2(c, d, e, a, b, 23);
|
||||||
|
R2(b, c, d, e, a, 24);
|
||||||
|
R2(a, b, c, d, e, 25);
|
||||||
|
R2(e, a, b, c, d, 26);
|
||||||
|
R2(d, e, a, b, c, 27);
|
||||||
|
R2(c, d, e, a, b, 28);
|
||||||
|
R2(b, c, d, e, a, 29);
|
||||||
|
R2(a, b, c, d, e, 30);
|
||||||
|
R2(e, a, b, c, d, 31);
|
||||||
|
R2(d, e, a, b, c, 32);
|
||||||
|
R2(c, d, e, a, b, 33);
|
||||||
|
R2(b, c, d, e, a, 34);
|
||||||
|
R2(a, b, c, d, e, 35);
|
||||||
|
R2(e, a, b, c, d, 36);
|
||||||
|
R2(d, e, a, b, c, 37);
|
||||||
|
R2(c, d, e, a, b, 38);
|
||||||
|
R2(b, c, d, e, a, 39);
|
||||||
|
R3(a, b, c, d, e, 40);
|
||||||
|
R3(e, a, b, c, d, 41);
|
||||||
|
R3(d, e, a, b, c, 42);
|
||||||
|
R3(c, d, e, a, b, 43);
|
||||||
|
R3(b, c, d, e, a, 44);
|
||||||
|
R3(a, b, c, d, e, 45);
|
||||||
|
R3(e, a, b, c, d, 46);
|
||||||
|
R3(d, e, a, b, c, 47);
|
||||||
|
R3(c, d, e, a, b, 48);
|
||||||
|
R3(b, c, d, e, a, 49);
|
||||||
|
R3(a, b, c, d, e, 50);
|
||||||
|
R3(e, a, b, c, d, 51);
|
||||||
|
R3(d, e, a, b, c, 52);
|
||||||
|
R3(c, d, e, a, b, 53);
|
||||||
|
R3(b, c, d, e, a, 54);
|
||||||
|
R3(a, b, c, d, e, 55);
|
||||||
|
R3(e, a, b, c, d, 56);
|
||||||
|
R3(d, e, a, b, c, 57);
|
||||||
|
R3(c, d, e, a, b, 58);
|
||||||
|
R3(b, c, d, e, a, 59);
|
||||||
|
R4(a, b, c, d, e, 60);
|
||||||
|
R4(e, a, b, c, d, 61);
|
||||||
|
R4(d, e, a, b, c, 62);
|
||||||
|
R4(c, d, e, a, b, 63);
|
||||||
|
R4(b, c, d, e, a, 64);
|
||||||
|
R4(a, b, c, d, e, 65);
|
||||||
|
R4(e, a, b, c, d, 66);
|
||||||
|
R4(d, e, a, b, c, 67);
|
||||||
|
R4(c, d, e, a, b, 68);
|
||||||
|
R4(b, c, d, e, a, 69);
|
||||||
|
R4(a, b, c, d, e, 70);
|
||||||
|
R4(e, a, b, c, d, 71);
|
||||||
|
R4(d, e, a, b, c, 72);
|
||||||
|
R4(c, d, e, a, b, 73);
|
||||||
|
R4(b, c, d, e, a, 74);
|
||||||
|
R4(a, b, c, d, e, 75);
|
||||||
|
R4(e, a, b, c, d, 76);
|
||||||
|
R4(d, e, a, b, c, 77);
|
||||||
|
R4(c, d, e, a, b, 78);
|
||||||
|
R4(b, c, d, e, a, 79);
|
||||||
|
/* Add the working vars back into context.state[] */
|
||||||
|
state[0] += a;
|
||||||
|
state[1] += b;
|
||||||
|
state[2] += c;
|
||||||
|
state[3] += d;
|
||||||
|
state[4] += e;
|
||||||
|
/* Wipe variables */
|
||||||
|
a = b = c = d = e = 0;
|
||||||
|
#ifdef SHA1HANDSOFF
|
||||||
|
memset(block, '\0', sizeof(block));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sha_init - Initialize new context */
|
||||||
|
|
||||||
|
static void sha_init(struct b_hash_ctx *context)
|
||||||
|
{
|
||||||
|
/* SHA1 initialization constants */
|
||||||
|
context->ctx_state.sha1.state[0] = 0x67452301;
|
||||||
|
context->ctx_state.sha1.state[1] = 0xEFCDAB89;
|
||||||
|
context->ctx_state.sha1.state[2] = 0x98BADCFE;
|
||||||
|
context->ctx_state.sha1.state[3] = 0x10325476;
|
||||||
|
context->ctx_state.sha1.state[4] = 0xC3D2E1F0;
|
||||||
|
context->ctx_state.sha1.count[0] = context->ctx_state.sha1.count[1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Run your data through this. */
|
||||||
|
|
||||||
|
static void sha_update(struct b_hash_ctx *context, const void *p, size_t len)
|
||||||
|
{
|
||||||
|
const unsigned char *data = p;
|
||||||
|
uint32_t i, j;
|
||||||
|
|
||||||
|
j = context->ctx_state.sha1.count[0];
|
||||||
|
if ((context->ctx_state.sha1.count[0] += len << 3) < j)
|
||||||
|
context->ctx_state.sha1.count[1]++;
|
||||||
|
context->ctx_state.sha1.count[1] += (len >> 29);
|
||||||
|
j = (j >> 3) & 63;
|
||||||
|
if ((j + len) > 63) {
|
||||||
|
memcpy(&context->ctx_state.sha1.buffer[j], data, (i = 64 - j));
|
||||||
|
SHA1Transform(
|
||||||
|
context->ctx_state.sha1.state,
|
||||||
|
context->ctx_state.sha1.buffer);
|
||||||
|
for (; i + 63 < len; i += 64) {
|
||||||
|
SHA1Transform(context->ctx_state.sha1.state, &data[i]);
|
||||||
|
}
|
||||||
|
j = 0;
|
||||||
|
} else
|
||||||
|
i = 0;
|
||||||
|
memcpy(&context->ctx_state.sha1.buffer[j], &data[i], len - i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add padding and return the message digest. */
|
||||||
|
|
||||||
|
static void sha_finish(struct b_hash_ctx *context, void *out, size_t max)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
unsigned char finalcount[8] = {0};
|
||||||
|
|
||||||
|
unsigned char c;
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
finalcount[i] = (unsigned char)((context->ctx_state.sha1
|
||||||
|
.count[(i >= 4 ? 0 : 1)]
|
||||||
|
>> ((3 - (i & 3)) * 8))
|
||||||
|
& 255); /* Endian independent */
|
||||||
|
}
|
||||||
|
|
||||||
|
char digest[B_DIGEST_LENGTH_SHA1];
|
||||||
|
c = 0200;
|
||||||
|
sha_update(context, &c, 1);
|
||||||
|
while ((context->ctx_state.sha1.count[0] & 504) != 448) {
|
||||||
|
c = 0000;
|
||||||
|
sha_update(context, &c, 1);
|
||||||
|
}
|
||||||
|
sha_update(context, finalcount, 8); /* Should cause a SHA1Transform() */
|
||||||
|
for (i = 0; i < 20; i++) {
|
||||||
|
digest[i] = (unsigned char)((context->ctx_state.sha1.state[i >> 2]
|
||||||
|
>> ((3 - (i & 3)) * 8))
|
||||||
|
& 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(out, digest, b_min(size_t, sizeof digest, max));
|
||||||
|
/* Wipe variables */
|
||||||
|
memset(context, '\0', sizeof(*context));
|
||||||
|
memset(&finalcount, '\0', sizeof(finalcount));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct b_hash_function_ops z__b_sha1_ops = {
|
||||||
|
.hash_init = sha_init,
|
||||||
|
.hash_update = sha_update,
|
||||||
|
.hash_finish = sha_finish,
|
||||||
|
};
|
||||||
42
core/hash/sha2_224.c
Normal file
42
core/hash/sha2_224.c
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
// SHA-224. Adapted from LibTomCrypt. This code is Public Domain
|
||||||
|
#include "hash.h"
|
||||||
|
|
||||||
|
#include <blue/core/hash.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
extern void z__b_sha2_256_update(
|
||||||
|
struct b_hash_ctx *md, const void *src, size_t inlen);
|
||||||
|
extern void z__b_sha2_256_finish(struct b_hash_ctx *md, void *out, size_t max);
|
||||||
|
|
||||||
|
static void sha_init(struct b_hash_ctx *md)
|
||||||
|
{
|
||||||
|
md->ctx_state.sha2_256.curlen = 0;
|
||||||
|
md->ctx_state.sha2_256.length = 0;
|
||||||
|
md->ctx_state.sha2_256.state[0] = 0xc1059ed8UL;
|
||||||
|
md->ctx_state.sha2_256.state[1] = 0x367cd507UL;
|
||||||
|
md->ctx_state.sha2_256.state[2] = 0x3070dd17UL;
|
||||||
|
md->ctx_state.sha2_256.state[3] = 0xf70e5939UL;
|
||||||
|
md->ctx_state.sha2_256.state[4] = 0xffc00b31UL;
|
||||||
|
md->ctx_state.sha2_256.state[5] = 0x68581511UL;
|
||||||
|
md->ctx_state.sha2_256.state[6] = 0x64f98fa7UL;
|
||||||
|
md->ctx_state.sha2_256.state[7] = 0xbefa4fa4UL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sha_update(struct b_hash_ctx *md, const void *in, size_t inlen)
|
||||||
|
{
|
||||||
|
z__b_sha2_256_update(md, in, inlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sha_finish(struct b_hash_ctx *md, void *out, size_t max)
|
||||||
|
{
|
||||||
|
unsigned char res[B_DIGEST_LENGTH_SHA2_256];
|
||||||
|
z__b_sha2_256_finish(md, res, max);
|
||||||
|
/* truncate the digest to 224 bits */
|
||||||
|
memcpy(out, res, b_min(size_t, max, B_DIGEST_LENGTH_224));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct b_hash_function_ops z__b_sha2_224_ops = {
|
||||||
|
.hash_init = sha_init,
|
||||||
|
.hash_update = sha_update,
|
||||||
|
.hash_finish = sha_finish,
|
||||||
|
};
|
||||||
215
core/hash/sha2_256.c
Normal file
215
core/hash/sha2_256.c
Normal file
@@ -0,0 +1,215 @@
|
|||||||
|
// SHA-256. Adapted from LibTomCrypt. This code is Public Domain
|
||||||
|
#include "hash.h"
|
||||||
|
|
||||||
|
#include <blue/core/hash.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static const uint32_t K[64] = {
|
||||||
|
0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
|
||||||
|
0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
|
||||||
|
0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
|
||||||
|
0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
|
||||||
|
0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
|
||||||
|
0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
|
||||||
|
0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
|
||||||
|
0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
|
||||||
|
0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
|
||||||
|
0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
|
||||||
|
0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
|
||||||
|
0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
|
||||||
|
0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint32_t min(uint32_t x, uint32_t y)
|
||||||
|
{
|
||||||
|
return x < y ? x : y;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t load32(const unsigned char *y)
|
||||||
|
{
|
||||||
|
return ((uint32_t)(y[0]) << 24) | ((uint32_t)(y[1]) << 16)
|
||||||
|
| ((uint32_t)(y[2]) << 8) | ((uint32_t)(y[3]) << 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void store64(uint64_t x, unsigned char *y)
|
||||||
|
{
|
||||||
|
for (int i = 0; i != 8; ++i)
|
||||||
|
y[i] = (x >> ((7 - i) * 8)) & 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void store32(uint32_t x, unsigned char *y)
|
||||||
|
{
|
||||||
|
for (int i = 0; i != 4; ++i)
|
||||||
|
y[i] = (x >> ((3 - i) * 8)) & 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t Ch(uint32_t x, uint32_t y, uint32_t z)
|
||||||
|
{
|
||||||
|
return z ^ (x & (y ^ z));
|
||||||
|
}
|
||||||
|
static uint32_t Maj(uint32_t x, uint32_t y, uint32_t z)
|
||||||
|
{
|
||||||
|
return ((x | y) & z) | (x & y);
|
||||||
|
}
|
||||||
|
static uint32_t Rot(uint32_t x, uint32_t n)
|
||||||
|
{
|
||||||
|
return (x >> (n & 31)) | (x << (32 - (n & 31)));
|
||||||
|
}
|
||||||
|
static uint32_t Sh(uint32_t x, uint32_t n)
|
||||||
|
{
|
||||||
|
return x >> n;
|
||||||
|
}
|
||||||
|
static uint32_t Sigma0(uint32_t x)
|
||||||
|
{
|
||||||
|
return Rot(x, 2) ^ Rot(x, 13) ^ Rot(x, 22);
|
||||||
|
}
|
||||||
|
static uint32_t Sigma1(uint32_t x)
|
||||||
|
{
|
||||||
|
return Rot(x, 6) ^ Rot(x, 11) ^ Rot(x, 25);
|
||||||
|
}
|
||||||
|
static uint32_t Gamma0(uint32_t x)
|
||||||
|
{
|
||||||
|
return Rot(x, 7) ^ Rot(x, 18) ^ Sh(x, 3);
|
||||||
|
}
|
||||||
|
static uint32_t Gamma1(uint32_t x)
|
||||||
|
{
|
||||||
|
return Rot(x, 17) ^ Rot(x, 19) ^ Sh(x, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void RND(
|
||||||
|
uint32_t *t0, uint32_t *t1, uint32_t W[], uint32_t a, uint32_t b,
|
||||||
|
uint32_t c, uint32_t *d, uint32_t e, uint32_t f, uint32_t g,
|
||||||
|
uint32_t *h, uint32_t i)
|
||||||
|
{
|
||||||
|
(*t0) = *h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];
|
||||||
|
(*t1) = Sigma0(a) + Maj(a, b, c);
|
||||||
|
(*d) += *t0;
|
||||||
|
(*h) = *t0 + *t1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sha_compress(struct b_hash_ctx *md, const unsigned char *buf)
|
||||||
|
{
|
||||||
|
uint32_t S[8], W[64], t0, t1, t;
|
||||||
|
|
||||||
|
// Copy state into S
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
S[i] = md->ctx_state.sha2_256.state[i];
|
||||||
|
|
||||||
|
// Copy the state into 512-bits into W[0..15]
|
||||||
|
for (int i = 0; i < 16; i++)
|
||||||
|
W[i] = load32(buf + (4 * i));
|
||||||
|
|
||||||
|
// Fill W[16..63]
|
||||||
|
for (int i = 16; i < 64; i++)
|
||||||
|
W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
|
||||||
|
|
||||||
|
// Compress
|
||||||
|
|
||||||
|
for (int i = 0; i < 64; ++i) {
|
||||||
|
RND(&t0, &t1, W, S[0], S[1], S[2], &S[3], S[4], S[5], S[6],
|
||||||
|
&S[7], i);
|
||||||
|
t = S[7];
|
||||||
|
S[7] = S[6];
|
||||||
|
S[6] = S[5];
|
||||||
|
S[5] = S[4];
|
||||||
|
S[4] = S[3];
|
||||||
|
S[3] = S[2];
|
||||||
|
S[2] = S[1];
|
||||||
|
S[1] = S[0];
|
||||||
|
S[0] = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Feedback
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
md->ctx_state.sha2_256.state[i]
|
||||||
|
= md->ctx_state.sha2_256.state[i] + S[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public interface
|
||||||
|
|
||||||
|
static void sha_init(struct b_hash_ctx *md)
|
||||||
|
{
|
||||||
|
md->ctx_state.sha2_256.curlen = 0;
|
||||||
|
md->ctx_state.sha2_256.length = 0;
|
||||||
|
md->ctx_state.sha2_256.state[0] = 0x6A09E667UL;
|
||||||
|
md->ctx_state.sha2_256.state[1] = 0xBB67AE85UL;
|
||||||
|
md->ctx_state.sha2_256.state[2] = 0x3C6EF372UL;
|
||||||
|
md->ctx_state.sha2_256.state[3] = 0xA54FF53AUL;
|
||||||
|
md->ctx_state.sha2_256.state[4] = 0x510E527FUL;
|
||||||
|
md->ctx_state.sha2_256.state[5] = 0x9B05688CUL;
|
||||||
|
md->ctx_state.sha2_256.state[6] = 0x1F83D9ABUL;
|
||||||
|
md->ctx_state.sha2_256.state[7] = 0x5BE0CD19UL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void z__b_sha2_256_update(struct b_hash_ctx *md, const void *src, size_t inlen)
|
||||||
|
{
|
||||||
|
const uint32_t block_size = sizeof md->ctx_state.sha2_256.buf;
|
||||||
|
const unsigned char *in = (const unsigned char *)(src);
|
||||||
|
|
||||||
|
while (inlen > 0) {
|
||||||
|
if (md->ctx_state.sha2_256.curlen == 0 && inlen >= block_size) {
|
||||||
|
sha_compress(md, in);
|
||||||
|
md->ctx_state.sha2_256.length += block_size * 8;
|
||||||
|
in += block_size;
|
||||||
|
inlen -= block_size;
|
||||||
|
} else {
|
||||||
|
uint32_t n = min(
|
||||||
|
inlen,
|
||||||
|
(block_size - md->ctx_state.sha2_256.curlen));
|
||||||
|
memcpy(md->ctx_state.sha2_256.buf
|
||||||
|
+ md->ctx_state.sha2_256.curlen,
|
||||||
|
in, n);
|
||||||
|
md->ctx_state.sha2_256.curlen += n;
|
||||||
|
in += n;
|
||||||
|
inlen -= n;
|
||||||
|
|
||||||
|
if (md->ctx_state.sha2_256.curlen == block_size) {
|
||||||
|
sha_compress(md, md->ctx_state.sha2_256.buf);
|
||||||
|
md->ctx_state.sha2_256.length += 8 * block_size;
|
||||||
|
md->ctx_state.sha2_256.curlen = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void z__b_sha2_256_finish(struct b_hash_ctx *md, void *out, size_t max)
|
||||||
|
{
|
||||||
|
// Increase the length of the message
|
||||||
|
md->ctx_state.sha2_256.length += md->ctx_state.sha2_256.curlen * 8;
|
||||||
|
|
||||||
|
// Append the '1' bit
|
||||||
|
md->ctx_state.sha2_256.buf[md->ctx_state.sha2_256.curlen++]
|
||||||
|
= (unsigned char)(0x80);
|
||||||
|
|
||||||
|
// If the length is currently above 56 bytes we append zeros then compress.
|
||||||
|
// Then we can fall back to padding zeros and length encoding like normal.
|
||||||
|
if (md->ctx_state.sha2_256.curlen > 56) {
|
||||||
|
while (md->ctx_state.sha2_256.curlen < 64)
|
||||||
|
md->ctx_state.sha2_256.buf[md->ctx_state.sha2_256.curlen++]
|
||||||
|
= 0;
|
||||||
|
sha_compress(md, md->ctx_state.sha2_256.buf);
|
||||||
|
md->ctx_state.sha2_256.curlen = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pad upto 56 bytes of zeroes
|
||||||
|
while (md->ctx_state.sha2_256.curlen < 56)
|
||||||
|
md->ctx_state.sha2_256.buf[md->ctx_state.sha2_256.curlen++] = 0;
|
||||||
|
|
||||||
|
// Store length
|
||||||
|
store64(md->ctx_state.sha2_256.length, md->ctx_state.sha2_256.buf + 56);
|
||||||
|
sha_compress(md, md->ctx_state.sha2_256.buf);
|
||||||
|
|
||||||
|
unsigned char digest[B_DIGEST_LENGTH_SHA2_256];
|
||||||
|
|
||||||
|
// Copy output
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
store32(md->ctx_state.sha2_256.state[i],
|
||||||
|
(unsigned char *)&digest[(4 * i)]);
|
||||||
|
|
||||||
|
memcpy(out, digest, b_min(size_t, sizeof digest, max));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct b_hash_function_ops z__b_sha2_256_ops = {
|
||||||
|
.hash_init = sha_init,
|
||||||
|
.hash_update = z__b_sha2_256_update,
|
||||||
|
.hash_finish = z__b_sha2_256_finish,
|
||||||
|
};
|
||||||
42
core/hash/sha2_384.c
Normal file
42
core/hash/sha2_384.c
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
// SHA-384. Adapted from LibTomCrypt. This code is Public Domain
|
||||||
|
#include "hash.h"
|
||||||
|
|
||||||
|
#include <blue/core/hash.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
extern void z__b_sha2_512_update(
|
||||||
|
struct b_hash_ctx *md, const void *src, size_t inlen);
|
||||||
|
extern void z__b_sha2_512_finish(struct b_hash_ctx *md, void *out, size_t max);
|
||||||
|
|
||||||
|
void sha_init(struct b_hash_ctx *md)
|
||||||
|
{
|
||||||
|
md->ctx_state.sha2_512.curlen = 0;
|
||||||
|
md->ctx_state.sha2_512.length = 0;
|
||||||
|
md->ctx_state.sha2_512.state[0] = 0xcbbb9d5dc1059ed8ULL;
|
||||||
|
md->ctx_state.sha2_512.state[1] = 0x629a292a367cd507ULL;
|
||||||
|
md->ctx_state.sha2_512.state[2] = 0x9159015a3070dd17ULL;
|
||||||
|
md->ctx_state.sha2_512.state[3] = 0x152fecd8f70e5939ULL;
|
||||||
|
md->ctx_state.sha2_512.state[4] = 0x67332667ffc00b31ULL;
|
||||||
|
md->ctx_state.sha2_512.state[5] = 0x8eb44a8768581511ULL;
|
||||||
|
md->ctx_state.sha2_512.state[6] = 0xdb0c2e0d64f98fa7ULL;
|
||||||
|
md->ctx_state.sha2_512.state[7] = 0x47b5481dbefa4fa4ULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sha_update(struct b_hash_ctx *md, const void *in, size_t inlen)
|
||||||
|
{
|
||||||
|
z__b_sha2_512_update(md, in, inlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sha_finish(struct b_hash_ctx *md, void *out, size_t max)
|
||||||
|
{
|
||||||
|
unsigned char res[B_DIGEST_LENGTH_SHA2_512];
|
||||||
|
z__b_sha2_512_finish(md, res, max);
|
||||||
|
/* truncate the digest to 384 bits */
|
||||||
|
memcpy(out, res, b_min(size_t, max, B_DIGEST_LENGTH_384));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct b_hash_function_ops z__b_sha2_384_ops = {
|
||||||
|
.hash_init = sha_init,
|
||||||
|
.hash_update = sha_update,
|
||||||
|
.hash_finish = sha_finish,
|
||||||
|
};
|
||||||
236
core/hash/sha2_512.c
Normal file
236
core/hash/sha2_512.c
Normal file
@@ -0,0 +1,236 @@
|
|||||||
|
// SHA-512. Adapted from LibTomCrypt. This code is Public Domain
|
||||||
|
#include "hash.h"
|
||||||
|
|
||||||
|
#include <blue/core/hash.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static const uint64_t K[80]
|
||||||
|
= {0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL,
|
||||||
|
0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
|
||||||
|
0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL,
|
||||||
|
0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
|
||||||
|
0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL,
|
||||||
|
0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
|
||||||
|
0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL,
|
||||||
|
0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
|
||||||
|
0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL,
|
||||||
|
0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
|
||||||
|
0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL,
|
||||||
|
0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
|
||||||
|
0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL,
|
||||||
|
0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
|
||||||
|
0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL,
|
||||||
|
0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
|
||||||
|
0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL,
|
||||||
|
0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
|
||||||
|
0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL,
|
||||||
|
0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
|
||||||
|
0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL,
|
||||||
|
0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
|
||||||
|
0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL,
|
||||||
|
0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
|
||||||
|
0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL,
|
||||||
|
0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
|
||||||
|
0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL};
|
||||||
|
|
||||||
|
static uint32_t min(uint32_t x, uint32_t y)
|
||||||
|
{
|
||||||
|
return x < y ? x : y;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void store64(uint64_t x, unsigned char *y)
|
||||||
|
{
|
||||||
|
for (int i = 0; i != 8; ++i)
|
||||||
|
y[i] = (x >> ((7 - i) * 8)) & 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t load64(const unsigned char *y)
|
||||||
|
{
|
||||||
|
uint64_t res = 0;
|
||||||
|
for (int i = 0; i != 8; ++i)
|
||||||
|
res |= (uint64_t)(y[i]) << ((7 - i) * 8);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t Ch(uint64_t x, uint64_t y, uint64_t z)
|
||||||
|
{
|
||||||
|
return z ^ (x & (y ^ z));
|
||||||
|
}
|
||||||
|
static uint64_t Maj(uint64_t x, uint64_t y, uint64_t z)
|
||||||
|
{
|
||||||
|
return ((x | y) & z) | (x & y);
|
||||||
|
}
|
||||||
|
static uint64_t Rot(uint64_t x, uint64_t n)
|
||||||
|
{
|
||||||
|
return (x >> (n & 63)) | (x << (64 - (n & 63)));
|
||||||
|
}
|
||||||
|
static uint64_t Sh(uint64_t x, uint64_t n)
|
||||||
|
{
|
||||||
|
return x >> n;
|
||||||
|
}
|
||||||
|
static uint64_t Sigma0(uint64_t x)
|
||||||
|
{
|
||||||
|
return Rot(x, 28) ^ Rot(x, 34) ^ Rot(x, 39);
|
||||||
|
}
|
||||||
|
static uint64_t Sigma1(uint64_t x)
|
||||||
|
{
|
||||||
|
return Rot(x, 14) ^ Rot(x, 18) ^ Rot(x, 41);
|
||||||
|
}
|
||||||
|
static uint64_t Gamma0(uint64_t x)
|
||||||
|
{
|
||||||
|
return Rot(x, 1) ^ Rot(x, 8) ^ Sh(x, 7);
|
||||||
|
}
|
||||||
|
static uint64_t Gamma1(uint64_t x)
|
||||||
|
{
|
||||||
|
return Rot(x, 19) ^ Rot(x, 61) ^ Sh(x, 6);
|
||||||
|
}
|
||||||
|
static void RND(
|
||||||
|
uint64_t W[], uint64_t *t0, uint64_t *t1, uint64_t a, uint64_t b,
|
||||||
|
uint64_t c, uint64_t *d, uint64_t e, uint64_t f, uint64_t g,
|
||||||
|
uint64_t *h, uint64_t i)
|
||||||
|
{
|
||||||
|
*t0 = *h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];
|
||||||
|
*t1 = Sigma0(a) + Maj(a, b, c);
|
||||||
|
*d += *t0;
|
||||||
|
*h = *t0 + *t1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sha_compress(struct b_hash_ctx *md, const unsigned char *buf)
|
||||||
|
{
|
||||||
|
uint64_t S[8], W[80], t0, t1;
|
||||||
|
|
||||||
|
// Copy state into S
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
S[i] = md->ctx_state.sha2_512.state[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the state into 1024-bits into W[0..15]
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
W[i] = load64(buf + (8 * i));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill W[16..79]
|
||||||
|
for (int i = 16; i < 80; i++) {
|
||||||
|
W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compress
|
||||||
|
|
||||||
|
for (int i = 0; i < 80; i += 8) {
|
||||||
|
RND(W, &t0, &t1, S[0], S[1], S[2], &S[3], S[4], S[5], S[6],
|
||||||
|
&S[7], i + 0);
|
||||||
|
RND(W, &t0, &t1, S[7], S[0], S[1], &S[2], S[3], S[4], S[5],
|
||||||
|
&S[6], i + 1);
|
||||||
|
RND(W, &t0, &t1, S[6], S[7], S[0], &S[1], S[2], S[3], S[4],
|
||||||
|
&S[5], i + 2);
|
||||||
|
RND(W, &t0, &t1, S[5], S[6], S[7], &S[0], S[1], S[2], S[3],
|
||||||
|
&S[4], i + 3);
|
||||||
|
RND(W, &t0, &t1, S[4], S[5], S[6], &S[7], S[0], S[1], S[2],
|
||||||
|
&S[3], i + 4);
|
||||||
|
RND(W, &t0, &t1, S[3], S[4], S[5], &S[6], S[7], S[0], S[1],
|
||||||
|
&S[2], i + 5);
|
||||||
|
RND(W, &t0, &t1, S[2], S[3], S[4], &S[5], S[6], S[7], S[0],
|
||||||
|
&S[1], i + 6);
|
||||||
|
RND(W, &t0, &t1, S[1], S[2], S[3], &S[4], S[5], S[6], S[7],
|
||||||
|
&S[0], i + 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Feedback
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
md->ctx_state.sha2_512.state[i]
|
||||||
|
= md->ctx_state.sha2_512.state[i] + S[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public interface
|
||||||
|
|
||||||
|
static void sha_init(struct b_hash_ctx *md)
|
||||||
|
{
|
||||||
|
md->ctx_state.sha2_512.curlen = 0;
|
||||||
|
md->ctx_state.sha2_512.length = 0;
|
||||||
|
md->ctx_state.sha2_512.state[0] = 0x6a09e667f3bcc908ULL;
|
||||||
|
md->ctx_state.sha2_512.state[1] = 0xbb67ae8584caa73bULL;
|
||||||
|
md->ctx_state.sha2_512.state[2] = 0x3c6ef372fe94f82bULL;
|
||||||
|
md->ctx_state.sha2_512.state[3] = 0xa54ff53a5f1d36f1ULL;
|
||||||
|
md->ctx_state.sha2_512.state[4] = 0x510e527fade682d1ULL;
|
||||||
|
md->ctx_state.sha2_512.state[5] = 0x9b05688c2b3e6c1fULL;
|
||||||
|
md->ctx_state.sha2_512.state[6] = 0x1f83d9abfb41bd6bULL;
|
||||||
|
md->ctx_state.sha2_512.state[7] = 0x5be0cd19137e2179ULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void z__b_sha2_512_update(struct b_hash_ctx *md, const void *src, size_t inlen)
|
||||||
|
{
|
||||||
|
const uint32_t block_size = sizeof md->ctx_state.sha2_512.block;
|
||||||
|
const unsigned char *in = (const unsigned char *)src;
|
||||||
|
|
||||||
|
while (inlen > 0) {
|
||||||
|
if (md->ctx_state.sha2_512.curlen == 0 && inlen >= block_size) {
|
||||||
|
sha_compress(md, in);
|
||||||
|
md->ctx_state.sha2_512.length += block_size * 8;
|
||||||
|
in += block_size;
|
||||||
|
inlen -= block_size;
|
||||||
|
} else {
|
||||||
|
uint32_t n = min(
|
||||||
|
inlen,
|
||||||
|
(block_size - md->ctx_state.sha2_512.curlen));
|
||||||
|
memcpy(md->ctx_state.sha2_512.block
|
||||||
|
+ md->ctx_state.sha2_512.curlen,
|
||||||
|
in, n);
|
||||||
|
md->ctx_state.sha2_512.curlen += n;
|
||||||
|
in += n;
|
||||||
|
inlen -= n;
|
||||||
|
|
||||||
|
if (md->ctx_state.sha2_512.curlen == block_size) {
|
||||||
|
sha_compress(md, md->ctx_state.sha2_512.block);
|
||||||
|
md->ctx_state.sha2_512.length += 8 * block_size;
|
||||||
|
md->ctx_state.sha2_512.curlen = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void z__b_sha2_512_finish(struct b_hash_ctx *md, void *out, size_t max)
|
||||||
|
{
|
||||||
|
// Increase the length of the message
|
||||||
|
md->ctx_state.sha2_512.length += md->ctx_state.sha2_512.curlen * 8ULL;
|
||||||
|
|
||||||
|
// Append the '1' bit
|
||||||
|
md->ctx_state.sha2_512.block[md->ctx_state.sha2_512.curlen++] = 0x80;
|
||||||
|
|
||||||
|
// If the length is currently above 112 bytes we append zeros then compress.
|
||||||
|
// Then we can fall back to padding zeros and length encoding like normal.
|
||||||
|
if (md->ctx_state.sha2_512.curlen > 112) {
|
||||||
|
while (md->ctx_state.sha2_512.curlen < 128)
|
||||||
|
md->ctx_state.sha2_512.block[md->ctx_state.sha2_512.curlen++]
|
||||||
|
= 0;
|
||||||
|
sha_compress(md, md->ctx_state.sha2_512.block);
|
||||||
|
md->ctx_state.sha2_512.curlen = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pad upto 120 bytes of zeroes
|
||||||
|
// note: that from 112 to 120 is the 64 MSB of the length. We assume
|
||||||
|
// that you won't hash 2^64 bits of data... :-)
|
||||||
|
while (md->ctx_state.sha2_512.curlen < 120) {
|
||||||
|
md->ctx_state.sha2_512.block[md->ctx_state.sha2_512.curlen++] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store length
|
||||||
|
store64(md->ctx_state.sha2_512.length, md->ctx_state.sha2_512.block + 120);
|
||||||
|
sha_compress(md, md->ctx_state.sha2_512.block);
|
||||||
|
|
||||||
|
unsigned char digest[B_DIGEST_LENGTH_SHA2_512];
|
||||||
|
|
||||||
|
// Copy output
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
store64(md->ctx_state.sha2_512.state[i],
|
||||||
|
(unsigned char *)&digest[(8 * i)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(out, digest, b_min(size_t, sizeof digest, max));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct b_hash_function_ops z__b_sha2_512_ops = {
|
||||||
|
.hash_init = sha_init,
|
||||||
|
.hash_update = z__b_sha2_512_update,
|
||||||
|
.hash_finish = z__b_sha2_512_finish,
|
||||||
|
};
|
||||||
333
core/hash/sha3.c
Normal file
333
core/hash/sha3.c
Normal file
@@ -0,0 +1,333 @@
|
|||||||
|
/*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015 Markku-Juhani O. Saarinen
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// sha3.c
|
||||||
|
// 19-Nov-11 Markku-Juhani O. Saarinen <mjos@iki.fi>
|
||||||
|
|
||||||
|
// Revised 07-Aug-15 to match with official release of FIPS PUB 202 "SHA3"
|
||||||
|
// Revised 03-Sep-15 for portability + OpenSSL - style API
|
||||||
|
|
||||||
|
#include "hash.h"
|
||||||
|
|
||||||
|
#include <blue/core/hash.h>
|
||||||
|
#include <blue/core/misc.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifndef KECCAKF_ROUNDS
|
||||||
|
#define KECCAKF_ROUNDS 24
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ROTL64
|
||||||
|
#define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y))))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// update the state with given number of rounds
|
||||||
|
|
||||||
|
void sha3_keccakf(uint64_t st[25])
|
||||||
|
{
|
||||||
|
// constants
|
||||||
|
const uint64_t keccakf_rndc[24]
|
||||||
|
= {0x0000000000000001, 0x0000000000008082, 0x800000000000808a,
|
||||||
|
0x8000000080008000, 0x000000000000808b, 0x0000000080000001,
|
||||||
|
0x8000000080008081, 0x8000000000008009, 0x000000000000008a,
|
||||||
|
0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
|
||||||
|
0x000000008000808b, 0x800000000000008b, 0x8000000000008089,
|
||||||
|
0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
|
||||||
|
0x000000000000800a, 0x800000008000000a, 0x8000000080008081,
|
||||||
|
0x8000000000008080, 0x0000000080000001, 0x8000000080008008};
|
||||||
|
const int keccakf_rotc[24]
|
||||||
|
= {1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14,
|
||||||
|
27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44};
|
||||||
|
const int keccakf_piln[24]
|
||||||
|
= {10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4,
|
||||||
|
15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1};
|
||||||
|
|
||||||
|
// variables
|
||||||
|
int i, j, r;
|
||||||
|
uint64_t t, bc[5];
|
||||||
|
|
||||||
|
#if !defined(LITTLE_ENDIAN)
|
||||||
|
uint8_t *v;
|
||||||
|
|
||||||
|
// endianess conversion. this is redundant on little-endian targets
|
||||||
|
for (i = 0; i < 25; i++) {
|
||||||
|
v = (uint8_t *)&st[i];
|
||||||
|
st[i] = ((uint64_t)v[0]) | (((uint64_t)v[1]) << 8)
|
||||||
|
| (((uint64_t)v[2]) << 16) | (((uint64_t)v[3]) << 24)
|
||||||
|
| (((uint64_t)v[4]) << 32) | (((uint64_t)v[5]) << 40)
|
||||||
|
| (((uint64_t)v[6]) << 48) | (((uint64_t)v[7]) << 56);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// actual iteration
|
||||||
|
for (r = 0; r < KECCAKF_ROUNDS; r++) {
|
||||||
|
|
||||||
|
// Theta
|
||||||
|
for (i = 0; i < 5; i++)
|
||||||
|
bc[i] = st[i] ^ st[i + 5] ^ st[i + 10] ^ st[i + 15]
|
||||||
|
^ st[i + 20];
|
||||||
|
|
||||||
|
for (i = 0; i < 5; i++) {
|
||||||
|
t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1);
|
||||||
|
for (j = 0; j < 25; j += 5)
|
||||||
|
st[j + i] ^= t;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rho Pi
|
||||||
|
t = st[1];
|
||||||
|
for (i = 0; i < 24; i++) {
|
||||||
|
j = keccakf_piln[i];
|
||||||
|
bc[0] = st[j];
|
||||||
|
st[j] = ROTL64(t, keccakf_rotc[i]);
|
||||||
|
t = bc[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Chi
|
||||||
|
for (j = 0; j < 25; j += 5) {
|
||||||
|
for (i = 0; i < 5; i++)
|
||||||
|
bc[i] = st[j + i];
|
||||||
|
for (i = 0; i < 5; i++)
|
||||||
|
st[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iota
|
||||||
|
st[0] ^= keccakf_rndc[r];
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(LITTLE_ENDIAN)
|
||||||
|
// endianess conversion. this is redundant on little-endian targets
|
||||||
|
for (i = 0; i < 25; i++) {
|
||||||
|
v = (uint8_t *)&st[i];
|
||||||
|
t = st[i];
|
||||||
|
v[0] = t & 0xFF;
|
||||||
|
v[1] = (t >> 8) & 0xFF;
|
||||||
|
v[2] = (t >> 16) & 0xFF;
|
||||||
|
v[3] = (t >> 24) & 0xFF;
|
||||||
|
v[4] = (t >> 32) & 0xFF;
|
||||||
|
v[5] = (t >> 40) & 0xFF;
|
||||||
|
v[6] = (t >> 48) & 0xFF;
|
||||||
|
v[7] = (t >> 56) & 0xFF;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the context for SHA3
|
||||||
|
|
||||||
|
int sha3_init(struct b_hash_ctx *c, int mdlen)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 25; i++)
|
||||||
|
c->ctx_state.sha3.st.q[i] = 0;
|
||||||
|
c->ctx_state.sha3.mdlen = mdlen;
|
||||||
|
c->ctx_state.sha3.rsiz = 200 - 2 * mdlen;
|
||||||
|
c->ctx_state.sha3.pt = 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update state with more data
|
||||||
|
|
||||||
|
void sha3_update(struct b_hash_ctx *c, const void *data, size_t len)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
j = c->ctx_state.sha3.pt;
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
c->ctx_state.sha3.st.b[j++] ^= ((const uint8_t *)data)[i];
|
||||||
|
if (j >= c->ctx_state.sha3.rsiz) {
|
||||||
|
sha3_keccakf(c->ctx_state.sha3.st.q);
|
||||||
|
j = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c->ctx_state.sha3.pt = j;
|
||||||
|
}
|
||||||
|
|
||||||
|
// finalize and output a hash
|
||||||
|
|
||||||
|
int sha3_final(void *md, struct b_hash_ctx *c)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
c->ctx_state.sha3.st.b[c->ctx_state.sha3.pt] ^= 0x06;
|
||||||
|
c->ctx_state.sha3.st.b[c->ctx_state.sha3.rsiz - 1] ^= 0x80;
|
||||||
|
sha3_keccakf(c->ctx_state.sha3.st.q);
|
||||||
|
|
||||||
|
for (i = 0; i < c->ctx_state.sha3.mdlen; i++) {
|
||||||
|
((uint8_t *)md)[i] = c->ctx_state.sha3.st.b[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute a SHA-3 hash (md) of given byte length from "in"
|
||||||
|
|
||||||
|
void *sha3(const void *in, size_t inlen, void *md, int mdlen)
|
||||||
|
{
|
||||||
|
struct b_hash_ctx sha3;
|
||||||
|
|
||||||
|
sha3_init(&sha3, mdlen);
|
||||||
|
sha3_update(&sha3, in, inlen);
|
||||||
|
sha3_final(md, &sha3);
|
||||||
|
|
||||||
|
return md;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SHAKE128 and SHAKE256 extensible-output functionality
|
||||||
|
|
||||||
|
void shake_xof(struct b_hash_ctx *c)
|
||||||
|
{
|
||||||
|
c->ctx_state.sha3.st.b[c->ctx_state.sha3.pt] ^= 0x1F;
|
||||||
|
c->ctx_state.sha3.st.b[c->ctx_state.sha3.rsiz - 1] ^= 0x80;
|
||||||
|
sha3_keccakf(c->ctx_state.sha3.st.q);
|
||||||
|
c->ctx_state.sha3.pt = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void shake_out(struct b_hash_ctx *c, void *out, size_t len)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
j = c->ctx_state.sha3.pt;
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
if (j >= c->ctx_state.sha3.rsiz) {
|
||||||
|
sha3_keccakf(c->ctx_state.sha3.st.q);
|
||||||
|
j = 0;
|
||||||
|
}
|
||||||
|
((uint8_t *)out)[i] = c->ctx_state.sha3.st.b[j++];
|
||||||
|
}
|
||||||
|
c->ctx_state.sha3.pt = j;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sha3_224_init(struct b_hash_ctx *ctx)
|
||||||
|
{
|
||||||
|
sha3_init(ctx, B_DIGEST_LENGTH_SHA3_224);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sha3_224_finish(struct b_hash_ctx *ctx, void *out, size_t max)
|
||||||
|
{
|
||||||
|
unsigned char md[B_DIGEST_LENGTH_SHA3_224];
|
||||||
|
sha3_final(md, ctx);
|
||||||
|
memcpy(out, md, b_min(size_t, sizeof md, max));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sha3_256_init(struct b_hash_ctx *ctx)
|
||||||
|
{
|
||||||
|
sha3_init(ctx, B_DIGEST_LENGTH_SHA3_256);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sha3_256_finish(struct b_hash_ctx *ctx, void *out, size_t max)
|
||||||
|
{
|
||||||
|
unsigned char md[B_DIGEST_LENGTH_SHA3_256];
|
||||||
|
sha3_final(md, ctx);
|
||||||
|
memcpy(out, md, b_min(size_t, sizeof md, max));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sha3_384_init(struct b_hash_ctx *ctx)
|
||||||
|
{
|
||||||
|
sha3_init(ctx, B_DIGEST_LENGTH_SHA3_384);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sha3_384_finish(struct b_hash_ctx *ctx, void *out, size_t max)
|
||||||
|
{
|
||||||
|
unsigned char md[B_DIGEST_LENGTH_SHA3_384];
|
||||||
|
sha3_final(md, ctx);
|
||||||
|
memcpy(out, md, b_min(size_t, sizeof md, max));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sha3_512_init(struct b_hash_ctx *ctx)
|
||||||
|
{
|
||||||
|
sha3_init(ctx, B_DIGEST_LENGTH_SHA3_512);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sha3_512_finish(struct b_hash_ctx *ctx, void *out, size_t max)
|
||||||
|
{
|
||||||
|
unsigned char md[B_DIGEST_LENGTH_SHA3_512];
|
||||||
|
sha3_final(md, ctx);
|
||||||
|
memcpy(out, md, b_min(size_t, sizeof md, max));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void shake128_init(struct b_hash_ctx *ctx)
|
||||||
|
{
|
||||||
|
sha3_init(ctx, B_DIGEST_LENGTH_SHAKE128);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void shake128_finish(struct b_hash_ctx *ctx, void *out, size_t max)
|
||||||
|
{
|
||||||
|
unsigned char md[B_DIGEST_LENGTH_SHAKE128];
|
||||||
|
shake_xof(ctx);
|
||||||
|
shake_out(ctx, md, sizeof md);
|
||||||
|
memcpy(out, md, b_min(size_t, sizeof md, max));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void shake256_init(struct b_hash_ctx *ctx)
|
||||||
|
{
|
||||||
|
sha3_init(ctx, B_DIGEST_LENGTH_SHAKE256);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void shake256_finish(struct b_hash_ctx *ctx, void *out, size_t max)
|
||||||
|
{
|
||||||
|
unsigned char md[B_DIGEST_LENGTH_SHAKE256];
|
||||||
|
shake_xof(ctx);
|
||||||
|
shake_out(ctx, md, sizeof md);
|
||||||
|
memcpy(out, md, b_min(size_t, sizeof md, max));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct b_hash_function_ops z__b_sha3_224_ops = {
|
||||||
|
.hash_init = sha3_224_init,
|
||||||
|
.hash_update = sha3_update,
|
||||||
|
.hash_finish = sha3_224_finish,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct b_hash_function_ops z__b_sha3_256_ops = {
|
||||||
|
.hash_init = sha3_256_init,
|
||||||
|
.hash_update = sha3_update,
|
||||||
|
.hash_finish = sha3_256_finish,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct b_hash_function_ops z__b_sha3_384_ops = {
|
||||||
|
.hash_init = sha3_384_init,
|
||||||
|
.hash_update = sha3_update,
|
||||||
|
.hash_finish = sha3_384_finish,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct b_hash_function_ops z__b_sha3_512_ops = {
|
||||||
|
.hash_init = sha3_512_init,
|
||||||
|
.hash_update = sha3_update,
|
||||||
|
.hash_finish = sha3_512_finish,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct b_hash_function_ops z__b_shake128_ops = {
|
||||||
|
.hash_init = shake128_init,
|
||||||
|
.hash_update = sha3_update,
|
||||||
|
.hash_finish = shake128_finish,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct b_hash_function_ops z__b_shake256_ops = {
|
||||||
|
.hash_init = shake256_init,
|
||||||
|
.hash_update = sha3_update,
|
||||||
|
.hash_finish = shake256_finish,
|
||||||
|
};
|
||||||
@@ -2,8 +2,108 @@
|
|||||||
#define BLUELIB_CORE_HASH_H_
|
#define BLUELIB_CORE_HASH_H_
|
||||||
|
|
||||||
#include <blue/core/misc.h>
|
#include <blue/core/misc.h>
|
||||||
|
#include <blue/core/status.h>
|
||||||
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
BLUE_API uint64_t b_hash_string(const char *s);
|
#define B_DIGEST_LENGTH_128 16
|
||||||
|
#define B_DIGEST_LENGTH_160 20
|
||||||
|
#define B_DIGEST_LENGTH_192 24
|
||||||
|
#define B_DIGEST_LENGTH_224 28
|
||||||
|
#define B_DIGEST_LENGTH_256 32
|
||||||
|
#define B_DIGEST_LENGTH_384 48
|
||||||
|
#define B_DIGEST_LENGTH_512 64
|
||||||
|
|
||||||
#endif
|
#define B_DIGEST_LENGTH_MD4 B_DIGEST_LENGTH_128
|
||||||
|
#define B_DIGEST_LENGTH_MD5 B_DIGEST_LENGTH_128
|
||||||
|
#define B_DIGEST_LENGTH_SHA1 B_DIGEST_LENGTH_160
|
||||||
|
#define B_DIGEST_LENGTH_SHA2_224 B_DIGEST_LENGTH_224
|
||||||
|
#define B_DIGEST_LENGTH_SHA2_256 B_DIGEST_LENGTH_256
|
||||||
|
#define B_DIGEST_LENGTH_SHA2_384 B_DIGEST_LENGTH_384
|
||||||
|
#define B_DIGEST_LENGTH_SHA2_512 B_DIGEST_LENGTH_512
|
||||||
|
#define B_DIGEST_LENGTH_SHA3_224 B_DIGEST_LENGTH_224
|
||||||
|
#define B_DIGEST_LENGTH_SHA3_256 B_DIGEST_LENGTH_256
|
||||||
|
#define B_DIGEST_LENGTH_SHA3_384 B_DIGEST_LENGTH_384
|
||||||
|
#define B_DIGEST_LENGTH_SHA3_512 B_DIGEST_LENGTH_512
|
||||||
|
#define B_DIGEST_LENGTH_SHAKE128 B_DIGEST_LENGTH_128
|
||||||
|
#define B_DIGEST_LENGTH_SHAKE256 B_DIGEST_LENGTH_256
|
||||||
|
|
||||||
|
struct b_hash_function_ops;
|
||||||
|
|
||||||
|
typedef enum b_hash_function {
|
||||||
|
B_HASH_NONE = 0,
|
||||||
|
B_HASH_MD4,
|
||||||
|
B_HASH_MD5,
|
||||||
|
B_HASH_SHA1,
|
||||||
|
B_HASH_SHA2_224,
|
||||||
|
B_HASH_SHA2_256,
|
||||||
|
B_HASH_SHA2_384,
|
||||||
|
B_HASH_SHA2_512,
|
||||||
|
B_HASH_SHA3_224,
|
||||||
|
B_HASH_SHA3_256,
|
||||||
|
B_HASH_SHA3_384,
|
||||||
|
B_HASH_SHA3_512,
|
||||||
|
B_HASH_SHAKE128,
|
||||||
|
B_HASH_SHAKE256,
|
||||||
|
} b_hash_function;
|
||||||
|
|
||||||
|
typedef struct b_hash_ctx {
|
||||||
|
b_hash_function ctx_func;
|
||||||
|
const struct b_hash_function_ops *ctx_ops;
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
uint32_t lo, hi;
|
||||||
|
uint32_t a, b, c, d;
|
||||||
|
uint32_t block[16];
|
||||||
|
unsigned char buffer[64];
|
||||||
|
} md4;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
unsigned int count[2];
|
||||||
|
unsigned int a, b, c, d;
|
||||||
|
unsigned int block[16];
|
||||||
|
unsigned char input[64];
|
||||||
|
} md5;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint32_t state[5];
|
||||||
|
uint32_t count[2];
|
||||||
|
unsigned char buffer[64];
|
||||||
|
} sha1;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint64_t curlen;
|
||||||
|
uint64_t length;
|
||||||
|
unsigned char buf[128];
|
||||||
|
uint32_t state[8];
|
||||||
|
} sha2_256;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint64_t curlen;
|
||||||
|
uint64_t length;
|
||||||
|
unsigned char block[256];
|
||||||
|
uint64_t state[8];
|
||||||
|
} sha2_512;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
union {
|
||||||
|
uint8_t b[200];
|
||||||
|
uint64_t q[25];
|
||||||
|
} st;
|
||||||
|
|
||||||
|
int pt, rsiz, mdlen;
|
||||||
|
} sha3;
|
||||||
|
} ctx_state;
|
||||||
|
} b_hash_ctx;
|
||||||
|
|
||||||
|
BLUE_API uint64_t b_hash_string(const char *s);
|
||||||
|
BLUE_API uint64_t b_hash_string_ex(const char *s, size_t *len);
|
||||||
|
|
||||||
|
BLUE_API b_status b_hash_ctx_init(b_hash_ctx *ctx, b_hash_function func);
|
||||||
|
BLUE_API b_status b_hash_ctx_reset(b_hash_ctx *ctx);
|
||||||
|
BLUE_API b_status b_hash_ctx_update(b_hash_ctx *ctx, const void *p, size_t len);
|
||||||
|
BLUE_API b_status b_hash_ctx_finish(
|
||||||
|
b_hash_ctx *ctx, void *out_digest, size_t out_max);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user