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