argon2 1.0.0 → 1.1.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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -1
  3. data/README.md +6 -5
  4. data/ext/argon2_wrap/argon_wrap.c +2 -1
  5. data/ext/argon2_wrap/test.c +5 -5
  6. data/ext/phc-winner-argon2/.gitattributes +5 -0
  7. data/ext/phc-winner-argon2/.gitignore +5 -0
  8. data/ext/phc-winner-argon2/Argon2.sln +98 -0
  9. data/ext/phc-winner-argon2/CHANGELOG.md +11 -0
  10. data/ext/phc-winner-argon2/Makefile +7 -2
  11. data/ext/phc-winner-argon2/README.md +27 -15
  12. data/ext/phc-winner-argon2/appveyor.yml +25 -0
  13. data/ext/phc-winner-argon2/export.sh +7 -0
  14. data/ext/phc-winner-argon2/include/argon2.h +24 -1
  15. data/ext/phc-winner-argon2/kats/argon2d +3 -1
  16. data/ext/phc-winner-argon2/kats/argon2d.shasum +1 -1
  17. data/ext/phc-winner-argon2/kats/argon2d_v16 +12304 -0
  18. data/ext/phc-winner-argon2/kats/argon2d_v16.shasum +1 -0
  19. data/ext/phc-winner-argon2/kats/argon2i +3 -1
  20. data/ext/phc-winner-argon2/kats/argon2i.shasum +1 -1
  21. data/ext/phc-winner-argon2/kats/argon2i_v16 +12304 -0
  22. data/ext/phc-winner-argon2/kats/argon2i_v16.shasum +1 -0
  23. data/ext/phc-winner-argon2/kats/check-sums.ps1 +42 -0
  24. data/ext/phc-winner-argon2/kats/check-sums.sh +1 -1
  25. data/ext/phc-winner-argon2/kats/test.ps1 +50 -0
  26. data/ext/phc-winner-argon2/kats/test.sh +45 -43
  27. data/ext/phc-winner-argon2/man/argon2.1 +47 -0
  28. data/ext/phc-winner-argon2/src/argon2.c +29 -15
  29. data/ext/phc-winner-argon2/src/bench.c +5 -22
  30. data/ext/phc-winner-argon2/src/core.c +3 -3
  31. data/ext/phc-winner-argon2/src/core.h +1 -3
  32. data/ext/phc-winner-argon2/src/encoding.c +22 -3
  33. data/ext/phc-winner-argon2/src/encoding.h +6 -0
  34. data/ext/phc-winner-argon2/src/genkat.c +23 -5
  35. data/ext/phc-winner-argon2/src/opt.c +42 -2
  36. data/ext/phc-winner-argon2/src/opt.h +10 -0
  37. data/ext/phc-winner-argon2/src/ref.c +51 -1
  38. data/ext/phc-winner-argon2/src/ref.h +10 -0
  39. data/ext/phc-winner-argon2/src/run.c +67 -42
  40. data/ext/phc-winner-argon2/src/test.c +160 -68
  41. data/ext/phc-winner-argon2/src/thread.c +1 -1
  42. data/ext/phc-winner-argon2/vs2015/Argon2Opt/Argon2Opt.vcxproj +158 -0
  43. data/ext/phc-winner-argon2/vs2015/Argon2Opt/Argon2Opt.vcxproj.filters +69 -0
  44. data/ext/phc-winner-argon2/vs2015/Argon2OptBench/Argon2OptBench.vcxproj +158 -0
  45. data/ext/phc-winner-argon2/vs2015/Argon2OptBench/Argon2OptBench.vcxproj.filters +69 -0
  46. data/ext/phc-winner-argon2/vs2015/Argon2OptGenKAT/Argon2OptGenKAT.vcxproj +167 -0
  47. data/ext/phc-winner-argon2/vs2015/Argon2OptGenKAT/Argon2OptGenKAT.vcxproj.filters +72 -0
  48. data/ext/phc-winner-argon2/vs2015/Argon2OptTestCI/Argon2OptTestCI.vcxproj +159 -0
  49. data/ext/phc-winner-argon2/vs2015/Argon2OptTestCI/Argon2OptTestCI.vcxproj.filters +69 -0
  50. data/ext/phc-winner-argon2/vs2015/Argon2Ref/Argon2Ref.vcxproj +158 -0
  51. data/ext/phc-winner-argon2/vs2015/Argon2Ref/Argon2Ref.vcxproj.filters +69 -0
  52. data/ext/phc-winner-argon2/vs2015/Argon2RefBench/Argon2RefBench.vcxproj +158 -0
  53. data/ext/phc-winner-argon2/vs2015/Argon2RefBench/Argon2RefBench.vcxproj.filters +69 -0
  54. data/ext/phc-winner-argon2/vs2015/Argon2RefGenKAT/Argon2RefGenKAT.vcxproj +159 -0
  55. data/ext/phc-winner-argon2/vs2015/Argon2RefGenKAT/Argon2RefGenKAT.vcxproj.filters +72 -0
  56. data/ext/phc-winner-argon2/vs2015/Argon2RefTestCI/Argon2RefTestCI.vcxproj +158 -0
  57. data/ext/phc-winner-argon2/vs2015/Argon2RefTestCI/Argon2RefTestCI.vcxproj.filters +69 -0
  58. data/lib/argon2.rb +5 -1
  59. data/lib/argon2/version.rb +1 -1
  60. metadata +29 -3
@@ -229,7 +229,7 @@ static const char *decode_decimal(const char *str, unsigned long *v) {
229
229
  *
230
230
  * The code below applies the following format:
231
231
  *
232
- * $argon2<T>$m=<num>,t=<num>,p=<num>[,keyid=<bin>][,data=<bin>][$<bin>[$<bin>]]
232
+ * $argon2<T>[$v=<num>]$m=<num>,t=<num>,p=<num>[,keyid=<bin>][,data=<bin>][$<bin>[$<bin>]]
233
233
  *
234
234
  * where <T> is either 'd' or 'i', <num> is a decimal integer (positive, fits in
235
235
  * an 'unsigned long'), and <bin> is Base64-encoded data (no '=' padding
@@ -303,6 +303,9 @@ int decode_string(argon2_context *ctx, const char *str, argon2_type type) {
303
303
  CC("$argon2d");
304
304
  else
305
305
  return ARGON2_INCORRECT_TYPE;
306
+ ctx->version = ARGON2_VERSION_10;
307
+ /* Reading the version number if the default is suppressed */
308
+ CC_opt("$v=", DECIMAL(ctx->version));
306
309
  CC("$m=");
307
310
  DECIMAL(ctx->m_cost);
308
311
  CC(",t=");
@@ -368,15 +371,17 @@ int encode_string(char *dst, size_t dst_len, argon2_context *ctx,
368
371
  } while ((void)0, 0)
369
372
 
370
373
  if (type == Argon2_i)
371
- SS("$argon2i$m=");
374
+ SS("$argon2i$v=");
372
375
  else if (type == Argon2_d)
373
- SS("$argon2d$m=");
376
+ SS("$argon2d$v=");
374
377
  else
375
378
  return ARGON2_ENCODING_FAIL;
376
379
 
377
380
  if (validate_inputs(ctx) != ARGON2_OK) {
378
381
  return validate_inputs(ctx);
379
382
  }
383
+ SX(ctx->version);
384
+ SS("$m=");
380
385
  SX(ctx->m_cost);
381
386
  SS(",t=");
382
387
  SX(ctx->t_cost);
@@ -405,3 +410,17 @@ int encode_string(char *dst, size_t dst_len, argon2_context *ctx,
405
410
  #undef SX
406
411
  #undef SB
407
412
  }
413
+
414
+ size_t b64len(uint32_t len) {
415
+ return (((size_t)len + 2) / 3) * 4;
416
+ }
417
+
418
+ size_t numlen(uint32_t num) {
419
+ size_t len = 1;
420
+ while (num >= 10) {
421
+ ++len;
422
+ num = num / 10;
423
+ }
424
+ return len;
425
+ }
426
+
@@ -31,4 +31,10 @@ int encode_string(char *dst, size_t dst_len, argon2_context *ctx,
31
31
  */
32
32
  int decode_string(argon2_context *ctx, const char *str, argon2_type type);
33
33
 
34
+ /* Returns the length of the encoded byte stream with length len */
35
+ size_t b64len(uint32_t len);
36
+
37
+ /* Returns the length of the encoded number num */
38
+ size_t numlen(uint32_t num);
39
+
34
40
  #endif
@@ -23,21 +23,24 @@ void initial_kat(const uint8_t *blockhash, const argon2_context *context,
23
23
  unsigned i;
24
24
 
25
25
  if (blockhash != NULL && context != NULL) {
26
- printf("=======================================");
26
+ printf("=======================================\n");
27
27
 
28
28
  switch (type) {
29
29
  case Argon2_d:
30
- printf("Argon2d\n");
30
+ printf("Argon2d version number %d\n", context->version);
31
31
  break;
32
32
 
33
33
  case Argon2_i:
34
- printf("Argon2i\n");
34
+ printf("Argon2i version number %d\n", context->version);
35
35
  break;
36
36
 
37
37
  default:
38
38
  break;
39
39
  }
40
40
 
41
+ printf("=======================================\n");
42
+
43
+
41
44
  printf("Memory: %u KiB, Iterations: %u, Parallelism: %u lanes, Tag "
42
45
  "length: %u bytes\n",
43
46
  context->m_cost, context->t_cost, context->lanes,
@@ -130,7 +133,7 @@ static void fatal(const char *error) {
130
133
  exit(1);
131
134
  }
132
135
 
133
- static void generate_testvectors(const char *type) {
136
+ static void generate_testvectors(const char *type, const uint32_t version) {
134
137
  #define TEST_OUTLEN 32
135
138
  #define TEST_PWDLEN 32
136
139
  #define TEST_SALTLEN 16
@@ -157,6 +160,7 @@ static void generate_testvectors(const char *type) {
157
160
 
158
161
  context.out = out;
159
162
  context.outlen = TEST_OUTLEN;
163
+ context.version = ARGON2_VERSION_NUMBER;
160
164
  context.pwd = pwd;
161
165
  context.pwdlen = TEST_PWDLEN;
162
166
  context.salt = salt;
@@ -173,6 +177,12 @@ static void generate_testvectors(const char *type) {
173
177
  context.free_cbk = myown_deallocator;
174
178
  context.flags = 0;
175
179
 
180
+ if(ARGON2_VERSION_10 == version || ARGON2_VERSION_NUMBER == version) {
181
+ context.version = version;
182
+ } else {
183
+ fatal("wrong Argon2 version number");
184
+ }
185
+
176
186
  #undef TEST_OUTLEN
177
187
  #undef TEST_PWDLEN
178
188
  #undef TEST_SALTLEN
@@ -188,7 +198,15 @@ static void generate_testvectors(const char *type) {
188
198
  }
189
199
 
190
200
  int main(int argc, char *argv[]) {
201
+ /* Argon2 type */
191
202
  const char *type = (argc > 1) ? argv[1] : "i";
192
- generate_testvectors(type);
203
+
204
+ /* Argon2 version number */
205
+ uint32_t version = ARGON2_VERSION_NUMBER;
206
+ if(argc > 2) {
207
+ version = strtoul(argv[2], NULL, 10);
208
+ }
209
+
210
+ generate_testvectors(type, version);
193
211
  return ARGON2_OK;
194
212
  }
@@ -21,7 +21,35 @@
21
21
  #include "blake2/blake2.h"
22
22
  #include "blake2/blamka-round-opt.h"
23
23
 
24
- void fill_block_with_xor(__m128i *state, const uint8_t *ref_block, uint8_t *next_block) {
24
+ void fill_block(__m128i *state, const uint8_t *ref_block, uint8_t *next_block) {
25
+ __m128i block_XY[ARGON2_OWORDS_IN_BLOCK];
26
+ uint32_t i;
27
+
28
+ for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
29
+ block_XY[i] = state[i] = _mm_xor_si128(
30
+ state[i], _mm_loadu_si128((__m128i const *)(&ref_block[16 * i])));
31
+ }
32
+
33
+ for (i = 0; i < 8; ++i) {
34
+ BLAKE2_ROUND(state[8 * i + 0], state[8 * i + 1], state[8 * i + 2],
35
+ state[8 * i + 3], state[8 * i + 4], state[8 * i + 5],
36
+ state[8 * i + 6], state[8 * i + 7]);
37
+ }
38
+
39
+ for (i = 0; i < 8; ++i) {
40
+ BLAKE2_ROUND(state[8 * 0 + i], state[8 * 1 + i], state[8 * 2 + i],
41
+ state[8 * 3 + i], state[8 * 4 + i], state[8 * 5 + i],
42
+ state[8 * 6 + i], state[8 * 7 + i]);
43
+ }
44
+
45
+ for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
46
+ state[i] = _mm_xor_si128(state[i], block_XY[i]);
47
+ _mm_storeu_si128((__m128i *)(&next_block[16 * i]), state[i]);
48
+ }
49
+ }
50
+
51
+ void fill_block_with_xor(__m128i *state, const uint8_t *ref_block,
52
+ uint8_t *next_block) {
25
53
  __m128i block_XY[ARGON2_OWORDS_IN_BLOCK];
26
54
  uint32_t i;
27
55
 
@@ -173,7 +201,19 @@ void fill_segment(const argon2_instance_t *instance,
173
201
  ref_block =
174
202
  instance->memory + instance->lane_length * ref_lane + ref_index;
175
203
  curr_block = instance->memory + curr_offset;
176
- fill_block_with_xor(state, (uint8_t *)ref_block->v, (uint8_t *)curr_block->v);
204
+ if (ARGON2_VERSION_10 == instance->version) {
205
+ /* version 1.2.1 and earlier: overwrite, not XOR */
206
+ fill_block(state, (uint8_t *)ref_block->v,
207
+ (uint8_t *)curr_block->v);
208
+ } else {
209
+ if(0 == position.pass) {
210
+ fill_block(state, (uint8_t *)ref_block->v,
211
+ (uint8_t *)curr_block->v);
212
+ } else {
213
+ fill_block_with_xor(state, (uint8_t *)ref_block->v,
214
+ (uint8_t *)curr_block->v);
215
+ }
216
+ }
177
217
  }
178
218
 
179
219
  free(pseudo_rands);
@@ -27,6 +27,16 @@
27
27
  */
28
28
  void fill_block_with_xor(__m128i *state, const uint8_t *ref_block, uint8_t *next_block);
29
29
 
30
+ /* LEGACY CODE: version 1.2.1 and earlier
31
+ * Function fills a new memory block by overwriting @next_block.
32
+ * @param state Pointer to the just produced block. Content will be updated(!)
33
+ * @param ref_block Pointer to the reference block
34
+ * @param next_block Pointer to the block to be XORed over. May coincide with @ref_block
35
+ * @pre all block pointers must be valid
36
+ */
37
+ void fill_block(__m128i *state, const uint8_t *ref_block, uint8_t *next_block);
38
+
39
+
30
40
  /*
31
41
  * Generate pseudo-random values to reference blocks in the segment and puts
32
42
  * them into the array
@@ -22,6 +22,45 @@
22
22
  #include "blake2/blake2-impl.h"
23
23
  #include "blake2/blake2.h"
24
24
 
25
+
26
+ void fill_block(const block *prev_block, const block *ref_block,
27
+ block *next_block) {
28
+ block blockR, block_tmp;
29
+ unsigned i;
30
+
31
+ copy_block(&blockR, ref_block);
32
+ xor_block(&blockR, prev_block);
33
+ copy_block(&block_tmp, &blockR);
34
+ /*Now blockR = ref_block + prev_block and bloc_tmp = ref_block + prev_block */
35
+ /* Apply Blake2 on columns of 64-bit words: (0,1,...,15) , then
36
+ (16,17,..31)... finally (112,113,...127) */
37
+ for (i = 0; i < 8; ++i) {
38
+ BLAKE2_ROUND_NOMSG(
39
+ blockR.v[16 * i], blockR.v[16 * i + 1], blockR.v[16 * i + 2],
40
+ blockR.v[16 * i + 3], blockR.v[16 * i + 4], blockR.v[16 * i + 5],
41
+ blockR.v[16 * i + 6], blockR.v[16 * i + 7], blockR.v[16 * i + 8],
42
+ blockR.v[16 * i + 9], blockR.v[16 * i + 10], blockR.v[16 * i + 11],
43
+ blockR.v[16 * i + 12], blockR.v[16 * i + 13], blockR.v[16 * i + 14],
44
+ blockR.v[16 * i + 15]);
45
+ }
46
+
47
+ /* Apply Blake2 on rows of 64-bit words: (0,1,16,17,...112,113), then
48
+ (2,3,18,19,...,114,115).. finally (14,15,30,31,...,126,127) */
49
+ for (i = 0; i < 8; i++) {
50
+ BLAKE2_ROUND_NOMSG(
51
+ blockR.v[2 * i], blockR.v[2 * i + 1], blockR.v[2 * i + 16],
52
+ blockR.v[2 * i + 17], blockR.v[2 * i + 32], blockR.v[2 * i + 33],
53
+ blockR.v[2 * i + 48], blockR.v[2 * i + 49], blockR.v[2 * i + 64],
54
+ blockR.v[2 * i + 65], blockR.v[2 * i + 80], blockR.v[2 * i + 81],
55
+ blockR.v[2 * i + 96], blockR.v[2 * i + 97], blockR.v[2 * i + 112],
56
+ blockR.v[2 * i + 113]);
57
+ }
58
+
59
+ copy_block(next_block, &block_tmp);
60
+ xor_block(next_block, &blockR);
61
+ }
62
+
63
+
25
64
  void fill_block_with_xor(const block *prev_block, const block *ref_block,
26
65
  block *next_block) {
27
66
  block blockR, block_tmp;
@@ -171,7 +210,18 @@ void fill_segment(const argon2_instance_t *instance,
171
210
  ref_block =
172
211
  instance->memory + instance->lane_length * ref_lane + ref_index;
173
212
  curr_block = instance->memory + curr_offset;
174
- fill_block_with_xor(instance->memory + prev_offset, ref_block, curr_block);
213
+ if (ARGON2_VERSION_10 == instance->version) {
214
+ /* version 1.2.1 and earlier: overwrite, not XOR */
215
+ fill_block(instance->memory + prev_offset, ref_block, curr_block);
216
+ } else {
217
+ if(0 == position.pass) {
218
+ fill_block(instance->memory + prev_offset, ref_block,
219
+ curr_block);
220
+ } else {
221
+ fill_block_with_xor(instance->memory + prev_offset, ref_block,
222
+ curr_block);
223
+ }
224
+ }
175
225
  }
176
226
 
177
227
  free(pseudo_rands);
@@ -26,6 +26,16 @@
26
26
  void fill_block_with_xor(const block *prev_block, const block *ref_block,
27
27
  block *next_block);
28
28
 
29
+ /* LEGACY CODE: version 1.2.1 and earlier
30
+ * Function fills a new memory block by overwriting @next_block.
31
+ * @param prev_block Pointer to the previous block
32
+ * @param ref_block Pointer to the reference block
33
+ * @param next_block Pointer to the block to be constructed
34
+ * @pre all block pointers must be valid
35
+ */
36
+ void fill_block(const block *prev_block, const block *ref_block,
37
+ block *next_block);
38
+
29
39
  /*
30
40
  * Generate pseudo-random values to reference blocks in the segment and puts
31
41
  * them into the array
@@ -28,12 +28,13 @@
28
28
  #define LANES_DEF 1
29
29
  #define THREADS_DEF 1
30
30
  #define OUTLEN_DEF 32
31
+ #define MAX_PASS_LEN 128
31
32
 
32
33
  #define UNUSED_PARAMETER(x) (void)(x)
33
34
 
34
35
  static void usage(const char *cmd) {
35
36
  printf("Usage: %s salt [-d] [-t iterations] [-m memory] "
36
- "[-p parallelism] [-h hash length]\n",
37
+ "[-p parallelism] [-h hash length] [-e|-r]\n",
37
38
  cmd);
38
39
  printf("\tPassword is read from stdin\n");
39
40
  printf("Parameters:\n");
@@ -47,6 +48,8 @@ static void usage(const char *cmd) {
47
48
  THREADS_DEF);
48
49
  printf("\t-h N\t\tSets hash output length to N bytes (default %d)\n",
49
50
  OUTLEN_DEF);
51
+ printf("\t-e\t\tOutput only encoded hash\n");
52
+ printf("\t-r\t\tOutput only the raw bytes of the hash\n");
50
53
  }
51
54
 
52
55
  static void fatal(const char *error) {
@@ -54,26 +57,14 @@ static void fatal(const char *error) {
54
57
  exit(1);
55
58
  }
56
59
 
57
- static uint32_t b64len(uint32_t len) {
58
- return ((len + 2) / 3) * 4;
59
- }
60
-
61
- static uint32_t numlen(uint32_t num) {
62
- uint32_t len = 1;
63
- while (num >= 10) {
64
- ++len;
65
- num = num / 10;
60
+ static void print_hex(uint8_t *bytes, size_t bytes_len) {
61
+ size_t i;
62
+ for (i = 0; i < bytes_len; ++i) {
63
+ printf("%02x", bytes[i]);
66
64
  }
67
- return len;
68
- }
69
-
70
- static uint32_t enclen(uint32_t outlen, uint32_t saltlen, uint32_t t_cost,
71
- uint32_t m_cost, uint32_t lanes) {
72
- return strlen("$argon2x$m=,t=,p=$$") + numlen(t_cost) + numlen(m_cost)
73
- + numlen(lanes) + b64len(saltlen) + b64len(outlen);
65
+ printf("\n");
74
66
  }
75
67
 
76
-
77
68
  /*
78
69
  Runs Argon2 with certain inputs and parameters, inputs not cleared. Prints the
79
70
  Base64-encoded hash string
@@ -84,14 +75,15 @@ Base64-encoded hash string
84
75
  @m_cost amount of requested memory in KB
85
76
  @lanes amount of requested parallelism
86
77
  @threads actual parallelism
87
- @type String, only "d" and "i" are accepted
78
+ @type String, only "d" and "i" are acceptedi
79
+ @encoded_only display only the encoded hash
80
+ @raw_only display only the hexadecimal of the hash
88
81
  */
89
82
  static void run(uint32_t outlen, char *pwd, char *salt, uint32_t t_cost,
90
83
  uint32_t m_cost, uint32_t lanes, uint32_t threads,
91
- argon2_type type) {
84
+ argon2_type type, int encoded_only, int raw_only) {
92
85
  clock_t start_time, stop_time;
93
86
  size_t pwdlen, saltlen, encodedlen;
94
- uint32_t i;
95
87
  int result;
96
88
 
97
89
  start_time = clock();
@@ -116,7 +108,7 @@ static void run(uint32_t outlen, char *pwd, char *salt, uint32_t t_cost,
116
108
  fatal("could not allocate memory for output");
117
109
  }
118
110
 
119
- encodedlen = enclen(outlen, saltlen, t_cost, m_cost, lanes);
111
+ encodedlen = argon2_encodedlen(t_cost, m_cost, lanes, saltlen, outlen);
120
112
  char* encoded = malloc(encodedlen + 1);
121
113
  if (!encoded) {
122
114
  secure_wipe_memory(pwd, strlen(pwd));
@@ -124,18 +116,29 @@ static void run(uint32_t outlen, char *pwd, char *salt, uint32_t t_cost,
124
116
  }
125
117
 
126
118
  result = argon2_hash(t_cost, m_cost, threads, pwd, pwdlen, salt, saltlen,
127
- out, outlen, encoded, encodedlen, type);
119
+ out, outlen, encoded, encodedlen, type,
120
+ ARGON2_VERSION_NUMBER);
128
121
  if (result != ARGON2_OK)
129
122
  fatal(argon2_error_message(result));
130
123
 
131
124
  stop_time = clock();
132
125
 
133
- printf("Hash:\t\t");
134
- for (i = 0; i < outlen; ++i) {
135
- printf("%02x", out[i]);
126
+ if (encoded_only)
127
+ puts(encoded);
128
+
129
+ if (raw_only)
130
+ print_hex(out, outlen);
131
+
132
+ if (encoded_only || raw_only) {
133
+ free(out);
134
+ free(encoded);
135
+ return;
136
136
  }
137
+
138
+ printf("Hash:\t\t");
139
+ print_hex(out, outlen);
137
140
  free(out);
138
- printf("\n");
141
+
139
142
  printf("Encoded:\t%s\n", encoded);
140
143
 
141
144
  printf("%2.3f seconds\n",
@@ -155,23 +158,32 @@ int main(int argc, char *argv[]) {
155
158
  uint32_t lanes = LANES_DEF;
156
159
  uint32_t threads = THREADS_DEF;
157
160
  argon2_type type = Argon2_i;
161
+ int encoded_only = 0;
162
+ int raw_only = 0;
158
163
  int i;
159
164
  size_t n;
160
- char pwd[128], *salt;
165
+ char pwd[MAX_PASS_LEN], *salt;
161
166
 
162
167
  if (argc < 2) {
163
168
  usage(argv[0]);
164
169
  return ARGON2_MISSING_ARGS;
165
170
  }
166
171
 
167
- salt = argv[1];
168
-
169
172
  /* get password from stdin */
170
- while ((n = fread(pwd, 1, sizeof pwd - 1, stdin)) > 0) {
171
- pwd[n] = '\0';
172
- if (pwd[n - 1] == '\n')
173
- pwd[n - 1] = '\0';
173
+ n = fread(pwd, 1, sizeof pwd - 1, stdin);
174
+ if(n < 1) {
175
+ fatal("no password read");
174
176
  }
177
+ if(n == MAX_PASS_LEN-1) {
178
+ fatal("Provided password longer than supported in command line utility");
179
+ }
180
+
181
+ pwd[n] = '\0';
182
+ if (pwd[n - 1] == '\n') {
183
+ pwd[n - 1] = '\0';
184
+ }
185
+
186
+ salt = argv[1];
175
187
 
176
188
  /* parse options */
177
189
  for (i = 2; i < argc; i++) {
@@ -231,19 +243,32 @@ int main(int argc, char *argv[]) {
231
243
  }
232
244
  } else if (!strcmp(a, "-d")) {
233
245
  type = Argon2_d;
246
+ } else if (!strcmp(a, "-e")) {
247
+ encoded_only = 1;
248
+ } else if (!strcmp(a, "-r")) {
249
+ raw_only = 1;
234
250
  } else {
235
251
  fatal("unknown argument");
236
252
  }
237
253
  }
238
- if (type == Argon2_i) {
239
- printf("Type:\t\tArgon2i\n");
240
- } else {
241
- printf("Type:\t\tArgon2d\n");
254
+
255
+ if(encoded_only && raw_only)
256
+ fatal("cannot provide both -e and -r");
257
+
258
+ if(!encoded_only && !raw_only) {
259
+ if (type == Argon2_i) {
260
+ printf("Type:\t\tArgon2i\n");
261
+ } else {
262
+ printf("Type:\t\tArgon2d\n");
263
+ }
264
+ printf("Iterations:\t%" PRIu32 " \n", t_cost);
265
+ printf("Memory:\t\t%" PRIu32 " KiB\n", m_cost);
266
+ printf("Parallelism:\t%" PRIu32 " \n", lanes);
242
267
  }
243
- printf("Iterations:\t%" PRIu32 " \n", t_cost);
244
- printf("Memory:\t\t%" PRIu32 " KiB\n", m_cost);
245
- printf("Parallelism:\t%" PRIu32 " \n", lanes);
246
- run(outlen, pwd, salt, t_cost, m_cost, lanes, threads, type);
268
+
269
+ run(outlen, pwd, salt, t_cost, m_cost, lanes, threads, type,
270
+ encoded_only, raw_only);
247
271
 
248
272
  return ARGON2_OK;
249
273
  }
274
+