Botan 2.19.1
Crypto and TLS for C&
sha3.cpp
Go to the documentation of this file.
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/sha3.h>
9#include <botan/loadstor.h>
10#include <botan/rotate.h>
11#include <botan/internal/sha3_round.h>
12#include <botan/exceptn.h>
13#include <botan/cpuid.h>
14
15namespace Botan {
16
17void SHA_3::permute(uint64_t A[25])
18 {
19#if defined(BOTAN_HAS_SHA3_BMI2)
20 if(CPUID::has_bmi2())
21 {
22 return permute_bmi2(A);
23 }
24#endif
25
26 static const uint64_t RC[24] = {
27 0x0000000000000001, 0x0000000000008082, 0x800000000000808A,
28 0x8000000080008000, 0x000000000000808B, 0x0000000080000001,
29 0x8000000080008081, 0x8000000000008009, 0x000000000000008A,
30 0x0000000000000088, 0x0000000080008009, 0x000000008000000A,
31 0x000000008000808B, 0x800000000000008B, 0x8000000000008089,
32 0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
33 0x000000000000800A, 0x800000008000000A, 0x8000000080008081,
34 0x8000000000008080, 0x0000000080000001, 0x8000000080008008
35 };
36
37 uint64_t T[25];
38
39 for(size_t i = 0; i != 24; i += 2)
40 {
41 SHA3_round(T, A, RC[i+0]);
42 SHA3_round(A, T, RC[i+1]);
43 }
44 }
45
46//static
47size_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 {
51 while(length > 0)
52 {
53 size_t to_take = std::min(length, bitrate / 8 - S_pos);
54
55 length -= to_take;
56
57 while(to_take && S_pos % 8)
58 {
59 S[S_pos / 8] ^= static_cast<uint64_t>(input[0]) << (8 * (S_pos % 8));
60
61 ++S_pos;
62 ++input;
63 --to_take;
64 }
65
66 while(to_take && to_take % 8 == 0)
67 {
68 S[S_pos / 8] ^= load_le<uint64_t>(input, 0);
69 S_pos += 8;
70 input += 8;
71 to_take -= 8;
72 }
73
74 while(to_take)
75 {
76 S[S_pos / 8] ^= static_cast<uint64_t>(input[0]) << (8 * (S_pos % 8));
77
78 ++S_pos;
79 ++input;
80 --to_take;
81 }
82
83 if(S_pos == bitrate / 8)
84 {
85 SHA_3::permute(S.data());
86 S_pos = 0;
87 }
88 }
89
90 return S_pos;
91 }
92
93//static
94void 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 {
98 BOTAN_ARG_CHECK(bitrate % 64 == 0, "SHA-3 bitrate must be multiple of 64");
99
100 S[S_pos / 8] ^= static_cast<uint64_t>(init_pad) << (8 * (S_pos % 8));
101 S[(bitrate / 64) - 1] ^= static_cast<uint64_t>(fini_pad) << 56;
102 SHA_3::permute(S.data());
103 }
104
105//static
106void SHA_3::expand(size_t bitrate,
108 uint8_t output[], size_t output_length)
109 {
110 BOTAN_ARG_CHECK(bitrate % 64 == 0, "SHA-3 bitrate must be multiple of 64");
111
112 const size_t byterate = bitrate / 8;
113
114 while(output_length > 0)
115 {
116 const size_t copying = std::min(byterate, output_length);
117
118 copy_out_vec_le(output, copying, S);
119
120 output += copying;
121 output_length -= copying;
122
123 if(output_length > 0)
124 {
125 SHA_3::permute(S.data());
126 }
127 }
128 }
129
130SHA_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 {
136 // We only support the parameters for SHA-3 in this constructor
137
138 if(output_bits != 224 && output_bits != 256 &&
139 output_bits != 384 && output_bits != 512)
140 throw Invalid_Argument("SHA_3: Invalid output length " +
141 std::to_string(output_bits));
142 }
143
144std::string SHA_3::name() const
145 {
146 return "SHA-3(" + std::to_string(m_output_bits) + ")";
147 }
148
149std::string SHA_3::provider() const
150 {
151#if defined(BOTAN_HAS_SHA3_BMI2)
152 if(CPUID::has_bmi2())
153 {
154 return "bmi2";
155 }
156#endif
157
158 return "base";
159 }
160
161std::unique_ptr<HashFunction> SHA_3::copy_state() const
162 {
163 return std::unique_ptr<HashFunction>(new SHA_3(*this));
164 }
165
167 {
168 return new SHA_3(m_output_bits);
169 }
170
172 {
173 zeroise(m_S);
174 m_S_pos = 0;
175 }
176
177void SHA_3::add_data(const uint8_t input[], size_t length)
178 {
179 m_S_pos = SHA_3::absorb(m_bitrate, m_S, m_S_pos, input, length);
180 }
181
182void SHA_3::final_result(uint8_t output[])
183 {
184 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 copy_out_vec_le(output, m_output_bits/8, m_S);
191
192 clear();
193 }
194
195}
#define BOTAN_ARG_CHECK(expr, msg)
Definition: assert.h:37
static void permute(uint64_t A[25])
Definition: sha3.cpp:17
void clear() override
Definition: sha3.cpp:171
HashFunction * clone() const override
Definition: sha3.cpp:166
SHA_3(size_t output_bits)
Definition: sha3.cpp:130
static void finish(size_t bitrate, secure_vector< uint64_t > &S, size_t S_pos, uint8_t init_pad, uint8_t fini_pad)
Definition: sha3.cpp:94
std::string provider() const override
Definition: sha3.cpp:149
static size_t absorb(size_t bitrate, secure_vector< uint64_t > &S, size_t S_pos, const uint8_t input[], size_t length)
Definition: sha3.cpp:47
static void expand(size_t bitrate, secure_vector< uint64_t > &S, uint8_t output[], size_t output_length)
Definition: sha3.cpp:106
std::string name() const override
Definition: sha3.cpp:144
size_t output_length() const override
Definition: sha3.h:33
std::unique_ptr< HashFunction > copy_state() const override
Definition: sha3.cpp:161
fe T
Definition: ge.cpp:37
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:213
Definition: alg_id.cpp:13
void zeroise(std::vector< T, Alloc > &vec)
Definition: secmem.h:117
void copy_out_vec_le(uint8_t out[], size_t out_bytes, const std::vector< T, Alloc > &in)
Definition: loadstor.h:694
void SHA3_round(uint64_t T[25], const uint64_t A[25], uint64_t RC)
Definition: sha3_round.h:53
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:65
uint64_t load_le< uint64_t >(const uint8_t in[], size_t off)
Definition: loadstor.h:237