Crypto++ 8.7
Free C++ class library of cryptographic schemes
lsh256.cpp
1// lsh.cpp - written and placed in the public domain by Jeffrey Walton
2// Based on the specification and source code provided by
3// Korea Internet & Security Agency (KISA) website. Also
4// see https://seed.kisa.or.kr/kisa/algorithm/EgovLSHInfo.do
5// and https://seed.kisa.or.kr/kisa/Board/22/detailView.do.
6
7// We are hitting some sort of GCC bug in the LSH AVX2 code path.
8// Clang is OK on the AVX2 code path. We believe it is GCC Issue
9// 82735, https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82735. It
10// makes using zeroupper a little tricky.
11
12#include "pch.h"
13#include "config.h"
14
15#include "lsh.h"
16#include "cpu.h"
17#include "misc.h"
18
19ANONYMOUS_NAMESPACE_BEGIN
20
21/* LSH Constants */
22
23const unsigned int LSH256_MSG_BLK_BYTE_LEN = 128;
24// const unsigned int LSH256_MSG_BLK_BIT_LEN = 1024;
25// const unsigned int LSH256_CV_BYTE_LEN = 64;
26const unsigned int LSH256_HASH_VAL_MAX_BYTE_LEN = 32;
27
28// const unsigned int MSG_BLK_WORD_LEN = 32;
29const unsigned int CV_WORD_LEN = 16;
30const unsigned int CONST_WORD_LEN = 8;
31const unsigned int HASH_VAL_MAX_WORD_LEN = 8;
32// const unsigned int WORD_BIT_LEN = 32;
33const unsigned int NUM_STEPS = 26;
34
35const unsigned int ROT_EVEN_ALPHA = 29;
36const unsigned int ROT_EVEN_BETA = 1;
37const unsigned int ROT_ODD_ALPHA = 5;
38const unsigned int ROT_ODD_BETA = 17;
39
40const unsigned int LSH_TYPE_256_256 = 0x0000020;
41const unsigned int LSH_TYPE_256_224 = 0x000001C;
42
43// const unsigned int LSH_TYPE_224 = LSH_TYPE_256_224;
44// const unsigned int LSH_TYPE_256 = LSH_TYPE_256_256;
45
46/* Error Code */
47
48const unsigned int LSH_SUCCESS = 0x0;
49// const unsigned int LSH_ERR_NULL_PTR = 0x2401;
50// const unsigned int LSH_ERR_INVALID_ALGTYPE = 0x2402;
51const unsigned int LSH_ERR_INVALID_DATABITLEN = 0x2403;
52const unsigned int LSH_ERR_INVALID_STATE = 0x2404;
53
54/* Index into our state array */
55
56const unsigned int AlgorithmType = 80;
57const unsigned int RemainingBits = 81;
58
59NAMESPACE_END
60
61NAMESPACE_BEGIN(CryptoPP)
62NAMESPACE_BEGIN(LSH)
63
64/* -------------------------------------------------------- *
65* LSH: iv
66* -------------------------------------------------------- */
67
68//extern const word32 LSH256_IV224[CV_WORD_LEN];
69//extern const word32 LSH256_IV256[CV_WORD_LEN];
70//extern const word32 LSH256_StepConstants[CONST_WORD_LEN * NUM_STEPS];
71
72CRYPTOPP_ALIGN_DATA(32)
73extern
74const word32 LSH256_IV224[CV_WORD_LEN] = {
75 0x068608D3, 0x62D8F7A7, 0xD76652AB, 0x4C600A43, 0xBDC40AA8, 0x1ECA0B68, 0xDA1A89BE, 0x3147D354,
76 0x707EB4F9, 0xF65B3862, 0x6B0B2ABE, 0x56B8EC0A, 0xCF237286, 0xEE0D1727, 0x33636595, 0x8BB8D05F
77};
78
79CRYPTOPP_ALIGN_DATA(32)
80extern
81const word32 LSH256_IV256[CV_WORD_LEN] = {
82 0x46a10f1f, 0xfddce486, 0xb41443a8, 0x198e6b9d, 0x3304388d, 0xb0f5a3c7, 0xb36061c4, 0x7adbd553,
83 0x105d5378, 0x2f74de54, 0x5c2f2d95, 0xf2553fbe, 0x8051357a, 0x138668c8, 0x47aa4484, 0xe01afb41
84};
85
86/* -------------------------------------------------------- *
87* LSH: step constants
88* -------------------------------------------------------- */
89
90extern
91const word32 LSH256_StepConstants[CONST_WORD_LEN * NUM_STEPS] = {
92 0x917caf90, 0x6c1b10a2, 0x6f352943, 0xcf778243, 0x2ceb7472, 0x29e96ff2, 0x8a9ba428, 0x2eeb2642,
93 0x0e2c4021, 0x872bb30e, 0xa45e6cb2, 0x46f9c612, 0x185fe69e, 0x1359621b, 0x263fccb2, 0x1a116870,
94 0x3a6c612f, 0xb2dec195, 0x02cb1f56, 0x40bfd858, 0x784684b6, 0x6cbb7d2e, 0x660c7ed8, 0x2b79d88a,
95 0xa6cd9069, 0x91a05747, 0xcdea7558, 0x00983098, 0xbecb3b2e, 0x2838ab9a, 0x728b573e, 0xa55262b5,
96 0x745dfa0f, 0x31f79ed8, 0xb85fce25, 0x98c8c898, 0x8a0669ec, 0x60e445c2, 0xfde295b0, 0xf7b5185a,
97 0xd2580983, 0x29967709, 0x182df3dd, 0x61916130, 0x90705676, 0x452a0822, 0xe07846ad, 0xaccd7351,
98 0x2a618d55, 0xc00d8032, 0x4621d0f5, 0xf2f29191, 0x00c6cd06, 0x6f322a67, 0x58bef48d, 0x7a40c4fd,
99 0x8beee27f, 0xcd8db2f2, 0x67f2c63b, 0xe5842383, 0xc793d306, 0xa15c91d6, 0x17b381e5, 0xbb05c277,
100 0x7ad1620a, 0x5b40a5bf, 0x5ab901a2, 0x69a7a768, 0x5b66d9cd, 0xfdee6877, 0xcb3566fc, 0xc0c83a32,
101 0x4c336c84, 0x9be6651a, 0x13baa3fc, 0x114f0fd1, 0xc240a728, 0xec56e074, 0x009c63c7, 0x89026cf2,
102 0x7f9ff0d0, 0x824b7fb5, 0xce5ea00f, 0x605ee0e2, 0x02e7cfea, 0x43375560, 0x9d002ac7, 0x8b6f5f7b,
103 0x1f90c14f, 0xcdcb3537, 0x2cfeafdd, 0xbf3fc342, 0xeab7b9ec, 0x7a8cb5a3, 0x9d2af264, 0xfacedb06,
104 0xb052106e, 0x99006d04, 0x2bae8d09, 0xff030601, 0xa271a6d6, 0x0742591d, 0xc81d5701, 0xc9a9e200,
105 0x02627f1e, 0x996d719d, 0xda3b9634, 0x02090800, 0x14187d78, 0x499b7624, 0xe57458c9, 0x738be2c9,
106 0x64e19d20, 0x06df0f36, 0x15d1cb0e, 0x0b110802, 0x2c95f58c, 0xe5119a6d, 0x59cd22ae, 0xff6eac3c,
107 0x467ebd84, 0xe5ee453c, 0xe79cd923, 0x1c190a0d, 0xc28b81b8, 0xf6ac0852, 0x26efd107, 0x6e1ae93b,
108 0xc53c41ca, 0xd4338221, 0x8475fd0a, 0x35231729, 0x4e0d3a7a, 0xa2b45b48, 0x16c0d82d, 0x890424a9,
109 0x017e0c8f, 0x07b5a3f5, 0xfa73078e, 0x583a405e, 0x5b47b4c8, 0x570fa3ea, 0xd7990543, 0x8d28ce32,
110 0x7f8a9b90, 0xbd5998fc, 0x6d7a9688, 0x927a9eb6, 0xa2fc7d23, 0x66b38e41, 0x709e491a, 0xb5f700bf,
111 0x0a262c0f, 0x16f295b9, 0xe8111ef5, 0x0d195548, 0x9f79a0c5, 0x1a41cfa7, 0x0ee7638a, 0xacf7c074,
112 0x30523b19, 0x09884ecf, 0xf93014dd, 0x266e9d55, 0x191a6664, 0x5c1176c1, 0xf64aed98, 0xa4b83520,
113 0x828d5449, 0x91d71dd8, 0x2944f2d6, 0x950bf27b, 0x3380ca7d, 0x6d88381d, 0x4138868e, 0x5ced55c4,
114 0x0fe19dcb, 0x68f4f669, 0x6e37c8ff, 0xa0fe6e10, 0xb44b47b0, 0xf5c0558a, 0x79bf14cf, 0x4a431a20,
115 0xf17f68da, 0x5deb5fd1, 0xa600c86d, 0x9f6c7eb0, 0xff92f864, 0xb615e07f, 0x38d3e448, 0x8d5d3a6a,
116 0x70e843cb, 0x494b312e, 0xa6c93613, 0x0beb2f4f, 0x928b5d63, 0xcbf66035, 0x0cb82c80, 0xea97a4f7,
117 0x592c0f3b, 0x947c5f77, 0x6fff49b9, 0xf71a7e5a, 0x1de8c0f5, 0xc2569600, 0xc4e4ac8c, 0x823c9ce1
118};
119
120NAMESPACE_END // LSH
121NAMESPACE_END // Crypto++
122
123ANONYMOUS_NAMESPACE_BEGIN
124
125using CryptoPP::byte;
126using CryptoPP::word32;
129
130using CryptoPP::GetBlock;
134
135using CryptoPP::LSH::LSH256_IV224;
136using CryptoPP::LSH::LSH256_IV256;
137using CryptoPP::LSH::LSH256_StepConstants;
138
139typedef byte lsh_u8;
140typedef word32 lsh_u32;
141typedef word32 lsh_uint;
142typedef word32 lsh_err;
143typedef word32 lsh_type;
144
145struct LSH256_Context
146{
147 LSH256_Context(word32* state, word32 algType, word32& remainingBitLength) :
148 cv_l(state+0), cv_r(state+8), sub_msgs(state+16),
149 last_block(reinterpret_cast<byte*>(state+48)),
150 remain_databitlen(remainingBitLength),
151 alg_type(static_cast<lsh_type>(algType)) {}
152
153 lsh_u32* cv_l; // start of our state block
154 lsh_u32* cv_r;
155 lsh_u32* sub_msgs;
156 lsh_u8* last_block;
157 lsh_u32& remain_databitlen;
158 lsh_type alg_type;
159};
160
161struct LSH256_Internal
162{
163 LSH256_Internal(word32* state) :
164 submsg_e_l(state+16), submsg_e_r(state+24),
165 submsg_o_l(state+32), submsg_o_r(state+40) { }
166
167 lsh_u32* submsg_e_l; /* even left sub-message */
168 lsh_u32* submsg_e_r; /* even right sub-message */
169 lsh_u32* submsg_o_l; /* odd left sub-message */
170 lsh_u32* submsg_o_r; /* odd right sub-message */
171};
172
173const word32 g_gamma256[8] = { 0, 8, 16, 24, 24, 16, 8, 0 };
174
175/* LSH AlgType Macro */
176
177inline bool LSH_IS_LSH512(lsh_uint val) {
178 return (val & 0xf0000) == 0;
179}
180
181inline lsh_uint LSH_GET_SMALL_HASHBIT(lsh_uint val) {
182 return val >> 24;
183}
184
185inline lsh_uint LSH_GET_HASHBYTE(lsh_uint val) {
186 return val & 0xffff;
187}
188
189inline lsh_uint LSH_GET_HASHBIT(lsh_uint val) {
190 return (LSH_GET_HASHBYTE(val) << 3) - LSH_GET_SMALL_HASHBIT(val);
191}
192
193inline lsh_u32 loadLE32(lsh_u32 v) {
195}
196
197lsh_u32 ROTL(lsh_u32 x, lsh_u32 r) {
198 return rotlFixed(x, r);
199}
200
201// Original code relied upon unaligned lsh_u32 buffer
202inline void load_msg_blk(LSH256_Internal* i_state, const lsh_u8 msgblk[LSH256_MSG_BLK_BYTE_LEN])
203{
204 CRYPTOPP_ASSERT(i_state != NULLPTR);
205
206 lsh_u32* submsg_e_l = i_state->submsg_e_l;
207 lsh_u32* submsg_e_r = i_state->submsg_e_r;
208 lsh_u32* submsg_o_l = i_state->submsg_o_l;
209 lsh_u32* submsg_o_r = i_state->submsg_o_r;
210
212
213 InBlock input(msgblk);
214 input(submsg_e_l[0])(submsg_e_l[1])(submsg_e_l[2])(submsg_e_l[3])
215 (submsg_e_l[4])(submsg_e_l[5])(submsg_e_l[6])(submsg_e_l[7])
216 (submsg_e_r[0])(submsg_e_r[1])(submsg_e_r[2])(submsg_e_r[3])
217 (submsg_e_r[4])(submsg_e_r[5])(submsg_e_r[6])(submsg_e_r[7])
218 (submsg_o_l[0])(submsg_o_l[1])(submsg_o_l[2])(submsg_o_l[3])
219 (submsg_o_l[4])(submsg_o_l[5])(submsg_o_l[6])(submsg_o_l[7])
220 (submsg_o_r[0])(submsg_o_r[1])(submsg_o_r[2])(submsg_o_r[3])
221 (submsg_o_r[4])(submsg_o_r[5])(submsg_o_r[6])(submsg_o_r[7]);
222}
223
224inline void msg_exp_even(LSH256_Internal* i_state)
225{
226 CRYPTOPP_ASSERT(i_state != NULLPTR);
227
228 lsh_u32* submsg_e_l = i_state->submsg_e_l;
229 lsh_u32* submsg_e_r = i_state->submsg_e_r;
230 lsh_u32* submsg_o_l = i_state->submsg_o_l;
231 lsh_u32* submsg_o_r = i_state->submsg_o_r;
232
233 lsh_u32 temp;
234 temp = submsg_e_l[0];
235 submsg_e_l[0] = submsg_o_l[0] + submsg_e_l[3];
236 submsg_e_l[3] = submsg_o_l[3] + submsg_e_l[1];
237 submsg_e_l[1] = submsg_o_l[1] + submsg_e_l[2];
238 submsg_e_l[2] = submsg_o_l[2] + temp;
239 temp = submsg_e_l[4];
240 submsg_e_l[4] = submsg_o_l[4] + submsg_e_l[7];
241 submsg_e_l[7] = submsg_o_l[7] + submsg_e_l[6];
242 submsg_e_l[6] = submsg_o_l[6] + submsg_e_l[5];
243 submsg_e_l[5] = submsg_o_l[5] + temp;
244 temp = submsg_e_r[0];
245 submsg_e_r[0] = submsg_o_r[0] + submsg_e_r[3];
246 submsg_e_r[3] = submsg_o_r[3] + submsg_e_r[1];
247 submsg_e_r[1] = submsg_o_r[1] + submsg_e_r[2];
248 submsg_e_r[2] = submsg_o_r[2] + temp;
249 temp = submsg_e_r[4];
250 submsg_e_r[4] = submsg_o_r[4] + submsg_e_r[7];
251 submsg_e_r[7] = submsg_o_r[7] + submsg_e_r[6];
252 submsg_e_r[6] = submsg_o_r[6] + submsg_e_r[5];
253 submsg_e_r[5] = submsg_o_r[5] + temp;
254}
255
256inline void msg_exp_odd(LSH256_Internal* i_state)
257{
258 CRYPTOPP_ASSERT(i_state != NULLPTR);
259
260 lsh_u32* submsg_e_l = i_state->submsg_e_l;
261 lsh_u32* submsg_e_r = i_state->submsg_e_r;
262 lsh_u32* submsg_o_l = i_state->submsg_o_l;
263 lsh_u32* submsg_o_r = i_state->submsg_o_r;
264
265 lsh_u32 temp;
266 temp = submsg_o_l[0];
267 submsg_o_l[0] = submsg_e_l[0] + submsg_o_l[3];
268 submsg_o_l[3] = submsg_e_l[3] + submsg_o_l[1];
269 submsg_o_l[1] = submsg_e_l[1] + submsg_o_l[2];
270 submsg_o_l[2] = submsg_e_l[2] + temp;
271 temp = submsg_o_l[4];
272 submsg_o_l[4] = submsg_e_l[4] + submsg_o_l[7];
273 submsg_o_l[7] = submsg_e_l[7] + submsg_o_l[6];
274 submsg_o_l[6] = submsg_e_l[6] + submsg_o_l[5];
275 submsg_o_l[5] = submsg_e_l[5] + temp;
276 temp = submsg_o_r[0];
277 submsg_o_r[0] = submsg_e_r[0] + submsg_o_r[3];
278 submsg_o_r[3] = submsg_e_r[3] + submsg_o_r[1];
279 submsg_o_r[1] = submsg_e_r[1] + submsg_o_r[2];
280 submsg_o_r[2] = submsg_e_r[2] + temp;
281 temp = submsg_o_r[4];
282 submsg_o_r[4] = submsg_e_r[4] + submsg_o_r[7];
283 submsg_o_r[7] = submsg_e_r[7] + submsg_o_r[6];
284 submsg_o_r[6] = submsg_e_r[6] + submsg_o_r[5];
285 submsg_o_r[5] = submsg_e_r[5] + temp;
286}
287
288inline void load_sc(const lsh_u32** p_const_v, size_t i)
289{
290 CRYPTOPP_ASSERT(p_const_v != NULLPTR);
291
292 *p_const_v = &LSH256_StepConstants[i];
293}
294
295inline void msg_add_even(lsh_u32 cv_l[8], lsh_u32 cv_r[8], LSH256_Internal* i_state)
296{
297 CRYPTOPP_ASSERT(i_state != NULLPTR);
298
299 lsh_u32* submsg_e_l = i_state->submsg_e_l;
300 lsh_u32* submsg_e_r = i_state->submsg_e_r;
301
302 cv_l[0] ^= submsg_e_l[0]; cv_l[1] ^= submsg_e_l[1];
303 cv_l[2] ^= submsg_e_l[2]; cv_l[3] ^= submsg_e_l[3];
304 cv_l[4] ^= submsg_e_l[4]; cv_l[5] ^= submsg_e_l[5];
305 cv_l[6] ^= submsg_e_l[6]; cv_l[7] ^= submsg_e_l[7];
306 cv_r[0] ^= submsg_e_r[0]; cv_r[1] ^= submsg_e_r[1];
307 cv_r[2] ^= submsg_e_r[2]; cv_r[3] ^= submsg_e_r[3];
308 cv_r[4] ^= submsg_e_r[4]; cv_r[5] ^= submsg_e_r[5];
309 cv_r[6] ^= submsg_e_r[6]; cv_r[7] ^= submsg_e_r[7];
310}
311
312inline void msg_add_odd(lsh_u32 cv_l[8], lsh_u32 cv_r[8], LSH256_Internal* i_state)
313{
314 CRYPTOPP_ASSERT(i_state != NULLPTR);
315
316 lsh_u32* submsg_o_l = i_state->submsg_o_l;
317 lsh_u32* submsg_o_r = i_state->submsg_o_r;
318
319 cv_l[0] ^= submsg_o_l[0]; cv_l[1] ^= submsg_o_l[1];
320 cv_l[2] ^= submsg_o_l[2]; cv_l[3] ^= submsg_o_l[3];
321 cv_l[4] ^= submsg_o_l[4]; cv_l[5] ^= submsg_o_l[5];
322 cv_l[6] ^= submsg_o_l[6]; cv_l[7] ^= submsg_o_l[7];
323 cv_r[0] ^= submsg_o_r[0]; cv_r[1] ^= submsg_o_r[1];
324 cv_r[2] ^= submsg_o_r[2]; cv_r[3] ^= submsg_o_r[3];
325 cv_r[4] ^= submsg_o_r[4]; cv_r[5] ^= submsg_o_r[5];
326 cv_r[6] ^= submsg_o_r[6]; cv_r[7] ^= submsg_o_r[7];
327}
328
329inline void add_blk(lsh_u32 cv_l[8], lsh_u32 cv_r[8])
330{
331 cv_l[0] += cv_r[0];
332 cv_l[1] += cv_r[1];
333 cv_l[2] += cv_r[2];
334 cv_l[3] += cv_r[3];
335 cv_l[4] += cv_r[4];
336 cv_l[5] += cv_r[5];
337 cv_l[6] += cv_r[6];
338 cv_l[7] += cv_r[7];
339}
340
341template <unsigned int R>
342inline void rotate_blk(lsh_u32 cv[8])
343{
344 cv[0] = rotlConstant<R>(cv[0]);
345 cv[1] = rotlConstant<R>(cv[1]);
346 cv[2] = rotlConstant<R>(cv[2]);
347 cv[3] = rotlConstant<R>(cv[3]);
348 cv[4] = rotlConstant<R>(cv[4]);
349 cv[5] = rotlConstant<R>(cv[5]);
350 cv[6] = rotlConstant<R>(cv[6]);
351 cv[7] = rotlConstant<R>(cv[7]);
352}
353
354inline void xor_with_const(lsh_u32 cv_l[8], const lsh_u32 const_v[8])
355{
356 cv_l[0] ^= const_v[0];
357 cv_l[1] ^= const_v[1];
358 cv_l[2] ^= const_v[2];
359 cv_l[3] ^= const_v[3];
360 cv_l[4] ^= const_v[4];
361 cv_l[5] ^= const_v[5];
362 cv_l[6] ^= const_v[6];
363 cv_l[7] ^= const_v[7];
364}
365
366inline void rotate_msg_gamma(lsh_u32 cv_r[8])
367{
368 cv_r[1] = rotlFixed(cv_r[1], g_gamma256[1]);
369 cv_r[2] = rotlFixed(cv_r[2], g_gamma256[2]);
370 cv_r[3] = rotlFixed(cv_r[3], g_gamma256[3]);
371 cv_r[4] = rotlFixed(cv_r[4], g_gamma256[4]);
372 cv_r[5] = rotlFixed(cv_r[5], g_gamma256[5]);
373 cv_r[6] = rotlFixed(cv_r[6], g_gamma256[6]);
374}
375
376inline void word_perm(lsh_u32 cv_l[8], lsh_u32 cv_r[8])
377{
378 lsh_u32 temp;
379 temp = cv_l[0];
380 cv_l[0] = cv_l[6];
381 cv_l[6] = cv_r[6];
382 cv_r[6] = cv_r[2];
383 cv_r[2] = cv_l[1];
384 cv_l[1] = cv_l[4];
385 cv_l[4] = cv_r[4];
386 cv_r[4] = cv_r[0];
387 cv_r[0] = cv_l[2];
388 cv_l[2] = cv_l[5];
389 cv_l[5] = cv_r[7];
390 cv_r[7] = cv_r[1];
391 cv_r[1] = temp;
392 temp = cv_l[3];
393 cv_l[3] = cv_l[7];
394 cv_l[7] = cv_r[5];
395 cv_r[5] = cv_r[3];
396 cv_r[3] = temp;
397};
398
399/* -------------------------------------------------------- *
400* step function
401* -------------------------------------------------------- */
402
403template <unsigned int Alpha, unsigned int Beta>
404inline void mix(lsh_u32 cv_l[8], lsh_u32 cv_r[8], const lsh_u32 const_v[8])
405{
406 add_blk(cv_l, cv_r);
407 rotate_blk<Alpha>(cv_l);
408 xor_with_const(cv_l, const_v);
409 add_blk(cv_r, cv_l);
410 rotate_blk<Beta>(cv_r);
411 add_blk(cv_l, cv_r);
412 rotate_msg_gamma(cv_r);
413}
414
415/* -------------------------------------------------------- *
416* compression function
417* -------------------------------------------------------- */
418
419inline void compress(LSH256_Context* ctx, const lsh_u8 pdMsgBlk[LSH256_MSG_BLK_BYTE_LEN])
420{
421 CRYPTOPP_ASSERT(ctx != NULLPTR);
422
423 LSH256_Internal s_state(ctx->cv_l);
424 LSH256_Internal* i_state = &s_state;
425
426 const lsh_u32* const_v = NULL;
427 lsh_u32* cv_l = ctx->cv_l;
428 lsh_u32* cv_r = ctx->cv_r;
429
430 load_msg_blk(i_state, pdMsgBlk);
431
432 msg_add_even(cv_l, cv_r, i_state);
433 load_sc(&const_v, 0);
434 mix<ROT_EVEN_ALPHA, ROT_EVEN_BETA>(cv_l, cv_r, const_v);
435 word_perm(cv_l, cv_r);
436
437 msg_add_odd(cv_l, cv_r, i_state);
438 load_sc(&const_v, 8);
439 mix<ROT_ODD_ALPHA, ROT_ODD_BETA>(cv_l, cv_r, const_v);
440 word_perm(cv_l, cv_r);
441
442 for (size_t i = 1; i < NUM_STEPS / 2; i++)
443 {
444 msg_exp_even(i_state);
445 msg_add_even(cv_l, cv_r, i_state);
446 load_sc(&const_v, 16 * i);
447 mix<ROT_EVEN_ALPHA, ROT_EVEN_BETA>(cv_l, cv_r, const_v);
448 word_perm(cv_l, cv_r);
449
450 msg_exp_odd(i_state);
451 msg_add_odd(cv_l, cv_r, i_state);
452 load_sc(&const_v, 16 * i + 8);
453 mix<ROT_ODD_ALPHA, ROT_ODD_BETA>(cv_l, cv_r, const_v);
454 word_perm(cv_l, cv_r);
455 }
456
457 msg_exp_even(i_state);
458 msg_add_even(cv_l, cv_r, i_state);
459}
460
461/* -------------------------------------------------------- */
462
463inline void load_iv(lsh_u32 cv_l[8], lsh_u32 cv_r[8], const lsh_u32 iv[16])
464{
465 cv_l[0] = iv[0];
466 cv_l[1] = iv[1];
467 cv_l[2] = iv[2];
468 cv_l[3] = iv[3];
469 cv_l[4] = iv[4];
470 cv_l[5] = iv[5];
471 cv_l[6] = iv[6];
472 cv_l[7] = iv[7];
473 cv_r[0] = iv[8];
474 cv_r[1] = iv[9];
475 cv_r[2] = iv[10];
476 cv_r[3] = iv[11];
477 cv_r[4] = iv[12];
478 cv_r[5] = iv[13];
479 cv_r[6] = iv[14];
480 cv_r[7] = iv[15];
481}
482
483inline void zero_iv(lsh_u32 cv_l[8], lsh_u32 cv_r[8])
484{
485 memset(cv_l, 0x00, 8*sizeof(lsh_u32));
486 memset(cv_r, 0x00, 8*sizeof(lsh_u32));
487}
488
489inline void zero_submsgs(LSH256_Context* ctx)
490{
491 CRYPTOPP_ASSERT(ctx != NULLPTR);
492
493 lsh_u32* sub_msgs = ctx->sub_msgs;
494 memset(sub_msgs, 0x00, 32*sizeof(lsh_u32));
495}
496
497inline void init224(LSH256_Context* ctx)
498{
499 CRYPTOPP_ASSERT(ctx != NULLPTR);
500
501 zero_submsgs(ctx);
502 load_iv(ctx->cv_l, ctx->cv_r, LSH256_IV224);
503}
504
505inline void init256(LSH256_Context* ctx)
506{
507 CRYPTOPP_ASSERT(ctx != NULLPTR);
508
509 zero_submsgs(ctx);
510 load_iv(ctx->cv_l, ctx->cv_r, LSH256_IV256);
511}
512
513/* -------------------------------------------------------- */
514
515inline void fin(LSH256_Context* ctx)
516{
517 CRYPTOPP_ASSERT(ctx != NULLPTR);
518
519 for (size_t i = 0; i < HASH_VAL_MAX_WORD_LEN; i++){
520 ctx->cv_l[i] = loadLE32(ctx->cv_l[i] ^ ctx->cv_r[i]);
521 }
522}
523
524/* -------------------------------------------------------- */
525
526inline void get_hash(LSH256_Context* ctx, lsh_u8* pbHashVal)
527{
528 CRYPTOPP_ASSERT(ctx != NULLPTR);
529 CRYPTOPP_ASSERT(ctx->alg_type != 0);
530 CRYPTOPP_ASSERT(pbHashVal != NULLPTR);
531
532 lsh_uint alg_type = ctx->alg_type;
533 lsh_uint hash_val_byte_len = LSH_GET_HASHBYTE(alg_type);
534 lsh_uint hash_val_bit_len = LSH_GET_SMALL_HASHBIT(alg_type);
535
536 // Multiplying by looks odd...
537 memcpy(pbHashVal, ctx->cv_l, hash_val_byte_len);
538 if (hash_val_bit_len){
539 pbHashVal[hash_val_byte_len-1] &= (((lsh_u8)0xff) << hash_val_bit_len);
540 }
541}
542
543/* -------------------------------------------------------- */
544
545lsh_err lsh256_init(LSH256_Context* ctx)
546{
547 CRYPTOPP_ASSERT(ctx != NULLPTR);
548 CRYPTOPP_ASSERT(ctx->alg_type != 0);
549
550 lsh_u32 alg_type = ctx->alg_type;
551 const lsh_u32* const_v = NULL;
552 ctx->remain_databitlen = 0;
553
554 switch (alg_type)
555 {
556 case LSH_TYPE_256_256:
557 init256(ctx);
558 return LSH_SUCCESS;
559 case LSH_TYPE_256_224:
560 init224(ctx);
561 return LSH_SUCCESS;
562 default:
563 break;
564 }
565
566 lsh_u32* cv_l = ctx->cv_l;
567 lsh_u32* cv_r = ctx->cv_r;
568
569 zero_iv(cv_l, cv_r);
570 cv_l[0] = LSH256_HASH_VAL_MAX_BYTE_LEN;
571 cv_l[1] = LSH_GET_HASHBIT(alg_type);
572
573 for (size_t i = 0; i < NUM_STEPS / 2; i++)
574 {
575 //Mix
576 load_sc(&const_v, i * 16);
577 mix<ROT_EVEN_ALPHA, ROT_EVEN_BETA>(cv_l, cv_r, const_v);
578 word_perm(cv_l, cv_r);
579
580 load_sc(&const_v, i * 16 + 8);
581 mix<ROT_ODD_ALPHA, ROT_ODD_BETA>(cv_l, cv_r, const_v);
582 word_perm(cv_l, cv_r);
583 }
584
585 return LSH_SUCCESS;
586}
587
588lsh_err lsh256_update(LSH256_Context* ctx, const lsh_u8* data, size_t databitlen)
589{
590 CRYPTOPP_ASSERT(ctx != NULLPTR);
591 CRYPTOPP_ASSERT(data != NULLPTR);
592 CRYPTOPP_ASSERT(databitlen % 8 == 0);
593 CRYPTOPP_ASSERT(ctx->alg_type != 0);
594
595 if (databitlen == 0){
596 return LSH_SUCCESS;
597 }
598
599 // We are byte oriented. tail bits will always be 0.
600 size_t databytelen = databitlen >> 3;
601 // lsh_uint pos2 = databitlen & 0x7;
602 const size_t pos2 = 0;
603
604 size_t remain_msg_byte = ctx->remain_databitlen >> 3;
605 // lsh_uint remain_msg_bit = ctx->remain_databitlen & 7;
606 const size_t remain_msg_bit = 0;
607
608 if (remain_msg_byte >= LSH256_MSG_BLK_BYTE_LEN){
609 return LSH_ERR_INVALID_STATE;
610 }
611 if (remain_msg_bit > 0){
612 return LSH_ERR_INVALID_DATABITLEN;
613 }
614
615 if (databytelen + remain_msg_byte < LSH256_MSG_BLK_BYTE_LEN)
616 {
617 memcpy(ctx->last_block + remain_msg_byte, data, databytelen);
618 ctx->remain_databitlen += (lsh_uint)databitlen;
619 remain_msg_byte += (lsh_uint)databytelen;
620 if (pos2){
621 ctx->last_block[remain_msg_byte] = data[databytelen] & ((0xff >> pos2) ^ 0xff);
622 }
623 return LSH_SUCCESS;
624 }
625
626 if (remain_msg_byte > 0){
627 size_t more_byte = LSH256_MSG_BLK_BYTE_LEN - remain_msg_byte;
628 memcpy(ctx->last_block + remain_msg_byte, data, more_byte);
629 compress(ctx, ctx->last_block);
630 data += more_byte;
631 databytelen -= more_byte;
632 remain_msg_byte = 0;
633 ctx->remain_databitlen = 0;
634 }
635
636 while (databytelen >= LSH256_MSG_BLK_BYTE_LEN)
637 {
638 // This call to compress caused some trouble.
639 // The data pointer can become unaligned in the
640 // previous block.
641 compress(ctx, data);
642 data += LSH256_MSG_BLK_BYTE_LEN;
643 databytelen -= LSH256_MSG_BLK_BYTE_LEN;
644 }
645
646 if (databytelen > 0){
647 memcpy(ctx->last_block, data, databytelen);
648 ctx->remain_databitlen = (lsh_uint)(databytelen << 3);
649 }
650
651 if (pos2){
652 ctx->last_block[databytelen] = data[databytelen] & ((0xff >> pos2) ^ 0xff);
653 ctx->remain_databitlen += pos2;
654 }
655
656 return LSH_SUCCESS;
657}
658
659lsh_err lsh256_final(LSH256_Context* ctx, lsh_u8* hashval)
660{
661 CRYPTOPP_ASSERT(ctx != NULLPTR);
662 CRYPTOPP_ASSERT(hashval != NULLPTR);
663
664 // We are byte oriented. tail bits will always be 0.
665 size_t remain_msg_byte = ctx->remain_databitlen >> 3;
666 // lsh_uint remain_msg_bit = ctx->remain_databitlen & 7;
667 const size_t remain_msg_bit = 0;
668
669 if (remain_msg_byte >= LSH256_MSG_BLK_BYTE_LEN){
670 return LSH_ERR_INVALID_STATE;
671 }
672
673 if (remain_msg_bit){
674 ctx->last_block[remain_msg_byte] |= (0x1 << (7 - remain_msg_bit));
675 }
676 else{
677 ctx->last_block[remain_msg_byte] = 0x80;
678 }
679 memset(ctx->last_block + remain_msg_byte + 1, 0, LSH256_MSG_BLK_BYTE_LEN - remain_msg_byte - 1);
680
681 compress(ctx, ctx->last_block);
682
683 fin(ctx);
684 get_hash(ctx, hashval);
685
686 return LSH_SUCCESS;
687}
688
689ANONYMOUS_NAMESPACE_END
690
691NAMESPACE_BEGIN(CryptoPP)
692
693#if defined(CRYPTOPP_ENABLE_64BIT_SSE)
694# if defined(CRYPTOPP_AVX2_AVAILABLE)
695 extern void LSH256_Base_Restart_AVX2(word32* state);
696 extern void LSH256_Base_Update_AVX2(word32* state, const byte *input, size_t size);
697 extern void LSH256_Base_TruncatedFinal_AVX2(word32* state, byte *hash, size_t size);
698# endif
699# if defined(CRYPTOPP_SSSE3_AVAILABLE)
700 extern void LSH256_Base_Restart_SSSE3(word32* state);
701 extern void LSH256_Base_Update_SSSE3(word32* state, const byte *input, size_t size);
702 extern void LSH256_Base_TruncatedFinal_SSSE3(word32* state, byte *hash, size_t size);
703# endif
704#endif
705
706void LSH256_Base_Restart_CXX(word32* state)
707{
708 state[RemainingBits] = 0;
709 LSH256_Context ctx(state, state[AlgorithmType], state[RemainingBits]);
710 lsh_err err = lsh256_init(&ctx);
711
712 if (err != LSH_SUCCESS)
713 throw Exception(Exception::OTHER_ERROR, "LSH256_Base: lsh256_init failed");
714}
715
716void LSH256_Base_Update_CXX(word32* state, const byte *input, size_t size)
717{
718 LSH256_Context ctx(state, state[AlgorithmType], state[RemainingBits]);
719 lsh_err err = lsh256_update(&ctx, input, 8*size);
720
721 if (err != LSH_SUCCESS)
722 throw Exception(Exception::OTHER_ERROR, "LSH256_Base: lsh256_update failed");
723}
724
725void LSH256_Base_TruncatedFinal_CXX(word32* state, byte *hash, size_t)
726{
727 LSH256_Context ctx(state, state[AlgorithmType], state[RemainingBits]);
728 lsh_err err = lsh256_final(&ctx, hash);
729
730 if (err != LSH_SUCCESS)
731 throw Exception(Exception::OTHER_ERROR, "LSH256_Base: lsh256_final failed");
732}
733
734std::string LSH256_Base::AlgorithmProvider() const
735{
736#if defined(CRYPTOPP_ENABLE_64BIT_SSE)
737#if defined(CRYPTOPP_AVX2_AVAILABLE)
738 if (HasAVX2())
739 return "AVX2";
740 else
741#endif
742#if defined(CRYPTOPP_SSSE3_AVAILABLE)
743 if (HasSSSE3())
744 return "SSSE3";
745 else
746#endif
747#endif // CRYPTOPP_ENABLE_64BIT_SSE
748
749 return "C++";
750}
751
753{
754#if defined(CRYPTOPP_AVX2_AVAILABLE) && defined(CRYPTOPP_ENABLE_64BIT_SSE)
755 if (HasAVX2())
756 LSH256_Base_Restart_AVX2(m_state);
757 else
758#endif
759#if defined(CRYPTOPP_SSSE3_AVAILABLE) && defined(CRYPTOPP_ENABLE_64BIT_SSE)
760 if (HasSSSE3())
761 LSH256_Base_Restart_SSSE3(m_state);
762 else
763#endif
764
765 LSH256_Base_Restart_CXX(m_state);
766}
767
768void LSH256_Base::Update(const byte *input, size_t size)
769{
770 CRYPTOPP_ASSERT(input != NULLPTR);
771 CRYPTOPP_ASSERT(size);
772
773#if defined(CRYPTOPP_AVX2_AVAILABLE) && defined(CRYPTOPP_ENABLE_64BIT_SSE)
774 if (HasAVX2())
775 LSH256_Base_Update_AVX2(m_state, input, size);
776 else
777#endif
778#if defined(CRYPTOPP_SSSE3_AVAILABLE) && defined(CRYPTOPP_ENABLE_64BIT_SSE)
779 if (HasSSSE3())
780 LSH256_Base_Update_SSSE3(m_state, input, size);
781 else
782#endif
783
784 LSH256_Base_Update_CXX(m_state, input, size);
785}
786
787void LSH256_Base::TruncatedFinal(byte *hash, size_t size)
788{
789 CRYPTOPP_ASSERT(hash != NULLPTR);
790 ThrowIfInvalidTruncatedSize(size);
791
792 // TODO: determine if LSH256 supports truncated hashes. See the code
793 // in get_hash(), where a bit-length is added to the last output
794 // byte of the hash function.
795 byte fullHash[LSH256_HASH_VAL_MAX_BYTE_LEN];
796 bool copyOut = (size < DigestSize());
797
798#if defined(CRYPTOPP_AVX2_AVAILABLE) && defined(CRYPTOPP_ENABLE_64BIT_SSE)
799 if (HasAVX2())
800 LSH256_Base_TruncatedFinal_AVX2(m_state, copyOut ? fullHash : hash, size);
801 else
802#endif
803#if defined(CRYPTOPP_SSSE3_AVAILABLE) && defined(CRYPTOPP_ENABLE_64BIT_SSE)
804 if (HasSSSE3())
805 LSH256_Base_TruncatedFinal_SSSE3(m_state, copyOut ? fullHash : hash, size);
806 else
807#endif
808
809 LSH256_Base_TruncatedFinal_CXX(m_state, copyOut ? fullHash : hash, size);
810
811 if (copyOut)
812 memcpy(hash, fullHash, size);
813
814 Restart();
815}
816
817NAMESPACE_END
Base class for all exceptions thrown by the library.
Definition: cryptlib.h:159
@ OTHER_ERROR
Some other error occurred not belonging to other categories.
Definition: cryptlib.h:177
Access a block of memory.
Definition: misc.h:2766
void TruncatedFinal(byte *hash, size_t size)
Computes the hash of the current message.
std::string AlgorithmProvider() const
Retrieve the provider of this algorithm.
void Update(const byte *input, size_t size)
Updates a hash with additional input.
void Restart()
Restart the hash.
unsigned int DigestSize() const
Provides the digest size of the hash.
Definition: lsh.h:44
Library configuration file.
unsigned char byte
8-bit unsigned datatype
Definition: config_int.h:56
unsigned int word32
32-bit unsigned datatype
Definition: config_int.h:62
Functions for CPU features and intrinsics.
@ LITTLE_ENDIAN_ORDER
byte order is little-endian
Definition: cryptlib.h:145
EnumToType< ByteOrder, LITTLE_ENDIAN_ORDER > LittleEndian
Provides a constant for LittleEndian.
Definition: cryptlib.h:150
Classes for the LSH hash functions.
Utility functions for the Crypto++ library.
T rotlConstant(T x)
Performs a left rotate.
Definition: misc.h:1548
T ConditionalByteReverse(ByteOrder order, T value)
Reverses bytes in a value depending upon endianness.
Definition: misc.h:2208
T rotlFixed(T x, unsigned int y)
Performs a left rotate.
Definition: misc.h:1599
Crypto++ library namespace.
Precompiled header file.
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:68