1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2001-2007, Tom St Denis 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /* LibTomCrypt, modular cryptographic library -- Tom St Denis 30 * 31 * LibTomCrypt is a library that provides various cryptographic 32 * algorithms in a highly modular and flexible manner. 33 * 34 * The library is free for all purposes without any express 35 * guarantee it works. 36 * 37 * Tom St Denis, tomstdenis@gmail.com, http://libtom.org 38 */ 39 #include "tomcrypt.h" 40 41 /** 42 @file sha1.c 43 LTC_SHA1 code by Tom St Denis 44 */ 45 46 47 #ifdef LTC_SHA1 48 49 const struct ltc_hash_descriptor sha1_desc = 50 { 51 "sha1", 52 2, 53 20, 54 64, 55 56 /* OID */ 57 { 1, 3, 14, 3, 2, 26, }, 58 6, 59 60 &sha1_init, 61 &sha1_process, 62 &sha1_done, 63 &sha1_test, 64 NULL 65 }; 66 67 #define F0(x,y,z) (z ^ (x & (y ^ z))) 68 #define F1(x,y,z) (x ^ y ^ z) 69 #define F2(x,y,z) ((x & y) | (z & (x | y))) 70 #define F3(x,y,z) (x ^ y ^ z) 71 72 #ifdef LTC_CLEAN_STACK 73 static int _sha1_compress(hash_state *md, unsigned char *buf) 74 #else 75 static int sha1_compress(hash_state *md, unsigned char *buf) 76 #endif 77 { 78 ulong32 a,b,c,d,e,W[80],i; 79 #ifdef LTC_SMALL_CODE 80 ulong32 t; 81 #endif 82 83 /* copy the state into 512-bits into W[0..15] */ 84 for (i = 0; i < 16; i++) { 85 LOAD32H(W[i], buf + (4*i)); 86 } 87 88 /* copy state */ 89 a = md->sha1.state[0]; 90 b = md->sha1.state[1]; 91 c = md->sha1.state[2]; 92 d = md->sha1.state[3]; 93 e = md->sha1.state[4]; 94 95 /* expand it */ 96 for (i = 16; i < 80; i++) { 97 W[i] = ROL(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1); 98 } 99 100 /* compress */ 101 /* round one */ 102 #define FF0(a,b,c,d,e,i) e = (ROLc(a, 5) + F0(b,c,d) + e + W[i] + 0x5a827999UL); b = ROLc(b, 30); 103 #define FF1(a,b,c,d,e,i) e = (ROLc(a, 5) + F1(b,c,d) + e + W[i] + 0x6ed9eba1UL); b = ROLc(b, 30); 104 #define FF2(a,b,c,d,e,i) e = (ROLc(a, 5) + F2(b,c,d) + e + W[i] + 0x8f1bbcdcUL); b = ROLc(b, 30); 105 #define FF3(a,b,c,d,e,i) e = (ROLc(a, 5) + F3(b,c,d) + e + W[i] + 0xca62c1d6UL); b = ROLc(b, 30); 106 107 #ifdef LTC_SMALL_CODE 108 109 for (i = 0; i < 20; ) { 110 FF0(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; 111 } 112 113 for (; i < 40; ) { 114 FF1(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; 115 } 116 117 for (; i < 60; ) { 118 FF2(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; 119 } 120 121 for (; i < 80; ) { 122 FF3(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; 123 } 124 125 #else 126 127 for (i = 0; i < 20; ) { 128 FF0(a,b,c,d,e,i++); 129 FF0(e,a,b,c,d,i++); 130 FF0(d,e,a,b,c,i++); 131 FF0(c,d,e,a,b,i++); 132 FF0(b,c,d,e,a,i++); 133 } 134 135 /* round two */ 136 for (; i < 40; ) { 137 FF1(a,b,c,d,e,i++); 138 FF1(e,a,b,c,d,i++); 139 FF1(d,e,a,b,c,i++); 140 FF1(c,d,e,a,b,i++); 141 FF1(b,c,d,e,a,i++); 142 } 143 144 /* round three */ 145 for (; i < 60; ) { 146 FF2(a,b,c,d,e,i++); 147 FF2(e,a,b,c,d,i++); 148 FF2(d,e,a,b,c,i++); 149 FF2(c,d,e,a,b,i++); 150 FF2(b,c,d,e,a,i++); 151 } 152 153 /* round four */ 154 for (; i < 80; ) { 155 FF3(a,b,c,d,e,i++); 156 FF3(e,a,b,c,d,i++); 157 FF3(d,e,a,b,c,i++); 158 FF3(c,d,e,a,b,i++); 159 FF3(b,c,d,e,a,i++); 160 } 161 #endif 162 163 #undef FF0 164 #undef FF1 165 #undef FF2 166 #undef FF3 167 168 /* store */ 169 md->sha1.state[0] = md->sha1.state[0] + a; 170 md->sha1.state[1] = md->sha1.state[1] + b; 171 md->sha1.state[2] = md->sha1.state[2] + c; 172 md->sha1.state[3] = md->sha1.state[3] + d; 173 md->sha1.state[4] = md->sha1.state[4] + e; 174 175 return CRYPT_OK; 176 } 177 178 #ifdef LTC_CLEAN_STACK 179 static int sha1_compress(hash_state *md, unsigned char *buf) 180 { 181 int err; 182 err = _sha1_compress(md, buf); 183 burn_stack(sizeof(ulong32) * 87); 184 return err; 185 } 186 #endif 187 188 /** 189 Initialize the hash state 190 @param md The hash state you wish to initialize 191 @return CRYPT_OK if successful 192 */ 193 int sha1_init(hash_state * md) 194 { 195 LTC_ARGCHK(md != NULL); 196 md->sha1.state[0] = 0x67452301UL; 197 md->sha1.state[1] = 0xefcdab89UL; 198 md->sha1.state[2] = 0x98badcfeUL; 199 md->sha1.state[3] = 0x10325476UL; 200 md->sha1.state[4] = 0xc3d2e1f0UL; 201 md->sha1.curlen = 0; 202 md->sha1.length = 0; 203 return CRYPT_OK; 204 } 205 206 /** 207 Process a block of memory though the hash 208 @param md The hash state 209 @param in The data to hash 210 @param inlen The length of the data (octets) 211 @return CRYPT_OK if successful 212 */ 213 HASH_PROCESS(sha1_process, sha1_compress, sha1, 64) 214 215 /** 216 Terminate the hash to get the digest 217 @param md The hash state 218 @param out [out] The destination of the hash (20 bytes) 219 @return CRYPT_OK if successful 220 */ 221 int sha1_done(hash_state * md, unsigned char *out) 222 { 223 int i; 224 225 LTC_ARGCHK(md != NULL); 226 LTC_ARGCHK(out != NULL); 227 228 if (md->sha1.curlen >= sizeof(md->sha1.buf)) { 229 return CRYPT_INVALID_ARG; 230 } 231 232 /* increase the length of the message */ 233 md->sha1.length += md->sha1.curlen * 8; 234 235 /* append the '1' bit */ 236 md->sha1.buf[md->sha1.curlen++] = (unsigned char)0x80; 237 238 /* if the length is currently above 56 bytes we append zeros 239 * then compress. Then we can fall back to padding zeros and length 240 * encoding like normal. 241 */ 242 if (md->sha1.curlen > 56) { 243 while (md->sha1.curlen < 64) { 244 md->sha1.buf[md->sha1.curlen++] = (unsigned char)0; 245 } 246 sha1_compress(md, md->sha1.buf); 247 md->sha1.curlen = 0; 248 } 249 250 /* pad upto 56 bytes of zeroes */ 251 while (md->sha1.curlen < 56) { 252 md->sha1.buf[md->sha1.curlen++] = (unsigned char)0; 253 } 254 255 /* store length */ 256 STORE64H(md->sha1.length, md->sha1.buf+56); 257 sha1_compress(md, md->sha1.buf); 258 259 /* copy output */ 260 for (i = 0; i < 5; i++) { 261 STORE32H(md->sha1.state[i], out+(4*i)); 262 } 263 #ifdef LTC_CLEAN_STACK 264 zeromem(md, sizeof(hash_state)); 265 #endif 266 return CRYPT_OK; 267 } 268 269 /** 270 Self-test the hash 271 @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled 272 */ 273 int sha1_test(void) 274 { 275 #ifndef LTC_TEST 276 return CRYPT_NOP; 277 #else 278 static const struct { 279 const char *msg; 280 unsigned char hash[20]; 281 } tests[] = { 282 { "abc", 283 { 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, 284 0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c, 285 0x9c, 0xd0, 0xd8, 0x9d } 286 }, 287 { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 288 { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 289 0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 290 0xE5, 0x46, 0x70, 0xF1 } 291 } 292 }; 293 294 int i; 295 unsigned char tmp[20]; 296 hash_state md; 297 298 for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { 299 sha1_init(&md); 300 sha1_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg)); 301 sha1_done(&md, tmp); 302 if (XMEMCMP(tmp, tests[i].hash, 20) != 0) { 303 return CRYPT_FAIL_TESTVECTOR; 304 } 305 } 306 return CRYPT_OK; 307 #endif 308 } 309 310 #endif 311 312 313 314 /* $Source: /cvs/libtom/libtomcrypt/src/hashes/sha1.c,v $ */ 315 /* $Revision: 1.10 $ */ 316 /* $Date: 2007/05/12 14:25:28 $ */ 317