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