/* $Id: haval_helper.c 218 2010-06-08 17:06:34Z tp $ */ /* * Helper code, included (three times !) by HAVAL implementation. * * TODO: try to merge this with md_helper.c. * * ==========================(LICENSE BEGIN)============================ * * Copyright (c) 2007-2010 Projet RNRT SAPHIR * * 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. * * ===========================(LICENSE END)============================= * * @author Thomas Pornin */ #undef SPH_XCAT #define SPH_XCAT(a, b) SPH_XCAT_(a, b) #undef SPH_XCAT_ #define SPH_XCAT_(a, b) a ## b static void #ifdef SPH_UPTR SPH_XCAT(SPH_XCAT(haval, PASSES), _short) #else SPH_XCAT(haval, PASSES) #endif (sph_haval_context *sc, const void *data, size_t len) { unsigned current; #if SPH_64 current = (unsigned)sc->count & 127U; #else current = (unsigned)sc->count_low & 127U; #endif while (len > 0) { unsigned clen; #if !SPH_64 sph_u32 clow, clow2; #endif clen = 128U - current; if (clen > len) clen = len; memcpy(sc->buf + current, data, clen); data = (const unsigned char *)data + clen; current += clen; len -= clen; if (current == 128U) { DSTATE; IN_PREPARE(sc->buf); RSTATE; SPH_XCAT(CORE, PASSES)(INW); WSTATE; current = 0; } #if SPH_64 sc->count += clen; #else clow = sc->count_low; clow2 = SPH_T32(clow + clen); sc->count_low = clow2; if (clow2 < clow) sc->count_high ++; #endif } } #ifdef SPH_UPTR static void SPH_XCAT(haval, PASSES)(sph_haval_context *sc, const void *data, size_t len) { unsigned current; size_t orig_len; #if !SPH_64 sph_u32 clow, clow2; #endif DSTATE; if (len < 256U) { SPH_XCAT(SPH_XCAT(haval, PASSES), _short)(sc, data, len); return; } #if SPH_64 current = (unsigned)sc->count & 127U; #else current = (unsigned)sc->count_low & 127U; #endif if (current > 0) { unsigned clen; clen = 128U - current; SPH_XCAT(SPH_XCAT(haval, PASSES), _short)(sc, data, clen); data = (const unsigned char *)data + clen; len -= clen; } #if !SPH_UNALIGNED if (((SPH_UPTR)data & 3U) != 0) { SPH_XCAT(SPH_XCAT(haval, PASSES), _short)(sc, data, len); return; } #endif orig_len = len; RSTATE; while (len >= 128U) { IN_PREPARE(data); SPH_XCAT(CORE, PASSES)(INW); data = (const unsigned char *)data + 128U; len -= 128U; } WSTATE; if (len > 0) memcpy(sc->buf, data, len); #if SPH_64 sc->count += (sph_u64)orig_len; #else clow = sc->count_low; clow2 = SPH_T32(clow + orig_len); sc->count_low = clow2; if (clow2 < clow) sc->count_high ++; orig_len >>= 12; orig_len >>= 10; orig_len >>= 10; sc->count_high += orig_len; #endif } #endif static void SPH_XCAT(SPH_XCAT(haval, PASSES), _close)(sph_haval_context *sc, unsigned ub, unsigned n, void *dst) { unsigned current; DSTATE; #if SPH_64 current = (unsigned)sc->count & 127U; #else current = (unsigned)sc->count_low & 127U; #endif sc->buf[current ++] = (0x01 << n) | ((ub & 0xFF) >> (8 - n)); RSTATE; if (current > 118U) { memset(sc->buf + current, 0, 128U - current); do { IN_PREPARE(sc->buf); SPH_XCAT(CORE, PASSES)(INW); } while (0); current = 0; } memset(sc->buf + current, 0, 118U - current); sc->buf[118] = 0x01 | (PASSES << 3); sc->buf[119] = sc->olen << 3; #if SPH_64 sph_enc64le_aligned(sc->buf + 120, SPH_T64(sc->count << 3)); #else sph_enc32le_aligned(sc->buf + 120, SPH_T32(sc->count_low << 3)); sph_enc32le_aligned(sc->buf + 124, SPH_T32((sc->count_high << 3) | (sc->count_low >> 29))); #endif do { IN_PREPARE(sc->buf); SPH_XCAT(CORE, PASSES)(INW); } while (0); WSTATE; haval_out(sc, dst); haval_init(sc, sc->olen, sc->passes); }