Crypto++  8.8
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 
19 ANONYMOUS_NAMESPACE_BEGIN
20 
21 /* LSH Constants */
22 
23 const 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;
26 const unsigned int LSH256_HASH_VAL_MAX_BYTE_LEN = 32;
27 
28 // const unsigned int MSG_BLK_WORD_LEN = 32;
29 const unsigned int CV_WORD_LEN = 16;
30 const unsigned int CONST_WORD_LEN = 8;
31 const unsigned int HASH_VAL_MAX_WORD_LEN = 8;
32 // const unsigned int WORD_BIT_LEN = 32;
33 const unsigned int NUM_STEPS = 26;
34 
35 const unsigned int ROT_EVEN_ALPHA = 29;
36 const unsigned int ROT_EVEN_BETA = 1;
37 const unsigned int ROT_ODD_ALPHA = 5;
38 const unsigned int ROT_ODD_BETA = 17;
39 
40 const unsigned int LSH_TYPE_256_256 = 0x0000020;
41 const 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 
48 const unsigned int LSH_SUCCESS = 0x0;
49 // const unsigned int LSH_ERR_NULL_PTR = 0x2401;
50 // const unsigned int LSH_ERR_INVALID_ALGTYPE = 0x2402;
51 const unsigned int LSH_ERR_INVALID_DATABITLEN = 0x2403;
52 const unsigned int LSH_ERR_INVALID_STATE = 0x2404;
53 
54 /* Index into our state array */
55 
56 const unsigned int AlgorithmType = 80;
57 const unsigned int RemainingBits = 81;
58 
59 NAMESPACE_END
60 
61 NAMESPACE_BEGIN(CryptoPP)
62 NAMESPACE_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 
72 CRYPTOPP_ALIGN_DATA(32)
73 extern
74 const 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 
79 CRYPTOPP_ALIGN_DATA(32)
80 extern
81 const 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 
90 extern
91 const 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 
120 NAMESPACE_END // LSH
121 NAMESPACE_END // Crypto++
122 
123 ANONYMOUS_NAMESPACE_BEGIN
124 
125 using CryptoPP::byte;
126 using CryptoPP::word32;
127 using CryptoPP::rotlFixed;
129 
130 using CryptoPP::GetBlock;
134 
135 using CryptoPP::LSH::LSH256_IV224;
136 using CryptoPP::LSH::LSH256_IV256;
137 using CryptoPP::LSH::LSH256_StepConstants;
138 
139 typedef byte lsh_u8;
140 typedef word32 lsh_u32;
141 typedef word32 lsh_uint;
142 typedef word32 lsh_err;
143 typedef word32 lsh_type;
144 
145 struct 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 
161 struct 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 
173 const word32 g_gamma256[8] = { 0, 8, 16, 24, 24, 16, 8, 0 };
174 
175 /* LSH AlgType Macro */
176 
177 inline bool LSH_IS_LSH512(lsh_uint val) {
178  return (val & 0xf0000) == 0;
179 }
180 
181 inline lsh_uint LSH_GET_SMALL_HASHBIT(lsh_uint val) {
182  return val >> 24;
183 }
184 
185 inline lsh_uint LSH_GET_HASHBYTE(lsh_uint val) {
186  return val & 0xffff;
187 }
188 
189 inline lsh_uint LSH_GET_HASHBIT(lsh_uint val) {
190  return (LSH_GET_HASHBYTE(val) << 3) - LSH_GET_SMALL_HASHBIT(val);
191 }
192 
193 inline lsh_u32 loadLE32(lsh_u32 v) {
195 }
196 
197 lsh_u32 ROTL(lsh_u32 x, lsh_u32 r) {
198  return rotlFixed(x, r);
199 }
200 
201 // Original code relied upon unaligned lsh_u32 buffer
202 inline 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 
224 inline 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 
256 inline 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 
288 inline 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 
295 inline 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 
312 inline 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 
329 inline 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 
341 template <unsigned int R>
342 inline 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 
354 inline 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 
366 inline 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 
376 inline 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 
403 template <unsigned int Alpha, unsigned int Beta>
404 inline 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 
419 inline 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 
463 inline 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 
483 inline void zero_iv(lsh_u32 cv_l[8], lsh_u32 cv_r[8])
484 {
485  std::memset(cv_l, 0x00, 8*sizeof(lsh_u32));
486  std::memset(cv_r, 0x00, 8*sizeof(lsh_u32));
487 }
488 
489 inline void zero_submsgs(LSH256_Context* ctx)
490 {
491  CRYPTOPP_ASSERT(ctx != NULLPTR);
492 
493  lsh_u32* sub_msgs = ctx->sub_msgs;
494  std::memset(sub_msgs, 0x00, 32*sizeof(lsh_u32));
495 }
496 
497 inline 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 
505 inline 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 
515 inline 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 
526 inline 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  std::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 
545 lsh_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 
588 lsh_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  std::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  std::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  std::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 
659 lsh_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  std::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 
689 ANONYMOUS_NAMESPACE_END
690 
691 NAMESPACE_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 
706 void 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 
716 void 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 
725 void 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 
734 std::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 
768 void 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 
787 void 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  std::memcpy(hash, fullHash, size);
813 
814  Restart();
815 }
816 
817 NAMESPACE_END
Base class for all exceptions thrown by the library.
Definition: cryptlib.h:164
@ OTHER_ERROR
Some other error occurred not belonging to other categories.
Definition: cryptlib.h:182
Access a block of memory.
Definition: misc.h:2975
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:66
unsigned int word32
32-bit unsigned datatype
Definition: config_int.h:72
Functions for CPU features and intrinsics.
@ LITTLE_ENDIAN_ORDER
byte order is little-endian
Definition: cryptlib.h:150
EnumToType< ByteOrder, LITTLE_ENDIAN_ORDER > LittleEndian
Provides a constant for LittleEndian.
Definition: cryptlib.h:155
Classes for the LSH hash functions.
Utility functions for the Crypto++ library.
T rotlConstant(T x)
Performs a left rotate.
Definition: misc.h:1757
T ConditionalByteReverse(ByteOrder order, T value)
Reverses bytes in a value depending upon endianness.
Definition: misc.h:2417
T rotlFixed(T x, unsigned int y)
Performs a left rotate.
Definition: misc.h:1808
Crypto++ library namespace.
Precompiled header file.
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:68