xref: /aosp_15_r20/external/llvm/lib/Support/SHA1.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
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  
init()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  
rol32(uint32_t number,uint8_t bits)50  static uint32_t rol32(uint32_t number, uint8_t bits) {
51    return ((number << bits) | (number >> (32 - bits)));
52  }
53  
hashBlock()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  
addUncounted(uint8_t data)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  
writebyte(uint8_t data)107  void SHA1::writebyte(uint8_t data) {
108    ++InternalState.ByteCount;
109    addUncounted(data);
110  }
111  
update(ArrayRef<uint8_t> Data)112  void SHA1::update(ArrayRef<uint8_t> Data) {
113    for (auto &C : Data)
114      writebyte(C);
115  }
116  
pad()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  
final()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  
result()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