1//======- SHA1.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 wrapping it in a C++ interface for LLVM, 12// and removing unnecessary code. 13// 14//===----------------------------------------------------------------------===// 15 16#include "llvm/Support/Host.h" 17#include "llvm/Support/SHA1.h" 18#include "llvm/ADT/ArrayRef.h" 19using namespace llvm; 20 21#include <stdint.h> 22#include <string.h> 23 24#if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN 25#define SHA_BIG_ENDIAN 26#endif 27 28/* code */ 29#define SHA1_K0 0x5a827999 30#define SHA1_K20 0x6ed9eba1 31#define SHA1_K40 0x8f1bbcdc 32#define SHA1_K60 0xca62c1d6 33 34#define SEED_0 0x67452301 35#define SEED_1 0xefcdab89 36#define SEED_2 0x98badcfe 37#define SEED_3 0x10325476 38#define SEED_4 0xc3d2e1f0 39 40void SHA1::init() { 41 InternalState.State[0] = SEED_0; 42 InternalState.State[1] = SEED_1; 43 InternalState.State[2] = SEED_2; 44 InternalState.State[3] = SEED_3; 45 InternalState.State[4] = SEED_4; 46 InternalState.ByteCount = 0; 47 InternalState.BufferOffset = 0; 48} 49 50static uint32_t rol32(uint32_t number, uint8_t bits) { 51 return ((number << bits) | (number >> (32 - bits))); 52} 53 54void SHA1::hashBlock() { 55 uint8_t i; 56 uint32_t a, b, c, d, e, t; 57 58 a = InternalState.State[0]; 59 b = InternalState.State[1]; 60 c = InternalState.State[2]; 61 d = InternalState.State[3]; 62 e = InternalState.State[4]; 63 for (i = 0; i < 80; i++) { 64 if (i >= 16) { 65 t = InternalState.Buffer[(i + 13) & 15] ^ 66 InternalState.Buffer[(i + 8) & 15] ^ 67 InternalState.Buffer[(i + 2) & 15] ^ InternalState.Buffer[i & 15]; 68 InternalState.Buffer[i & 15] = rol32(t, 1); 69 } 70 if (i < 20) { 71 t = (d ^ (b & (c ^ d))) + SHA1_K0; 72 } else if (i < 40) { 73 t = (b ^ c ^ d) + SHA1_K20; 74 } else if (i < 60) { 75 t = ((b & c) | (d & (b | c))) + SHA1_K40; 76 } else { 77 t = (b ^ c ^ d) + SHA1_K60; 78 } 79 t += rol32(a, 5) + e + InternalState.Buffer[i & 15]; 80 e = d; 81 d = c; 82 c = rol32(b, 30); 83 b = a; 84 a = t; 85 } 86 InternalState.State[0] += a; 87 InternalState.State[1] += b; 88 InternalState.State[2] += c; 89 InternalState.State[3] += d; 90 InternalState.State[4] += e; 91} 92 93void SHA1::addUncounted(uint8_t data) { 94 uint8_t *const b = (uint8_t *)InternalState.Buffer; 95#ifdef SHA_BIG_ENDIAN 96 b[InternalState.BufferOffset] = data; 97#else 98 b[InternalState.BufferOffset ^ 3] = data; 99#endif 100 InternalState.BufferOffset++; 101 if (InternalState.BufferOffset == BLOCK_LENGTH) { 102 hashBlock(); 103 InternalState.BufferOffset = 0; 104 } 105} 106 107void SHA1::writebyte(uint8_t data) { 108 ++InternalState.ByteCount; 109 addUncounted(data); 110} 111 112void SHA1::update(ArrayRef<uint8_t> Data) { 113 for (auto &C : Data) 114 writebyte(C); 115} 116 117void SHA1::pad() { 118 // Implement SHA-1 padding (fips180-2 5.1.1) 119 120 // Pad with 0x80 followed by 0x00 until the end of the block 121 addUncounted(0x80); 122 while (InternalState.BufferOffset != 56) 123 addUncounted(0x00); 124 125 // Append length in the last 8 bytes 126 addUncounted(0); // We're only using 32 bit lengths 127 addUncounted(0); // But SHA-1 supports 64 bit lengths 128 addUncounted(0); // So zero pad the top bits 129 addUncounted(InternalState.ByteCount >> 29); // Shifting to multiply by 8 130 addUncounted(InternalState.ByteCount >> 131 21); // as SHA-1 supports bitstreams as well as 132 addUncounted(InternalState.ByteCount >> 13); // byte. 133 addUncounted(InternalState.ByteCount >> 5); 134 addUncounted(InternalState.ByteCount << 3); 135} 136 137StringRef SHA1::final() { 138 // Pad to complete the last block 139 pad(); 140 141#ifdef SHA_BIG_ENDIAN 142 // Just copy the current state 143 for (int i = 0; i < 5; i++) { 144 HashResult[i] = InternalState.State[i]; 145 } 146#else 147 // Swap byte order back 148 for (int i = 0; i < 5; i++) { 149 HashResult[i] = (((InternalState.State[i]) << 24) & 0xff000000) | 150 (((InternalState.State[i]) << 8) & 0x00ff0000) | 151 (((InternalState.State[i]) >> 8) & 0x0000ff00) | 152 (((InternalState.State[i]) >> 24) & 0x000000ff); 153 } 154#endif 155 156 // Return pointer to hash (20 characters) 157 return StringRef((char *)HashResult, HASH_LENGTH); 158} 159 160StringRef SHA1::result() { 161 auto StateToRestore = InternalState; 162 163 auto Hash = final(); 164 165 // Restore the state 166 InternalState = StateToRestore; 167 168 // Return pointer to hash (20 characters) 169 return Hash; 170} 171