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