argon2 1.0.0 → 1.1.0

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