Kagome
Polkadot Runtime Engine in C++17
blake2s.cpp
Go to the documentation of this file.
1 
6 // taken from here
7 // https://github.com/mjosaarinen/blake2_mjosref/blob/master/blake2s.c
8 
9 // blake2s.c
10 // A simple blake2s Reference Implementation.
11 
12 #include "blake2s.h"
13 
14 #include <cstdint>
15 
16 namespace kagome::crypto {
17 
18 #define _256_bits 32
19 
20  // Cyclic right rotation.
21 
22 #ifndef ROTR32
23 #define ROTR32(x, y) (((x) >> (y)) ^ ((x) << (32 - (y))))
24 #endif
25 
26  // Little-endian byte access.
27 
28  // state context
29  typedef struct {
30  uint8_t b[64]; // input buffer
31  uint32_t h[8]; // chained state
32  uint32_t t[2]; // total number of bytes
33  size_t c; // pointer for b[]
34  size_t outlen; // digest size
36 
37 #define B2S_GET32(p) \
38  (((uint32_t)((uint8_t *)(p))[0]) ^ (((uint32_t)((uint8_t *)(p))[1]) << 8) \
39  ^ (((uint32_t)((uint8_t *)(p))[2]) << 16) \
40  ^ (((uint32_t)((uint8_t *)(p))[3]) << 24))
41 
42  // Mixing function G.
43 
44 #define B2S_G(a, b, c, d, x, y) \
45  { \
46  v[a] = v[a] + v[b] + (x); \
47  v[d] = ROTR32(v[d] ^ v[a], 16); \
48  v[c] = v[c] + v[d]; \
49  v[b] = ROTR32(v[b] ^ v[c], 12); \
50  v[a] = v[a] + v[b] + (y); \
51  v[d] = ROTR32(v[d] ^ v[a], 8); \
52  v[c] = v[c] + v[d]; \
53  v[b] = ROTR32(v[b] ^ v[c], 7); \
54  }
55 
56  // Initialization Vector.
57 
58  static const uint32_t blake2s_iv[8] = {0x6A09E667,
59  0xBB67AE85,
60  0x3C6EF372,
61  0xA54FF53A,
62  0x510E527F,
63  0x9B05688C,
64  0x1F83D9AB,
65  0x5BE0CD19};
66 
67  // Compression function. "last" flag indicates last block.
68 
69  static void blake2s_compress(blake2s_ctx_full *ctx, int last) {
70  const uint8_t sigma[10][16] = {
71  {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
72  {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
73  {11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4},
74  {7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8},
75  {9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13},
76  {2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9},
77  {12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11},
78  {13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10},
79  {6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5},
80  {10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0}};
81  int i;
82  uint32_t v[16];
83  uint32_t m[16];
84 
85  for (i = 0; i < 8; i++) { // init work variables
86  v[i] = ctx->h[i];
87  v[i + 8] = blake2s_iv[i];
88  }
89 
90  v[12] ^= ctx->t[0]; // low 32 bits of offset
91  v[13] ^= ctx->t[1]; // high 32 bits
92  if (last) { // last block flag set ?
93  v[14] = ~v[14];
94  }
95 
96  for (i = 0; i < 16; i++) { // get little-endian words
97  m[i] = B2S_GET32(&ctx->b[4 * i]);
98  }
99 
100  for (i = 0; i < 10; i++) { // ten rounds
101  B2S_G(0, 4, 8, 12, m[sigma[i][0]], m[sigma[i][1]]);
102  B2S_G(1, 5, 9, 13, m[sigma[i][2]], m[sigma[i][3]]);
103  B2S_G(2, 6, 10, 14, m[sigma[i][4]], m[sigma[i][5]]);
104  B2S_G(3, 7, 11, 15, m[sigma[i][6]], m[sigma[i][7]]);
105  B2S_G(0, 5, 10, 15, m[sigma[i][8]], m[sigma[i][9]]);
106  B2S_G(1, 6, 11, 12, m[sigma[i][10]], m[sigma[i][11]]);
107  B2S_G(2, 7, 8, 13, m[sigma[i][12]], m[sigma[i][13]]);
108  B2S_G(3, 4, 9, 14, m[sigma[i][14]], m[sigma[i][15]]);
109  }
110 
111  for (i = 0; i < 8; ++i) {
112  ctx->h[i] ^= v[i] ^ v[i + 8];
113  }
114  }
115 
116  // Add "inlen" bytes from "in" into the hash.
117  void blake2s_update(blake2s_ctx *ctx_opaque, const void *in, size_t inlen) {
118  blake2s_ctx_full *ctx = (blake2s_ctx_full *)ctx_opaque->opaque;
119 
120  size_t i;
121 
122  for (i = 0; i < inlen; i++) {
123  if (ctx->c == 64) { // buffer full ?
124  ctx->t[0] += ctx->c; // add counters
125  if (ctx->t[0] < ctx->c) { // carry overflow ?
126  ctx->t[1]++; // high word
127  }
128  blake2s_compress(ctx, 0); // compress (not last)
129  ctx->c = 0; // counter to zero
130  }
131  ctx->b[ctx->c++] = ((const uint8_t *)in)[i];
132  }
133  }
134 
135  // Generate the message digest (size given in init).
136  // Result placed in "out".
137 
138  void blake2s_final(blake2s_ctx *ctx_opaque, void *out) {
139  blake2s_ctx_full *ctx = (blake2s_ctx_full *)ctx_opaque->opaque;
140 
141  size_t i;
142 
143  ctx->t[0] += ctx->c; // mark last block offset
144  if (ctx->t[0] < ctx->c) { // carry overflow
145  ctx->t[1]++; // high word
146  }
147 
148  while (ctx->c < 64) { // fill up with zeros
149  ctx->b[ctx->c++] = 0;
150  }
151  blake2s_compress(ctx, 1); // final block flag = 1
152 
153  // little endian convert and store
154  for (i = 0; i < ctx->outlen; i++) {
155  ((uint8_t *)out)[i] = (uint8_t)((ctx->h[i >> 2] >> (8 * (i & 3))) & 0xFF);
156  }
157  }
158 
159  int blake2s_init(blake2s_ctx *ctx_opaque,
160  size_t outlen,
161  const void *key,
162  size_t keylen) {
163  blake2s_ctx_full *ctx = (blake2s_ctx_full *)ctx_opaque->opaque;
164 
165  size_t i;
166 
167  if (outlen == 0 || outlen > 32 || keylen > 32) {
168  return -1; // illegal parameters
169  }
170 
171  for (i = 0; i < 8; i++) { // state, "param block"
172  ctx->h[i] = blake2s_iv[i];
173  }
174 
175  ctx->h[0] ^= 0x01010000 ^ (keylen << 8) ^ outlen;
176 
177  ctx->t[0] = 0; // input count low word
178  ctx->t[1] = 0; // input count high word
179  ctx->c = 0; // pointer within buffer
180  ctx->outlen = outlen;
181 
182  for (i = keylen; i < 64; i++) { // zero input block
183  ctx->b[i] = 0;
184  }
185 
186  if (keylen > 0) {
187  blake2s_update(ctx_opaque, key, keylen);
188  ctx->c = 64; // at the end
189  }
190 
191  return 0;
192  }
193 
194  int blake2s(void *out,
195  size_t outlen,
196  const void *key,
197  size_t keylen,
198  const void *in,
199  size_t inlen) {
200  blake2s_ctx ctx;
201 
202  if (blake2s_init(&ctx, outlen, key, keylen)) {
203  return -1;
204  }
205 
206  blake2s_update(&ctx, in, inlen);
207  blake2s_final(&ctx, out);
208 
209  return 0;
210  }
211 
212  void blake2s_256_init(blake2s_ctx *ctx_opaque) {
213  blake2s_init(ctx_opaque, _256_bits, NULL, 0);
214  }
215 
216  void blake2s_256(void *out, const void *in, size_t inlen) {
217  blake2s(out, _256_bits, NULL, 0, in, inlen);
218  }
219 } // namespace kagome::crypto
static const uint32_t blake2s_iv[8]
Definition: blake2s.cpp:58
void blake2s_256(void *out, const void *in, size_t inlen)
One-shot convenience function to calculate blake2s_256 hash.
Definition: blake2s.cpp:216
#define B2S_G(a, b, c, d, x, y)
Definition: blake2s.cpp:44
int blake2s(void *out, size_t outlen, const void *key, size_t keylen, const void *in, size_t inlen)
All in one blake2s hashing function.
Definition: blake2s.cpp:194
unsigned char opaque[128]
Definition: blake2s.h:17
static void blake2s_compress(blake2s_ctx_full *ctx, int last)
Definition: blake2s.cpp:69
void blake2s_final(blake2s_ctx *ctx_opaque, void *out)
Finalize hash calculation.
Definition: blake2s.cpp:138
int blake2s_init(blake2s_ctx *ctx_opaque, size_t outlen, const void *key, size_t keylen)
Generic blake2s init function.
Definition: blake2s.cpp:159
#define _256_bits
Definition: blake2s.cpp:18
void blake2s_256_init(blake2s_ctx *ctx_opaque)
Initialize hash context.
Definition: blake2s.cpp:212
void blake2s_update(blake2s_ctx *ctx_opaque, const void *in, size_t inlen)
Update context with incoming bytes.
Definition: blake2s.cpp:117
#define B2S_GET32(p)
Definition: blake2s.cpp:37