argon2 0.1.4 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +5 -9
  3. data/.travis.yml +0 -1
  4. data/CONTRIBUTING.md +12 -0
  5. data/Changelog.md +10 -11
  6. data/README.md +23 -14
  7. data/ext/argon2_wrap/Makefile +8 -6
  8. data/ext/argon2_wrap/argon_wrap.c +23 -12
  9. data/ext/argon2_wrap/test.c +14 -42
  10. data/ext/phc-winner-argon2/.gitignore +5 -1
  11. data/ext/phc-winner-argon2/.travis.yml +14 -0
  12. data/ext/phc-winner-argon2/Makefile +33 -12
  13. data/ext/phc-winner-argon2/README.md +48 -19
  14. data/ext/phc-winner-argon2/argon2-specs.pdf +0 -0
  15. data/ext/phc-winner-argon2/{src → include}/argon2.h +137 -137
  16. data/ext/phc-winner-argon2/kats/argon2d +12290 -12290
  17. data/ext/phc-winner-argon2/kats/argon2d.shasum +1 -1
  18. data/ext/phc-winner-argon2/kats/argon2i +12290 -12290
  19. data/ext/phc-winner-argon2/kats/argon2i.shasum +1 -1
  20. data/ext/phc-winner-argon2/opt.o +0 -0
  21. data/ext/phc-winner-argon2/src/argon2.c +125 -145
  22. data/ext/phc-winner-argon2/src/bench.c +5 -5
  23. data/ext/phc-winner-argon2/src/core.c +15 -20
  24. data/ext/phc-winner-argon2/src/core.h +5 -2
  25. data/ext/phc-winner-argon2/src/encoding.c +45 -72
  26. data/ext/phc-winner-argon2/src/encoding.h +24 -0
  27. data/ext/phc-winner-argon2/src/genkat.c +2 -2
  28. data/ext/phc-winner-argon2/src/opt.c +19 -10
  29. data/ext/phc-winner-argon2/src/opt.h +5 -17
  30. data/ext/phc-winner-argon2/src/ref.c +12 -9
  31. data/ext/phc-winner-argon2/src/ref.h +4 -12
  32. data/ext/phc-winner-argon2/src/run.c +67 -42
  33. data/ext/phc-winner-argon2/src/test.c +131 -0
  34. data/lib/argon2.rb +6 -5
  35. data/lib/argon2/constants.rb +3 -2
  36. data/lib/argon2/engine.rb +1 -0
  37. data/lib/argon2/errors.rb +37 -36
  38. data/lib/argon2/ffi_engine.rb +10 -10
  39. data/lib/argon2/version.rb +2 -1
  40. metadata +7 -12
@@ -24,12 +24,14 @@
24
24
  #define ALIGN(x)
25
25
  #endif
26
26
 
27
+ #define CONST_CAST(x) (x)(uintptr_t)
28
+
27
29
  /*************************Argon2 internal
28
30
  * constants**************************************************/
29
31
 
30
32
  enum argon2_core_constants {
31
33
  /* Version of the algorithm */
32
- ARGON2_VERSION_NUMBER = 0x10,
34
+ ARGON2_VERSION_NUMBER = 0x13,
33
35
 
34
36
  /* Memory block size in bytes */
35
37
  ARGON2_BLOCK_SIZE = 1024,
@@ -212,7 +214,8 @@ void fill_segment(const argon2_instance_t *instance,
212
214
  * Function that fills the entire memory t_cost times based on the first two
213
215
  * blocks in each lane
214
216
  * @param instance Pointer to the current instance
217
+ * @return ARGON2_OK if successful, @context->state
215
218
  */
216
- void fill_memory_blocks(argon2_instance_t *instance);
219
+ int fill_memory_blocks(argon2_instance_t *instance);
217
220
 
218
221
  #endif
@@ -3,9 +3,10 @@
3
3
  #include <string.h>
4
4
  #include <limits.h>
5
5
  #include "encoding.h"
6
+ #include "core.h"
6
7
 
7
- #/*
8
- * Example code for a decoder and encoder of "hash strings", with Argon2i
8
+ /*
9
+ * Example code for a decoder and encoder of "hash strings", with Argon2
9
10
  * parameters.
10
11
  *
11
12
  * This code comprises three sections:
@@ -17,7 +18,7 @@
17
18
  * the relevant functions are made public (non-static) and be given
18
19
  * reasonable names to avoid collisions with other functions.
19
20
  *
20
- * -- The second section is specific to Argon2i. It encodes and decodes
21
+ * -- The second section is specific to Argon2. It encodes and decodes
21
22
  * the parameters, salts and outputs. It does not compute the hash
22
23
  * itself.
23
24
  *
@@ -58,7 +59,7 @@
58
59
  * Some macros for constant-time comparisons. These work over values in
59
60
  * the 0..255 range. Returned value is 0x00 on "false", 0xFF on "true".
60
61
  */
61
- #define EQ(x, y) ((((0U-((unsigned)(x) ^ (unsigned)(y))) >> 8) & 0xFF) ^ 0xFF)
62
+ #define EQ(x, y) ((((0U - ((unsigned)(x) ^ (unsigned)(y))) >> 8) & 0xFF) ^ 0xFF)
62
63
  #define GT(x, y) ((((unsigned)(y) - (unsigned)(x)) >> 8) & 0xFF)
63
64
  #define GE(x, y) (GT(y, x) ^ 0xFF)
64
65
  #define LT(x, y) GT(y, x)
@@ -122,11 +123,11 @@ static size_t to_base64(char *dst, size_t dst_len, const void *src,
122
123
  acc_len += 8;
123
124
  while (acc_len >= 6) {
124
125
  acc_len -= 6;
125
- *dst++ = (char) b64_byte_to_char((acc >> acc_len) & 0x3F);
126
+ *dst++ = (char)b64_byte_to_char((acc >> acc_len) & 0x3F);
126
127
  }
127
128
  }
128
129
  if (acc_len > 0) {
129
- *dst++ = (char) b64_byte_to_char((acc << (6 - acc_len)) & 0x3F);
130
+ *dst++ = (char)b64_byte_to_char((acc << (6 - acc_len)) & 0x3F);
130
131
  }
131
132
  *dst++ = 0;
132
133
  return olen;
@@ -224,16 +225,17 @@ static const char *decode_decimal(const char *str, unsigned long *v) {
224
225
 
225
226
  /* ==================================================================== */
226
227
  /*
227
- * Code specific to Argon2i.
228
+ * Code specific to Argon2.
228
229
  *
229
230
  * The code below applies the following format:
230
231
  *
231
- * $argon2i$m=<num>,t=<num>,p=<num>[,keyid=<bin>][,data=<bin>][$<bin>[$<bin>]]
232
+ * $argon2<T>$m=<num>,t=<num>,p=<num>[,keyid=<bin>][,data=<bin>][$<bin>[$<bin>]]
232
233
  *
233
- * where <num> is a decimal integer (positive, fits in an 'unsigned long')
234
- * and <bin> is Base64-encoded data (no '=' padding characters, no newline
235
- * or whitespace). The "keyid" is a binary identifier for a key (up to 8
236
- * bytes); "data" is associated data (up to 32 bytes). When the 'keyid'
234
+ * where <T> is either 'd' or 'i', <num> is a decimal integer (positive, fits in
235
+ * an 'unsigned long'), and <bin> is Base64-encoded data (no '=' padding
236
+ * characters, no newline or whitespace).
237
+ * The "keyid" is a binary identifier for a key (up to 8 bytes);
238
+ * "data" is associated data (up to 32 bytes). When the 'keyid'
237
239
  * (resp. the 'data') is empty, then it is ommitted from the output.
238
240
  *
239
241
  * The last two binary chunks (encoded in Base64) are, in that order,
@@ -242,20 +244,19 @@ static const char *decode_decimal(const char *str, unsigned long *v) {
242
244
  * The output length is always exactly 32 bytes.
243
245
  */
244
246
 
245
- /*
246
- * Decode an Argon2i hash string into the provided structure 'ctx'.
247
- * Returned value is 1 on success, 0 on error.
248
- */
249
247
  int decode_string(argon2_context *ctx, const char *str, argon2_type type) {
248
+
249
+ /* check for prefix */
250
250
  #define CC(prefix) \
251
251
  do { \
252
252
  size_t cc_len = strlen(prefix); \
253
253
  if (strncmp(str, prefix, cc_len) != 0) { \
254
- return 0; \
254
+ return ARGON2_DECODING_FAIL; \
255
255
  } \
256
256
  str += cc_len; \
257
257
  } while ((void)0, 0)
258
258
 
259
+ /* prefix checking with supplied code */
259
260
  #define CC_opt(prefix, code) \
260
261
  do { \
261
262
  size_t cc_len = strlen(prefix); \
@@ -265,12 +266,13 @@ int decode_string(argon2_context *ctx, const char *str, argon2_type type) {
265
266
  } \
266
267
  } while ((void)0, 0)
267
268
 
269
+ /* Decoding prefix into decimal */
268
270
  #define DECIMAL(x) \
269
271
  do { \
270
272
  unsigned long dec_x; \
271
273
  str = decode_decimal(str, &dec_x); \
272
274
  if (str == NULL) { \
273
- return 0; \
275
+ return ARGON2_DECODING_FAIL; \
274
276
  } \
275
277
  (x) = dec_x; \
276
278
  } while ((void)0, 0)
@@ -280,7 +282,7 @@ int decode_string(argon2_context *ctx, const char *str, argon2_type type) {
280
282
  size_t bin_len = (max_len); \
281
283
  str = from_base64(buf, &bin_len, str); \
282
284
  if (str == NULL || bin_len > UINT32_MAX) { \
283
- return 0; \
285
+ return ARGON2_DECODING_FAIL; \
284
286
  } \
285
287
  (len) = (uint32_t)bin_len; \
286
288
  } while ((void)0, 0)
@@ -288,16 +290,19 @@ int decode_string(argon2_context *ctx, const char *str, argon2_type type) {
288
290
  size_t maxadlen = ctx->adlen;
289
291
  size_t maxsaltlen = ctx->saltlen;
290
292
  size_t maxoutlen = ctx->outlen;
293
+ int validation_result;
291
294
 
292
295
  ctx->adlen = 0;
293
296
  ctx->saltlen = 0;
294
297
  ctx->outlen = 0;
298
+ ctx->pwdlen = 0;
299
+
295
300
  if (type == Argon2_i)
296
301
  CC("$argon2i");
297
302
  else if (type == Argon2_d)
298
303
  CC("$argon2d");
299
304
  else
300
- return 0;
305
+ return ARGON2_INCORRECT_TYPE;
301
306
  CC("$m=");
302
307
  DECIMAL(ctx->m_cost);
303
308
  CC(",t=");
@@ -306,75 +311,39 @@ int decode_string(argon2_context *ctx, const char *str, argon2_type type) {
306
311
  DECIMAL(ctx->lanes);
307
312
  ctx->threads = ctx->lanes;
308
313
 
309
- /*
310
- * Both m and t must be no more than 2^32-1. The tests below
311
- * use a shift by 30 bits to avoid a direct comparison with
312
- * 0xFFFFFFFF, which may trigger a spurious compiler warning
313
- * on machines where 'unsigned long' is a 32-bit type.
314
- */
315
- if (ctx->m_cost < 1 || (ctx->m_cost >> 30) > 3) {
316
- return 0;
317
- }
318
- if (ctx->t_cost < 1 || (ctx->t_cost >> 30) > 3) {
319
- return 0;
320
- }
321
-
322
- /*
323
- * The parallelism p must be between 1 and 255. The memory cost
324
- * parameter, expressed in kilobytes, must be at least 8 times
325
- * the value of p.
326
- */
327
- if (ctx->lanes < 1 || ctx->lanes > 255) {
328
- return 0;
329
- }
330
- if (ctx->m_cost < (ctx->lanes << 3)) {
331
- return 0;
332
- }
333
-
334
314
  CC_opt(",data=", BIN(ctx->ad, maxadlen, ctx->adlen));
335
315
  if (*str == 0) {
336
- return 1;
316
+ return ARGON2_OK;
337
317
  }
338
318
  CC("$");
339
319
  BIN(ctx->salt, maxsaltlen, ctx->saltlen);
340
- if (ctx->saltlen < 8) {
341
- return 0;
342
- }
343
320
  if (*str == 0) {
344
- return 1;
321
+ return ARGON2_OK;
345
322
  }
346
323
  CC("$");
347
324
  BIN(ctx->out, maxoutlen, ctx->outlen);
348
- if (ctx->outlen < 12) {
349
- return 0;
325
+ validation_result = validate_inputs(ctx);
326
+ if (validation_result != ARGON2_OK) {
327
+ return validation_result;
328
+ }
329
+ if (*str == 0) {
330
+ return ARGON2_OK;
331
+ } else {
332
+ return ARGON2_DECODING_FAIL;
350
333
  }
351
- return *str == 0;
352
-
353
334
  #undef CC
354
335
  #undef CC_opt
355
336
  #undef DECIMAL
356
337
  #undef BIN
357
338
  }
358
339
 
359
- /*
360
- * encode an argon2i hash string into the provided buffer. 'dst_len'
361
- * contains the size, in characters, of the 'dst' buffer; if 'dst_len'
362
- * is less than the number of required characters (including the
363
- * terminating 0), then this function returns 0.
364
- *
365
- * if pp->output_len is 0, then the hash string will be a salt string
366
- * (no output). if pp->salt_len is also 0, then the string will be a
367
- * parameter-only string (no salt and no output).
368
- *
369
- * on success, 1 is returned.
370
- */
371
340
  int encode_string(char *dst, size_t dst_len, argon2_context *ctx,
372
341
  argon2_type type) {
373
342
  #define SS(str) \
374
343
  do { \
375
344
  size_t pp_len = strlen(str); \
376
345
  if (pp_len >= dst_len) { \
377
- return 0; \
346
+ return ARGON2_ENCODING_FAIL; \
378
347
  } \
379
348
  memcpy(dst, str, pp_len + 1); \
380
349
  dst += pp_len; \
@@ -392,7 +361,7 @@ int encode_string(char *dst, size_t dst_len, argon2_context *ctx,
392
361
  do { \
393
362
  size_t sb_len = to_base64(dst, dst_len, buf, len); \
394
363
  if (sb_len == (size_t)-1) { \
395
- return 0; \
364
+ return ARGON2_ENCODING_FAIL; \
396
365
  } \
397
366
  dst += sb_len; \
398
367
  dst_len -= sb_len; \
@@ -403,7 +372,11 @@ int encode_string(char *dst, size_t dst_len, argon2_context *ctx,
403
372
  else if (type == Argon2_d)
404
373
  SS("$argon2d$m=");
405
374
  else
406
- return 0;
375
+ return ARGON2_ENCODING_FAIL;
376
+
377
+ if (validate_inputs(ctx) != ARGON2_OK) {
378
+ return validate_inputs(ctx);
379
+ }
407
380
  SX(ctx->m_cost);
408
381
  SS(",t=");
409
382
  SX(ctx->t_cost);
@@ -416,17 +389,17 @@ int encode_string(char *dst, size_t dst_len, argon2_context *ctx,
416
389
  }
417
390
 
418
391
  if (ctx->saltlen == 0)
419
- return 1;
392
+ return ARGON2_OK;
420
393
 
421
394
  SS("$");
422
395
  SB(ctx->salt, ctx->saltlen);
423
396
 
424
397
  if (ctx->outlen == 0)
425
- return 1;
398
+ return ARGON2_OK;
426
399
 
427
400
  SS("$");
428
401
  SB(ctx->out, ctx->outlen);
429
- return 1;
402
+ return ARGON2_OK;
430
403
 
431
404
  #undef SS
432
405
  #undef SX
@@ -2,9 +2,33 @@
2
2
  #define ENCODING_H
3
3
  #include "argon2.h"
4
4
 
5
+ #define ARGON2_MAX_DECODED_LANES UINT32_C(255)
6
+ #define ARGON2_MIN_DECODED_SALT_LEN UINT32_C(8)
7
+ #define ARGON2_MIN_DECODED_OUT_LEN UINT32_C(12)
8
+
9
+ /*
10
+ * encode an Argon2 hash string into the provided buffer. 'dst_len'
11
+ * contains the size, in characters, of the 'dst' buffer; if 'dst_len'
12
+ * is less than the number of required characters (including the
13
+ * terminating 0), then this function returns ARGON2_ENCODING_ERROR.
14
+ *
15
+ * if ctx->outlen is 0, then the hash string will be a salt string
16
+ * (no output). if ctx->saltlen is also 0, then the string will be a
17
+ * parameter-only string (no salt and no output).
18
+ *
19
+ * on success, ARGON2_OK is returned.
20
+ *
21
+ * No other parameters are checked
22
+ */
5
23
  int encode_string(char *dst, size_t dst_len, argon2_context *ctx,
6
24
  argon2_type type);
7
25
 
26
+ /*
27
+ * Decodes an Argon2 hash string into the provided structure 'ctx'.
28
+ * The fields ctx.saltlen, ctx.adlen, ctx.outlen set the maximal salt, ad, out
29
+ * length values that are allowed; invalid input string causes an error.
30
+ * Returned value is ARGON2_OK on success, other ARGON2_ codes on error.
31
+ */
8
32
  int decode_string(argon2_context *ctx, const char *str, argon2_type type);
9
33
 
10
34
  #endif
@@ -180,9 +180,9 @@ static void generate_testvectors(const char *type) {
180
180
  #undef TEST_ADLEN
181
181
 
182
182
  if (!strcmp(type, "d")) {
183
- argon2d(&context);
183
+ argon2d_ctx(&context);
184
184
  } else if (!strcmp(type, "i")) {
185
- argon2i(&context);
185
+ argon2i_ctx(&context);
186
186
  } else
187
187
  fatal("wrong Argon2 type");
188
188
  }
@@ -16,19 +16,20 @@
16
16
  #include <stdlib.h>
17
17
 
18
18
  #include "argon2.h"
19
- #include "core.h"
20
19
  #include "opt.h"
21
20
 
22
21
  #include "blake2/blake2.h"
23
22
  #include "blake2/blamka-round-opt.h"
24
23
 
25
- void fill_block(__m128i *state, const uint8_t *ref_block, uint8_t *next_block) {
24
+ void fill_block_with_xor(__m128i *state, const uint8_t *ref_block, uint8_t *next_block) {
26
25
  __m128i block_XY[ARGON2_OWORDS_IN_BLOCK];
27
26
  uint32_t i;
28
27
 
29
- for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
30
- block_XY[i] = state[i] = _mm_xor_si128(
28
+ for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
29
+ state[i] = _mm_xor_si128(
31
30
  state[i], _mm_loadu_si128((__m128i const *)(&ref_block[16 * i])));
31
+ block_XY[i] = _mm_xor_si128(
32
+ state[i], _mm_loadu_si128((__m128i const *)(&next_block[16 * i])));
32
33
  }
33
34
 
34
35
  for (i = 0; i < 8; ++i) {
@@ -52,7 +53,7 @@ void fill_block(__m128i *state, const uint8_t *ref_block, uint8_t *next_block) {
52
53
  void generate_addresses(const argon2_instance_t *instance,
53
54
  const argon2_position_t *position,
54
55
  uint64_t *pseudo_rands) {
55
- block address_block, input_block;
56
+ block address_block, input_block, tmp_block;
56
57
  uint32_t i;
57
58
 
58
59
  init_block_value(&address_block, 0);
@@ -68,14 +69,20 @@ void generate_addresses(const argon2_instance_t *instance,
68
69
 
69
70
  for (i = 0; i < instance->segment_length; ++i) {
70
71
  if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) {
72
+ /*Temporary zero-initialized blocks*/
71
73
  __m128i zero_block[ARGON2_OWORDS_IN_BLOCK];
72
74
  __m128i zero2_block[ARGON2_OWORDS_IN_BLOCK];
73
75
  memset(zero_block, 0, sizeof(zero_block));
74
76
  memset(zero2_block, 0, sizeof(zero2_block));
77
+ init_block_value(&address_block, 0);
78
+ init_block_value(&tmp_block, 0);
79
+ /*Increasing index counter*/
75
80
  input_block.v[6]++;
76
- fill_block(zero_block, (uint8_t *)&input_block.v,
77
- (uint8_t *)&address_block.v);
78
- fill_block(zero2_block, (uint8_t *)&address_block.v,
81
+ /*First iteration of G*/
82
+ fill_block_with_xor(zero_block, (uint8_t *)&input_block.v,
83
+ (uint8_t *)&tmp_block.v);
84
+ /*Second iteration of G*/
85
+ fill_block_with_xor(zero2_block, (uint8_t *)&tmp_block.v,
79
86
  (uint8_t *)&address_block.v);
80
87
  }
81
88
 
@@ -91,7 +98,7 @@ void fill_segment(const argon2_instance_t *instance,
91
98
  uint32_t prev_offset, curr_offset;
92
99
  uint32_t starting_index, i;
93
100
  __m128i state[64];
94
- int data_independent_addressing = (instance->type == Argon2_i);
101
+ int data_independent_addressing;
95
102
 
96
103
  /* Pseudo-random values that determine the reference block position */
97
104
  uint64_t *pseudo_rands = NULL;
@@ -100,6 +107,8 @@ void fill_segment(const argon2_instance_t *instance,
100
107
  return;
101
108
  }
102
109
 
110
+ data_independent_addressing = (instance->type == Argon2_i);
111
+
103
112
  pseudo_rands =
104
113
  (uint64_t *)malloc(sizeof(uint64_t) * instance->segment_length);
105
114
  if (pseudo_rands == NULL) {
@@ -164,7 +173,7 @@ void fill_segment(const argon2_instance_t *instance,
164
173
  ref_block =
165
174
  instance->memory + instance->lane_length * ref_lane + ref_index;
166
175
  curr_block = instance->memory + curr_offset;
167
- fill_block(state, (uint8_t *)ref_block->v, (uint8_t *)curr_block->v);
176
+ fill_block_with_xor(state, (uint8_t *)ref_block->v, (uint8_t *)curr_block->v);
168
177
  }
169
178
 
170
179
  free(pseudo_rands);
@@ -14,19 +14,18 @@
14
14
  #ifndef ARGON2_OPT_H
15
15
  #define ARGON2_OPT_H
16
16
 
17
- #include <stdint.h>
18
- #include <emmintrin.h>
19
- #include "argon2.h"
20
17
  #include "core.h"
18
+ #include <emmintrin.h>
21
19
 
22
20
  /*
23
- * Function fills a new memory block. Differs from the
21
+ * Function fills a new memory block by XORing the new block over the old one. Memory must be initialized.
22
+ * After finishing, @state is identical to @next_block
24
23
  * @param state Pointer to the just produced block. Content will be updated(!)
25
24
  * @param ref_block Pointer to the reference block
26
- * @param next_block Pointer to the block to be constructed
25
+ * @param next_block Pointer to the block to be XORed over. May coincide with @ref_block
27
26
  * @pre all block pointers must be valid
28
27
  */
29
- void fill_block(__m128i *state, const uint8_t *ref_block, uint8_t *next_block);
28
+ void fill_block_with_xor(__m128i *state, const uint8_t *ref_block, uint8_t *next_block);
30
29
 
31
30
  /*
32
31
  * Generate pseudo-random values to reference blocks in the segment and puts
@@ -40,15 +39,4 @@ void generate_addresses(const argon2_instance_t *instance,
40
39
  const argon2_position_t *position,
41
40
  uint64_t *pseudo_rands);
42
41
 
43
- /*
44
- * Function that fills the segment using previous segments also from other
45
- * threads.
46
- * Identical to the reference code except that it calls optimized FillBlock()
47
- * @param instance Pointer to the current instance
48
- * @param position Current position
49
- * @pre all block pointers must be valid
50
- */
51
- void fill_segment(const argon2_instance_t *instance,
52
- argon2_position_t position);
53
-
54
42
  #endif /* ARGON2_OPT_H */