Coverage Report

Created: 2026-09-14 07:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/botan/src/lib/hash/sha1/sha1.cpp
Line
Count
Source
1
/*
2
* SHA-1
3
* (C) 1999-2008,2011 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7
8
#include <botan/internal/sha1.h>
9
10
#include <botan/internal/bit_ops.h>
11
#include <botan/internal/loadstor.h>
12
#include <botan/internal/rotate.h>
13
#include <botan/internal/stl_util.h>
14
#include <array>
15
16
#if defined(BOTAN_HAS_CPUID)
17
   #include <botan/internal/cpuid.h>
18
#endif
19
20
namespace Botan {
21
22
namespace SHA1_F {
23
24
namespace {
25
26
/*
27
* SHA-1 F1 Function
28
*/
29
0
inline void F1(uint32_t A, uint32_t& B, uint32_t C, uint32_t D, uint32_t& E, uint32_t msg) {
30
0
   E += choose(B, C, D) + msg + 0x5A827999 + rotl<5>(A);
31
0
   B = rotl<30>(B);
32
0
}
33
34
/*
35
* SHA-1 F2 Function
36
*/
37
0
inline void F2(uint32_t A, uint32_t& B, uint32_t C, uint32_t D, uint32_t& E, uint32_t msg) {
38
0
   E += (B ^ C ^ D) + msg + 0x6ED9EBA1 + rotl<5>(A);
39
0
   B = rotl<30>(B);
40
0
}
41
42
/*
43
* SHA-1 F3 Function
44
*/
45
0
inline void F3(uint32_t A, uint32_t& B, uint32_t C, uint32_t D, uint32_t& E, uint32_t msg) {
46
0
   E += majority(B, C, D) + msg + 0x8F1BBCDC + rotl<5>(A);
47
0
   B = rotl<30>(B);
48
0
}
49
50
/*
51
* SHA-1 F4 Function
52
*/
53
0
inline void F4(uint32_t A, uint32_t& B, uint32_t C, uint32_t D, uint32_t& E, uint32_t msg) {
54
0
   E += (B ^ C ^ D) + msg + 0xCA62C1D6 + rotl<5>(A);
55
0
   B = rotl<30>(B);
56
0
}
57
58
}  // namespace
59
60
}  // namespace SHA1_F
61
62
/*
63
* SHA-1 Compression Function
64
*/
65
0
void SHA_1::compress_n(digest_type& digest, std::span<const uint8_t> input, size_t blocks) {
66
0
   using namespace SHA1_F;
67
68
0
#if defined(BOTAN_HAS_SHA1_X86_SHA_NI)
69
0
   if(CPUID::has(CPUID::Feature::SHA)) {
70
0
      return sha1_compress_x86(digest, input, blocks);
71
0
   }
72
0
#endif
73
74
#if defined(BOTAN_HAS_SHA1_ARMV8)
75
   if(CPUID::has(CPUID::Feature::SHA1)) {
76
      return sha1_armv8_compress_n(digest, input, blocks);
77
   }
78
#endif
79
80
0
#if defined(BOTAN_HAS_SHA1_SIMD_4X32)
81
0
   if(CPUID::has(CPUID::Feature::SIMD_4X32)) {
82
0
      return simd_compress_n(digest, input, blocks);
83
0
   }
84
85
0
#endif
86
87
0
   uint32_t A = digest[0], B = digest[1], C = digest[2], D = digest[3], E = digest[4];
88
0
   std::array<uint32_t, 80> W;
89
0
   auto W_in = std::span{W}.first<block_bytes / sizeof(uint32_t)>();
90
91
0
   BufferSlicer in(input);
92
93
0
   for(size_t i = 0; i != blocks; ++i) {
94
0
      load_be(W_in, in.take<block_bytes>());
95
96
      // clang-format off
97
98
0
      for(size_t j = 16; j != 80; j += 8) {
99
0
         W[j + 0] = rotl<1>(W[j - 3] ^ W[j - 8] ^ W[j - 14] ^ W[j - 16]);
100
0
         W[j + 1] = rotl<1>(W[j - 2] ^ W[j - 7] ^ W[j - 13] ^ W[j - 15]);
101
0
         W[j + 2] = rotl<1>(W[j - 1] ^ W[j - 6] ^ W[j - 12] ^ W[j - 14]);
102
0
         W[j + 3] = rotl<1>(W[j    ] ^ W[j - 5] ^ W[j - 11] ^ W[j - 13]);
103
0
         W[j + 4] = rotl<1>(W[j + 1] ^ W[j - 4] ^ W[j - 10] ^ W[j - 12]);
104
0
         W[j + 5] = rotl<1>(W[j + 2] ^ W[j - 3] ^ W[j -  9] ^ W[j - 11]);
105
0
         W[j + 6] = rotl<1>(W[j + 3] ^ W[j - 2] ^ W[j -  8] ^ W[j - 10]);
106
0
         W[j + 7] = rotl<1>(W[j + 4] ^ W[j - 1] ^ W[j -  7] ^ W[j -  9]);
107
0
      }
108
109
      // clang-format on
110
111
0
      F1(A, B, C, D, E, W[0]);
112
0
      F1(E, A, B, C, D, W[1]);
113
0
      F1(D, E, A, B, C, W[2]);
114
0
      F1(C, D, E, A, B, W[3]);
115
0
      F1(B, C, D, E, A, W[4]);
116
0
      F1(A, B, C, D, E, W[5]);
117
0
      F1(E, A, B, C, D, W[6]);
118
0
      F1(D, E, A, B, C, W[7]);
119
0
      F1(C, D, E, A, B, W[8]);
120
0
      F1(B, C, D, E, A, W[9]);
121
0
      F1(A, B, C, D, E, W[10]);
122
0
      F1(E, A, B, C, D, W[11]);
123
0
      F1(D, E, A, B, C, W[12]);
124
0
      F1(C, D, E, A, B, W[13]);
125
0
      F1(B, C, D, E, A, W[14]);
126
0
      F1(A, B, C, D, E, W[15]);
127
0
      F1(E, A, B, C, D, W[16]);
128
0
      F1(D, E, A, B, C, W[17]);
129
0
      F1(C, D, E, A, B, W[18]);
130
0
      F1(B, C, D, E, A, W[19]);
131
132
0
      F2(A, B, C, D, E, W[20]);
133
0
      F2(E, A, B, C, D, W[21]);
134
0
      F2(D, E, A, B, C, W[22]);
135
0
      F2(C, D, E, A, B, W[23]);
136
0
      F2(B, C, D, E, A, W[24]);
137
0
      F2(A, B, C, D, E, W[25]);
138
0
      F2(E, A, B, C, D, W[26]);
139
0
      F2(D, E, A, B, C, W[27]);
140
0
      F2(C, D, E, A, B, W[28]);
141
0
      F2(B, C, D, E, A, W[29]);
142
0
      F2(A, B, C, D, E, W[30]);
143
0
      F2(E, A, B, C, D, W[31]);
144
0
      F2(D, E, A, B, C, W[32]);
145
0
      F2(C, D, E, A, B, W[33]);
146
0
      F2(B, C, D, E, A, W[34]);
147
0
      F2(A, B, C, D, E, W[35]);
148
0
      F2(E, A, B, C, D, W[36]);
149
0
      F2(D, E, A, B, C, W[37]);
150
0
      F2(C, D, E, A, B, W[38]);
151
0
      F2(B, C, D, E, A, W[39]);
152
153
0
      F3(A, B, C, D, E, W[40]);
154
0
      F3(E, A, B, C, D, W[41]);
155
0
      F3(D, E, A, B, C, W[42]);
156
0
      F3(C, D, E, A, B, W[43]);
157
0
      F3(B, C, D, E, A, W[44]);
158
0
      F3(A, B, C, D, E, W[45]);
159
0
      F3(E, A, B, C, D, W[46]);
160
0
      F3(D, E, A, B, C, W[47]);
161
0
      F3(C, D, E, A, B, W[48]);
162
0
      F3(B, C, D, E, A, W[49]);
163
0
      F3(A, B, C, D, E, W[50]);
164
0
      F3(E, A, B, C, D, W[51]);
165
0
      F3(D, E, A, B, C, W[52]);
166
0
      F3(C, D, E, A, B, W[53]);
167
0
      F3(B, C, D, E, A, W[54]);
168
0
      F3(A, B, C, D, E, W[55]);
169
0
      F3(E, A, B, C, D, W[56]);
170
0
      F3(D, E, A, B, C, W[57]);
171
0
      F3(C, D, E, A, B, W[58]);
172
0
      F3(B, C, D, E, A, W[59]);
173
174
0
      F4(A, B, C, D, E, W[60]);
175
0
      F4(E, A, B, C, D, W[61]);
176
0
      F4(D, E, A, B, C, W[62]);
177
0
      F4(C, D, E, A, B, W[63]);
178
0
      F4(B, C, D, E, A, W[64]);
179
0
      F4(A, B, C, D, E, W[65]);
180
0
      F4(E, A, B, C, D, W[66]);
181
0
      F4(D, E, A, B, C, W[67]);
182
0
      F4(C, D, E, A, B, W[68]);
183
0
      F4(B, C, D, E, A, W[69]);
184
0
      F4(A, B, C, D, E, W[70]);
185
0
      F4(E, A, B, C, D, W[71]);
186
0
      F4(D, E, A, B, C, W[72]);
187
0
      F4(C, D, E, A, B, W[73]);
188
0
      F4(B, C, D, E, A, W[74]);
189
0
      F4(A, B, C, D, E, W[75]);
190
0
      F4(E, A, B, C, D, W[76]);
191
0
      F4(D, E, A, B, C, W[77]);
192
0
      F4(C, D, E, A, B, W[78]);
193
0
      F4(B, C, D, E, A, W[79]);
194
195
0
      A = (digest[0] += A);
196
0
      B = (digest[1] += B);
197
0
      C = (digest[2] += C);
198
0
      D = (digest[3] += D);
199
0
      E = (digest[4] += E);
200
0
   }
201
0
}
202
203
/*
204
* Clear memory of sensitive data
205
*/
206
0
void SHA_1::init(digest_type& digest) {
207
0
   digest.assign({0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0});
208
0
}
209
210
0
std::string SHA_1::provider() const {
211
0
#if defined(BOTAN_HAS_SHA1_X86_SHA_NI)
212
0
   if(auto feat = CPUID::check(CPUID::Feature::SHA)) {
213
0
      return *feat;
214
0
   }
215
0
#endif
216
217
#if defined(BOTAN_HAS_SHA1_ARMV8)
218
   if(auto feat = CPUID::check(CPUID::Feature::SHA1)) {
219
      return *feat;
220
   }
221
#endif
222
223
0
#if defined(BOTAN_HAS_SHA1_SIMD_4X32)
224
0
   if(auto feat = CPUID::check(CPUID::Feature::SIMD_4X32)) {
225
0
      return *feat;
226
0
   }
227
0
#endif
228
229
0
   return "base";
230
0
}
231
232
0
std::unique_ptr<HashFunction> SHA_1::new_object() const {
233
0
   return std::make_unique<SHA_1>();
234
0
}
235
236
0
std::unique_ptr<HashFunction> SHA_1::copy_state() const {
237
0
   return std::make_unique<SHA_1>(*this);
238
0
}
239
240
0
void SHA_1::add_data(std::span<const uint8_t> input) {
241
0
   m_md.update(input);
242
0
}
243
244
0
void SHA_1::final_result(std::span<uint8_t> output) {
245
0
   m_md.final(output);
246
0
}
247
248
}  // namespace Botan