argon2 0.0.1 → 0.0.2

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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -0
  3. data/.travis.yml +2 -0
  4. data/README.md +25 -9
  5. data/argon2.gemspec +10 -2
  6. data/bin/console +1 -1
  7. data/bin/setup +3 -0
  8. data/ext/argon2_wrap/Makefile +72 -0
  9. data/ext/argon2_wrap/argon_wrap.c +65 -0
  10. data/ext/argon2_wrap/extconf.rb +1 -0
  11. data/ext/argon2_wrap/test.c +67 -0
  12. data/ext/phc-winner-argon2/.gitignore +7 -0
  13. data/ext/phc-winner-argon2/LICENSE +31 -0
  14. data/ext/phc-winner-argon2/Makefile +102 -0
  15. data/ext/phc-winner-argon2/README.md +193 -0
  16. data/ext/phc-winner-argon2/argon2-specs.pdf +0 -0
  17. data/ext/phc-winner-argon2/kats/argon2d +12302 -0
  18. data/ext/phc-winner-argon2/kats/argon2d.shasum +1 -0
  19. data/ext/phc-winner-argon2/kats/argon2i +12302 -0
  20. data/ext/phc-winner-argon2/kats/argon2i.shasum +1 -0
  21. data/ext/phc-winner-argon2/kats/check-sums.sh +13 -0
  22. data/ext/phc-winner-argon2/kats/test.sh +47 -0
  23. data/ext/phc-winner-argon2/src/argon2.c +360 -0
  24. data/ext/phc-winner-argon2/src/argon2.h +298 -0
  25. data/ext/phc-winner-argon2/src/bench.c +111 -0
  26. data/ext/phc-winner-argon2/src/blake2/blake2-impl.h +143 -0
  27. data/ext/phc-winner-argon2/src/blake2/blake2.h +74 -0
  28. data/ext/phc-winner-argon2/src/blake2/blake2b.c +372 -0
  29. data/ext/phc-winner-argon2/src/blake2/blamka-round-opt.h +162 -0
  30. data/ext/phc-winner-argon2/src/blake2/blamka-round-ref.h +39 -0
  31. data/ext/phc-winner-argon2/src/core.c +662 -0
  32. data/ext/phc-winner-argon2/src/core.h +226 -0
  33. data/ext/phc-winner-argon2/src/genkat.c +194 -0
  34. data/ext/phc-winner-argon2/src/genkat.h +45 -0
  35. data/ext/phc-winner-argon2/src/opt.c +173 -0
  36. data/ext/phc-winner-argon2/src/opt.h +49 -0
  37. data/ext/phc-winner-argon2/src/ref.c +175 -0
  38. data/ext/phc-winner-argon2/src/ref.h +49 -0
  39. data/ext/phc-winner-argon2/src/run.c +223 -0
  40. data/ext/phc-winner-argon2/src/thread.c +36 -0
  41. data/ext/phc-winner-argon2/src/thread.h +46 -0
  42. data/lib/argon2.rb +15 -32
  43. data/lib/argon2/constants.rb +6 -0
  44. data/lib/argon2/engine.rb +10 -0
  45. data/lib/argon2/errors.rb +36 -0
  46. data/lib/argon2/ffi_engine.rb +47 -0
  47. data/lib/argon2/version.rb +1 -1
  48. metadata +75 -11
@@ -0,0 +1,173 @@
1
+ /*
2
+ * Argon2 source code package
3
+ *
4
+ * Written by Daniel Dinu and Dmitry Khovratovich, 2015
5
+ *
6
+ * This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
7
+ *
8
+ * You should have received a copy of the CC0 Public Domain Dedication along
9
+ * with
10
+ * this software. If not, see
11
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
12
+ */
13
+
14
+ #include <stdint.h>
15
+ #include <string.h>
16
+ #include <stdlib.h>
17
+
18
+ #include <immintrin.h>
19
+
20
+ #include "argon2.h"
21
+ #include "core.h"
22
+ #include "opt.h"
23
+
24
+ #include "blake2/blake2.h"
25
+ #include "blake2/blamka-round-opt.h"
26
+
27
+ void fill_block(__m128i *state, const uint8_t *ref_block, uint8_t *next_block) {
28
+ __m128i block_XY[ARGON2_QWORDS_IN_BLOCK];
29
+ uint32_t i;
30
+
31
+ for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; i++) {
32
+ block_XY[i] = state[i] = _mm_xor_si128(
33
+ state[i], _mm_loadu_si128((__m128i const *)(&ref_block[16 * i])));
34
+ }
35
+
36
+ for (i = 0; i < 8; ++i) {
37
+ BLAKE2_ROUND(state[8 * i + 0], state[8 * i + 1], state[8 * i + 2],
38
+ state[8 * i + 3], state[8 * i + 4], state[8 * i + 5],
39
+ state[8 * i + 6], state[8 * i + 7]);
40
+ }
41
+
42
+ for (i = 0; i < 8; ++i) {
43
+ BLAKE2_ROUND(state[8 * 0 + i], state[8 * 1 + i], state[8 * 2 + i],
44
+ state[8 * 3 + i], state[8 * 4 + i], state[8 * 5 + i],
45
+ state[8 * 6 + i], state[8 * 7 + i]);
46
+ }
47
+
48
+ for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; i++) {
49
+ state[i] = _mm_xor_si128(state[i], block_XY[i]);
50
+ _mm_storeu_si128((__m128i *)(&next_block[16 * i]), state[i]);
51
+ }
52
+ }
53
+
54
+ void generate_addresses(const argon2_instance_t *instance,
55
+ const argon2_position_t *position,
56
+ uint64_t *pseudo_rands) {
57
+ block address_block, input_block;
58
+ uint32_t i;
59
+
60
+ init_block_value(&address_block, 0);
61
+ init_block_value(&input_block, 0);
62
+
63
+ if (instance != NULL && position != NULL) {
64
+ input_block.v[0] = position->pass;
65
+ input_block.v[1] = position->lane;
66
+ input_block.v[2] = position->slice;
67
+ input_block.v[3] = instance->memory_blocks;
68
+ input_block.v[4] = instance->passes;
69
+ input_block.v[5] = instance->type;
70
+
71
+ for (i = 0; i < instance->segment_length; ++i) {
72
+ if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) {
73
+ __m128i zero_block[ARGON2_QWORDS_IN_BLOCK];
74
+ __m128i zero2_block[ARGON2_QWORDS_IN_BLOCK];
75
+ memset(zero_block, 0, sizeof(zero_block));
76
+ memset(zero2_block, 0, sizeof(zero2_block));
77
+ input_block.v[6]++;
78
+ fill_block(zero_block, (uint8_t *)&input_block.v,
79
+ (uint8_t *)&address_block.v);
80
+ fill_block(zero2_block, (uint8_t *)&address_block.v,
81
+ (uint8_t *)&address_block.v);
82
+ }
83
+
84
+ pseudo_rands[i] = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK];
85
+ }
86
+ }
87
+ }
88
+
89
+ void fill_segment(const argon2_instance_t *instance,
90
+ argon2_position_t position) {
91
+ block *ref_block = NULL, *curr_block = NULL;
92
+ uint64_t pseudo_rand, ref_index, ref_lane;
93
+ uint32_t prev_offset, curr_offset;
94
+ uint32_t starting_index, i;
95
+ __m128i state[64];
96
+ int data_independent_addressing = (instance->type == Argon2_i);
97
+
98
+ /* Pseudo-random values that determine the reference block position */
99
+ uint64_t *pseudo_rands = NULL;
100
+
101
+ if (instance == NULL) {
102
+ return;
103
+ }
104
+
105
+ pseudo_rands =
106
+ (uint64_t *)malloc(sizeof(uint64_t) * instance->segment_length);
107
+ if (pseudo_rands == NULL) {
108
+ return;
109
+ }
110
+
111
+ if (data_independent_addressing) {
112
+ generate_addresses(instance, &position, pseudo_rands);
113
+ }
114
+
115
+ starting_index = 0;
116
+
117
+ if ((0 == position.pass) && (0 == position.slice)) {
118
+ starting_index = 2; /* we have already generated the first two blocks */
119
+ }
120
+
121
+ /* Offset of the current block */
122
+ curr_offset = position.lane * instance->lane_length +
123
+ position.slice * instance->segment_length + starting_index;
124
+
125
+ if (0 == curr_offset % instance->lane_length) {
126
+ /* Last block in this lane */
127
+ prev_offset = curr_offset + instance->lane_length - 1;
128
+ } else {
129
+ /* Previous block */
130
+ prev_offset = curr_offset - 1;
131
+ }
132
+
133
+ memcpy(state, ((instance->memory + prev_offset)->v), ARGON2_BLOCK_SIZE);
134
+
135
+ for (i = starting_index; i < instance->segment_length;
136
+ ++i, ++curr_offset, ++prev_offset) {
137
+ /*1.1 Rotating prev_offset if needed */
138
+ if (curr_offset % instance->lane_length == 1) {
139
+ prev_offset = curr_offset - 1;
140
+ }
141
+
142
+ /* 1.2 Computing the index of the reference block */
143
+ /* 1.2.1 Taking pseudo-random value from the previous block */
144
+ if (data_independent_addressing) {
145
+ pseudo_rand = pseudo_rands[i];
146
+ } else {
147
+ pseudo_rand = instance->memory[prev_offset].v[0];
148
+ }
149
+
150
+ /* 1.2.2 Computing the lane of the reference block */
151
+ ref_lane = ((pseudo_rand >> 32)) % instance->lanes;
152
+
153
+ if ((position.pass == 0) && (position.slice == 0)) {
154
+ /* Can not reference other lanes yet */
155
+ ref_lane = position.lane;
156
+ }
157
+
158
+ /* 1.2.3 Computing the number of possible reference block within the
159
+ * lane.
160
+ */
161
+ position.index = i;
162
+ ref_index = index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF,
163
+ ref_lane == position.lane);
164
+
165
+ /* 2 Creating a new block */
166
+ ref_block =
167
+ instance->memory + instance->lane_length * ref_lane + ref_index;
168
+ curr_block = instance->memory + curr_offset;
169
+ fill_block(state, (uint8_t *)ref_block->v, (uint8_t *)curr_block->v);
170
+ }
171
+
172
+ free(pseudo_rands);
173
+ }
@@ -0,0 +1,49 @@
1
+ /*
2
+ * Argon2 source code package
3
+ *
4
+ * Written by Daniel Dinu and Dmitry Khovratovich, 2015
5
+ *
6
+ * This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
7
+ *
8
+ * You should have received a copy of the CC0 Public Domain Dedication along
9
+ * with
10
+ * this software. If not, see
11
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
12
+ */
13
+
14
+ #ifndef ARGON2_OPT_H
15
+ #define ARGON2_OPT_H
16
+
17
+ /*
18
+ * Function fills a new memory block. Differs from the
19
+ * @param state Pointer to the just produced block. Content will be updated(!)
20
+ * @param ref_block Pointer to the reference block
21
+ * @param next_block Pointer to the block to be constructed
22
+ * @pre all block pointers must be valid
23
+ */
24
+ void fill_block(__m128i *state, const uint8_t *ref_block, uint8_t *next_block);
25
+
26
+ /*
27
+ * Generate pseudo-random values to reference blocks in the segment and puts
28
+ * them into the array
29
+ * @param instance Pointer to the current instance
30
+ * @param position Pointer to the current position
31
+ * @param pseudo_rands Pointer to the array of 64-bit values
32
+ * @pre pseudo_rands must point to @a instance->segment_length allocated values
33
+ */
34
+ void generate_addresses(const argon2_instance_t *instance,
35
+ const argon2_position_t *position,
36
+ uint64_t *pseudo_rands);
37
+
38
+ /*
39
+ * Function that fills the segment using previous segments also from other
40
+ * threads.
41
+ * Identical to the reference code except that it calls optimized FillBlock()
42
+ * @param instance Pointer to the current instance
43
+ * @param position Current position
44
+ * @pre all block pointers must be valid
45
+ */
46
+ void fill_segment(const argon2_instance_t *instance,
47
+ argon2_position_t position);
48
+
49
+ #endif /* ARGON2_OPT_H */
@@ -0,0 +1,175 @@
1
+ /*
2
+ * Argon2 source code package
3
+ *
4
+ * Written by Daniel Dinu and Dmitry Khovratovich, 2015
5
+ *
6
+ * This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
7
+ *
8
+ * You should have received a copy of the CC0 Public Domain Dedication along
9
+ * with
10
+ * this software. If not, see
11
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
12
+ */
13
+
14
+ #include <stdint.h>
15
+ #include <string.h>
16
+ #include <stdlib.h>
17
+
18
+ #include "argon2.h"
19
+ #include "core.h"
20
+ #include "ref.h"
21
+
22
+ #include "blake2/blamka-round-ref.h"
23
+ #include "blake2/blake2-impl.h"
24
+ #include "blake2/blake2.h"
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
+
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
+ void generate_addresses(const argon2_instance_t *instance,
64
+ const argon2_position_t *position,
65
+ uint64_t *pseudo_rands) {
66
+ block zero_block, input_block, address_block;
67
+ uint32_t i;
68
+
69
+ init_block_value(&zero_block, 0);
70
+ init_block_value(&input_block, 0);
71
+ init_block_value(&address_block, 0);
72
+
73
+ if (instance != NULL && position != NULL) {
74
+ input_block.v[0] = position->pass;
75
+ input_block.v[1] = position->lane;
76
+ input_block.v[2] = position->slice;
77
+ input_block.v[3] = instance->memory_blocks;
78
+ input_block.v[4] = instance->passes;
79
+ input_block.v[5] = instance->type;
80
+
81
+ for (i = 0; i < instance->segment_length; ++i) {
82
+ if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) {
83
+ input_block.v[6]++;
84
+ fill_block(&zero_block, &input_block, &address_block);
85
+ fill_block(&zero_block, &address_block, &address_block);
86
+ }
87
+
88
+ pseudo_rands[i] = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK];
89
+ }
90
+ }
91
+ }
92
+
93
+ void fill_segment(const argon2_instance_t *instance,
94
+ argon2_position_t position) {
95
+ block *ref_block = NULL, *curr_block = NULL;
96
+ uint64_t pseudo_rand, ref_index, ref_lane;
97
+ uint32_t prev_offset, curr_offset;
98
+ uint32_t starting_index;
99
+ uint32_t i;
100
+ int data_independent_addressing = (instance->type == Argon2_i);
101
+ /* Pseudo-random values that determine the reference block position */
102
+ uint64_t *pseudo_rands = NULL;
103
+
104
+ if (instance == NULL) {
105
+ return;
106
+ }
107
+
108
+ pseudo_rands =
109
+ (uint64_t *)malloc(sizeof(uint64_t) * (instance->segment_length));
110
+
111
+ if (pseudo_rands == NULL) {
112
+ return;
113
+ }
114
+
115
+ if (data_independent_addressing) {
116
+ generate_addresses(instance, &position, pseudo_rands);
117
+ }
118
+
119
+ starting_index = 0;
120
+
121
+ if ((0 == position.pass) && (0 == position.slice)) {
122
+ starting_index = 2; /* we have already generated the first two blocks */
123
+ }
124
+
125
+ /* Offset of the current block */
126
+ curr_offset = position.lane * instance->lane_length +
127
+ position.slice * instance->segment_length + starting_index;
128
+
129
+ if (0 == curr_offset % instance->lane_length) {
130
+ /* Last block in this lane */
131
+ prev_offset = curr_offset + instance->lane_length - 1;
132
+ } else {
133
+ /* Previous block */
134
+ prev_offset = curr_offset - 1;
135
+ }
136
+
137
+ for (i = starting_index; i < instance->segment_length;
138
+ ++i, ++curr_offset, ++prev_offset) {
139
+ /*1.1 Rotating prev_offset if needed */
140
+ if (curr_offset % instance->lane_length == 1) {
141
+ prev_offset = curr_offset - 1;
142
+ }
143
+
144
+ /* 1.2 Computing the index of the reference block */
145
+ /* 1.2.1 Taking pseudo-random value from the previous block */
146
+ if (data_independent_addressing) {
147
+ pseudo_rand = pseudo_rands[i];
148
+ } else {
149
+ pseudo_rand = instance->memory[prev_offset].v[0];
150
+ }
151
+
152
+ /* 1.2.2 Computing the lane of the reference block */
153
+ ref_lane = ((pseudo_rand >> 32)) % instance->lanes;
154
+
155
+ if ((position.pass == 0) && (position.slice == 0)) {
156
+ /* Can not reference other lanes yet */
157
+ ref_lane = position.lane;
158
+ }
159
+
160
+ /* 1.2.3 Computing the number of possible reference block within the
161
+ * lane.
162
+ */
163
+ position.index = i;
164
+ ref_index = index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF,
165
+ ref_lane == position.lane);
166
+
167
+ /* 2 Creating a new block */
168
+ ref_block =
169
+ instance->memory + instance->lane_length * ref_lane + ref_index;
170
+ curr_block = instance->memory + curr_offset;
171
+ fill_block(instance->memory + prev_offset, ref_block, curr_block);
172
+ }
173
+
174
+ free(pseudo_rands);
175
+ }
@@ -0,0 +1,49 @@
1
+ /*
2
+ * Argon2 source code package
3
+ *
4
+ * Written by Daniel Dinu and Dmitry Khovratovich, 2015
5
+ *
6
+ * This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
7
+ *
8
+ * You should have received a copy of the CC0 Public Domain Dedication along
9
+ * with
10
+ * this software. If not, see
11
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
12
+ */
13
+
14
+ #ifndef ARGON2_REF_H
15
+ #define ARGON2_REF_H
16
+
17
+ /*
18
+ * Function fills a new memory block
19
+ * @param prev_block Pointer to the previous block
20
+ * @param ref_block Pointer to the reference block
21
+ * @param next_block Pointer to the block to be constructed
22
+ * @pre all block pointers must be valid
23
+ */
24
+ void fill_block(const block *prev_block, const block *ref_block,
25
+ block *next_block);
26
+
27
+ /*
28
+ * Generate pseudo-random values to reference blocks in the segment and puts
29
+ * them into the array
30
+ * @param instance Pointer to the current instance
31
+ * @param position Pointer to the current position
32
+ * @param pseudo_rands Pointer to the array of 64-bit values
33
+ * @pre pseudo_rands must point to @a instance->segment_length allocated values
34
+ */
35
+ void generate_addresses(const argon2_instance_t *instance,
36
+ const argon2_position_t *position,
37
+ uint64_t *pseudo_rands);
38
+
39
+ /*
40
+ * Function that fills the segment using previous segments also from other
41
+ * threads
42
+ * @param instance Pointer to the current instance
43
+ * @param position Current position
44
+ * @pre all block pointers must be valid
45
+ */
46
+ void fill_segment(const argon2_instance_t *instance,
47
+ argon2_position_t position);
48
+
49
+ #endif /* ARGON2_REF_H */
@@ -0,0 +1,223 @@
1
+ /*
2
+ * Argon2 source code package
3
+ *
4
+ * Written by Daniel Dinu and Dmitry Khovratovich, 2015
5
+ *
6
+ * This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
7
+ *
8
+ * You should have received a copy of the CC0 Public Domain Dedication along
9
+ * with
10
+ * this software. If not, see
11
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
12
+ */
13
+
14
+ #include <stdio.h>
15
+ #include <stdint.h>
16
+ #include <inttypes.h>
17
+ #include <stdlib.h>
18
+ #include <string.h>
19
+ #include <time.h>
20
+
21
+ #include "argon2.h"
22
+ #include "core.h"
23
+
24
+ #define T_COST_DEF 3
25
+ #define LOG_M_COST_DEF 12 /* 2^12 = 4 MiB */
26
+ #define LANES_DEF 1
27
+ #define THREADS_DEF 1
28
+ #define OUT_LEN 32
29
+ #define SALT_LEN 16
30
+
31
+ #define UNUSED_PARAMETER(x) (void)(x)
32
+
33
+ static void usage(const char *cmd) {
34
+ printf("Usage: %s pwd salt [-d] [-t iterations] [-m memory] "
35
+ "[-p parallelism]\n",
36
+ cmd);
37
+
38
+ printf("Parameters:\n");
39
+ printf("\tpwd\t\tThe password to hash\n");
40
+ printf("\tsalt\t\tThe salt to use, at most 16 characters\n");
41
+ printf("\t-d\t\tUse Argon2d instead of Argon2i (which is the default)\n");
42
+ printf("\t-t N\t\tSets the number of iterations to N (default = %d)\n",
43
+ T_COST_DEF);
44
+ printf("\t-m N\t\tSets the memory usage of 2^N KiB (default %d)\n",
45
+ LOG_M_COST_DEF);
46
+ printf("\t-p N\t\tSets parallelism to N threads (default %d)\n",
47
+ THREADS_DEF);
48
+ }
49
+
50
+ static void fatal(const char *error) {
51
+ fprintf(stderr, "Error: %s\n", error);
52
+ exit(1);
53
+ }
54
+
55
+ /*
56
+ Runs Argon2 with certain inputs and parameters, inputs not cleared. Prints the
57
+ Base64-encoded hash string
58
+ @out output array with at least 32 bytes allocated
59
+ @pwd NULL-terminated string, presumably from argv[]
60
+ @salt salt array with at least SALTLEN_DEF bytes allocated
61
+ @t_cost number of iterations
62
+ @m_cost amount of requested memory in KB
63
+ @lanes amount of requested parallelism
64
+ @threads actual parallelism
65
+ @type String, only "d" and "i" are accepted
66
+ */
67
+ static void run(uint8_t *out, char *pwd, uint8_t *salt, uint32_t t_cost,
68
+ uint32_t m_cost, uint32_t lanes, uint32_t threads,
69
+ const char *type) {
70
+ clock_t start_time, stop_time;
71
+ unsigned pwd_length;
72
+ argon2_context context;
73
+ uint32_t i;
74
+
75
+ start_time = clock();
76
+
77
+ if (!pwd) {
78
+ fatal("password missing");
79
+ }
80
+
81
+ if (!salt) {
82
+ secure_wipe_memory(pwd, strlen(pwd));
83
+ fatal("salt missing");
84
+ }
85
+
86
+ pwd_length = strlen(pwd);
87
+
88
+ UNUSED_PARAMETER(threads);
89
+
90
+ context.out = out;
91
+ context.outlen = OUT_LEN;
92
+ context.pwd = (uint8_t *)pwd;
93
+ context.pwdlen = pwd_length;
94
+ context.salt = salt;
95
+ context.saltlen = SALT_LEN;
96
+ context.secret = NULL;
97
+ context.secretlen = 0;
98
+ context.ad = NULL;
99
+ context.adlen = 0;
100
+ context.t_cost = t_cost;
101
+ context.m_cost = m_cost;
102
+ context.lanes = lanes;
103
+ context.threads = lanes;
104
+ context.allocate_cbk = NULL;
105
+ context.free_cbk = NULL;
106
+ context.flags = ARGON2_FLAG_CLEAR_PASSWORD;
107
+
108
+ if (!strcmp(type, "d")) {
109
+ int result = argon2d(&context);
110
+ if (result != ARGON2_OK)
111
+ fatal(error_message(result));
112
+ } else if (!strcmp(type, "i")) {
113
+ int result = argon2i(&context);
114
+ if (result != ARGON2_OK)
115
+ fatal(error_message(result));
116
+ } else {
117
+ secure_wipe_memory(pwd, strlen(pwd));
118
+ fatal("wrong Argon2 type");
119
+ }
120
+
121
+ stop_time = clock();
122
+
123
+ /* add back when proper decoding */
124
+ /*
125
+ char encoded[300];
126
+ encode_string(encoded, sizeof encoded, &context);
127
+ printf("%s\n", encoded);
128
+ */
129
+ printf("Hash:\t\t");
130
+ for (i = 0; i < context.outlen; ++i) {
131
+ printf("%02x", context.out[i]);
132
+ }
133
+ printf("\n");
134
+
135
+ printf("%2.3f seconds\n",
136
+ ((double)stop_time - start_time) / (CLOCKS_PER_SEC));
137
+ }
138
+
139
+ int main(int argc, char *argv[]) {
140
+ unsigned char out[OUT_LEN];
141
+ uint32_t m_cost = 1 << LOG_M_COST_DEF;
142
+ uint32_t t_cost = T_COST_DEF;
143
+ uint32_t lanes = LANES_DEF;
144
+ uint32_t threads = THREADS_DEF;
145
+ char *pwd = NULL;
146
+ uint8_t salt[SALT_LEN];
147
+ const char *type = "i";
148
+ int i;
149
+
150
+ if (argc < 3) {
151
+ usage(argv[0]);
152
+ return ARGON2_MISSING_ARGS;
153
+ }
154
+
155
+ /* get password and salt from command line */
156
+ pwd = argv[1];
157
+ if (strlen(argv[2]) > SALT_LEN) {
158
+ fatal("salt too long");
159
+ }
160
+ memset(salt, 0x00, SALT_LEN); /* pad with null bytes */
161
+ memcpy(salt, argv[2], strlen(argv[2]));
162
+
163
+ /* parse options */
164
+ for (i = 3; i < argc; i++) {
165
+ const char *a = argv[i];
166
+ unsigned long input = 0;
167
+ if (!strcmp(a, "-m")) {
168
+ if (i < argc - 1) {
169
+ i++;
170
+ input = strtoul(argv[i], NULL, 10);
171
+ if (input == 0 || input == ULONG_MAX ||
172
+ input > ARGON2_MAX_MEMORY_BITS) {
173
+ fatal("bad numeric input for -m");
174
+ }
175
+ m_cost = ARGON2_MIN(UINT64_C(1) << input, UINT32_C(0xFFFFFFFF));
176
+ if (m_cost > ARGON2_MAX_MEMORY) {
177
+ fatal("m_cost overflow");
178
+ }
179
+ continue;
180
+ } else {
181
+ fatal("missing -m argument");
182
+ }
183
+ } else if (!strcmp(a, "-t")) {
184
+ if (i < argc - 1) {
185
+ i++;
186
+ input = strtoul(argv[i], NULL, 10);
187
+ if (input == 0 || input == ULONG_MAX ||
188
+ input > ARGON2_MAX_TIME) {
189
+ fatal("bad numeric input for -t");
190
+ }
191
+ t_cost = input;
192
+ continue;
193
+ } else {
194
+ fatal("missing -t argument");
195
+ }
196
+ } else if (!strcmp(a, "-p")) {
197
+ if (i < argc - 1) {
198
+ i++;
199
+ input = strtoul(argv[i], NULL, 10);
200
+ if (input == 0 || input == ULONG_MAX ||
201
+ input > ARGON2_MAX_THREADS || input > ARGON2_MAX_LANES) {
202
+ fatal("bad numeric input for -p");
203
+ }
204
+ threads = input;
205
+ lanes = threads;
206
+ continue;
207
+ } else {
208
+ fatal("missing -p argument");
209
+ }
210
+ } else if (!strcmp(a, "-d")) {
211
+ type = "d";
212
+ } else {
213
+ fatal("unknown argument");
214
+ }
215
+ }
216
+ printf("Type:\t\tArgon2%c\n", type[0]);
217
+ printf("Iterations:\t%" PRIu32 " \n", t_cost);
218
+ printf("Memory:\t\t%" PRIu32 " KiB\n", m_cost);
219
+ printf("Parallelism:\t%" PRIu32 " \n", lanes);
220
+ run(out, pwd, salt, t_cost, m_cost, lanes, threads, type);
221
+
222
+ return ARGON2_OK;
223
+ }