/* $Id: md_helper.c 216 2010-06-08 09:46:57Z tp $ */ /* * This file contains some functions which implement the external data * handling and padding for Merkle-Damgard hash functions which follow * the conventions set out by MD4 (little-endian) or SHA-1 (big-endian). * * API: this file is meant to be included, not compiled as a stand-alone * file. Some macros must be defined: * RFUN name for the round function * HASH "short name" for the hash function * BE32 defined for big-endian, 32-bit based (e.g. SHA-1) * LE32 defined for little-endian, 32-bit based (e.g. MD5) * BE64 defined for big-endian, 64-bit based (e.g. SHA-512) * LE64 defined for little-endian, 64-bit based (no example yet) * PW01 if defined, append 0x01 instead of 0x80 (for Tiger) * BLEN if defined, length of a message block (in bytes) * PLW1 if defined, length is defined on one 64-bit word only (for Tiger) * PLW4 if defined, length is defined on four 64-bit words (for WHIRLPOOL) * SVAL if defined, reference to the context state information * * BLEN is used when a message block is not 16 (32-bit or 64-bit) words: * this is used for instance for Tiger, which works on 64-bit words but * uses 512-bit message blocks (eight 64-bit words). PLW1 and PLW4 are * ignored if 32-bit words are used; if 64-bit words are used and PLW1 is * set, then only one word (64 bits) will be used to encode the input * message length (in bits), otherwise two words will be used (as in * SHA-384 and SHA-512). If 64-bit words are used and PLW4 is defined (but * not PLW1), four 64-bit words will be used to encode the message length * (in bits). Note that regardless of those settings, only 64-bit message * lengths are supported (in bits): messages longer than 2 Exabytes will be * improperly hashed (this is unlikely to happen soon: 2 Exabytes is about * 2 millions Terabytes, which is huge). * * If CLOSE_ONLY is defined, then this file defines only the sph_XXX_close() * function. This is used for Tiger2, which is identical to Tiger except * when it comes to the padding (Tiger2 uses the standard 0x80 byte instead * of the 0x01 from original Tiger). * * The RFUN function is invoked with two arguments, the first pointing to * aligned data (as a "const void *"), the second being state information * from the context structure. By default, this state information is the * "val" field from the context, and this field is assumed to be an array * of words ("sph_u32" or "sph_u64", depending on BE32/LE32/BE64/LE64). * from the context structure. The "val" field can have any type, except * for the output encoding which assumes that it is an array of "sph_u32" * values. By defining NO_OUTPUT, this last step is deactivated; the * includer code is then responsible for writing out the hash result. When * NO_OUTPUT is defined, the third parameter to the "close()" function is * ignored. * * ==========================(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 */ #ifdef _MSC_VER #pragma warning(disable : 4146) #endif #undef SPH_XCAT #define SPH_XCAT(a, b) SPH_XCAT_(a, b) #undef SPH_XCAT_ #define SPH_XCAT_(a, b) a##b #undef SPH_BLEN #undef SPH_WLEN #if defined BE64 || defined LE64 #define SPH_BLEN 128U #define SPH_WLEN 8U #else #define SPH_BLEN 64U #define SPH_WLEN 4U #endif #ifdef BLEN #undef SPH_BLEN #define SPH_BLEN BLEN #endif #undef SPH_MAXPAD #if defined PLW1 #define SPH_MAXPAD (SPH_BLEN - SPH_WLEN) #elif defined PLW4 #define SPH_MAXPAD (SPH_BLEN - (SPH_WLEN << 2)) #else #define SPH_MAXPAD (SPH_BLEN - (SPH_WLEN << 1)) #endif #undef SPH_VAL #undef SPH_NO_OUTPUT #ifdef SVAL #define SPH_VAL SVAL #define SPH_NO_OUTPUT 1 #else #define SPH_VAL sc->val #endif #ifndef CLOSE_ONLY #ifdef SPH_UPTR static void SPH_XCAT(HASH, _short)(void *cc, const void *data, size_t len) #else void HASH(void *cc, const void *data, size_t len) #endif { SPH_XCAT(HASH, _context) * sc; __m256i *vdata = (__m256i *)data; size_t ptr; sc = cc; ptr = (unsigned)sc->count & (SPH_BLEN - 1U); while (len > 0) { size_t clen; clen = SPH_BLEN - ptr; if (clen > len) clen = len; memcpy_256(sc->buf + (ptr >> 3), vdata, clen >> 3); vdata = vdata + (clen >> 3); ptr += clen; len -= clen; if (ptr == SPH_BLEN) { RFUN(sc->buf, SPH_VAL); ptr = 0; } sc->count += clen; } } #ifdef SPH_UPTR void HASH(void *cc, const void *data, size_t len) { SPH_XCAT(HASH, _context) * sc; __m256i *vdata = (__m256i *)data; unsigned ptr; if (len < (2 * SPH_BLEN)) { SPH_XCAT(HASH, _short)(cc, data, len); return; } sc = cc; ptr = (unsigned)sc->count & (SPH_BLEN - 1U); if (ptr > 0) { unsigned t; t = SPH_BLEN - ptr; SPH_XCAT(HASH, _short)(cc, data, t); vdata = vdata + (t >> 3); len -= t; } SPH_XCAT(HASH, _short)(cc, data, len); } #endif #endif /* * Perform padding and produce result. The context is NOT reinitialized * by this function. */ static void SPH_XCAT(HASH, _addbits_and_close)(void *cc, unsigned ub __attribute__((unused)), unsigned n __attribute__((unused)), void *dst, unsigned rnum) { SPH_XCAT(HASH, _context) * sc; unsigned ptr, u; sc = cc; ptr = (unsigned)sc->count & (SPH_BLEN - 1U); // uint64_t *b= (uint64_t*)sc->buf; // uint64_t *s= (uint64_t*)sc->state; // printf("Vptr 1= %u\n", ptr); // printf("VBuf %016llx %016llx %016llx %016llx\n", b[0], b[4], b[8], b[12] ); // printf("VBuf %016llx %016llx %016llx %016llx\n", b[16], b[20], b[24], b[28] // ); #ifdef PW01 sc->buf[ptr >> 3] = _mm256_set1_epi64x(0x100 >> 8); // sc->buf[ptr++] = 0x100 >> 8; #else // need to overwrite exactly one byte // sc->buf[ptr>>3] = _mm256_set_epi64x( 0, 0, 0, 0x80 ); sc->buf[ptr >> 3] = _mm256_set1_epi64x(0x80); // ptr++; #endif ptr += 8; // printf("Vptr 2= %u\n", ptr); // printf("VBuf %016llx %016llx %016llx %016llx\n", b[0], b[4], b[8], b[12] ); // printf("VBuf %016llx %016llx %016llx %016llx\n", b[16], b[20], b[24], b[28] // ); if (ptr > SPH_MAXPAD) { memset_zero_256(sc->buf + (ptr >> 3), (SPH_BLEN - ptr) >> 3); RFUN(sc->buf, SPH_VAL); memset_zero_256(sc->buf, SPH_MAXPAD >> 3); } else { memset_zero_256(sc->buf + (ptr >> 3), (SPH_MAXPAD - ptr) >> 3); } #if defined BE64 #if defined PLW1 sc->buf[SPH_MAXPAD >> 3] = mm256_bswap_64(_mm256_set1_epi64x(sc->count << 3)); #elif defined PLW4 memset_zero_256(sc->buf + (SPH_MAXPAD >> 3), (2 * SPH_WLEN) >> 3); sc->buf[(SPH_MAXPAD + 2 * SPH_WLEN) >> 3] = mm256_bswap_64(_mm256_set1_epi64x(sc->count >> 61)); sc->buf[(SPH_MAXPAD + 3 * SPH_WLEN) >> 3] = mm256_bswap_64(_mm256_set1_epi64x(sc->count << 3)); #else sc->buf[(SPH_MAXPAD + 2 * SPH_WLEN) >> 3] = mm256_bswap_64(_mm256_set1_epi64x(sc->count >> 61)); sc->buf[(SPH_MAXPAD + 3 * SPH_WLEN) >> 3] = mm256_bswap_64(_mm256_set1_epi64x(sc->count << 3)); #endif // PLW #else // LE64 #if defined PLW1 sc->buf[SPH_MAXPAD >> 3] = _mm256_set1_epi64x(sc->count << 3); #elif defined PLW4 sc->buf[SPH_MAXPAD >> 3] = _mm256_set1_epi64x(sc->count << 3); sc->buf[(SPH_MAXPAD + SPH_WLEN) >> 3] = _mm256_set1_epi64x(c->count >> 61); memset_zero_256(sc->buf + ((SPH_MAXPAD + 2 * SPH_WLEN) >> 3), 2 * SPH_WLEN); #else sc->buf[SPH_MAXPAD >> 3] = _mm256_set1_epi64x(sc->count << 3); sc->buf[(SPH_MAXPAD + SPH_WLEN) >> 3] = _mm256_set1_epi64x(sc->count >> 61); #endif // PLW #endif // LE64 // printf("Vptr 3= %u\n", ptr); // printf("VBuf %016llx %016llx %016llx %016llx\n", b[0], b[4], b[8], b[12] // ); printf("VBuf %016llx %016llx %016llx %016llx\n", b[16], b[20], b[24], // b[28] ); RFUN(sc->buf, SPH_VAL); // printf("Vptr after= %u\n", ptr); // printf("VState %016llx %016llx %016llx %016llx\n", s[0], s[4], s[8], s[12] // ); printf("VState %016llx %016llx %016llx %016llx\n", s[16], s[20], s[24], // s[28] ); #ifdef SPH_NO_OUTPUT (void)dst; (void)rnum; (void)u; #else for (u = 0; u < rnum; u++) { #if defined BE64 ((__m256i *)dst)[u] = mm256_bswap_64(sc->val[u]); #else // LE64 ((__m256i *)dst)[u] = sc->val[u]; #endif } #endif } static void SPH_XCAT(HASH, _mdclose)(void *cc, void *dst, unsigned rnum) { SPH_XCAT(HASH, _addbits_and_close)(cc, 0, 0, dst, rnum); }