11cb0ef41Sopenharmony_ci/* 21cb0ef41Sopenharmony_ci * Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved. 31cb0ef41Sopenharmony_ci * 41cb0ef41Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 51cb0ef41Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 61cb0ef41Sopenharmony_ci * in the file LICENSE in the source distribution or at 71cb0ef41Sopenharmony_ci * https://www.openssl.org/source/license.html 81cb0ef41Sopenharmony_ci */ 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ci/** 111cb0ef41Sopenharmony_ci * The Whirlpool hashing function. 121cb0ef41Sopenharmony_ci * 131cb0ef41Sopenharmony_ci * See 141cb0ef41Sopenharmony_ci * P.S.L.M. Barreto, V. Rijmen, 151cb0ef41Sopenharmony_ci * ``The Whirlpool hashing function,'' 161cb0ef41Sopenharmony_ci * NESSIE submission, 2000 (tweaked version, 2001), 171cb0ef41Sopenharmony_ci * <https://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/whirlpool.zip> 181cb0ef41Sopenharmony_ci * 191cb0ef41Sopenharmony_ci * Based on "@version 3.0 (2003.03.12)" by Paulo S.L.M. Barreto and 201cb0ef41Sopenharmony_ci * Vincent Rijmen. Lookup "reference implementations" on 211cb0ef41Sopenharmony_ci * <http://planeta.terra.com.br/informatica/paulobarreto/> 221cb0ef41Sopenharmony_ci * 231cb0ef41Sopenharmony_ci * ============================================================================= 241cb0ef41Sopenharmony_ci * 251cb0ef41Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS 261cb0ef41Sopenharmony_ci * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 271cb0ef41Sopenharmony_ci * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 281cb0ef41Sopenharmony_ci * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE 291cb0ef41Sopenharmony_ci * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 301cb0ef41Sopenharmony_ci * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 311cb0ef41Sopenharmony_ci * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 321cb0ef41Sopenharmony_ci * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 331cb0ef41Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 341cb0ef41Sopenharmony_ci * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 351cb0ef41Sopenharmony_ci * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 361cb0ef41Sopenharmony_ci * 371cb0ef41Sopenharmony_ci */ 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ci/* 401cb0ef41Sopenharmony_ci * OpenSSL-specific implementation notes. 411cb0ef41Sopenharmony_ci * 421cb0ef41Sopenharmony_ci * WHIRLPOOL_Update as well as one-stroke WHIRLPOOL both expect 431cb0ef41Sopenharmony_ci * number of *bytes* as input length argument. Bit-oriented routine 441cb0ef41Sopenharmony_ci * as specified by authors is called WHIRLPOOL_BitUpdate[!] and 451cb0ef41Sopenharmony_ci * does not have one-stroke counterpart. 461cb0ef41Sopenharmony_ci * 471cb0ef41Sopenharmony_ci * WHIRLPOOL_BitUpdate implements byte-oriented loop, essentially 481cb0ef41Sopenharmony_ci * to serve WHIRLPOOL_Update. This is done for performance. 491cb0ef41Sopenharmony_ci * 501cb0ef41Sopenharmony_ci * Unlike authors' reference implementation, block processing 511cb0ef41Sopenharmony_ci * routine whirlpool_block is designed to operate on multi-block 521cb0ef41Sopenharmony_ci * input. This is done for performance. 531cb0ef41Sopenharmony_ci */ 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_ci/* 561cb0ef41Sopenharmony_ci * Whirlpool low level APIs are deprecated for public use, but still ok for 571cb0ef41Sopenharmony_ci * internal use. 581cb0ef41Sopenharmony_ci */ 591cb0ef41Sopenharmony_ci#include "internal/deprecated.h" 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_ci#include <openssl/crypto.h> 621cb0ef41Sopenharmony_ci#include "wp_local.h" 631cb0ef41Sopenharmony_ci#include <string.h> 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_ciint WHIRLPOOL_Init(WHIRLPOOL_CTX *c) 661cb0ef41Sopenharmony_ci{ 671cb0ef41Sopenharmony_ci memset(c, 0, sizeof(*c)); 681cb0ef41Sopenharmony_ci return 1; 691cb0ef41Sopenharmony_ci} 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ciint WHIRLPOOL_Update(WHIRLPOOL_CTX *c, const void *_inp, size_t bytes) 721cb0ef41Sopenharmony_ci{ 731cb0ef41Sopenharmony_ci /* 741cb0ef41Sopenharmony_ci * Well, largest suitable chunk size actually is 751cb0ef41Sopenharmony_ci * (1<<(sizeof(size_t)*8-3))-64, but below number is large enough for not 761cb0ef41Sopenharmony_ci * to care about excessive calls to WHIRLPOOL_BitUpdate... 771cb0ef41Sopenharmony_ci */ 781cb0ef41Sopenharmony_ci size_t chunk = ((size_t)1) << (sizeof(size_t) * 8 - 4); 791cb0ef41Sopenharmony_ci const unsigned char *inp = _inp; 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ci while (bytes >= chunk) { 821cb0ef41Sopenharmony_ci WHIRLPOOL_BitUpdate(c, inp, chunk * 8); 831cb0ef41Sopenharmony_ci bytes -= chunk; 841cb0ef41Sopenharmony_ci inp += chunk; 851cb0ef41Sopenharmony_ci } 861cb0ef41Sopenharmony_ci if (bytes) 871cb0ef41Sopenharmony_ci WHIRLPOOL_BitUpdate(c, inp, bytes * 8); 881cb0ef41Sopenharmony_ci 891cb0ef41Sopenharmony_ci return 1; 901cb0ef41Sopenharmony_ci} 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_civoid WHIRLPOOL_BitUpdate(WHIRLPOOL_CTX *c, const void *_inp, size_t bits) 931cb0ef41Sopenharmony_ci{ 941cb0ef41Sopenharmony_ci size_t n; 951cb0ef41Sopenharmony_ci unsigned int bitoff = c->bitoff, 961cb0ef41Sopenharmony_ci bitrem = bitoff % 8, inpgap = (8 - (unsigned int)bits % 8) & 7; 971cb0ef41Sopenharmony_ci const unsigned char *inp = _inp; 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_ci /* 1001cb0ef41Sopenharmony_ci * This 256-bit increment procedure relies on the size_t being natural 1011cb0ef41Sopenharmony_ci * size of CPU register, so that we don't have to mask the value in order 1021cb0ef41Sopenharmony_ci * to detect overflows. 1031cb0ef41Sopenharmony_ci */ 1041cb0ef41Sopenharmony_ci c->bitlen[0] += bits; 1051cb0ef41Sopenharmony_ci if (c->bitlen[0] < bits) { /* overflow */ 1061cb0ef41Sopenharmony_ci n = 1; 1071cb0ef41Sopenharmony_ci do { 1081cb0ef41Sopenharmony_ci c->bitlen[n]++; 1091cb0ef41Sopenharmony_ci } while (c->bitlen[n] == 0 1101cb0ef41Sopenharmony_ci && ++n < (WHIRLPOOL_COUNTER / sizeof(size_t))); 1111cb0ef41Sopenharmony_ci } 1121cb0ef41Sopenharmony_ci#ifndef OPENSSL_SMALL_FOOTPRINT 1131cb0ef41Sopenharmony_ci reconsider: 1141cb0ef41Sopenharmony_ci if (inpgap == 0 && bitrem == 0) { /* byte-oriented loop */ 1151cb0ef41Sopenharmony_ci while (bits) { 1161cb0ef41Sopenharmony_ci if (bitoff == 0 && (n = bits / WHIRLPOOL_BBLOCK)) { 1171cb0ef41Sopenharmony_ci whirlpool_block(c, inp, n); 1181cb0ef41Sopenharmony_ci inp += n * WHIRLPOOL_BBLOCK / 8; 1191cb0ef41Sopenharmony_ci bits %= WHIRLPOOL_BBLOCK; 1201cb0ef41Sopenharmony_ci } else { 1211cb0ef41Sopenharmony_ci unsigned int byteoff = bitoff / 8; 1221cb0ef41Sopenharmony_ci 1231cb0ef41Sopenharmony_ci bitrem = WHIRLPOOL_BBLOCK - bitoff; /* re-use bitrem */ 1241cb0ef41Sopenharmony_ci if (bits >= bitrem) { 1251cb0ef41Sopenharmony_ci bits -= bitrem; 1261cb0ef41Sopenharmony_ci bitrem /= 8; 1271cb0ef41Sopenharmony_ci memcpy(c->data + byteoff, inp, bitrem); 1281cb0ef41Sopenharmony_ci inp += bitrem; 1291cb0ef41Sopenharmony_ci whirlpool_block(c, c->data, 1); 1301cb0ef41Sopenharmony_ci bitoff = 0; 1311cb0ef41Sopenharmony_ci } else { 1321cb0ef41Sopenharmony_ci memcpy(c->data + byteoff, inp, bits / 8); 1331cb0ef41Sopenharmony_ci bitoff += (unsigned int)bits; 1341cb0ef41Sopenharmony_ci bits = 0; 1351cb0ef41Sopenharmony_ci } 1361cb0ef41Sopenharmony_ci c->bitoff = bitoff; 1371cb0ef41Sopenharmony_ci } 1381cb0ef41Sopenharmony_ci } 1391cb0ef41Sopenharmony_ci } else /* bit-oriented loop */ 1401cb0ef41Sopenharmony_ci#endif 1411cb0ef41Sopenharmony_ci { 1421cb0ef41Sopenharmony_ci /*- 1431cb0ef41Sopenharmony_ci inp 1441cb0ef41Sopenharmony_ci | 1451cb0ef41Sopenharmony_ci +-------+-------+------- 1461cb0ef41Sopenharmony_ci ||||||||||||||||||||| 1471cb0ef41Sopenharmony_ci +-------+-------+------- 1481cb0ef41Sopenharmony_ci +-------+-------+-------+-------+------- 1491cb0ef41Sopenharmony_ci |||||||||||||| c->data 1501cb0ef41Sopenharmony_ci +-------+-------+-------+-------+------- 1511cb0ef41Sopenharmony_ci | 1521cb0ef41Sopenharmony_ci c->bitoff/8 1531cb0ef41Sopenharmony_ci */ 1541cb0ef41Sopenharmony_ci while (bits) { 1551cb0ef41Sopenharmony_ci unsigned int byteoff = bitoff / 8; 1561cb0ef41Sopenharmony_ci unsigned char b; 1571cb0ef41Sopenharmony_ci 1581cb0ef41Sopenharmony_ci#ifndef OPENSSL_SMALL_FOOTPRINT 1591cb0ef41Sopenharmony_ci if (bitrem == inpgap) { 1601cb0ef41Sopenharmony_ci c->data[byteoff++] |= inp[0] & (0xff >> inpgap); 1611cb0ef41Sopenharmony_ci inpgap = 8 - inpgap; 1621cb0ef41Sopenharmony_ci bitoff += inpgap; 1631cb0ef41Sopenharmony_ci bitrem = 0; /* bitoff%8 */ 1641cb0ef41Sopenharmony_ci bits -= inpgap; 1651cb0ef41Sopenharmony_ci inpgap = 0; /* bits%8 */ 1661cb0ef41Sopenharmony_ci inp++; 1671cb0ef41Sopenharmony_ci if (bitoff == WHIRLPOOL_BBLOCK) { 1681cb0ef41Sopenharmony_ci whirlpool_block(c, c->data, 1); 1691cb0ef41Sopenharmony_ci bitoff = 0; 1701cb0ef41Sopenharmony_ci } 1711cb0ef41Sopenharmony_ci c->bitoff = bitoff; 1721cb0ef41Sopenharmony_ci goto reconsider; 1731cb0ef41Sopenharmony_ci } else 1741cb0ef41Sopenharmony_ci#endif 1751cb0ef41Sopenharmony_ci if (bits > 8) { 1761cb0ef41Sopenharmony_ci b = ((inp[0] << inpgap) | (inp[1] >> (8 - inpgap))); 1771cb0ef41Sopenharmony_ci b &= 0xff; 1781cb0ef41Sopenharmony_ci if (bitrem) 1791cb0ef41Sopenharmony_ci c->data[byteoff++] |= b >> bitrem; 1801cb0ef41Sopenharmony_ci else 1811cb0ef41Sopenharmony_ci c->data[byteoff++] = b; 1821cb0ef41Sopenharmony_ci bitoff += 8; 1831cb0ef41Sopenharmony_ci bits -= 8; 1841cb0ef41Sopenharmony_ci inp++; 1851cb0ef41Sopenharmony_ci if (bitoff >= WHIRLPOOL_BBLOCK) { 1861cb0ef41Sopenharmony_ci whirlpool_block(c, c->data, 1); 1871cb0ef41Sopenharmony_ci byteoff = 0; 1881cb0ef41Sopenharmony_ci bitoff %= WHIRLPOOL_BBLOCK; 1891cb0ef41Sopenharmony_ci } 1901cb0ef41Sopenharmony_ci if (bitrem) 1911cb0ef41Sopenharmony_ci c->data[byteoff] = b << (8 - bitrem); 1921cb0ef41Sopenharmony_ci } else { /* remaining less than or equal to 8 bits */ 1931cb0ef41Sopenharmony_ci 1941cb0ef41Sopenharmony_ci b = (inp[0] << inpgap) & 0xff; 1951cb0ef41Sopenharmony_ci if (bitrem) 1961cb0ef41Sopenharmony_ci c->data[byteoff++] |= b >> bitrem; 1971cb0ef41Sopenharmony_ci else 1981cb0ef41Sopenharmony_ci c->data[byteoff++] = b; 1991cb0ef41Sopenharmony_ci bitoff += (unsigned int)bits; 2001cb0ef41Sopenharmony_ci if (bitoff == WHIRLPOOL_BBLOCK) { 2011cb0ef41Sopenharmony_ci whirlpool_block(c, c->data, 1); 2021cb0ef41Sopenharmony_ci byteoff = 0; 2031cb0ef41Sopenharmony_ci bitoff %= WHIRLPOOL_BBLOCK; 2041cb0ef41Sopenharmony_ci } 2051cb0ef41Sopenharmony_ci if (bitrem) 2061cb0ef41Sopenharmony_ci c->data[byteoff] = b << (8 - bitrem); 2071cb0ef41Sopenharmony_ci bits = 0; 2081cb0ef41Sopenharmony_ci } 2091cb0ef41Sopenharmony_ci c->bitoff = bitoff; 2101cb0ef41Sopenharmony_ci } 2111cb0ef41Sopenharmony_ci } 2121cb0ef41Sopenharmony_ci} 2131cb0ef41Sopenharmony_ci 2141cb0ef41Sopenharmony_ciint WHIRLPOOL_Final(unsigned char *md, WHIRLPOOL_CTX *c) 2151cb0ef41Sopenharmony_ci{ 2161cb0ef41Sopenharmony_ci unsigned int bitoff = c->bitoff, byteoff = bitoff / 8; 2171cb0ef41Sopenharmony_ci size_t i, j, v; 2181cb0ef41Sopenharmony_ci unsigned char *p; 2191cb0ef41Sopenharmony_ci 2201cb0ef41Sopenharmony_ci bitoff %= 8; 2211cb0ef41Sopenharmony_ci if (bitoff) 2221cb0ef41Sopenharmony_ci c->data[byteoff] |= 0x80 >> bitoff; 2231cb0ef41Sopenharmony_ci else 2241cb0ef41Sopenharmony_ci c->data[byteoff] = 0x80; 2251cb0ef41Sopenharmony_ci byteoff++; 2261cb0ef41Sopenharmony_ci 2271cb0ef41Sopenharmony_ci /* pad with zeros */ 2281cb0ef41Sopenharmony_ci if (byteoff > (WHIRLPOOL_BBLOCK / 8 - WHIRLPOOL_COUNTER)) { 2291cb0ef41Sopenharmony_ci if (byteoff < WHIRLPOOL_BBLOCK / 8) 2301cb0ef41Sopenharmony_ci memset(&c->data[byteoff], 0, WHIRLPOOL_BBLOCK / 8 - byteoff); 2311cb0ef41Sopenharmony_ci whirlpool_block(c, c->data, 1); 2321cb0ef41Sopenharmony_ci byteoff = 0; 2331cb0ef41Sopenharmony_ci } 2341cb0ef41Sopenharmony_ci if (byteoff < (WHIRLPOOL_BBLOCK / 8 - WHIRLPOOL_COUNTER)) 2351cb0ef41Sopenharmony_ci memset(&c->data[byteoff], 0, 2361cb0ef41Sopenharmony_ci (WHIRLPOOL_BBLOCK / 8 - WHIRLPOOL_COUNTER) - byteoff); 2371cb0ef41Sopenharmony_ci /* smash 256-bit c->bitlen in big-endian order */ 2381cb0ef41Sopenharmony_ci p = &c->data[WHIRLPOOL_BBLOCK / 8 - 1]; /* last byte in c->data */ 2391cb0ef41Sopenharmony_ci for (i = 0; i < WHIRLPOOL_COUNTER / sizeof(size_t); i++) 2401cb0ef41Sopenharmony_ci for (v = c->bitlen[i], j = 0; j < sizeof(size_t); j++, v >>= 8) 2411cb0ef41Sopenharmony_ci *p-- = (unsigned char)(v & 0xff); 2421cb0ef41Sopenharmony_ci 2431cb0ef41Sopenharmony_ci whirlpool_block(c, c->data, 1); 2441cb0ef41Sopenharmony_ci 2451cb0ef41Sopenharmony_ci if (md) { 2461cb0ef41Sopenharmony_ci memcpy(md, c->H.c, WHIRLPOOL_DIGEST_LENGTH); 2471cb0ef41Sopenharmony_ci OPENSSL_cleanse(c, sizeof(*c)); 2481cb0ef41Sopenharmony_ci return 1; 2491cb0ef41Sopenharmony_ci } 2501cb0ef41Sopenharmony_ci return 0; 2511cb0ef41Sopenharmony_ci} 2521cb0ef41Sopenharmony_ci 2531cb0ef41Sopenharmony_ciunsigned char *WHIRLPOOL(const void *inp, size_t bytes, unsigned char *md) 2541cb0ef41Sopenharmony_ci{ 2551cb0ef41Sopenharmony_ci WHIRLPOOL_CTX ctx; 2561cb0ef41Sopenharmony_ci static unsigned char m[WHIRLPOOL_DIGEST_LENGTH]; 2571cb0ef41Sopenharmony_ci 2581cb0ef41Sopenharmony_ci if (md == NULL) 2591cb0ef41Sopenharmony_ci md = m; 2601cb0ef41Sopenharmony_ci WHIRLPOOL_Init(&ctx); 2611cb0ef41Sopenharmony_ci WHIRLPOOL_Update(&ctx, inp, bytes); 2621cb0ef41Sopenharmony_ci WHIRLPOOL_Final(md, &ctx); 2631cb0ef41Sopenharmony_ci return md; 2641cb0ef41Sopenharmony_ci} 265