/* $Id: md_helper.c 216 2010-06-08 09:46:57Z tp $ */1/*2* This file contains some functions which implement the external data3* handling and padding for Merkle-Damgard hash functions which follow4* the conventions set out by MD4 (little-endian) or SHA-1 (big-endian).5*6* API: this file is meant to be included, not compiled as a stand-alone7* file. Some macros must be defined:8* RFUN name for the round function9* HASH "short name" for the hash function10* BE32 defined for big-endian, 32-bit based (e.g. SHA-1)11* LE32 defined for little-endian, 32-bit based (e.g. MD5)12* BE64 defined for big-endian, 64-bit based (e.g. SHA-512)13* LE64 defined for little-endian, 64-bit based (no example yet)14* PW01 if defined, append 0x01 instead of 0x80 (for Tiger)15* BLEN if defined, length of a message block (in bytes)16* PLW1 if defined, length is defined on one 64-bit word only (for Tiger)17* PLW4 if defined, length is defined on four 64-bit words (for WHIRLPOOL)18* SVAL if defined, reference to the context state information19*20* BLEN is used when a message block is not 16 (32-bit or 64-bit) words:21* this is used for instance for Tiger, which works on 64-bit words but22* uses 512-bit message blocks (eight 64-bit words). PLW1 and PLW4 are23* ignored if 32-bit words are used; if 64-bit words are used and PLW1 is24* set, then only one word (64 bits) will be used to encode the input25* message length (in bits), otherwise two words will be used (as in26* SHA-384 and SHA-512). If 64-bit words are used and PLW4 is defined (but27* not PLW1), four 64-bit words will be used to encode the message length28* (in bits). Note that regardless of those settings, only 64-bit message29* lengths are supported (in bits): messages longer than 2 Exabytes will be30* improperly hashed (this is unlikely to happen soon: 2 Exabytes is about31* 2 millions Terabytes, which is huge).32*33* If CLOSE_ONLY is defined, then this file defines only the sph_XXX_close()34* function. This is used for Tiger2, which is identical to Tiger except35* when it comes to the padding (Tiger2 uses the standard 0x80 byte instead36* of the 0x01 from original Tiger).37*38* The RFUN function is invoked with two arguments, the first pointing to39* aligned data (as a "const void *"), the second being state information40* from the context structure. By default, this state information is the41* "val" field from the context, and this field is assumed to be an array42* of words ("sph_u32" or "sph_u64", depending on BE32/LE32/BE64/LE64).43* from the context structure. The "val" field can have any type, except44* for the output encoding which assumes that it is an array of "sph_u32"45* values. By defining NO_OUTPUT, this last step is deactivated; the46* includer code is then responsible for writing out the hash result. When47* NO_OUTPUT is defined, the third parameter to the "close()" function is48* ignored.49*50* ==========================(LICENSE BEGIN)============================51*52* Copyright (c) 2007-2010 Projet RNRT SAPHIR53*54* Permission is hereby granted, free of charge, to any person obtaining55* a copy of this software and associated documentation files (the56* "Software"), to deal in the Software without restriction, including57* without limitation the rights to use, copy, modify, merge, publish,58* distribute, sublicense, and/or sell copies of the Software, and to59* permit persons to whom the Software is furnished to do so, subject to60* the following conditions:61*62* The above copyright notice and this permission notice shall be63* included in all copies or substantial portions of the Software.64*65* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,66* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF67* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.68* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY69* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,70* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE71* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.72*73* ===========================(LICENSE END)=============================74*75* @author Thomas Pornin <[email protected]>76*/7778#ifdef _MSC_VER79#pragma warning (disable: 4146)80#endif8182#undef SPH_XCAT83#define SPH_XCAT(a, b) SPH_XCAT_(a, b)84#undef SPH_XCAT_85#define SPH_XCAT_(a, b) a ## b8687#undef SPH_BLEN88#undef SPH_WLEN89#if defined BE64 || defined LE6490#define SPH_BLEN 128U91#define SPH_WLEN 8U92#else93#define SPH_BLEN 64U94#define SPH_WLEN 4U95#endif9697#ifdef BLEN98#undef SPH_BLEN99#define SPH_BLEN BLEN100#endif101102#undef SPH_MAXPAD103#if defined PLW1104#define SPH_MAXPAD (SPH_BLEN - SPH_WLEN)105#elif defined PLW4106#define SPH_MAXPAD (SPH_BLEN - (SPH_WLEN << 2))107#else108#define SPH_MAXPAD (SPH_BLEN - (SPH_WLEN << 1))109#endif110111#undef SPH_VAL112#undef SPH_NO_OUTPUT113#ifdef SVAL114#define SPH_VAL SVAL115#define SPH_NO_OUTPUT 1116#else117#define SPH_VAL sc->val118#endif119120#ifndef CLOSE_ONLY121122#ifdef SPH_UPTR123static void124SPH_XCAT(HASH, _short)(void *cc, const void *data, size_t len)125#else126void127SPH_XCAT(sph_, HASH)(void *cc, const void *data, size_t len)128#endif129{130SPH_XCAT(sph_, SPH_XCAT(HASH, _context)) *sc;131size_t current;132133sc = cc;134#if SPH_64135current = (unsigned)sc->count & (SPH_BLEN - 1U);136#else137current = (unsigned)sc->count_low & (SPH_BLEN - 1U);138#endif139while (len > 0) {140size_t clen;141#if !SPH_64142sph_u32 clow, clow2;143#endif144145clen = SPH_BLEN - current;146if (clen > len)147clen = len;148memcpy(sc->buf + current, data, clen);149data = (const unsigned char *)data + clen;150current += clen;151len -= clen;152if (current == SPH_BLEN) {153RFUN(sc->buf, SPH_VAL);154current = 0;155}156#if SPH_64157sc->count += clen;158#else159clow = sc->count_low;160clow2 = SPH_T32(clow + clen);161sc->count_low = clow2;162if (clow2 < clow)163sc->count_high ++;164#endif165}166}167168#ifdef SPH_UPTR169void170SPH_XCAT(sph_, HASH)(void *cc, const void *data, size_t len)171{172SPH_XCAT(sph_, SPH_XCAT(HASH, _context)) *sc;173unsigned current;174size_t orig_len;175#if !SPH_64176sph_u32 clow, clow2;177#endif178179if (len < (2 * SPH_BLEN)) {180SPH_XCAT(HASH, _short)(cc, data, len);181return;182}183sc = cc;184#if SPH_64185current = (unsigned)sc->count & (SPH_BLEN - 1U);186#else187current = (unsigned)sc->count_low & (SPH_BLEN - 1U);188#endif189if (current > 0) {190unsigned t;191192t = SPH_BLEN - current;193SPH_XCAT(HASH, _short)(cc, data, t);194data = (const unsigned char *)data + t;195len -= t;196}197#if !SPH_UNALIGNED198if (((SPH_UPTR)data & (SPH_WLEN - 1U)) != 0) {199SPH_XCAT(HASH, _short)(cc, data, len);200return;201}202#endif203orig_len = len;204while (len >= SPH_BLEN) {205RFUN(data, SPH_VAL);206len -= SPH_BLEN;207data = (const unsigned char *)data + SPH_BLEN;208}209if (len > 0)210memcpy(sc->buf, data, len);211#if SPH_64212sc->count += (sph_u64)orig_len;213#else214clow = sc->count_low;215clow2 = SPH_T32(clow + orig_len);216sc->count_low = clow2;217if (clow2 < clow)218sc->count_high ++;219/*220* This code handles the improbable situation where "size_t" is221* greater than 32 bits, and yet we do not have a 64-bit type.222*/223orig_len >>= 12;224orig_len >>= 10;225orig_len >>= 10;226sc->count_high += orig_len;227#endif228}229#endif230231#endif232233/*234* Perform padding and produce result. The context is NOT reinitialized235* by this function.236*/237static void238SPH_XCAT(HASH, _addbits_and_close)(void *cc,239unsigned ub, unsigned n, void *dst, unsigned rnum)240{241SPH_XCAT(sph_, SPH_XCAT(HASH, _context)) *sc;242unsigned current, u;243#if !SPH_64244sph_u32 low, high;245#endif246247sc = cc;248#if SPH_64249current = (unsigned)sc->count & (SPH_BLEN - 1U);250#else251current = (unsigned)sc->count_low & (SPH_BLEN - 1U);252#endif253#ifdef PW01254sc->buf[current ++] = (0x100 | (ub & 0xFF)) >> (8 - n);255#else256{257unsigned z;258259z = 0x80 >> n;260sc->buf[current ++] = ((ub & -z) | z) & 0xFF;261}262#endif263if (current > SPH_MAXPAD) {264memset(sc->buf + current, 0, SPH_BLEN - current);265RFUN(sc->buf, SPH_VAL);266memset(sc->buf, 0, SPH_MAXPAD);267} else {268memset(sc->buf + current, 0, SPH_MAXPAD - current);269}270#if defined BE64271#if defined PLW1272sph_enc64be_aligned(sc->buf + SPH_MAXPAD,273SPH_T64(sc->count << 3) + (sph_u64)n);274#elif defined PLW4275memset(sc->buf + SPH_MAXPAD, 0, 2 * SPH_WLEN);276sph_enc64be_aligned(sc->buf + SPH_MAXPAD + 2 * SPH_WLEN,277sc->count >> 61);278sph_enc64be_aligned(sc->buf + SPH_MAXPAD + 3 * SPH_WLEN,279SPH_T64(sc->count << 3) + (sph_u64)n);280#else281sph_enc64be_aligned(sc->buf + SPH_MAXPAD, sc->count >> 61);282sph_enc64be_aligned(sc->buf + SPH_MAXPAD + SPH_WLEN,283SPH_T64(sc->count << 3) + (sph_u64)n);284#endif285#elif defined LE64286#if defined PLW1287sph_enc64le_aligned(sc->buf + SPH_MAXPAD,288SPH_T64(sc->count << 3) + (sph_u64)n);289#elif defined PLW1290sph_enc64le_aligned(sc->buf + SPH_MAXPAD,291SPH_T64(sc->count << 3) + (sph_u64)n);292sph_enc64le_aligned(sc->buf + SPH_MAXPAD + SPH_WLEN, sc->count >> 61);293memset(sc->buf + SPH_MAXPAD + 2 * SPH_WLEN, 0, 2 * SPH_WLEN);294#else295sph_enc64le_aligned(sc->buf + SPH_MAXPAD,296SPH_T64(sc->count << 3) + (sph_u64)n);297sph_enc64le_aligned(sc->buf + SPH_MAXPAD + SPH_WLEN, sc->count >> 61);298#endif299#else300#if SPH_64301#ifdef BE32302sph_enc64be_aligned(sc->buf + SPH_MAXPAD,303SPH_T64(sc->count << 3) + (sph_u64)n);304#else305sph_enc64le_aligned(sc->buf + SPH_MAXPAD,306SPH_T64(sc->count << 3) + (sph_u64)n);307#endif308#else309low = sc->count_low;310high = SPH_T32((sc->count_high << 3) | (low >> 29));311low = SPH_T32(low << 3) + (sph_u32)n;312#ifdef BE32313sph_enc32be(sc->buf + SPH_MAXPAD, high);314sph_enc32be(sc->buf + SPH_MAXPAD + SPH_WLEN, low);315#else316sph_enc32le(sc->buf + SPH_MAXPAD, low);317sph_enc32le(sc->buf + SPH_MAXPAD + SPH_WLEN, high);318#endif319#endif320#endif321RFUN(sc->buf, SPH_VAL);322#ifdef SPH_NO_OUTPUT323(void)dst;324(void)rnum;325(void)u;326#else327for (u = 0; u < rnum; u ++) {328#if defined BE64329sph_enc64be((unsigned char *)dst + 8 * u, sc->val[u]);330#elif defined LE64331sph_enc64le((unsigned char *)dst + 8 * u, sc->val[u]);332#elif defined BE32333sph_enc32be((unsigned char *)dst + 4 * u, sc->val[u]);334#else335sph_enc32le((unsigned char *)dst + 4 * u, sc->val[u]);336#endif337}338#endif339}340341static void342SPH_XCAT(HASH, _close)(void *cc, void *dst, unsigned rnum)343{344SPH_XCAT(HASH, _addbits_and_close)(cc, 0, 0, dst, rnum);345}346347348