/src/botan/src/lib/hash/sha3/sha3.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * SHA-3 |
3 | | * (C) 2010,2016 Jack Lloyd |
4 | | * |
5 | | * Botan is released under the Simplified BSD License (see license.txt) |
6 | | */ |
7 | | |
8 | | #include <botan/internal/sha3.h> |
9 | | #include <botan/internal/sha3_round.h> |
10 | | #include <botan/internal/loadstor.h> |
11 | | #include <botan/exceptn.h> |
12 | | #include <botan/internal/cpuid.h> |
13 | | |
14 | | namespace Botan { |
15 | | |
16 | | //static |
17 | | void SHA_3::permute(uint64_t A[25]) |
18 | 2.22k | { |
19 | 2.22k | #if defined(BOTAN_HAS_SHA3_BMI2) |
20 | 2.22k | if(CPUID::has_bmi2()) |
21 | 2.22k | { |
22 | 2.22k | return permute_bmi2(A); |
23 | 2.22k | } |
24 | 0 | #endif |
25 | | |
26 | 0 | static const uint64_t RC[24] = { |
27 | 0 | 0x0000000000000001, 0x0000000000008082, 0x800000000000808A, |
28 | 0 | 0x8000000080008000, 0x000000000000808B, 0x0000000080000001, |
29 | 0 | 0x8000000080008081, 0x8000000000008009, 0x000000000000008A, |
30 | 0 | 0x0000000000000088, 0x0000000080008009, 0x000000008000000A, |
31 | 0 | 0x000000008000808B, 0x800000000000008B, 0x8000000000008089, |
32 | 0 | 0x8000000000008003, 0x8000000000008002, 0x8000000000000080, |
33 | 0 | 0x000000000000800A, 0x800000008000000A, 0x8000000080008081, |
34 | 0 | 0x8000000000008080, 0x0000000080000001, 0x8000000080008008 |
35 | 0 | }; |
36 | |
|
37 | 0 | uint64_t T[25]; |
38 | |
|
39 | 0 | for(size_t i = 0; i != 24; i += 2) |
40 | 0 | { |
41 | 0 | SHA3_round(T, A, RC[i+0]); |
42 | 0 | SHA3_round(A, T, RC[i+1]); |
43 | 0 | } |
44 | 0 | } |
45 | | |
46 | | //static |
47 | | size_t SHA_3::absorb(size_t bitrate, |
48 | | secure_vector<uint64_t>& S, size_t S_pos, |
49 | | const uint8_t input[], size_t length) |
50 | 1.32k | { |
51 | 3.71k | while(length > 0) |
52 | 2.38k | { |
53 | 2.38k | size_t to_take = std::min(length, bitrate / 8 - S_pos); |
54 | | |
55 | 2.38k | length -= to_take; |
56 | | |
57 | 2.99k | while(to_take && S_pos % 8) |
58 | 610 | { |
59 | 610 | S[S_pos / 8] ^= static_cast<uint64_t>(input[0]) << (8 * (S_pos % 8)); |
60 | | |
61 | 610 | ++S_pos; |
62 | 610 | ++input; |
63 | 610 | --to_take; |
64 | 610 | } |
65 | | |
66 | 25.6k | while(to_take && to_take % 8 == 0) |
67 | 23.3k | { |
68 | 23.3k | S[S_pos / 8] ^= load_le<uint64_t>(input, 0); |
69 | 23.3k | S_pos += 8; |
70 | 23.3k | input += 8; |
71 | 23.3k | to_take -= 8; |
72 | 23.3k | } |
73 | | |
74 | 11.3k | while(to_take) |
75 | 8.97k | { |
76 | 8.97k | S[S_pos / 8] ^= static_cast<uint64_t>(input[0]) << (8 * (S_pos % 8)); |
77 | | |
78 | 8.97k | ++S_pos; |
79 | 8.97k | ++input; |
80 | 8.97k | --to_take; |
81 | 8.97k | } |
82 | | |
83 | 2.38k | if(S_pos == bitrate / 8) |
84 | 1.90k | { |
85 | 1.90k | SHA_3::permute(S.data()); |
86 | 1.90k | S_pos = 0; |
87 | 1.90k | } |
88 | 2.38k | } |
89 | | |
90 | 1.32k | return S_pos; |
91 | 1.32k | } |
92 | | |
93 | | //static |
94 | | void SHA_3::finish(size_t bitrate, |
95 | | secure_vector<uint64_t>& S, size_t S_pos, |
96 | | uint8_t init_pad, uint8_t fini_pad) |
97 | 323 | { |
98 | 323 | BOTAN_ARG_CHECK(bitrate % 64 == 0, "SHA-3 bitrate must be multiple of 64"); |
99 | | |
100 | 323 | S[S_pos / 8] ^= static_cast<uint64_t>(init_pad) << (8 * (S_pos % 8)); |
101 | 323 | S[(bitrate / 64) - 1] ^= static_cast<uint64_t>(fini_pad) << 56; |
102 | 323 | SHA_3::permute(S.data()); |
103 | 323 | } |
104 | | |
105 | | //static |
106 | | void SHA_3::expand(size_t bitrate, |
107 | | secure_vector<uint64_t>& S, |
108 | | uint8_t output[], size_t output_length) |
109 | 0 | { |
110 | 0 | BOTAN_ARG_CHECK(bitrate % 64 == 0, "SHA-3 bitrate must be multiple of 64"); |
111 | |
|
112 | 0 | const size_t byterate = bitrate / 8; |
113 | |
|
114 | 0 | while(output_length > 0) |
115 | 0 | { |
116 | 0 | const size_t copying = std::min(byterate, output_length); |
117 | |
|
118 | 0 | copy_out_vec_le(output, copying, S); |
119 | |
|
120 | 0 | output += copying; |
121 | 0 | output_length -= copying; |
122 | |
|
123 | 0 | if(output_length > 0) |
124 | 0 | { |
125 | 0 | SHA_3::permute(S.data()); |
126 | 0 | } |
127 | 0 | } |
128 | 0 | } |
129 | | |
130 | | SHA_3::SHA_3(size_t output_bits) : |
131 | | m_output_bits(output_bits), |
132 | | m_bitrate(1600 - 2*output_bits), |
133 | | m_S(25), |
134 | | m_S_pos(0) |
135 | 229 | { |
136 | | // We only support the parameters for SHA-3 in this constructor |
137 | | |
138 | 229 | if(output_bits != 224 && output_bits != 256 && |
139 | 229 | output_bits != 384 && output_bits != 512) |
140 | 0 | throw Invalid_Argument("SHA_3: Invalid output length " + |
141 | 0 | std::to_string(output_bits)); |
142 | 229 | } |
143 | | |
144 | | std::string SHA_3::name() const |
145 | 5 | { |
146 | 5 | return "SHA-3(" + std::to_string(m_output_bits) + ")"; |
147 | 5 | } |
148 | | |
149 | | std::string SHA_3::provider() const |
150 | 0 | { |
151 | 0 | #if defined(BOTAN_HAS_SHA3_BMI2) |
152 | 0 | if(CPUID::has_bmi2()) |
153 | 0 | { |
154 | 0 | return "bmi2"; |
155 | 0 | } |
156 | 0 | #endif |
157 | | |
158 | 0 | return "base"; |
159 | 0 | } |
160 | | |
161 | | std::unique_ptr<HashFunction> SHA_3::copy_state() const |
162 | 0 | { |
163 | 0 | return std::make_unique<SHA_3>(*this); |
164 | 0 | } |
165 | | |
166 | | std::unique_ptr<HashFunction> SHA_3::new_object() const |
167 | 0 | { |
168 | 0 | return std::make_unique<SHA_3>(m_output_bits); |
169 | 0 | } |
170 | | |
171 | | void SHA_3::clear() |
172 | 401 | { |
173 | 401 | zeroise(m_S); |
174 | 401 | m_S_pos = 0; |
175 | 401 | } |
176 | | |
177 | | void SHA_3::add_data(const uint8_t input[], size_t length) |
178 | 1.32k | { |
179 | 1.32k | m_S_pos = SHA_3::absorb(m_bitrate, m_S, m_S_pos, input, length); |
180 | 1.32k | } |
181 | | |
182 | | void SHA_3::final_result(uint8_t output[]) |
183 | 323 | { |
184 | 323 | SHA_3::finish(m_bitrate, m_S, m_S_pos, 0x06, 0x80); |
185 | | |
186 | | /* |
187 | | * We never have to run the permutation again because we only support |
188 | | * limited output lengths |
189 | | */ |
190 | 323 | copy_out_vec_le(output, m_output_bits/8, m_S); |
191 | | |
192 | 323 | clear(); |
193 | 323 | } |
194 | | |
195 | | } |