argon2 0.1.4 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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 */