diff options
Diffstat (limited to 'thirdparty/openssl/crypto/whrlpool/wp_dgst.c')
-rw-r--r-- | thirdparty/openssl/crypto/whrlpool/wp_dgst.c | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/thirdparty/openssl/crypto/whrlpool/wp_dgst.c b/thirdparty/openssl/crypto/whrlpool/wp_dgst.c new file mode 100644 index 0000000000..e33bb4f833 --- /dev/null +++ b/thirdparty/openssl/crypto/whrlpool/wp_dgst.c @@ -0,0 +1,257 @@ +/** + * The Whirlpool hashing function. + * + * <P> + * <b>References</b> + * + * <P> + * The Whirlpool algorithm was developed by + * <a href="mailto:pbarreto@scopus.com.br">Paulo S. L. M. Barreto</a> and + * <a href="mailto:vincent.rijmen@cryptomathic.com">Vincent Rijmen</a>. + * + * See + * P.S.L.M. Barreto, V. Rijmen, + * ``The Whirlpool hashing function,'' + * NESSIE submission, 2000 (tweaked version, 2001), + * <https://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/whirlpool.zip> + * + * Based on "@version 3.0 (2003.03.12)" by Paulo S.L.M. Barreto and + * Vincent Rijmen. Lookup "reference implementations" on + * <http://planeta.terra.com.br/informatica/paulobarreto/> + * + * ============================================================================= + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* + * OpenSSL-specific implementation notes. + * + * WHIRLPOOL_Update as well as one-stroke WHIRLPOOL both expect + * number of *bytes* as input length argument. Bit-oriented routine + * as specified by authors is called WHIRLPOOL_BitUpdate[!] and + * does not have one-stroke counterpart. + * + * WHIRLPOOL_BitUpdate implements byte-oriented loop, essentially + * to serve WHIRLPOOL_Update. This is done for performance. + * + * Unlike authors' reference implementation, block processing + * routine whirlpool_block is designed to operate on multi-block + * input. This is done for perfomance. + */ + +#include "wp_locl.h" +#include <openssl/crypto.h> +#include <string.h> + +fips_md_init(WHIRLPOOL) +{ + memset(c, 0, sizeof(*c)); + return (1); +} + +int WHIRLPOOL_Update(WHIRLPOOL_CTX *c, const void *_inp, size_t bytes) +{ + /* + * Well, largest suitable chunk size actually is + * (1<<(sizeof(size_t)*8-3))-64, but below number is large enough for not + * to care about excessive calls to WHIRLPOOL_BitUpdate... + */ + size_t chunk = ((size_t)1) << (sizeof(size_t) * 8 - 4); + const unsigned char *inp = _inp; + + while (bytes >= chunk) { + WHIRLPOOL_BitUpdate(c, inp, chunk * 8); + bytes -= chunk; + inp += chunk; + } + if (bytes) + WHIRLPOOL_BitUpdate(c, inp, bytes * 8); + + return (1); +} + +void WHIRLPOOL_BitUpdate(WHIRLPOOL_CTX *c, const void *_inp, size_t bits) +{ + size_t n; + unsigned int bitoff = c->bitoff, + bitrem = bitoff % 8, inpgap = (8 - (unsigned int)bits % 8) & 7; + const unsigned char *inp = _inp; + + /* + * This 256-bit increment procedure relies on the size_t being natural + * size of CPU register, so that we don't have to mask the value in order + * to detect overflows. + */ + c->bitlen[0] += bits; + if (c->bitlen[0] < bits) { /* overflow */ + n = 1; + do { + c->bitlen[n]++; + } while (c->bitlen[n] == 0 + && ++n < (WHIRLPOOL_COUNTER / sizeof(size_t))); + } +#ifndef OPENSSL_SMALL_FOOTPRINT + reconsider: + if (inpgap == 0 && bitrem == 0) { /* byte-oriented loop */ + while (bits) { + if (bitoff == 0 && (n = bits / WHIRLPOOL_BBLOCK)) { + whirlpool_block(c, inp, n); + inp += n * WHIRLPOOL_BBLOCK / 8; + bits %= WHIRLPOOL_BBLOCK; + } else { + unsigned int byteoff = bitoff / 8; + + bitrem = WHIRLPOOL_BBLOCK - bitoff; /* re-use bitrem */ + if (bits >= bitrem) { + bits -= bitrem; + bitrem /= 8; + memcpy(c->data + byteoff, inp, bitrem); + inp += bitrem; + whirlpool_block(c, c->data, 1); + bitoff = 0; + } else { + memcpy(c->data + byteoff, inp, bits / 8); + bitoff += (unsigned int)bits; + bits = 0; + } + c->bitoff = bitoff; + } + } + } else /* bit-oriented loop */ +#endif + { + /*- + inp + | + +-------+-------+------- + ||||||||||||||||||||| + +-------+-------+------- + +-------+-------+-------+-------+------- + |||||||||||||| c->data + +-------+-------+-------+-------+------- + | + c->bitoff/8 + */ + while (bits) { + unsigned int byteoff = bitoff / 8; + unsigned char b; + +#ifndef OPENSSL_SMALL_FOOTPRINT + if (bitrem == inpgap) { + c->data[byteoff++] |= inp[0] & (0xff >> inpgap); + inpgap = 8 - inpgap; + bitoff += inpgap; + bitrem = 0; /* bitoff%8 */ + bits -= inpgap; + inpgap = 0; /* bits%8 */ + inp++; + if (bitoff == WHIRLPOOL_BBLOCK) { + whirlpool_block(c, c->data, 1); + bitoff = 0; + } + c->bitoff = bitoff; + goto reconsider; + } else +#endif + if (bits >= 8) { + b = ((inp[0] << inpgap) | (inp[1] >> (8 - inpgap))); + b &= 0xff; + if (bitrem) + c->data[byteoff++] |= b >> bitrem; + else + c->data[byteoff++] = b; + bitoff += 8; + bits -= 8; + inp++; + if (bitoff >= WHIRLPOOL_BBLOCK) { + whirlpool_block(c, c->data, 1); + byteoff = 0; + bitoff %= WHIRLPOOL_BBLOCK; + } + if (bitrem) + c->data[byteoff] = b << (8 - bitrem); + } else { /* remaining less than 8 bits */ + + b = (inp[0] << inpgap) & 0xff; + if (bitrem) + c->data[byteoff++] |= b >> bitrem; + else + c->data[byteoff++] = b; + bitoff += (unsigned int)bits; + if (bitoff == WHIRLPOOL_BBLOCK) { + whirlpool_block(c, c->data, 1); + byteoff = 0; + bitoff %= WHIRLPOOL_BBLOCK; + } + if (bitrem) + c->data[byteoff] = b << (8 - bitrem); + bits = 0; + } + c->bitoff = bitoff; + } + } +} + +int WHIRLPOOL_Final(unsigned char *md, WHIRLPOOL_CTX *c) +{ + unsigned int bitoff = c->bitoff, byteoff = bitoff / 8; + size_t i, j, v; + unsigned char *p; + + bitoff %= 8; + if (bitoff) + c->data[byteoff] |= 0x80 >> bitoff; + else + c->data[byteoff] = 0x80; + byteoff++; + + /* pad with zeros */ + if (byteoff > (WHIRLPOOL_BBLOCK / 8 - WHIRLPOOL_COUNTER)) { + if (byteoff < WHIRLPOOL_BBLOCK / 8) + memset(&c->data[byteoff], 0, WHIRLPOOL_BBLOCK / 8 - byteoff); + whirlpool_block(c, c->data, 1); + byteoff = 0; + } + if (byteoff < (WHIRLPOOL_BBLOCK / 8 - WHIRLPOOL_COUNTER)) + memset(&c->data[byteoff], 0, + (WHIRLPOOL_BBLOCK / 8 - WHIRLPOOL_COUNTER) - byteoff); + /* smash 256-bit c->bitlen in big-endian order */ + p = &c->data[WHIRLPOOL_BBLOCK / 8 - 1]; /* last byte in c->data */ + for (i = 0; i < WHIRLPOOL_COUNTER / sizeof(size_t); i++) + for (v = c->bitlen[i], j = 0; j < sizeof(size_t); j++, v >>= 8) + *p-- = (unsigned char)(v & 0xff); + + whirlpool_block(c, c->data, 1); + + if (md) { + memcpy(md, c->H.c, WHIRLPOOL_DIGEST_LENGTH); + memset(c, 0, sizeof(*c)); + return (1); + } + return (0); +} + +unsigned char *WHIRLPOOL(const void *inp, size_t bytes, unsigned char *md) +{ + WHIRLPOOL_CTX ctx; + static unsigned char m[WHIRLPOOL_DIGEST_LENGTH]; + + if (md == NULL) + md = m; + WHIRLPOOL_Init(&ctx); + WHIRLPOOL_Update(&ctx, inp, bytes); + WHIRLPOOL_Final(md, &ctx); + return (md); +} |