#include "hash.h" #include #include #include #include #include #include #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_cstr(const char *s) { size_t x = 0; return b_hash_cstr_ex(s, &x); } uint64_t b_hash_cstr_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; } static void update_rope(const b_rope *rope, void *arg) { struct b_hash_ctx *ctx = arg; unsigned int type = B_ROPE_TYPE(rope->r_flags); char tmp[64]; size_t len = 0; switch (type) { case B_ROPE_F_CHAR: b_hash_ctx_update(ctx, &rope->r_v.v_char, sizeof rope->r_v.v_char); break; case B_ROPE_F_CSTR: case B_ROPE_F_CSTR_BORROWED: case B_ROPE_F_CSTR_STATIC: b_hash_ctx_update( ctx, rope->r_v.v_cstr.s, strlen(rope->r_v.v_cstr.s)); break; case B_ROPE_F_INT: len = snprintf(tmp, sizeof tmp, "%" PRIdPTR, rope->r_v.v_int); b_hash_ctx_update(ctx, tmp, len); break; case B_ROPE_F_UINT: len = snprintf(tmp, sizeof tmp, "%" PRIuPTR, rope->r_v.v_uint); b_hash_ctx_update(ctx, tmp, len); break; default: break; } } enum b_status b_hash_ctx_update_rope( struct b_hash_ctx *ctx, const struct b_rope *rope) { b_rope_iterate(rope, update_rope, ctx); 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; }