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.
- checksums.yaml +4 -4
- data/.gitignore +4 -0
- data/.travis.yml +2 -0
- data/README.md +25 -9
- data/argon2.gemspec +10 -2
- data/bin/console +1 -1
- data/bin/setup +3 -0
- data/ext/argon2_wrap/Makefile +72 -0
- data/ext/argon2_wrap/argon_wrap.c +65 -0
- data/ext/argon2_wrap/extconf.rb +1 -0
- data/ext/argon2_wrap/test.c +67 -0
- data/ext/phc-winner-argon2/.gitignore +7 -0
- data/ext/phc-winner-argon2/LICENSE +31 -0
- data/ext/phc-winner-argon2/Makefile +102 -0
- data/ext/phc-winner-argon2/README.md +193 -0
- data/ext/phc-winner-argon2/argon2-specs.pdf +0 -0
- data/ext/phc-winner-argon2/kats/argon2d +12302 -0
- data/ext/phc-winner-argon2/kats/argon2d.shasum +1 -0
- data/ext/phc-winner-argon2/kats/argon2i +12302 -0
- data/ext/phc-winner-argon2/kats/argon2i.shasum +1 -0
- data/ext/phc-winner-argon2/kats/check-sums.sh +13 -0
- data/ext/phc-winner-argon2/kats/test.sh +47 -0
- data/ext/phc-winner-argon2/src/argon2.c +360 -0
- data/ext/phc-winner-argon2/src/argon2.h +298 -0
- data/ext/phc-winner-argon2/src/bench.c +111 -0
- data/ext/phc-winner-argon2/src/blake2/blake2-impl.h +143 -0
- data/ext/phc-winner-argon2/src/blake2/blake2.h +74 -0
- data/ext/phc-winner-argon2/src/blake2/blake2b.c +372 -0
- data/ext/phc-winner-argon2/src/blake2/blamka-round-opt.h +162 -0
- data/ext/phc-winner-argon2/src/blake2/blamka-round-ref.h +39 -0
- data/ext/phc-winner-argon2/src/core.c +662 -0
- data/ext/phc-winner-argon2/src/core.h +226 -0
- data/ext/phc-winner-argon2/src/genkat.c +194 -0
- data/ext/phc-winner-argon2/src/genkat.h +45 -0
- data/ext/phc-winner-argon2/src/opt.c +173 -0
- data/ext/phc-winner-argon2/src/opt.h +49 -0
- data/ext/phc-winner-argon2/src/ref.c +175 -0
- data/ext/phc-winner-argon2/src/ref.h +49 -0
- data/ext/phc-winner-argon2/src/run.c +223 -0
- data/ext/phc-winner-argon2/src/thread.c +36 -0
- data/ext/phc-winner-argon2/src/thread.h +46 -0
- data/lib/argon2.rb +15 -32
- data/lib/argon2/constants.rb +6 -0
- data/lib/argon2/engine.rb +10 -0
- data/lib/argon2/errors.rb +36 -0
- data/lib/argon2/ffi_engine.rb +47 -0
- data/lib/argon2/version.rb +1 -1
- 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
|
+
}
|