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