1 //===- FuzzerSHA1.h - Private copy of the SHA1 implementation ---*- C++ -* ===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // This code is taken from public domain 10 // (http://oauth.googlecode.com/svn/code/c/liboauth/src/sha1.c) 11 // and modified by adding anonymous namespace, adding an interface 12 // function fuzzer::ComputeSHA1() and removing unnecessary code. 13 // 14 // lib/Fuzzer can not use SHA1 implementation from openssl because 15 // openssl may not be available and because we may be fuzzing openssl itself. 16 // For the same reason we do not want to depend on SHA1 from LLVM tree. 17 //===----------------------------------------------------------------------===// 18 19 #include "FuzzerInternal.h" 20 21 /* This code is public-domain - it is based on libcrypt 22 * placed in the public domain by Wei Dai and other contributors. 23 */ 24 25 #include <stdint.h> 26 #include <string.h> 27 28 namespace { // Added for LibFuzzer 29 30 #ifdef __BIG_ENDIAN__ 31 # define SHA_BIG_ENDIAN 32 #elif defined __LITTLE_ENDIAN__ 33 /* override */ 34 #elif defined __BYTE_ORDER 35 # if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 36 # define SHA_BIG_ENDIAN 37 # endif 38 #else // ! defined __LITTLE_ENDIAN__ 39 # include <endian.h> // machine/endian.h 40 # if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 41 # define SHA_BIG_ENDIAN 42 # endif 43 #endif 44 45 46 /* header */ 47 48 #define HASH_LENGTH 20 49 #define BLOCK_LENGTH 64 50 51 typedef struct sha1nfo { 52 uint32_t buffer[BLOCK_LENGTH/4]; 53 uint32_t state[HASH_LENGTH/4]; 54 uint32_t byteCount; 55 uint8_t bufferOffset; 56 uint8_t keyBuffer[BLOCK_LENGTH]; 57 uint8_t innerHash[HASH_LENGTH]; 58 } sha1nfo; 59 60 /* public API - prototypes - TODO: doxygen*/ 61 62 /** 63 */ 64 void sha1_init(sha1nfo *s); 65 /** 66 */ 67 void sha1_writebyte(sha1nfo *s, uint8_t data); 68 /** 69 */ 70 void sha1_write(sha1nfo *s, const char *data, size_t len); 71 /** 72 */ 73 uint8_t* sha1_result(sha1nfo *s); 74 75 76 /* code */ 77 #define SHA1_K0 0x5a827999 78 #define SHA1_K20 0x6ed9eba1 79 #define SHA1_K40 0x8f1bbcdc 80 #define SHA1_K60 0xca62c1d6 81 82 void sha1_init(sha1nfo *s) { 83 s->state[0] = 0x67452301; 84 s->state[1] = 0xefcdab89; 85 s->state[2] = 0x98badcfe; 86 s->state[3] = 0x10325476; 87 s->state[4] = 0xc3d2e1f0; 88 s->byteCount = 0; 89 s->bufferOffset = 0; 90 } 91 92 uint32_t sha1_rol32(uint32_t number, uint8_t bits) { 93 return ((number << bits) | (number >> (32-bits))); 94 } 95 96 void sha1_hashBlock(sha1nfo *s) { 97 uint8_t i; 98 uint32_t a,b,c,d,e,t; 99 100 a=s->state[0]; 101 b=s->state[1]; 102 c=s->state[2]; 103 d=s->state[3]; 104 e=s->state[4]; 105 for (i=0; i<80; i++) { 106 if (i>=16) { 107 t = s->buffer[(i+13)&15] ^ s->buffer[(i+8)&15] ^ s->buffer[(i+2)&15] ^ s->buffer[i&15]; 108 s->buffer[i&15] = sha1_rol32(t,1); 109 } 110 if (i<20) { 111 t = (d ^ (b & (c ^ d))) + SHA1_K0; 112 } else if (i<40) { 113 t = (b ^ c ^ d) + SHA1_K20; 114 } else if (i<60) { 115 t = ((b & c) | (d & (b | c))) + SHA1_K40; 116 } else { 117 t = (b ^ c ^ d) + SHA1_K60; 118 } 119 t+=sha1_rol32(a,5) + e + s->buffer[i&15]; 120 e=d; 121 d=c; 122 c=sha1_rol32(b,30); 123 b=a; 124 a=t; 125 } 126 s->state[0] += a; 127 s->state[1] += b; 128 s->state[2] += c; 129 s->state[3] += d; 130 s->state[4] += e; 131 } 132 133 void sha1_addUncounted(sha1nfo *s, uint8_t data) { 134 uint8_t * const b = (uint8_t*) s->buffer; 135 #ifdef SHA_BIG_ENDIAN 136 b[s->bufferOffset] = data; 137 #else 138 b[s->bufferOffset ^ 3] = data; 139 #endif 140 s->bufferOffset++; 141 if (s->bufferOffset == BLOCK_LENGTH) { 142 sha1_hashBlock(s); 143 s->bufferOffset = 0; 144 } 145 } 146 147 void sha1_writebyte(sha1nfo *s, uint8_t data) { 148 ++s->byteCount; 149 sha1_addUncounted(s, data); 150 } 151 152 void sha1_write(sha1nfo *s, const char *data, size_t len) { 153 for (;len--;) sha1_writebyte(s, (uint8_t) *data++); 154 } 155 156 void sha1_pad(sha1nfo *s) { 157 // Implement SHA-1 padding (fips180-2 5.1.1) 158 159 // Pad with 0x80 followed by 0x00 until the end of the block 160 sha1_addUncounted(s, 0x80); 161 while (s->bufferOffset != 56) sha1_addUncounted(s, 0x00); 162 163 // Append length in the last 8 bytes 164 sha1_addUncounted(s, 0); // We're only using 32 bit lengths 165 sha1_addUncounted(s, 0); // But SHA-1 supports 64 bit lengths 166 sha1_addUncounted(s, 0); // So zero pad the top bits 167 sha1_addUncounted(s, s->byteCount >> 29); // Shifting to multiply by 8 168 sha1_addUncounted(s, s->byteCount >> 21); // as SHA-1 supports bitstreams as well as 169 sha1_addUncounted(s, s->byteCount >> 13); // byte. 170 sha1_addUncounted(s, s->byteCount >> 5); 171 sha1_addUncounted(s, s->byteCount << 3); 172 } 173 174 uint8_t* sha1_result(sha1nfo *s) { 175 // Pad to complete the last block 176 sha1_pad(s); 177 178 #ifndef SHA_BIG_ENDIAN 179 // Swap byte order back 180 int i; 181 for (i=0; i<5; i++) { 182 s->state[i]= 183 (((s->state[i])<<24)& 0xff000000) 184 | (((s->state[i])<<8) & 0x00ff0000) 185 | (((s->state[i])>>8) & 0x0000ff00) 186 | (((s->state[i])>>24)& 0x000000ff); 187 } 188 #endif 189 190 // Return pointer to hash (20 characters) 191 return (uint8_t*) s->state; 192 } 193 194 } // namespace; Added for LibFuzzer 195 196 // The rest is added for LibFuzzer 197 void fuzzer::ComputeSHA1(const uint8_t *Data, size_t Len, uint8_t *Out) { 198 sha1nfo s; 199 sha1_init(&s); 200 sha1_write(&s, (const char*)Data, Len); 201 memcpy(Out, sha1_result(&s), HASH_LENGTH); 202 } 203