Coverage Report

Created: 2022-08-24 06:31

/src/libressl/crypto/whrlpool/wp_dgst.c
Line
Count
Source (jump to first uncovered line)
1
/* $OpenBSD: wp_dgst.c,v 1.4 2014/07/12 11:25:25 miod Exp $ */
2
/**
3
 * The Whirlpool hashing function.
4
 *
5
 * <P>
6
 * <b>References</b>
7
 *
8
 * <P>
9
 * The Whirlpool algorithm was developed by
10
 * <a href="mailto:pbarreto@scopus.com.br">Paulo S. L. M. Barreto</a> and
11
 * <a href="mailto:vincent.rijmen@cryptomathic.com">Vincent Rijmen</a>.
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 "wp_locl.h"
56
#include <openssl/crypto.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
  /* Well, largest suitable chunk size actually is
68
   * (1<<(sizeof(size_t)*8-3))-64, but below number
69
   * is large enough for not to care about excessive
70
   * calls to WHIRLPOOL_BitUpdate... */
71
0
  size_t chunk = ((size_t)1)<<(sizeof(size_t)*8-4);
72
0
  const unsigned char *inp = _inp;
73
74
0
  while (bytes>=chunk)
75
0
    {
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,
91
0
      inpgap = (8-(unsigned int)bits%8)&7;
92
0
  const unsigned char *inp=_inp;
93
94
  /* This 256-bit increment procedure relies on the size_t
95
   * being natural size of CPU register, so that we don't
96
   * have to mask the value in order to detect overflows. */
97
0
  c->bitlen[0] += bits;
98
0
  if (c->bitlen[0] < bits) /* overflow */
99
0
    {
100
0
    n = 1;
101
0
    do  {   c->bitlen[n]++;
102
0
        } while(c->bitlen[n]==0
103
0
            && ++n<(WHIRLPOOL_COUNTER/sizeof(size_t)));
104
0
    }
105
106
0
#ifndef OPENSSL_SMALL_FOOTPRINT
107
0
  reconsider:
108
0
  if (inpgap==0 && bitrem==0) /* byte-oriented loop */
109
0
    {
110
0
    while (bits)
111
0
      {
112
0
      if (bitoff==0 && (n=bits/WHIRLPOOL_BBLOCK))
113
0
        {
114
0
        whirlpool_block(c,inp,n);
115
0
        inp  += n*WHIRLPOOL_BBLOCK/8;
116
0
        bits %= WHIRLPOOL_BBLOCK;
117
0
        }
118
0
      else
119
0
        {
120
0
        unsigned int byteoff = bitoff/8;
121
122
0
        bitrem = WHIRLPOOL_BBLOCK - bitoff;/* re-use bitrem */
123
0
        if (bits >= bitrem)
124
0
          {
125
0
          bits -= bitrem;
126
0
          bitrem /= 8;
127
0
          memcpy(c->data+byteoff,inp,bitrem);
128
0
          inp  += bitrem;
129
0
          whirlpool_block(c,c->data,1);
130
0
          bitoff = 0;
131
0
          }
132
0
        else
133
0
          {
134
0
          memcpy(c->data+byteoff,inp,bits/8);
135
0
          bitoff += (unsigned int)bits;
136
0
          bits = 0;
137
0
          }
138
0
        c->bitoff = bitoff;
139
0
        }
140
0
      }
141
0
    }
142
0
  else        /* bit-oriented loop */
143
0
#endif
144
0
    {
145
    /*
146
         inp
147
         |
148
         +-------+-------+-------
149
            |||||||||||||||||||||
150
         +-------+-------+-------
151
    +-------+-------+-------+-------+-------
152
    ||||||||||||||        c->data
153
    +-------+-------+-------+-------+-------
154
      |
155
      c->bitoff/8
156
    */
157
0
    while (bits)
158
0
      {
159
0
      unsigned int  byteoff = bitoff/8;
160
0
      unsigned char b;
161
162
0
#ifndef OPENSSL_SMALL_FOOTPRINT
163
0
      if (bitrem==inpgap)
164
0
        {
165
0
        c->data[byteoff++] |= inp[0] & (0xff>>inpgap);
166
0
        inpgap = 8-inpgap;
167
0
        bitoff += inpgap;  bitrem = 0;  /* bitoff%8 */
168
0
        bits   -= inpgap;  inpgap = 0;  /* bits%8   */
169
0
        inp++;
170
0
        if (bitoff==WHIRLPOOL_BBLOCK)
171
0
          {
172
0
          whirlpool_block(c,c->data,1);
173
0
          bitoff = 0;
174
0
          }
175
0
        c->bitoff = bitoff;
176
0
        goto reconsider;
177
0
        }
178
0
      else
179
0
#endif
180
0
      if (bits>=8)
181
0
        {
182
0
        b  = ((inp[0]<<inpgap) | (inp[1]>>(8-inpgap)));
183
0
        b &= 0xff;
184
0
        if (bitrem) c->data[byteoff++] |= b>>bitrem;
185
0
        else    c->data[byteoff++]  = b;
186
0
        bitoff += 8;
187
0
        bits   -= 8;
188
0
        inp++;
189
0
        if (bitoff>=WHIRLPOOL_BBLOCK)
190
0
          {
191
0
          whirlpool_block(c,c->data,1);
192
0
          byteoff  = 0;
193
0
          bitoff  %= WHIRLPOOL_BBLOCK;
194
0
          }
195
0
        if (bitrem) c->data[byteoff] = b<<(8-bitrem);
196
0
        }
197
0
      else  /* remaining less than 8 bits */
198
0
        {
199
0
        b = (inp[0]<<inpgap)&0xff;
200
0
        if (bitrem) c->data[byteoff++] |= b>>bitrem;
201
0
        else    c->data[byteoff++]  = b;
202
0
        bitoff += (unsigned int)bits;
203
0
        if (bitoff==WHIRLPOOL_BBLOCK)
204
0
          {
205
0
          whirlpool_block(c,c->data,1);
206
0
          byteoff  = 0;
207
0
                bitoff  %= WHIRLPOOL_BBLOCK;
208
0
          }
209
0
        if (bitrem) c->data[byteoff] = b<<(8-bitrem);
210
0
        bits = 0;
211
0
        }
212
0
      c->bitoff = bitoff;
213
0
      }
214
0
    }
215
0
  }
216
217
int WHIRLPOOL_Final (unsigned char *md,WHIRLPOOL_CTX *c)
218
0
  {
219
0
  unsigned int  bitoff  = c->bitoff,
220
0
      byteoff = bitoff/8;
221
0
  size_t    i,j,v;
222
0
  unsigned char  *p;
223
224
0
  bitoff %= 8;
225
0
  if (bitoff) c->data[byteoff] |= 0x80>>bitoff;
226
0
  else    c->data[byteoff]  = 0x80;
227
0
  byteoff++;
228
229
  /* pad with zeros */
230
0
  if (byteoff > (WHIRLPOOL_BBLOCK/8-WHIRLPOOL_COUNTER))
231
0
    {
232
0
    if (byteoff<WHIRLPOOL_BBLOCK/8)
233
0
      memset(&c->data[byteoff],0,WHIRLPOOL_BBLOCK/8-byteoff);
234
0
    whirlpool_block(c,c->data,1);
235
0
    byteoff = 0;
236
0
    }
237
0
  if (byteoff < (WHIRLPOOL_BBLOCK/8-WHIRLPOOL_COUNTER))
238
0
    memset(&c->data[byteoff],0,
239
0
      (WHIRLPOOL_BBLOCK/8-WHIRLPOOL_COUNTER)-byteoff);
240
  /* smash 256-bit c->bitlen in big-endian order */
241
0
  p = &c->data[WHIRLPOOL_BBLOCK/8-1];  /* last byte in c->data */
242
0
  for(i=0;i<WHIRLPOOL_COUNTER/sizeof(size_t);i++)
243
0
    for(v=c->bitlen[i],j=0;j<sizeof(size_t);j++,v>>=8)
244
0
      *p-- = (unsigned char)(v&0xff);
245
246
0
  whirlpool_block(c,c->data,1);
247
248
0
  if (md) {
249
0
    memcpy(md,c->H.c,WHIRLPOOL_DIGEST_LENGTH);
250
0
    memset(c,0,sizeof(*c));
251
0
    return(1);
252
0
    }
253
0
  return(0);
254
0
  }
255
256
unsigned char *WHIRLPOOL(const void *inp, size_t bytes,unsigned char *md)
257
0
  {
258
0
  WHIRLPOOL_CTX ctx;
259
0
  static unsigned char m[WHIRLPOOL_DIGEST_LENGTH];
260
261
0
  if (md == NULL) md=m;
262
0
  WHIRLPOOL_Init(&ctx);
263
0
  WHIRLPOOL_Update(&ctx,inp,bytes);
264
0
  WHIRLPOOL_Final(md,&ctx);
265
0
  return(md);
266
0
  }