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