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" 19 using 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 40 void 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 50 static uint32_t rol32(uint32_t number, uint8_t bits) { 51 return ((number << bits) | (number >> (32 - bits))); 52 } 53 54 void 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 93 void 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 107 void SHA1::writebyte(uint8_t data) { 108 ++InternalState.ByteCount; 109 addUncounted(data); 110 } 111 112 void SHA1::update(ArrayRef<uint8_t> Data) { 113 for (auto &C : Data) 114 writebyte(C); 115 } 116 117 void 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 137 StringRef 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 160 StringRef 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