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