1
|
|
/*
|
2
|
|
*******************************************************************************
|
3
|
|
\file bash_hash.c
|
4
|
|
\brief STB 34.101.77 (bash): hashing algorithms
|
5
|
|
\project bee2 [cryptographic library]
|
6
|
|
\author (C) Sergey Agievich [agievich@{bsu.by|gmail.com}]
|
7
|
|
\author (C) Vlad Semenov [semenov.vlad.by@gmail.com]
|
8
|
|
\created 2014.07.15
|
9
|
|
\version 2020.06.23
|
10
|
|
\license This program is released under the GNU General Public License
|
11
|
|
version 3. See Copyright Notices in bee2/info.h.
|
12
|
|
*******************************************************************************
|
13
|
|
*/
|
14
|
|
|
15
|
|
#include "bee2/core/blob.h"
|
16
|
|
#include "bee2/core/err.h"
|
17
|
|
#include "bee2/core/mem.h"
|
18
|
|
#include "bee2/core/u64.h"
|
19
|
|
#include "bee2/core/util.h"
|
20
|
|
#include "bee2/crypto/bash.h"
|
21
|
|
|
22
|
|
/*
|
23
|
|
*******************************************************************************
|
24
|
|
Хэширование
|
25
|
|
*******************************************************************************
|
26
|
|
*/
|
27
|
|
|
28
|
|
typedef struct {
|
29
|
|
octet s[192]; /*< состояние */
|
30
|
|
octet s1[192]; /*< копия s */
|
31
|
|
size_t buf_len; /*< длина буфера */
|
32
|
|
size_t pos; /*< позиция в буфере (накоплено октетов) */
|
33
|
|
octet stack[]; /*< [bashF_deep()] стек bashF */
|
34
|
|
} bash_hash_st;
|
35
|
|
|
36
|
1
|
size_t bashHash_keep()
|
37
|
|
{
|
38
|
1
|
return sizeof(bash_hash_st) + bashF_deep();
|
39
|
|
}
|
40
|
|
|
41
|
1
|
void bashHashStart(void* state, size_t l)
|
42
|
|
{
|
43
|
1
|
bash_hash_st* st = (bash_hash_st*)state;
|
44
|
1
|
ASSERT(l > 0 && l % 16 == 0 && l <= 256);
|
45
|
1
|
ASSERT(memIsValid(st, bashHash_keep()));
|
46
|
|
// s <- 0^{1536 - 64} || <l / 4>_{64}
|
47
|
1
|
memSetZero(st->s, sizeof(st->s));
|
48
|
1
|
st->s[192 - 8] = (octet)(l / 4);
|
49
|
|
// длина блока
|
50
|
1
|
st->buf_len = 192 - l / 2;
|
51
|
|
// нет накопленнных октетов
|
52
|
1
|
st->pos = 0;
|
53
|
|
}
|
54
|
|
|
55
|
1
|
void bashHashStepH(const void* buf, size_t count, void* state)
|
56
|
|
{
|
57
|
1
|
bash_hash_st* st = (bash_hash_st*)state;
|
58
|
1
|
ASSERT(memIsDisjoint2(st, bashHash_keep(), buf, count));
|
59
|
|
// не накопился полный буфер?
|
60
|
1
|
if (count < st->buf_len - st->pos)
|
61
|
|
{
|
62
|
1
|
memCopy(st->s + st->pos, buf, count);
|
63
|
1
|
st->pos += count;
|
64
|
1
|
return;
|
65
|
|
}
|
66
|
|
// новый полный буфер
|
67
|
1
|
memCopy(st->s + st->pos, buf, st->buf_len - st->pos);
|
68
|
1
|
buf = (const octet*)buf + st->buf_len - st->pos;
|
69
|
1
|
count -= st->buf_len - st->pos;
|
70
|
1
|
bashF(st->s, st->stack);
|
71
|
|
// цикл по полным блокам
|
72
|
1
|
while (count >= st->buf_len)
|
73
|
|
{
|
74
|
1
|
memCopy(st->s, buf, st->buf_len);
|
75
|
1
|
buf = (const octet*)buf + st->buf_len;
|
76
|
1
|
count -= st->buf_len;
|
77
|
1
|
bashF(st->s, st->stack);
|
78
|
|
}
|
79
|
|
// неполный блок?
|
80
|
1
|
if (st->pos = count)
|
81
|
1
|
memCopy(st->s, buf, count);
|
82
|
|
}
|
83
|
|
|
84
|
1
|
static void bashHashStepG_internal(size_t hash_len, void* state)
|
85
|
|
{
|
86
|
1
|
bash_hash_st* st = (bash_hash_st*)state;
|
87
|
1
|
ASSERT(memIsValid(st, bashHash_keep()));
|
88
|
1
|
ASSERT(st->buf_len + hash_len * 2 <= 192);
|
89
|
|
// создать копию s
|
90
|
1
|
memCopy(st->s1, st->s, sizeof(st->s));
|
91
|
|
// есть необработанные данные?
|
92
|
1
|
if (st->pos)
|
93
|
|
{
|
94
|
1
|
memSetZero(st->s1 + st->pos, st->buf_len - st->pos);
|
95
|
1
|
st->s1[st->pos] = 0x40;
|
96
|
|
}
|
97
|
|
// дополнительный блок
|
98
|
|
else
|
99
|
|
{
|
100
|
1
|
memSetZero(st->s1, st->buf_len);
|
101
|
1
|
st->s1[0] = 0x40;
|
102
|
|
}
|
103
|
|
// последний шаг
|
104
|
1
|
bashF(st->s1, st->stack);
|
105
|
|
}
|
106
|
|
|
107
|
1
|
void bashHashStepG(octet hash[], size_t hash_len, void* state)
|
108
|
|
{
|
109
|
1
|
bash_hash_st* st = (bash_hash_st*)state;
|
110
|
1
|
bashHashStepG_internal(hash_len, state);
|
111
|
1
|
memMove(hash, st->s1, hash_len);
|
112
|
|
}
|
113
|
|
|
114
|
0
|
bool_t bashHashStepV(const octet hash[], size_t hash_len, void* state)
|
115
|
|
{
|
116
|
0
|
bash_hash_st* st = (bash_hash_st*)state;
|
117
|
0
|
bashHashStepG_internal(hash_len, state);
|
118
|
0
|
return memEq(hash, st->s1, hash_len);
|
119
|
|
}
|
120
|
|
|
121
|
1
|
err_t bashHash(octet hash[], size_t l, const void* src, size_t count)
|
122
|
|
{
|
123
|
|
void* state;
|
124
|
|
// проверить входные данные
|
125
|
1
|
if (l == 0 || l % 16 != 0 || l > 256)
|
126
|
0
|
return ERR_BAD_PARAMS;
|
127
|
1
|
if (!memIsValid(src, count) || !memIsValid(hash, l / 4))
|
128
|
0
|
return ERR_BAD_INPUT;
|
129
|
|
// создать состояние
|
130
|
1
|
state = blobCreate(bashHash_keep());
|
131
|
1
|
if (state == 0)
|
132
|
0
|
return ERR_OUTOFMEMORY;
|
133
|
|
// вычислить хэш-значение
|
134
|
1
|
bashHashStart(state, l);
|
135
|
1
|
bashHashStepH(src, count, state);
|
136
|
1
|
bashHashStepG(hash, l / 4, state);
|
137
|
|
// завершить
|
138
|
1
|
blobClose(state);
|
139
|
1
|
return ERR_OK;
|
140
|
|
}
|