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