Coverage Report

Created: 2025-12-31 06:16

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/sha1_f.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
/*
23
* SHA-1 Compression Function
24
*/
25
0
void SHA_1::compress_n(digest_type& digest, std::span<const uint8_t> input, size_t blocks) {
26
0
   using namespace SHA1_F;
27
28
0
#if defined(BOTAN_HAS_SHA1_X86_SHA_NI)
29
0
   if(CPUID::has(CPUID::Feature::SHA)) {
30
0
      return sha1_compress_x86(digest, input, blocks);
31
0
   }
32
0
#endif
33
34
#if defined(BOTAN_HAS_SHA1_ARMV8)
35
   if(CPUID::has(CPUID::Feature::SHA1)) {
36
      return sha1_armv8_compress_n(digest, input, blocks);
37
   }
38
#endif
39
40
0
#if defined(BOTAN_HAS_SHA1_AVX2)
41
0
   if(CPUID::has(CPUID::Feature::AVX2, CPUID::Feature::BMI)) {
42
0
      return avx2_compress_n(digest, input, blocks);
43
0
   }
44
0
#endif
45
46
0
#if defined(BOTAN_HAS_SHA1_SIMD_4X32)
47
0
   if(CPUID::has(CPUID::Feature::SIMD_4X32)) {
48
0
      return simd_compress_n(digest, input, blocks);
49
0
   }
50
0
#endif
51
52
0
   uint32_t A = digest[0];
53
0
   uint32_t B = digest[1];
54
0
   uint32_t C = digest[2];
55
0
   uint32_t D = digest[3];
56
0
   uint32_t E = digest[4];
57
0
   std::array<uint32_t, 80> W{};
58
0
   auto W_in = std::span{W}.first<block_bytes / sizeof(uint32_t)>();
59
60
0
   BufferSlicer in(input);
61
62
0
   for(size_t i = 0; i != blocks; ++i) {
63
0
      load_be(W_in, in.take<block_bytes>());
64
65
      // clang-format off
66
67
0
      for(size_t j = 16; j != 80; j += 8) {
68
0
         W[j + 0] = rotl<1>(W[j - 3] ^ W[j - 8] ^ W[j - 14] ^ W[j - 16]);
69
0
         W[j + 1] = rotl<1>(W[j - 2] ^ W[j - 7] ^ W[j - 13] ^ W[j - 15]);
70
0
         W[j + 2] = rotl<1>(W[j - 1] ^ W[j - 6] ^ W[j - 12] ^ W[j - 14]);
71
0
         W[j + 3] = rotl<1>(W[j    ] ^ W[j - 5] ^ W[j - 11] ^ W[j - 13]);
72
0
         W[j + 4] = rotl<1>(W[j + 1] ^ W[j - 4] ^ W[j - 10] ^ W[j - 12]);
73
0
         W[j + 5] = rotl<1>(W[j + 2] ^ W[j - 3] ^ W[j -  9] ^ W[j - 11]);
74
0
         W[j + 6] = rotl<1>(W[j + 3] ^ W[j - 2] ^ W[j -  8] ^ W[j - 10]);
75
0
         W[j + 7] = rotl<1>(W[j + 4] ^ W[j - 1] ^ W[j -  7] ^ W[j -  9]);
76
0
      }
77
78
      // clang-format on
79
80
0
      F1(A, B, C, D, E, W[0] + K1);
81
0
      F1(E, A, B, C, D, W[1] + K1);
82
0
      F1(D, E, A, B, C, W[2] + K1);
83
0
      F1(C, D, E, A, B, W[3] + K1);
84
0
      F1(B, C, D, E, A, W[4] + K1);
85
0
      F1(A, B, C, D, E, W[5] + K1);
86
0
      F1(E, A, B, C, D, W[6] + K1);
87
0
      F1(D, E, A, B, C, W[7] + K1);
88
0
      F1(C, D, E, A, B, W[8] + K1);
89
0
      F1(B, C, D, E, A, W[9] + K1);
90
0
      F1(A, B, C, D, E, W[10] + K1);
91
0
      F1(E, A, B, C, D, W[11] + K1);
92
0
      F1(D, E, A, B, C, W[12] + K1);
93
0
      F1(C, D, E, A, B, W[13] + K1);
94
0
      F1(B, C, D, E, A, W[14] + K1);
95
0
      F1(A, B, C, D, E, W[15] + K1);
96
0
      F1(E, A, B, C, D, W[16] + K1);
97
0
      F1(D, E, A, B, C, W[17] + K1);
98
0
      F1(C, D, E, A, B, W[18] + K1);
99
0
      F1(B, C, D, E, A, W[19] + K1);
100
101
0
      F2(A, B, C, D, E, W[20] + K2);
102
0
      F2(E, A, B, C, D, W[21] + K2);
103
0
      F2(D, E, A, B, C, W[22] + K2);
104
0
      F2(C, D, E, A, B, W[23] + K2);
105
0
      F2(B, C, D, E, A, W[24] + K2);
106
0
      F2(A, B, C, D, E, W[25] + K2);
107
0
      F2(E, A, B, C, D, W[26] + K2);
108
0
      F2(D, E, A, B, C, W[27] + K2);
109
0
      F2(C, D, E, A, B, W[28] + K2);
110
0
      F2(B, C, D, E, A, W[29] + K2);
111
0
      F2(A, B, C, D, E, W[30] + K2);
112
0
      F2(E, A, B, C, D, W[31] + K2);
113
0
      F2(D, E, A, B, C, W[32] + K2);
114
0
      F2(C, D, E, A, B, W[33] + K2);
115
0
      F2(B, C, D, E, A, W[34] + K2);
116
0
      F2(A, B, C, D, E, W[35] + K2);
117
0
      F2(E, A, B, C, D, W[36] + K2);
118
0
      F2(D, E, A, B, C, W[37] + K2);
119
0
      F2(C, D, E, A, B, W[38] + K2);
120
0
      F2(B, C, D, E, A, W[39] + K2);
121
122
0
      F3(A, B, C, D, E, W[40] + K3);
123
0
      F3(E, A, B, C, D, W[41] + K3);
124
0
      F3(D, E, A, B, C, W[42] + K3);
125
0
      F3(C, D, E, A, B, W[43] + K3);
126
0
      F3(B, C, D, E, A, W[44] + K3);
127
0
      F3(A, B, C, D, E, W[45] + K3);
128
0
      F3(E, A, B, C, D, W[46] + K3);
129
0
      F3(D, E, A, B, C, W[47] + K3);
130
0
      F3(C, D, E, A, B, W[48] + K3);
131
0
      F3(B, C, D, E, A, W[49] + K3);
132
0
      F3(A, B, C, D, E, W[50] + K3);
133
0
      F3(E, A, B, C, D, W[51] + K3);
134
0
      F3(D, E, A, B, C, W[52] + K3);
135
0
      F3(C, D, E, A, B, W[53] + K3);
136
0
      F3(B, C, D, E, A, W[54] + K3);
137
0
      F3(A, B, C, D, E, W[55] + K3);
138
0
      F3(E, A, B, C, D, W[56] + K3);
139
0
      F3(D, E, A, B, C, W[57] + K3);
140
0
      F3(C, D, E, A, B, W[58] + K3);
141
0
      F3(B, C, D, E, A, W[59] + K3);
142
143
0
      F4(A, B, C, D, E, W[60] + K4);
144
0
      F4(E, A, B, C, D, W[61] + K4);
145
0
      F4(D, E, A, B, C, W[62] + K4);
146
0
      F4(C, D, E, A, B, W[63] + K4);
147
0
      F4(B, C, D, E, A, W[64] + K4);
148
0
      F4(A, B, C, D, E, W[65] + K4);
149
0
      F4(E, A, B, C, D, W[66] + K4);
150
0
      F4(D, E, A, B, C, W[67] + K4);
151
0
      F4(C, D, E, A, B, W[68] + K4);
152
0
      F4(B, C, D, E, A, W[69] + K4);
153
0
      F4(A, B, C, D, E, W[70] + K4);
154
0
      F4(E, A, B, C, D, W[71] + K4);
155
0
      F4(D, E, A, B, C, W[72] + K4);
156
0
      F4(C, D, E, A, B, W[73] + K4);
157
0
      F4(B, C, D, E, A, W[74] + K4);
158
0
      F4(A, B, C, D, E, W[75] + K4);
159
0
      F4(E, A, B, C, D, W[76] + K4);
160
0
      F4(D, E, A, B, C, W[77] + K4);
161
0
      F4(C, D, E, A, B, W[78] + K4);
162
0
      F4(B, C, D, E, A, W[79] + K4);
163
164
0
      A = (digest[0] += A);
165
0
      B = (digest[1] += B);
166
0
      C = (digest[2] += C);
167
0
      D = (digest[3] += D);
168
0
      E = (digest[4] += E);
169
0
   }
170
0
}
171
172
/*
173
* Clear memory of sensitive data
174
*/
175
0
void SHA_1::init(digest_type& digest) {
176
0
   digest.assign({0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0});
177
0
}
178
179
0
std::string SHA_1::provider() const {
180
0
#if defined(BOTAN_HAS_SHA1_X86_SHA_NI)
181
0
   if(auto feat = CPUID::check(CPUID::Feature::SHA)) {
182
0
      return *feat;
183
0
   }
184
0
#endif
185
186
#if defined(BOTAN_HAS_SHA1_ARMV8)
187
   if(auto feat = CPUID::check(CPUID::Feature::SHA1)) {
188
      return *feat;
189
   }
190
#endif
191
192
0
#if defined(BOTAN_HAS_SHA1_AVX2)
193
0
   if(auto feat = CPUID::check(CPUID::Feature::AVX2, CPUID::Feature::BMI)) {
194
0
      return *feat;
195
0
   }
196
0
#endif
197
198
0
#if defined(BOTAN_HAS_SHA1_SIMD_4X32)
199
0
   if(auto feat = CPUID::check(CPUID::Feature::SIMD_4X32)) {
200
0
      return *feat;
201
0
   }
202
0
#endif
203
204
0
   return "base";
205
0
}
206
207
0
std::unique_ptr<HashFunction> SHA_1::new_object() const {
208
0
   return std::make_unique<SHA_1>();
209
0
}
210
211
0
std::unique_ptr<HashFunction> SHA_1::copy_state() const {
212
0
   return std::make_unique<SHA_1>(*this);
213
0
}
214
215
0
void SHA_1::add_data(std::span<const uint8_t> input) {
216
0
   m_md.update(input);
217
0
}
218
219
0
void SHA_1::final_result(std::span<uint8_t> output) {
220
0
   m_md.final(output);
221
0
}
222
223
}  // namespace Botan