10b57cec5SDimitry Andric //===- FuzzerSHA1.h - Private copy of the SHA1 implementation ---*- C++ -* ===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // This code is taken from public domain 90b57cec5SDimitry Andric // (http://oauth.googlecode.com/svn/code/c/liboauth/src/sha1.c) 100b57cec5SDimitry Andric // and modified by adding anonymous namespace, adding an interface 110b57cec5SDimitry Andric // function fuzzer::ComputeSHA1() and removing unnecessary code. 120b57cec5SDimitry Andric // 130b57cec5SDimitry Andric // lib/Fuzzer can not use SHA1 implementation from openssl because 140b57cec5SDimitry Andric // openssl may not be available and because we may be fuzzing openssl itself. 150b57cec5SDimitry Andric // For the same reason we do not want to depend on SHA1 from LLVM tree. 160b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 170b57cec5SDimitry Andric 180b57cec5SDimitry Andric #include "FuzzerSHA1.h" 190b57cec5SDimitry Andric #include "FuzzerDefs.h" 20*5ffd83dbSDimitry Andric #include "FuzzerPlatform.h" 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric /* This code is public-domain - it is based on libcrypt 230b57cec5SDimitry Andric * placed in the public domain by Wei Dai and other contributors. 240b57cec5SDimitry Andric */ 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric #include <iomanip> 270b57cec5SDimitry Andric #include <sstream> 280b57cec5SDimitry Andric #include <stdint.h> 290b57cec5SDimitry Andric #include <string.h> 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric namespace { // Added for LibFuzzer 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric #ifdef __BIG_ENDIAN__ 340b57cec5SDimitry Andric # define SHA_BIG_ENDIAN 350b57cec5SDimitry Andric // Windows is always little endian and MSVC doesn't have <endian.h> 360b57cec5SDimitry Andric #elif defined __LITTLE_ENDIAN__ || LIBFUZZER_WINDOWS 370b57cec5SDimitry Andric /* override */ 380b57cec5SDimitry Andric #elif defined __BYTE_ORDER 390b57cec5SDimitry Andric # if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 400b57cec5SDimitry Andric # define SHA_BIG_ENDIAN 410b57cec5SDimitry Andric # endif 420b57cec5SDimitry Andric #else // ! defined __LITTLE_ENDIAN__ 430b57cec5SDimitry Andric # include <endian.h> // machine/endian.h 440b57cec5SDimitry Andric # if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 450b57cec5SDimitry Andric # define SHA_BIG_ENDIAN 460b57cec5SDimitry Andric # endif 470b57cec5SDimitry Andric #endif 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric /* header */ 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric #define HASH_LENGTH 20 530b57cec5SDimitry Andric #define BLOCK_LENGTH 64 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric typedef struct sha1nfo { 560b57cec5SDimitry Andric uint32_t buffer[BLOCK_LENGTH/4]; 570b57cec5SDimitry Andric uint32_t state[HASH_LENGTH/4]; 580b57cec5SDimitry Andric uint32_t byteCount; 590b57cec5SDimitry Andric uint8_t bufferOffset; 600b57cec5SDimitry Andric uint8_t keyBuffer[BLOCK_LENGTH]; 610b57cec5SDimitry Andric uint8_t innerHash[HASH_LENGTH]; 620b57cec5SDimitry Andric } sha1nfo; 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric /* public API - prototypes - TODO: doxygen*/ 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric /** 670b57cec5SDimitry Andric */ 680b57cec5SDimitry Andric void sha1_init(sha1nfo *s); 690b57cec5SDimitry Andric /** 700b57cec5SDimitry Andric */ 710b57cec5SDimitry Andric void sha1_writebyte(sha1nfo *s, uint8_t data); 720b57cec5SDimitry Andric /** 730b57cec5SDimitry Andric */ 740b57cec5SDimitry Andric void sha1_write(sha1nfo *s, const char *data, size_t len); 750b57cec5SDimitry Andric /** 760b57cec5SDimitry Andric */ 770b57cec5SDimitry Andric uint8_t* sha1_result(sha1nfo *s); 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric /* code */ 810b57cec5SDimitry Andric #define SHA1_K0 0x5a827999 820b57cec5SDimitry Andric #define SHA1_K20 0x6ed9eba1 830b57cec5SDimitry Andric #define SHA1_K40 0x8f1bbcdc 840b57cec5SDimitry Andric #define SHA1_K60 0xca62c1d6 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric void sha1_init(sha1nfo *s) { 870b57cec5SDimitry Andric s->state[0] = 0x67452301; 880b57cec5SDimitry Andric s->state[1] = 0xefcdab89; 890b57cec5SDimitry Andric s->state[2] = 0x98badcfe; 900b57cec5SDimitry Andric s->state[3] = 0x10325476; 910b57cec5SDimitry Andric s->state[4] = 0xc3d2e1f0; 920b57cec5SDimitry Andric s->byteCount = 0; 930b57cec5SDimitry Andric s->bufferOffset = 0; 940b57cec5SDimitry Andric } 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric uint32_t sha1_rol32(uint32_t number, uint8_t bits) { 970b57cec5SDimitry Andric return ((number << bits) | (number >> (32-bits))); 980b57cec5SDimitry Andric } 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric void sha1_hashBlock(sha1nfo *s) { 1010b57cec5SDimitry Andric uint8_t i; 1020b57cec5SDimitry Andric uint32_t a,b,c,d,e,t; 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric a=s->state[0]; 1050b57cec5SDimitry Andric b=s->state[1]; 1060b57cec5SDimitry Andric c=s->state[2]; 1070b57cec5SDimitry Andric d=s->state[3]; 1080b57cec5SDimitry Andric e=s->state[4]; 1090b57cec5SDimitry Andric for (i=0; i<80; i++) { 1100b57cec5SDimitry Andric if (i>=16) { 1110b57cec5SDimitry Andric t = s->buffer[(i+13)&15] ^ s->buffer[(i+8)&15] ^ s->buffer[(i+2)&15] ^ s->buffer[i&15]; 1120b57cec5SDimitry Andric s->buffer[i&15] = sha1_rol32(t,1); 1130b57cec5SDimitry Andric } 1140b57cec5SDimitry Andric if (i<20) { 1150b57cec5SDimitry Andric t = (d ^ (b & (c ^ d))) + SHA1_K0; 1160b57cec5SDimitry Andric } else if (i<40) { 1170b57cec5SDimitry Andric t = (b ^ c ^ d) + SHA1_K20; 1180b57cec5SDimitry Andric } else if (i<60) { 1190b57cec5SDimitry Andric t = ((b & c) | (d & (b | c))) + SHA1_K40; 1200b57cec5SDimitry Andric } else { 1210b57cec5SDimitry Andric t = (b ^ c ^ d) + SHA1_K60; 1220b57cec5SDimitry Andric } 1230b57cec5SDimitry Andric t+=sha1_rol32(a,5) + e + s->buffer[i&15]; 1240b57cec5SDimitry Andric e=d; 1250b57cec5SDimitry Andric d=c; 1260b57cec5SDimitry Andric c=sha1_rol32(b,30); 1270b57cec5SDimitry Andric b=a; 1280b57cec5SDimitry Andric a=t; 1290b57cec5SDimitry Andric } 1300b57cec5SDimitry Andric s->state[0] += a; 1310b57cec5SDimitry Andric s->state[1] += b; 1320b57cec5SDimitry Andric s->state[2] += c; 1330b57cec5SDimitry Andric s->state[3] += d; 1340b57cec5SDimitry Andric s->state[4] += e; 1350b57cec5SDimitry Andric } 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric void sha1_addUncounted(sha1nfo *s, uint8_t data) { 1380b57cec5SDimitry Andric uint8_t * const b = (uint8_t*) s->buffer; 1390b57cec5SDimitry Andric #ifdef SHA_BIG_ENDIAN 1400b57cec5SDimitry Andric b[s->bufferOffset] = data; 1410b57cec5SDimitry Andric #else 1420b57cec5SDimitry Andric b[s->bufferOffset ^ 3] = data; 1430b57cec5SDimitry Andric #endif 1440b57cec5SDimitry Andric s->bufferOffset++; 1450b57cec5SDimitry Andric if (s->bufferOffset == BLOCK_LENGTH) { 1460b57cec5SDimitry Andric sha1_hashBlock(s); 1470b57cec5SDimitry Andric s->bufferOffset = 0; 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric } 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric void sha1_writebyte(sha1nfo *s, uint8_t data) { 1520b57cec5SDimitry Andric ++s->byteCount; 1530b57cec5SDimitry Andric sha1_addUncounted(s, data); 1540b57cec5SDimitry Andric } 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric void sha1_write(sha1nfo *s, const char *data, size_t len) { 1570b57cec5SDimitry Andric for (;len--;) sha1_writebyte(s, (uint8_t) *data++); 1580b57cec5SDimitry Andric } 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric void sha1_pad(sha1nfo *s) { 1610b57cec5SDimitry Andric // Implement SHA-1 padding (fips180-2 §5.1.1) 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric // Pad with 0x80 followed by 0x00 until the end of the block 1640b57cec5SDimitry Andric sha1_addUncounted(s, 0x80); 1650b57cec5SDimitry Andric while (s->bufferOffset != 56) sha1_addUncounted(s, 0x00); 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andric // Append length in the last 8 bytes 1680b57cec5SDimitry Andric sha1_addUncounted(s, 0); // We're only using 32 bit lengths 1690b57cec5SDimitry Andric sha1_addUncounted(s, 0); // But SHA-1 supports 64 bit lengths 1700b57cec5SDimitry Andric sha1_addUncounted(s, 0); // So zero pad the top bits 1710b57cec5SDimitry Andric sha1_addUncounted(s, s->byteCount >> 29); // Shifting to multiply by 8 1720b57cec5SDimitry Andric sha1_addUncounted(s, s->byteCount >> 21); // as SHA-1 supports bitstreams as well as 1730b57cec5SDimitry Andric sha1_addUncounted(s, s->byteCount >> 13); // byte. 1740b57cec5SDimitry Andric sha1_addUncounted(s, s->byteCount >> 5); 1750b57cec5SDimitry Andric sha1_addUncounted(s, s->byteCount << 3); 1760b57cec5SDimitry Andric } 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric uint8_t* sha1_result(sha1nfo *s) { 1790b57cec5SDimitry Andric // Pad to complete the last block 1800b57cec5SDimitry Andric sha1_pad(s); 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric #ifndef SHA_BIG_ENDIAN 1830b57cec5SDimitry Andric // Swap byte order back 1840b57cec5SDimitry Andric int i; 1850b57cec5SDimitry Andric for (i=0; i<5; i++) { 1860b57cec5SDimitry Andric s->state[i]= 1870b57cec5SDimitry Andric (((s->state[i])<<24)& 0xff000000) 1880b57cec5SDimitry Andric | (((s->state[i])<<8) & 0x00ff0000) 1890b57cec5SDimitry Andric | (((s->state[i])>>8) & 0x0000ff00) 1900b57cec5SDimitry Andric | (((s->state[i])>>24)& 0x000000ff); 1910b57cec5SDimitry Andric } 1920b57cec5SDimitry Andric #endif 1930b57cec5SDimitry Andric 1940b57cec5SDimitry Andric // Return pointer to hash (20 characters) 1950b57cec5SDimitry Andric return (uint8_t*) s->state; 1960b57cec5SDimitry Andric } 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric } // namespace; Added for LibFuzzer 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andric namespace fuzzer { 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric // The rest is added for LibFuzzer 2030b57cec5SDimitry Andric void ComputeSHA1(const uint8_t *Data, size_t Len, uint8_t *Out) { 2040b57cec5SDimitry Andric sha1nfo s; 2050b57cec5SDimitry Andric sha1_init(&s); 2060b57cec5SDimitry Andric sha1_write(&s, (const char*)Data, Len); 2070b57cec5SDimitry Andric memcpy(Out, sha1_result(&s), HASH_LENGTH); 2080b57cec5SDimitry Andric } 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric std::string Sha1ToString(const uint8_t Sha1[kSHA1NumBytes]) { 2110b57cec5SDimitry Andric std::stringstream SS; 2120b57cec5SDimitry Andric for (int i = 0; i < kSHA1NumBytes; i++) 2130b57cec5SDimitry Andric SS << std::hex << std::setfill('0') << std::setw(2) << (unsigned)Sha1[i]; 2140b57cec5SDimitry Andric return SS.str(); 2150b57cec5SDimitry Andric } 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric std::string Hash(const Unit &U) { 2180b57cec5SDimitry Andric uint8_t Hash[kSHA1NumBytes]; 2190b57cec5SDimitry Andric ComputeSHA1(U.data(), U.size(), Hash); 2200b57cec5SDimitry Andric return Sha1ToString(Hash); 2210b57cec5SDimitry Andric } 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric } 224