/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 |