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