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