FuzzerSHA1.cpp revision 353358
138451Smsmith//===- FuzzerSHA1.h - Private copy of the SHA1 implementation ---*- C++ -* ===// 238451Smsmith// 338451Smsmith// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 438451Smsmith// See https://llvm.org/LICENSE.txt for license information. 538451Smsmith// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 638451Smsmith// 738451Smsmith//===----------------------------------------------------------------------===// 838451Smsmith// This code is taken from public domain 938451Smsmith// (http://oauth.googlecode.com/svn/code/c/liboauth/src/sha1.c) 1038451Smsmith// and modified by adding anonymous namespace, adding an interface 1138451Smsmith// function fuzzer::ComputeSHA1() and removing unnecessary code. 1238451Smsmith// 1338451Smsmith// lib/Fuzzer can not use SHA1 implementation from openssl because 1438451Smsmith// openssl may not be available and because we may be fuzzing openssl itself. 1538451Smsmith// For the same reason we do not want to depend on SHA1 from LLVM tree. 1638451Smsmith//===----------------------------------------------------------------------===// 1738451Smsmith 1838451Smsmith#include "FuzzerSHA1.h" 1938451Smsmith#include "FuzzerDefs.h" 2038451Smsmith 2138451Smsmith/* This code is public-domain - it is based on libcrypt 2238451Smsmith * placed in the public domain by Wei Dai and other contributors. 2338451Smsmith */ 2438451Smsmith 2538451Smsmith#include <iomanip> 2638451Smsmith#include <sstream> 2738451Smsmith#include <stdint.h> 2838451Smsmith#include <string.h> 2938451Smsmith 3038451Smsmithnamespace { // Added for LibFuzzer 3138451Smsmith 3238451Smsmith#ifdef __BIG_ENDIAN__ 3338451Smsmith# define SHA_BIG_ENDIAN 3484221Sdillon// Windows is always little endian and MSVC doesn't have <endian.h> 3584221Sdillon#elif defined __LITTLE_ENDIAN__ || LIBFUZZER_WINDOWS 3684221Sdillon/* override */ 3738451Smsmith#elif defined __BYTE_ORDER 3838451Smsmith# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 3938451Smsmith# define SHA_BIG_ENDIAN 4038451Smsmith# endif 4138451Smsmith#else // ! defined __LITTLE_ENDIAN__ 4238451Smsmith# include <endian.h> // machine/endian.h 4338451Smsmith# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 4438451Smsmith# define SHA_BIG_ENDIAN 4538451Smsmith# endif 4638451Smsmith#endif 4738451Smsmith 4838451Smsmith 4938451Smsmith/* header */ 5038451Smsmith 5138451Smsmith#define HASH_LENGTH 20 5238451Smsmith#define BLOCK_LENGTH 64 5338451Smsmith 5438451Smsmithtypedef struct sha1nfo { 5538451Smsmith uint32_t buffer[BLOCK_LENGTH/4]; 5638451Smsmith uint32_t state[HASH_LENGTH/4]; 5738451Smsmith uint32_t byteCount; 5838451Smsmith uint8_t bufferOffset; 5938451Smsmith uint8_t keyBuffer[BLOCK_LENGTH]; 6038451Smsmith uint8_t innerHash[HASH_LENGTH]; 6138451Smsmith} sha1nfo; 6238451Smsmith 63223124Srodrigc/* public API - prototypes - TODO: doxygen*/ 64223124Srodrigc 6539468Smsmith/** 6638451Smsmith */ 67223488Srodrigcvoid sha1_init(sha1nfo *s); 6838451Smsmith/** 6938451Smsmith */ 7038451Smsmithvoid sha1_writebyte(sha1nfo *s, uint8_t data); 71223124Srodrigc/** 7238451Smsmith */ 73223488Srodrigcvoid sha1_write(sha1nfo *s, const char *data, size_t len); 74223124Srodrigc/** 75223124Srodrigc */ 76223124Srodrigcuint8_t* sha1_result(sha1nfo *s); 77223124Srodrigc 7838451Smsmith 7938451Smsmith/* code */ 8059766Sjlemon#define SHA1_K0 0x5a827999 8159766Sjlemon#define SHA1_K20 0x6ed9eba1 8259766Sjlemon#define SHA1_K40 0x8f1bbcdc 8359766Sjlemon#define SHA1_K60 0xca62c1d6 8459766Sjlemon 8559766Sjlemonvoid sha1_init(sha1nfo *s) { 8659766Sjlemon s->state[0] = 0x67452301; 8759766Sjlemon s->state[1] = 0xefcdab89; 8838451Smsmith s->state[2] = 0x98badcfe; 8938451Smsmith s->state[3] = 0x10325476; 9038451Smsmith s->state[4] = 0xc3d2e1f0; 9138451Smsmith s->byteCount = 0; 9238451Smsmith s->bufferOffset = 0; 93223124Srodrigc} 9438451Smsmith 95223124Srodrigcuint32_t sha1_rol32(uint32_t number, uint8_t bits) { 96223488Srodrigc return ((number << bits) | (number >> (32-bits))); 97223124Srodrigc} 98223124Srodrigc 99223124Srodrigcvoid sha1_hashBlock(sha1nfo *s) { 100223124Srodrigc uint8_t i; 10138451Smsmith uint32_t a,b,c,d,e,t; 102223124Srodrigc 103223124Srodrigc a=s->state[0]; 104223124Srodrigc b=s->state[1]; 105223488Srodrigc c=s->state[2]; 106223124Srodrigc d=s->state[3]; 107223124Srodrigc e=s->state[4]; 10838451Smsmith for (i=0; i<80; i++) { 10938451Smsmith if (i>=16) { 11038451Smsmith t = s->buffer[(i+13)&15] ^ s->buffer[(i+8)&15] ^ s->buffer[(i+2)&15] ^ s->buffer[i&15]; 11138451Smsmith s->buffer[i&15] = sha1_rol32(t,1); 11238451Smsmith } 11338451Smsmith if (i<20) { 11438451Smsmith t = (d ^ (b & (c ^ d))) + SHA1_K0; 115223124Srodrigc } else if (i<40) { 116223488Srodrigc t = (b ^ c ^ d) + SHA1_K20; 11738451Smsmith } else if (i<60) { 11838451Smsmith t = ((b & c) | (d & (b | c))) + SHA1_K40; 11938451Smsmith } else { 120223124Srodrigc t = (b ^ c ^ d) + SHA1_K60; 121223128Srodrigc } 12238451Smsmith t+=sha1_rol32(a,5) + e + s->buffer[i&15]; 12338451Smsmith e=d; 124223488Srodrigc d=c; 125223488Srodrigc c=sha1_rol32(b,30); 12638451Smsmith b=a; 12738451Smsmith a=t; 12838451Smsmith } 12938451Smsmith s->state[0] += a; 13038451Smsmith s->state[1] += b; 13138451Smsmith s->state[2] += c; 13238451Smsmith s->state[3] += d; 133223488Srodrigc s->state[4] += e; 134223488Srodrigc} 13538451Smsmith 13638451Smsmithvoid sha1_addUncounted(sha1nfo *s, uint8_t data) { 137223488Srodrigc uint8_t * const b = (uint8_t*) s->buffer; 138223488Srodrigc#ifdef SHA_BIG_ENDIAN 139223488Srodrigc b[s->bufferOffset] = data; 140223488Srodrigc#else 141223488Srodrigc b[s->bufferOffset ^ 3] = data; 142223488Srodrigc#endif 143223488Srodrigc s->bufferOffset++; 144223488Srodrigc if (s->bufferOffset == BLOCK_LENGTH) { 145223488Srodrigc sha1_hashBlock(s); 146223488Srodrigc s->bufferOffset = 0; 147223488Srodrigc } 148223488Srodrigc} 149223488Srodrigc 150223488Srodrigcvoid sha1_writebyte(sha1nfo *s, uint8_t data) { 151223488Srodrigc ++s->byteCount; 152223488Srodrigc sha1_addUncounted(s, data); 153223488Srodrigc} 154223488Srodrigc 155223488Srodrigcvoid sha1_write(sha1nfo *s, const char *data, size_t len) { 156223488Srodrigc for (;len--;) sha1_writebyte(s, (uint8_t) *data++); 157223488Srodrigc} 158223488Srodrigc 159223488Srodrigcvoid sha1_pad(sha1nfo *s) { 160223488Srodrigc // Implement SHA-1 padding (fips180-2 ��5.1.1) 161223488Srodrigc 162223488Srodrigc // Pad with 0x80 followed by 0x00 until the end of the block 163223488Srodrigc sha1_addUncounted(s, 0x80); 164223488Srodrigc while (s->bufferOffset != 56) sha1_addUncounted(s, 0x00); 165223488Srodrigc 166223488Srodrigc // Append length in the last 8 bytes 167223488Srodrigc sha1_addUncounted(s, 0); // We're only using 32 bit lengths 168223488Srodrigc sha1_addUncounted(s, 0); // But SHA-1 supports 64 bit lengths 169223488Srodrigc sha1_addUncounted(s, 0); // So zero pad the top bits 170223488Srodrigc sha1_addUncounted(s, s->byteCount >> 29); // Shifting to multiply by 8 171223488Srodrigc sha1_addUncounted(s, s->byteCount >> 21); // as SHA-1 supports bitstreams as well as 172223488Srodrigc sha1_addUncounted(s, s->byteCount >> 13); // byte. 173223488Srodrigc sha1_addUncounted(s, s->byteCount >> 5); 174223488Srodrigc sha1_addUncounted(s, s->byteCount << 3); 175223488Srodrigc} 176223488Srodrigc 177223488Srodrigcuint8_t* sha1_result(sha1nfo *s) { 178223488Srodrigc // Pad to complete the last block 179223488Srodrigc sha1_pad(s); 180223488Srodrigc 181223488Srodrigc#ifndef SHA_BIG_ENDIAN 182223488Srodrigc // Swap byte order back 183223488Srodrigc int i; 184223124Srodrigc for (i=0; i<5; i++) { 185223124Srodrigc s->state[i]= 18638451Smsmith (((s->state[i])<<24)& 0xff000000) 187223124Srodrigc | (((s->state[i])<<8) & 0x00ff0000) 18838451Smsmith | (((s->state[i])>>8) & 0x0000ff00) 18938451Smsmith | (((s->state[i])>>24)& 0x000000ff); 19079034Smikeh } 19179034Smikeh#endif 19238451Smsmith 19338451Smsmith // Return pointer to hash (20 characters) 19477369Smsmith return (uint8_t*) s->state; 19538451Smsmith} 19638451Smsmith 19738451Smsmith} // namespace; Added for LibFuzzer 198223124Srodrigc 19938451Smsmithnamespace fuzzer { 20038451Smsmith 20138451Smsmith// The rest is added for LibFuzzer 20238451Smsmithvoid ComputeSHA1(const uint8_t *Data, size_t Len, uint8_t *Out) { 20338451Smsmith sha1nfo s; 20438451Smsmith sha1_init(&s); 20538451Smsmith sha1_write(&s, (const char*)Data, Len); 20638451Smsmith memcpy(Out, sha1_result(&s), HASH_LENGTH); 20738451Smsmith} 20838451Smsmith 20938451Smsmithstd::string Sha1ToString(const uint8_t Sha1[kSHA1NumBytes]) { 21038451Smsmith std::stringstream SS; 21138451Smsmith for (int i = 0; i < kSHA1NumBytes; i++) 21238451Smsmith SS << std::hex << std::setfill('0') << std::setw(2) << (unsigned)Sha1[i]; 21392913Sobrien return SS.str(); 21438451Smsmith} 21538451Smsmith 21638451Smsmithstd::string Hash(const Unit &U) { 21738451Smsmith uint8_t Hash[kSHA1NumBytes]; 21838451Smsmith ComputeSHA1(U.data(), U.size(), Hash); 21938451Smsmith return Sha1ToString(Hash); 22038451Smsmith} 221223488Srodrigc 22238451Smsmith} 22338451Smsmith