1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci/** 11e1051a39Sopenharmony_ci * The Whirlpool hashing function. 12e1051a39Sopenharmony_ci * 13e1051a39Sopenharmony_ci * See 14e1051a39Sopenharmony_ci * P.S.L.M. Barreto, V. Rijmen, 15e1051a39Sopenharmony_ci * ``The Whirlpool hashing function,'' 16e1051a39Sopenharmony_ci * NESSIE submission, 2000 (tweaked version, 2001), 17e1051a39Sopenharmony_ci * <https://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/whirlpool.zip> 18e1051a39Sopenharmony_ci * 19e1051a39Sopenharmony_ci * Based on "@version 3.0 (2003.03.12)" by Paulo S.L.M. Barreto and 20e1051a39Sopenharmony_ci * Vincent Rijmen. Lookup "reference implementations" on 21e1051a39Sopenharmony_ci * <http://planeta.terra.com.br/informatica/paulobarreto/> 22e1051a39Sopenharmony_ci * 23e1051a39Sopenharmony_ci * ============================================================================= 24e1051a39Sopenharmony_ci * 25e1051a39Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS 26e1051a39Sopenharmony_ci * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 27e1051a39Sopenharmony_ci * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28e1051a39Sopenharmony_ci * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE 29e1051a39Sopenharmony_ci * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30e1051a39Sopenharmony_ci * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31e1051a39Sopenharmony_ci * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 32e1051a39Sopenharmony_ci * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 33e1051a39Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 34e1051a39Sopenharmony_ci * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 35e1051a39Sopenharmony_ci * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36e1051a39Sopenharmony_ci * 37e1051a39Sopenharmony_ci */ 38e1051a39Sopenharmony_ci 39e1051a39Sopenharmony_ci/* 40e1051a39Sopenharmony_ci * OpenSSL-specific implementation notes. 41e1051a39Sopenharmony_ci * 42e1051a39Sopenharmony_ci * WHIRLPOOL_Update as well as one-stroke WHIRLPOOL both expect 43e1051a39Sopenharmony_ci * number of *bytes* as input length argument. Bit-oriented routine 44e1051a39Sopenharmony_ci * as specified by authors is called WHIRLPOOL_BitUpdate[!] and 45e1051a39Sopenharmony_ci * does not have one-stroke counterpart. 46e1051a39Sopenharmony_ci * 47e1051a39Sopenharmony_ci * WHIRLPOOL_BitUpdate implements byte-oriented loop, essentially 48e1051a39Sopenharmony_ci * to serve WHIRLPOOL_Update. This is done for performance. 49e1051a39Sopenharmony_ci * 50e1051a39Sopenharmony_ci * Unlike authors' reference implementation, block processing 51e1051a39Sopenharmony_ci * routine whirlpool_block is designed to operate on multi-block 52e1051a39Sopenharmony_ci * input. This is done for performance. 53e1051a39Sopenharmony_ci */ 54e1051a39Sopenharmony_ci 55e1051a39Sopenharmony_ci/* 56e1051a39Sopenharmony_ci * Whirlpool low level APIs are deprecated for public use, but still ok for 57e1051a39Sopenharmony_ci * internal use. 58e1051a39Sopenharmony_ci */ 59e1051a39Sopenharmony_ci#include "internal/deprecated.h" 60e1051a39Sopenharmony_ci 61e1051a39Sopenharmony_ci#include <openssl/crypto.h> 62e1051a39Sopenharmony_ci#include "wp_local.h" 63e1051a39Sopenharmony_ci#include <string.h> 64e1051a39Sopenharmony_ci 65e1051a39Sopenharmony_ciint WHIRLPOOL_Init(WHIRLPOOL_CTX *c) 66e1051a39Sopenharmony_ci{ 67e1051a39Sopenharmony_ci memset(c, 0, sizeof(*c)); 68e1051a39Sopenharmony_ci return 1; 69e1051a39Sopenharmony_ci} 70e1051a39Sopenharmony_ci 71e1051a39Sopenharmony_ciint WHIRLPOOL_Update(WHIRLPOOL_CTX *c, const void *_inp, size_t bytes) 72e1051a39Sopenharmony_ci{ 73e1051a39Sopenharmony_ci /* 74e1051a39Sopenharmony_ci * Well, largest suitable chunk size actually is 75e1051a39Sopenharmony_ci * (1<<(sizeof(size_t)*8-3))-64, but below number is large enough for not 76e1051a39Sopenharmony_ci * to care about excessive calls to WHIRLPOOL_BitUpdate... 77e1051a39Sopenharmony_ci */ 78e1051a39Sopenharmony_ci size_t chunk = ((size_t)1) << (sizeof(size_t) * 8 - 4); 79e1051a39Sopenharmony_ci const unsigned char *inp = _inp; 80e1051a39Sopenharmony_ci 81e1051a39Sopenharmony_ci while (bytes >= chunk) { 82e1051a39Sopenharmony_ci WHIRLPOOL_BitUpdate(c, inp, chunk * 8); 83e1051a39Sopenharmony_ci bytes -= chunk; 84e1051a39Sopenharmony_ci inp += chunk; 85e1051a39Sopenharmony_ci } 86e1051a39Sopenharmony_ci if (bytes) 87e1051a39Sopenharmony_ci WHIRLPOOL_BitUpdate(c, inp, bytes * 8); 88e1051a39Sopenharmony_ci 89e1051a39Sopenharmony_ci return 1; 90e1051a39Sopenharmony_ci} 91e1051a39Sopenharmony_ci 92e1051a39Sopenharmony_civoid WHIRLPOOL_BitUpdate(WHIRLPOOL_CTX *c, const void *_inp, size_t bits) 93e1051a39Sopenharmony_ci{ 94e1051a39Sopenharmony_ci size_t n; 95e1051a39Sopenharmony_ci unsigned int bitoff = c->bitoff, 96e1051a39Sopenharmony_ci bitrem = bitoff % 8, inpgap = (8 - (unsigned int)bits % 8) & 7; 97e1051a39Sopenharmony_ci const unsigned char *inp = _inp; 98e1051a39Sopenharmony_ci 99e1051a39Sopenharmony_ci /* 100e1051a39Sopenharmony_ci * This 256-bit increment procedure relies on the size_t being natural 101e1051a39Sopenharmony_ci * size of CPU register, so that we don't have to mask the value in order 102e1051a39Sopenharmony_ci * to detect overflows. 103e1051a39Sopenharmony_ci */ 104e1051a39Sopenharmony_ci c->bitlen[0] += bits; 105e1051a39Sopenharmony_ci if (c->bitlen[0] < bits) { /* overflow */ 106e1051a39Sopenharmony_ci n = 1; 107e1051a39Sopenharmony_ci do { 108e1051a39Sopenharmony_ci c->bitlen[n]++; 109e1051a39Sopenharmony_ci } while (c->bitlen[n] == 0 110e1051a39Sopenharmony_ci && ++n < (WHIRLPOOL_COUNTER / sizeof(size_t))); 111e1051a39Sopenharmony_ci } 112e1051a39Sopenharmony_ci#ifndef OPENSSL_SMALL_FOOTPRINT 113e1051a39Sopenharmony_ci reconsider: 114e1051a39Sopenharmony_ci if (inpgap == 0 && bitrem == 0) { /* byte-oriented loop */ 115e1051a39Sopenharmony_ci while (bits) { 116e1051a39Sopenharmony_ci if (bitoff == 0 && (n = bits / WHIRLPOOL_BBLOCK)) { 117e1051a39Sopenharmony_ci whirlpool_block(c, inp, n); 118e1051a39Sopenharmony_ci inp += n * WHIRLPOOL_BBLOCK / 8; 119e1051a39Sopenharmony_ci bits %= WHIRLPOOL_BBLOCK; 120e1051a39Sopenharmony_ci } else { 121e1051a39Sopenharmony_ci unsigned int byteoff = bitoff / 8; 122e1051a39Sopenharmony_ci 123e1051a39Sopenharmony_ci bitrem = WHIRLPOOL_BBLOCK - bitoff; /* re-use bitrem */ 124e1051a39Sopenharmony_ci if (bits >= bitrem) { 125e1051a39Sopenharmony_ci bits -= bitrem; 126e1051a39Sopenharmony_ci bitrem /= 8; 127e1051a39Sopenharmony_ci memcpy(c->data + byteoff, inp, bitrem); 128e1051a39Sopenharmony_ci inp += bitrem; 129e1051a39Sopenharmony_ci whirlpool_block(c, c->data, 1); 130e1051a39Sopenharmony_ci bitoff = 0; 131e1051a39Sopenharmony_ci } else { 132e1051a39Sopenharmony_ci memcpy(c->data + byteoff, inp, bits / 8); 133e1051a39Sopenharmony_ci bitoff += (unsigned int)bits; 134e1051a39Sopenharmony_ci bits = 0; 135e1051a39Sopenharmony_ci } 136e1051a39Sopenharmony_ci c->bitoff = bitoff; 137e1051a39Sopenharmony_ci } 138e1051a39Sopenharmony_ci } 139e1051a39Sopenharmony_ci } else /* bit-oriented loop */ 140e1051a39Sopenharmony_ci#endif 141e1051a39Sopenharmony_ci { 142e1051a39Sopenharmony_ci /*- 143e1051a39Sopenharmony_ci inp 144e1051a39Sopenharmony_ci | 145e1051a39Sopenharmony_ci +-------+-------+------- 146e1051a39Sopenharmony_ci ||||||||||||||||||||| 147e1051a39Sopenharmony_ci +-------+-------+------- 148e1051a39Sopenharmony_ci +-------+-------+-------+-------+------- 149e1051a39Sopenharmony_ci |||||||||||||| c->data 150e1051a39Sopenharmony_ci +-------+-------+-------+-------+------- 151e1051a39Sopenharmony_ci | 152e1051a39Sopenharmony_ci c->bitoff/8 153e1051a39Sopenharmony_ci */ 154e1051a39Sopenharmony_ci while (bits) { 155e1051a39Sopenharmony_ci unsigned int byteoff = bitoff / 8; 156e1051a39Sopenharmony_ci unsigned char b; 157e1051a39Sopenharmony_ci 158e1051a39Sopenharmony_ci#ifndef OPENSSL_SMALL_FOOTPRINT 159e1051a39Sopenharmony_ci if (bitrem == inpgap) { 160e1051a39Sopenharmony_ci c->data[byteoff++] |= inp[0] & (0xff >> inpgap); 161e1051a39Sopenharmony_ci inpgap = 8 - inpgap; 162e1051a39Sopenharmony_ci bitoff += inpgap; 163e1051a39Sopenharmony_ci bitrem = 0; /* bitoff%8 */ 164e1051a39Sopenharmony_ci bits -= inpgap; 165e1051a39Sopenharmony_ci inpgap = 0; /* bits%8 */ 166e1051a39Sopenharmony_ci inp++; 167e1051a39Sopenharmony_ci if (bitoff == WHIRLPOOL_BBLOCK) { 168e1051a39Sopenharmony_ci whirlpool_block(c, c->data, 1); 169e1051a39Sopenharmony_ci bitoff = 0; 170e1051a39Sopenharmony_ci } 171e1051a39Sopenharmony_ci c->bitoff = bitoff; 172e1051a39Sopenharmony_ci goto reconsider; 173e1051a39Sopenharmony_ci } else 174e1051a39Sopenharmony_ci#endif 175e1051a39Sopenharmony_ci if (bits > 8) { 176e1051a39Sopenharmony_ci b = ((inp[0] << inpgap) | (inp[1] >> (8 - inpgap))); 177e1051a39Sopenharmony_ci b &= 0xff; 178e1051a39Sopenharmony_ci if (bitrem) 179e1051a39Sopenharmony_ci c->data[byteoff++] |= b >> bitrem; 180e1051a39Sopenharmony_ci else 181e1051a39Sopenharmony_ci c->data[byteoff++] = b; 182e1051a39Sopenharmony_ci bitoff += 8; 183e1051a39Sopenharmony_ci bits -= 8; 184e1051a39Sopenharmony_ci inp++; 185e1051a39Sopenharmony_ci if (bitoff >= WHIRLPOOL_BBLOCK) { 186e1051a39Sopenharmony_ci whirlpool_block(c, c->data, 1); 187e1051a39Sopenharmony_ci byteoff = 0; 188e1051a39Sopenharmony_ci bitoff %= WHIRLPOOL_BBLOCK; 189e1051a39Sopenharmony_ci } 190e1051a39Sopenharmony_ci if (bitrem) 191e1051a39Sopenharmony_ci c->data[byteoff] = b << (8 - bitrem); 192e1051a39Sopenharmony_ci } else { /* remaining less than or equal to 8 bits */ 193e1051a39Sopenharmony_ci 194e1051a39Sopenharmony_ci b = (inp[0] << inpgap) & 0xff; 195e1051a39Sopenharmony_ci if (bitrem) 196e1051a39Sopenharmony_ci c->data[byteoff++] |= b >> bitrem; 197e1051a39Sopenharmony_ci else 198e1051a39Sopenharmony_ci c->data[byteoff++] = b; 199e1051a39Sopenharmony_ci bitoff += (unsigned int)bits; 200e1051a39Sopenharmony_ci if (bitoff == WHIRLPOOL_BBLOCK) { 201e1051a39Sopenharmony_ci whirlpool_block(c, c->data, 1); 202e1051a39Sopenharmony_ci byteoff = 0; 203e1051a39Sopenharmony_ci bitoff %= WHIRLPOOL_BBLOCK; 204e1051a39Sopenharmony_ci } 205e1051a39Sopenharmony_ci if (bitrem) 206e1051a39Sopenharmony_ci c->data[byteoff] = b << (8 - bitrem); 207e1051a39Sopenharmony_ci bits = 0; 208e1051a39Sopenharmony_ci } 209e1051a39Sopenharmony_ci c->bitoff = bitoff; 210e1051a39Sopenharmony_ci } 211e1051a39Sopenharmony_ci } 212e1051a39Sopenharmony_ci} 213e1051a39Sopenharmony_ci 214e1051a39Sopenharmony_ciint WHIRLPOOL_Final(unsigned char *md, WHIRLPOOL_CTX *c) 215e1051a39Sopenharmony_ci{ 216e1051a39Sopenharmony_ci unsigned int bitoff = c->bitoff, byteoff = bitoff / 8; 217e1051a39Sopenharmony_ci size_t i, j, v; 218e1051a39Sopenharmony_ci unsigned char *p; 219e1051a39Sopenharmony_ci 220e1051a39Sopenharmony_ci bitoff %= 8; 221e1051a39Sopenharmony_ci if (bitoff) 222e1051a39Sopenharmony_ci c->data[byteoff] |= 0x80 >> bitoff; 223e1051a39Sopenharmony_ci else 224e1051a39Sopenharmony_ci c->data[byteoff] = 0x80; 225e1051a39Sopenharmony_ci byteoff++; 226e1051a39Sopenharmony_ci 227e1051a39Sopenharmony_ci /* pad with zeros */ 228e1051a39Sopenharmony_ci if (byteoff > (WHIRLPOOL_BBLOCK / 8 - WHIRLPOOL_COUNTER)) { 229e1051a39Sopenharmony_ci if (byteoff < WHIRLPOOL_BBLOCK / 8) 230e1051a39Sopenharmony_ci memset(&c->data[byteoff], 0, WHIRLPOOL_BBLOCK / 8 - byteoff); 231e1051a39Sopenharmony_ci whirlpool_block(c, c->data, 1); 232e1051a39Sopenharmony_ci byteoff = 0; 233e1051a39Sopenharmony_ci } 234e1051a39Sopenharmony_ci if (byteoff < (WHIRLPOOL_BBLOCK / 8 - WHIRLPOOL_COUNTER)) 235e1051a39Sopenharmony_ci memset(&c->data[byteoff], 0, 236e1051a39Sopenharmony_ci (WHIRLPOOL_BBLOCK / 8 - WHIRLPOOL_COUNTER) - byteoff); 237e1051a39Sopenharmony_ci /* smash 256-bit c->bitlen in big-endian order */ 238e1051a39Sopenharmony_ci p = &c->data[WHIRLPOOL_BBLOCK / 8 - 1]; /* last byte in c->data */ 239e1051a39Sopenharmony_ci for (i = 0; i < WHIRLPOOL_COUNTER / sizeof(size_t); i++) 240e1051a39Sopenharmony_ci for (v = c->bitlen[i], j = 0; j < sizeof(size_t); j++, v >>= 8) 241e1051a39Sopenharmony_ci *p-- = (unsigned char)(v & 0xff); 242e1051a39Sopenharmony_ci 243e1051a39Sopenharmony_ci whirlpool_block(c, c->data, 1); 244e1051a39Sopenharmony_ci 245e1051a39Sopenharmony_ci if (md) { 246e1051a39Sopenharmony_ci memcpy(md, c->H.c, WHIRLPOOL_DIGEST_LENGTH); 247e1051a39Sopenharmony_ci OPENSSL_cleanse(c, sizeof(*c)); 248e1051a39Sopenharmony_ci return 1; 249e1051a39Sopenharmony_ci } 250e1051a39Sopenharmony_ci return 0; 251e1051a39Sopenharmony_ci} 252e1051a39Sopenharmony_ci 253e1051a39Sopenharmony_ciunsigned char *WHIRLPOOL(const void *inp, size_t bytes, unsigned char *md) 254e1051a39Sopenharmony_ci{ 255e1051a39Sopenharmony_ci WHIRLPOOL_CTX ctx; 256e1051a39Sopenharmony_ci static unsigned char m[WHIRLPOOL_DIGEST_LENGTH]; 257e1051a39Sopenharmony_ci 258e1051a39Sopenharmony_ci if (md == NULL) 259e1051a39Sopenharmony_ci md = m; 260e1051a39Sopenharmony_ci WHIRLPOOL_Init(&ctx); 261e1051a39Sopenharmony_ci WHIRLPOOL_Update(&ctx, inp, bytes); 262e1051a39Sopenharmony_ci WHIRLPOOL_Final(md, &ctx); 263e1051a39Sopenharmony_ci return md; 264e1051a39Sopenharmony_ci} 265