You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
190 lines
4.6 KiB
190 lines
4.6 KiB
/* $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 <thomas.pornin@cryptolog.com> |
|
*/ |
|
|
|
#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); |
|
}
|
|
|