Path: blob/main/contrib/bearssl/src/hash/multihash.c
39507 views
/*1* Copyright (c) 2016 Thomas Pornin <[email protected]>2*3* Permission is hereby granted, free of charge, to any person obtaining4* a copy of this software and associated documentation files (the5* "Software"), to deal in the Software without restriction, including6* without limitation the rights to use, copy, modify, merge, publish,7* distribute, sublicense, and/or sell copies of the Software, and to8* permit persons to whom the Software is furnished to do so, subject to9* the following conditions:10*11* The above copyright notice and this permission notice shall be12* included in all copies or substantial portions of the Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,15* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF16* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND17* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS18* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN19* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN20* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE21* SOFTWARE.22*/2324#include "inner.h"2526/*27* An aggregate context that is large enough for all supported hash28* functions.29*/30typedef union {31const br_hash_class *vtable;32br_md5_context md5;33br_sha1_context sha1;34br_sha224_context sha224;35br_sha256_context sha256;36br_sha384_context sha384;37br_sha512_context sha512;38} gen_hash_context;3940/*41* Get the offset to the state for a specific hash function within the42* context structure. This shall be called only for the supported hash43* functions,44*/45static size_t46get_state_offset(int id)47{48if (id >= 5) {49/*50* SHA-384 has id 5, and SHA-512 has id 6. Both use51* eight 64-bit words for their state.52*/53return offsetof(br_multihash_context, val_64)54+ ((size_t)(id - 5) * (8 * sizeof(uint64_t)));55} else {56/*57* MD5 has id 1, SHA-1 has id 2, SHA-224 has id 3 and58* SHA-256 has id 4. They use 32-bit words for their59* states (4 words for MD5, 5 for SHA-1, 8 for SHA-22460* and 8 for SHA-256).61*/62unsigned x;6364x = id - 1;65x = ((x + (x & (x >> 1))) << 2) + (x >> 1);66return offsetof(br_multihash_context, val_32)67+ x * sizeof(uint32_t);68}69}7071/* see bearssl_hash.h */72void73br_multihash_zero(br_multihash_context *ctx)74{75/*76* This is not standard, but yields very short and efficient code,77* and it works "everywhere".78*/79memset(ctx, 0, sizeof *ctx);80}8182/* see bearssl_hash.h */83void84br_multihash_init(br_multihash_context *ctx)85{86int i;8788ctx->count = 0;89for (i = 1; i <= 6; i ++) {90const br_hash_class *hc;9192hc = ctx->impl[i - 1];93if (hc != NULL) {94gen_hash_context g;9596hc->init(&g.vtable);97hc->state(&g.vtable,98(unsigned char *)ctx + get_state_offset(i));99}100}101}102103/* see bearssl_hash.h */104void105br_multihash_update(br_multihash_context *ctx, const void *data, size_t len)106{107const unsigned char *buf;108size_t ptr;109110buf = data;111ptr = (size_t)ctx->count & 127;112while (len > 0) {113size_t clen;114115clen = 128 - ptr;116if (clen > len) {117clen = len;118}119memcpy(ctx->buf + ptr, buf, clen);120ptr += clen;121buf += clen;122len -= clen;123ctx->count += (uint64_t)clen;124if (ptr == 128) {125int i;126127for (i = 1; i <= 6; i ++) {128const br_hash_class *hc;129130hc = ctx->impl[i - 1];131if (hc != NULL) {132gen_hash_context g;133unsigned char *state;134135state = (unsigned char *)ctx136+ get_state_offset(i);137hc->set_state(&g.vtable,138state, ctx->count - 128);139hc->update(&g.vtable, ctx->buf, 128);140hc->state(&g.vtable, state);141}142}143ptr = 0;144}145}146}147148/* see bearssl_hash.h */149size_t150br_multihash_out(const br_multihash_context *ctx, int id, void *dst)151{152const br_hash_class *hc;153gen_hash_context g;154const unsigned char *state;155156hc = ctx->impl[id - 1];157if (hc == NULL) {158return 0;159}160state = (const unsigned char *)ctx + get_state_offset(id);161hc->set_state(&g.vtable, state, ctx->count & ~(uint64_t)127);162hc->update(&g.vtable, ctx->buf, ctx->count & (uint64_t)127);163hc->out(&g.vtable, dst);164return (hc->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK;165}166167168