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 @@
|
|
1
|
+
d94efacfa5efcdfeb513c829cccda7d9003640e1de64b12fad80f92aad1ab8a4 argon2i
|
@@ -0,0 +1,47 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
make genkat > /dev/null
|
4
|
+
if [ $? -ne 0 ]
|
5
|
+
then
|
6
|
+
exit $?
|
7
|
+
fi
|
8
|
+
|
9
|
+
printf "argon2i "
|
10
|
+
./genkat i > tmp
|
11
|
+
if diff tmp kats/argon2i
|
12
|
+
then printf "OK"
|
13
|
+
else printf "ERROR"
|
14
|
+
fi
|
15
|
+
printf "\n"
|
16
|
+
|
17
|
+
printf "argon2d "
|
18
|
+
./genkat d > tmp
|
19
|
+
if diff tmp kats/argon2d
|
20
|
+
then printf "OK"
|
21
|
+
else printf "ERROR"
|
22
|
+
fi
|
23
|
+
printf "\n"
|
24
|
+
|
25
|
+
make genkat OPT=TRUE > /dev/null
|
26
|
+
if [ $? -ne 0 ]
|
27
|
+
then
|
28
|
+
exit $?
|
29
|
+
fi
|
30
|
+
|
31
|
+
printf "argon2i "
|
32
|
+
./genkat i > tmp
|
33
|
+
if diff tmp kats/argon2i
|
34
|
+
then printf "OK"
|
35
|
+
else printf "ERROR"
|
36
|
+
fi
|
37
|
+
printf "\n"
|
38
|
+
|
39
|
+
printf "argon2d "
|
40
|
+
./genkat d > tmp
|
41
|
+
if diff tmp kats/argon2d
|
42
|
+
then printf "OK"
|
43
|
+
else printf "ERROR"
|
44
|
+
fi
|
45
|
+
printf "\n"
|
46
|
+
|
47
|
+
rm -f tmp
|
@@ -0,0 +1,360 @@
|
|
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 <stdio.h>
|
17
|
+
#include <limits.h>
|
18
|
+
|
19
|
+
#include "argon2.h"
|
20
|
+
#include "core.h"
|
21
|
+
|
22
|
+
/* Error messages */
|
23
|
+
static const char *Argon2_ErrorMessage[] = {
|
24
|
+
/*{ARGON2_OK, */ "OK",
|
25
|
+
/*},
|
26
|
+
|
27
|
+
{ARGON2_OUTPUT_PTR_NULL, */ "Output pointer is NULL",
|
28
|
+
/*},
|
29
|
+
|
30
|
+
{ARGON2_OUTPUT_TOO_SHORT, */ "Output is too short",
|
31
|
+
/*},
|
32
|
+
{ARGON2_OUTPUT_TOO_LONG, */ "Output is too long",
|
33
|
+
/*},
|
34
|
+
|
35
|
+
{ARGON2_PWD_TOO_SHORT, */ "Password is too short",
|
36
|
+
/*},
|
37
|
+
{ARGON2_PWD_TOO_LONG, */ "Password is too long",
|
38
|
+
/*},
|
39
|
+
|
40
|
+
{ARGON2_SALT_TOO_SHORT, */ "Salt is too short",
|
41
|
+
/*},
|
42
|
+
{ARGON2_SALT_TOO_LONG, */ "Salt is too long",
|
43
|
+
/*},
|
44
|
+
|
45
|
+
{ARGON2_AD_TOO_SHORT, */ "Associated data is too short",
|
46
|
+
/*},
|
47
|
+
{ARGON2_AD_TOO_LONG, */ "Associated date is too long",
|
48
|
+
/*},
|
49
|
+
|
50
|
+
{ARGON2_SECRET_TOO_SHORT, */ "Secret is too short",
|
51
|
+
/*},
|
52
|
+
{ARGON2_SECRET_TOO_LONG, */ "Secret is too long",
|
53
|
+
/*},
|
54
|
+
|
55
|
+
{ARGON2_TIME_TOO_SMALL, */ "Time cost is too small",
|
56
|
+
/*},
|
57
|
+
{ARGON2_TIME_TOO_LARGE, */ "Time cost is too large",
|
58
|
+
/*},
|
59
|
+
|
60
|
+
{ARGON2_MEMORY_TOO_LITTLE, */ "Memory cost is too small",
|
61
|
+
/*},
|
62
|
+
{ARGON2_MEMORY_TOO_MUCH, */ "Memory cost is too large",
|
63
|
+
/*},
|
64
|
+
|
65
|
+
{ARGON2_LANES_TOO_FEW, */ "Too few lanes",
|
66
|
+
/*},
|
67
|
+
{ARGON2_LANES_TOO_MANY, */ "Too many lanes",
|
68
|
+
/*},
|
69
|
+
|
70
|
+
{ARGON2_PWD_PTR_MISMATCH, */ "Password pointer is NULL, but password length is not 0",
|
71
|
+
/*},
|
72
|
+
{ARGON2_SALT_PTR_MISMATCH, */ "Salt pointer is NULL, but salt length is not 0",
|
73
|
+
/*},
|
74
|
+
{ARGON2_SECRET_PTR_MISMATCH, */ "Secret pointer is NULL, but secret length is not 0",
|
75
|
+
/*},
|
76
|
+
{ARGON2_AD_PTR_MISMATCH, */ "Associated data pointer is NULL, but ad length is not 0",
|
77
|
+
/*},
|
78
|
+
|
79
|
+
{ARGON2_MEMORY_ALLOCATION_ERROR, */ "Memory allocation error",
|
80
|
+
/*},
|
81
|
+
|
82
|
+
{ARGON2_FREE_MEMORY_CBK_NULL, */ "The free memory callback is NULL",
|
83
|
+
/*},
|
84
|
+
{ARGON2_ALLOCATE_MEMORY_CBK_NULL, */ "The allocate memory callback is NULL",
|
85
|
+
/*},
|
86
|
+
|
87
|
+
{ARGON2_INCORRECT_PARAMETER, */ "Argon2_Context context is NULL",
|
88
|
+
/*},
|
89
|
+
{ARGON2_INCORRECT_TYPE, */ "There is no such version of Argon2",
|
90
|
+
/*},
|
91
|
+
|
92
|
+
{ARGON2_OUT_PTR_MISMATCH, */ "Output pointer mismatch",
|
93
|
+
/*},
|
94
|
+
|
95
|
+
{ARGON2_THREADS_TOO_FEW, */ "Not enough threads",
|
96
|
+
/*},
|
97
|
+
{ARGON2_THREADS_TOO_MANY, */ "Too many threads",
|
98
|
+
/*},
|
99
|
+
{ARGON2_MISSING_ARGS, */ "Missing arguments", /*},*/
|
100
|
+
};
|
101
|
+
|
102
|
+
int hash_argon2i(void *out, size_t outlen, const void *in, size_t inlen,
|
103
|
+
const void *salt, size_t saltlen, unsigned int t_cost,
|
104
|
+
unsigned int m_cost) {
|
105
|
+
|
106
|
+
argon2_context context;
|
107
|
+
|
108
|
+
/* Detect and reject overflowing sizes */
|
109
|
+
/* TODO: This should probably be fixed in the function signature */
|
110
|
+
if (inlen > UINT32_MAX) {
|
111
|
+
return ARGON2_PWD_TOO_LONG;
|
112
|
+
}
|
113
|
+
|
114
|
+
if (outlen > UINT32_MAX) {
|
115
|
+
return ARGON2_OUTPUT_TOO_LONG;
|
116
|
+
}
|
117
|
+
|
118
|
+
if (saltlen > UINT32_MAX) {
|
119
|
+
return ARGON2_SALT_TOO_LONG;
|
120
|
+
}
|
121
|
+
|
122
|
+
context.out = (uint8_t *)out;
|
123
|
+
context.outlen = (uint32_t)outlen;
|
124
|
+
context.pwd = (uint8_t *)in;
|
125
|
+
context.pwdlen = (uint32_t)inlen;
|
126
|
+
context.salt = (uint8_t *)salt;
|
127
|
+
context.saltlen = (uint32_t)saltlen;
|
128
|
+
context.secret = NULL;
|
129
|
+
context.secretlen = 0;
|
130
|
+
context.ad = NULL;
|
131
|
+
context.adlen = 0;
|
132
|
+
context.t_cost = t_cost;
|
133
|
+
context.m_cost = m_cost;
|
134
|
+
context.lanes = 1;
|
135
|
+
context.threads = 1;
|
136
|
+
context.allocate_cbk = NULL;
|
137
|
+
context.free_cbk = NULL;
|
138
|
+
context.flags = ARGON2_DEFAULT_FLAGS;
|
139
|
+
|
140
|
+
return argon2_core(&context, Argon2_i);
|
141
|
+
}
|
142
|
+
|
143
|
+
int hash_argon2d(void *out, size_t outlen, const void *in, size_t inlen,
|
144
|
+
const void *salt, size_t saltlen, unsigned int t_cost,
|
145
|
+
unsigned int m_cost) {
|
146
|
+
argon2_context context;
|
147
|
+
|
148
|
+
/* Detect and reject overflowing sizes */
|
149
|
+
/* TODO: This should probably be fixed in the function signature */
|
150
|
+
if (inlen > UINT32_MAX) {
|
151
|
+
return ARGON2_PWD_TOO_LONG;
|
152
|
+
}
|
153
|
+
|
154
|
+
if (outlen > UINT32_MAX) {
|
155
|
+
return ARGON2_OUTPUT_TOO_LONG;
|
156
|
+
}
|
157
|
+
|
158
|
+
if (saltlen > UINT32_MAX) {
|
159
|
+
return ARGON2_SALT_TOO_LONG;
|
160
|
+
}
|
161
|
+
|
162
|
+
context.out = (uint8_t *)out;
|
163
|
+
context.outlen = (uint32_t)outlen;
|
164
|
+
context.pwd = (uint8_t *)in;
|
165
|
+
context.pwdlen = (uint32_t)inlen;
|
166
|
+
context.salt = (uint8_t *)salt;
|
167
|
+
context.saltlen = (uint32_t)saltlen;
|
168
|
+
context.secret = NULL;
|
169
|
+
context.secretlen = 0;
|
170
|
+
context.ad = NULL;
|
171
|
+
context.adlen = 0;
|
172
|
+
context.t_cost = t_cost;
|
173
|
+
context.m_cost = m_cost;
|
174
|
+
context.lanes = 1;
|
175
|
+
context.threads = 1;
|
176
|
+
context.allocate_cbk = NULL;
|
177
|
+
context.free_cbk = NULL;
|
178
|
+
context.flags = ARGON2_DEFAULT_FLAGS;
|
179
|
+
|
180
|
+
return argon2_core(&context, Argon2_d);
|
181
|
+
}
|
182
|
+
|
183
|
+
int argon2d(argon2_context *context) { return argon2_core(context, Argon2_d); }
|
184
|
+
|
185
|
+
int argon2i(argon2_context *context) { return argon2_core(context, Argon2_i); }
|
186
|
+
|
187
|
+
int verify_d(argon2_context *context, const char *hash) {
|
188
|
+
int result;
|
189
|
+
if (0 == context->outlen || NULL == hash) {
|
190
|
+
return ARGON2_OUT_PTR_MISMATCH;
|
191
|
+
}
|
192
|
+
|
193
|
+
result = argon2_core(context, Argon2_d);
|
194
|
+
|
195
|
+
if (ARGON2_OK != result) {
|
196
|
+
return result;
|
197
|
+
}
|
198
|
+
|
199
|
+
return 0 == memcmp(hash, context->out, context->outlen);
|
200
|
+
}
|
201
|
+
|
202
|
+
const char *error_message(int error_code) {
|
203
|
+
enum {
|
204
|
+
/* Make sure---at compile time---that the enum size matches the array
|
205
|
+
size */
|
206
|
+
ERROR_STRING_CHECK =
|
207
|
+
1 /
|
208
|
+
!!((sizeof(Argon2_ErrorMessage) / sizeof(Argon2_ErrorMessage[0])) ==
|
209
|
+
ARGON2_ERROR_CODES_LENGTH)
|
210
|
+
};
|
211
|
+
if (error_code < ARGON2_ERROR_CODES_LENGTH) {
|
212
|
+
return Argon2_ErrorMessage[(argon2_error_codes)error_code];
|
213
|
+
}
|
214
|
+
return "Unknown error code.";
|
215
|
+
}
|
216
|
+
|
217
|
+
/* encoding/decoding helpers */
|
218
|
+
|
219
|
+
/*
|
220
|
+
* Some macros for constant-time comparisons. These work over values in
|
221
|
+
* the 0..255 range. Returned value is 0x00 on "false", 0xFF on "true".
|
222
|
+
*/
|
223
|
+
#define EQ(x, y) ((((0U - ((unsigned)(x) ^ (unsigned)(y))) >> 8) & 0xFF) ^ 0xFF)
|
224
|
+
#define GT(x, y) ((((unsigned)(y) - (unsigned)(x)) >> 8) & 0xFF)
|
225
|
+
#define GE(x, y) (GT(y, x) ^ 0xFF)
|
226
|
+
#define LT(x, y) GT(y, x)
|
227
|
+
#define LE(x, y) GE(y, x)
|
228
|
+
|
229
|
+
/*
|
230
|
+
* Convert value x (0..63) to corresponding Base64 character.
|
231
|
+
*/
|
232
|
+
static int b64_byte_to_char(unsigned x) {
|
233
|
+
return (LT(x, 26) & (x + 'A')) |
|
234
|
+
(GE(x, 26) & LT(x, 52) & (x + ('a' - 26))) |
|
235
|
+
(GE(x, 52) & LT(x, 62) & (x + ('0' - 52))) | (EQ(x, 62) & '+') |
|
236
|
+
(EQ(x, 63) & '/');
|
237
|
+
}
|
238
|
+
|
239
|
+
/*
|
240
|
+
* Convert some bytes to Base64. 'dst_len' is the length (in characters)
|
241
|
+
* of the output buffer 'dst'; if that buffer is not large enough to
|
242
|
+
* receive the result (including the terminating 0), then (size_t)-1
|
243
|
+
* is returned. Otherwise, the zero-terminated Base64 string is written
|
244
|
+
* in the buffer, and the output length (counted WITHOUT the terminating
|
245
|
+
* zero) is returned.
|
246
|
+
*/
|
247
|
+
static size_t to_base64(char *dst, size_t dst_len, const void *src,
|
248
|
+
size_t src_len) {
|
249
|
+
size_t olen;
|
250
|
+
const unsigned char *buf;
|
251
|
+
unsigned acc, acc_len;
|
252
|
+
|
253
|
+
olen = (src_len / 3) << 2;
|
254
|
+
switch (src_len % 3) {
|
255
|
+
case 2:
|
256
|
+
olen++;
|
257
|
+
/* fall through */
|
258
|
+
case 1:
|
259
|
+
olen += 2;
|
260
|
+
break;
|
261
|
+
}
|
262
|
+
if (dst_len <= olen) {
|
263
|
+
return (size_t)-1;
|
264
|
+
}
|
265
|
+
acc = 0;
|
266
|
+
acc_len = 0;
|
267
|
+
buf = (const unsigned char *)src;
|
268
|
+
while (src_len-- > 0) {
|
269
|
+
acc = (acc << 8) + (*buf++);
|
270
|
+
acc_len += 8;
|
271
|
+
while (acc_len >= 6) {
|
272
|
+
acc_len -= 6;
|
273
|
+
*dst++ = b64_byte_to_char((acc >> acc_len) & 0x3F);
|
274
|
+
}
|
275
|
+
}
|
276
|
+
if (acc_len > 0) {
|
277
|
+
*dst++ = b64_byte_to_char((acc << (6 - acc_len)) & 0x3F);
|
278
|
+
}
|
279
|
+
*dst++ = 0;
|
280
|
+
return olen;
|
281
|
+
}
|
282
|
+
|
283
|
+
/* ==================================================================== */
|
284
|
+
/*
|
285
|
+
* Code specific to Argon2i.
|
286
|
+
*
|
287
|
+
* The code below applies the following format:
|
288
|
+
*
|
289
|
+
* $argon2i$m=<num>,t=<num>,p=<num>[,keyid=<bin>][,data=<bin>][$<bin>[$<bin>]]
|
290
|
+
*
|
291
|
+
* where <num> is a decimal integer (positive, fits in an 'unsigned long')
|
292
|
+
* and <bin> is Base64-encoded data (no '=' padding characters, no newline
|
293
|
+
* or whitespace). The "keyid" is a binary identifier for a key (up to 8
|
294
|
+
* bytes); "data" is associated data (up to 32 bytes). When the 'keyid'
|
295
|
+
* (resp. the 'data') is empty, then it is ommitted from the output.
|
296
|
+
*
|
297
|
+
* The last two binary chunks (encoded in Base64) are, in that order,
|
298
|
+
* the salt and the output. Both are optional, but you cannot have an
|
299
|
+
* output without a salt. The binary salt length is between 8 and 48 bytes.
|
300
|
+
* The output length is always exactly 32 bytes.
|
301
|
+
*/
|
302
|
+
|
303
|
+
int encode_string(char *dst, size_t dst_len, argon2_context *ctx) {
|
304
|
+
#define SS(str) \
|
305
|
+
do { \
|
306
|
+
size_t pp_len = strlen(str); \
|
307
|
+
if (pp_len >= dst_len) { \
|
308
|
+
return 0; \
|
309
|
+
} \
|
310
|
+
memcpy(dst, str, pp_len + 1); \
|
311
|
+
dst += pp_len; \
|
312
|
+
dst_len -= pp_len; \
|
313
|
+
} while (0)
|
314
|
+
|
315
|
+
#define SX(x) \
|
316
|
+
do { \
|
317
|
+
char tmp[30]; \
|
318
|
+
sprintf(tmp, "%lu", (unsigned long)(x)); \
|
319
|
+
SS(tmp); \
|
320
|
+
} while (0);
|
321
|
+
|
322
|
+
#define SB(buf, len) \
|
323
|
+
do { \
|
324
|
+
size_t sb_len = to_base64(dst, dst_len, buf, len); \
|
325
|
+
if (sb_len == (size_t)-1) { \
|
326
|
+
return 0; \
|
327
|
+
} \
|
328
|
+
dst += sb_len; \
|
329
|
+
dst_len -= sb_len; \
|
330
|
+
} while (0);
|
331
|
+
|
332
|
+
SS("$argon2i$m=");
|
333
|
+
SX(ctx->m_cost);
|
334
|
+
SS(",t=");
|
335
|
+
SX(ctx->t_cost);
|
336
|
+
SS(",p=");
|
337
|
+
SX(ctx->lanes);
|
338
|
+
|
339
|
+
if (ctx->adlen > 0) {
|
340
|
+
SS(",data=");
|
341
|
+
SB(ctx->ad, ctx->adlen);
|
342
|
+
}
|
343
|
+
|
344
|
+
if (ctx->saltlen == 0)
|
345
|
+
return 1;
|
346
|
+
|
347
|
+
SS("$");
|
348
|
+
SB(ctx->salt, ctx->saltlen);
|
349
|
+
|
350
|
+
if (ctx->outlen == 0)
|
351
|
+
return 1;
|
352
|
+
|
353
|
+
SS("$");
|
354
|
+
SB(ctx->out, ctx->outlen);
|
355
|
+
return 1;
|
356
|
+
|
357
|
+
#undef SS
|
358
|
+
#undef SX
|
359
|
+
#undef SB
|
360
|
+
}
|
@@ -0,0 +1,298 @@
|
|
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
|
+
#ifndef ARGON2_H
|
14
|
+
#define ARGON2_H
|
15
|
+
|
16
|
+
#include <stdint.h>
|
17
|
+
#include <stddef.h>
|
18
|
+
#include <limits.h>
|
19
|
+
|
20
|
+
#if defined(__cplusplus)
|
21
|
+
extern "C" {
|
22
|
+
#endif
|
23
|
+
|
24
|
+
/*************************Argon2 input parameter
|
25
|
+
* restrictions**************************************************/
|
26
|
+
|
27
|
+
/* Minimum and maximum number of lanes (degree of parallelism) */
|
28
|
+
#define ARGON2_MIN_LANES UINT32_C(1)
|
29
|
+
#define ARGON2_MAX_LANES UINT32_C(0xFFFFFF)
|
30
|
+
|
31
|
+
/* Minimum and maximum number of threads */
|
32
|
+
#define ARGON2_MIN_THREADS UINT32_C(1)
|
33
|
+
#define ARGON2_MAX_THREADS UINT32_C(0xFFFFFF)
|
34
|
+
|
35
|
+
/* Number of synchronization points between lanes per pass */
|
36
|
+
#define ARGON2_SYNC_POINTS UINT32_C(4)
|
37
|
+
|
38
|
+
/* Minimum and maximum digest size in bytes */
|
39
|
+
#define ARGON2_MIN_OUTLEN UINT32_C(4)
|
40
|
+
#define ARGON2_MAX_OUTLEN UINT32_C(0xFFFFFFFF)
|
41
|
+
|
42
|
+
/* Minimum and maximum number of memory blocks (each of BLOCK_SIZE bytes) */
|
43
|
+
#define ARGON2_MIN_MEMORY (2 * ARGON2_SYNC_POINTS) /* 2 blocks per slice */
|
44
|
+
|
45
|
+
#define ARGON2_MIN(a, b) ((a) < (b) ? (a) : (b))
|
46
|
+
/* Max memory size is half the addressing space, topping at 2^32 blocks (4 TB)
|
47
|
+
*/
|
48
|
+
#define ARGON2_MAX_MEMORY_BITS \
|
49
|
+
ARGON2_MIN(UINT32_C(32), (sizeof(void *) * CHAR_BIT - 10 - 1))
|
50
|
+
#define ARGON2_MAX_MEMORY \
|
51
|
+
ARGON2_MIN(UINT32_C(0xFFFFFFFF), UINT64_C(1) << ARGON2_MAX_MEMORY_BITS)
|
52
|
+
|
53
|
+
/* Minimum and maximum number of passes */
|
54
|
+
#define ARGON2_MIN_TIME UINT32_C(1)
|
55
|
+
#define ARGON2_MAX_TIME UINT32_C(0xFFFFFFFF)
|
56
|
+
|
57
|
+
/* Minimum and maximum password length in bytes */
|
58
|
+
#define ARGON2_MIN_PWD_LENGTH UINT32_C(0)
|
59
|
+
#define ARGON2_MAX_PWD_LENGTH UINT32_C(0xFFFFFFFF)
|
60
|
+
|
61
|
+
/* Minimum and maximum associated data length in bytes */
|
62
|
+
#define ARGON2_MIN_AD_LENGTH UINT32_C(0)
|
63
|
+
#define ARGON2_MAX_AD_LENGTH UINT32_C(0xFFFFFFFF)
|
64
|
+
|
65
|
+
/* Minimum and maximum salt length in bytes */
|
66
|
+
#define ARGON2_MIN_SALT_LENGTH UINT32_C(8)
|
67
|
+
#define ARGON2_MAX_SALT_LENGTH UINT32_C(0xFFFFFFFF)
|
68
|
+
|
69
|
+
/* Minimum and maximum key length in bytes */
|
70
|
+
#define ARGON2_MIN_SECRET UINT32_C(0)
|
71
|
+
#define ARGON2_MAX_SECRET UINT32_C(0xFFFFFFFF)
|
72
|
+
|
73
|
+
#define ARGON2_FLAG_CLEAR_PASSWORD (UINT32_C(1) << 0)
|
74
|
+
#define ARGON2_FLAG_CLEAR_SECRET (UINT32_C(1) << 1)
|
75
|
+
#define ARGON2_FLAG_CLEAR_MEMORY (UINT32_C(1) << 2)
|
76
|
+
#define ARGON2_DEFAULT_FLAGS \
|
77
|
+
(ARGON2_FLAG_CLEAR_PASSWORD | ARGON2_FLAG_CLEAR_MEMORY)
|
78
|
+
|
79
|
+
/* Error codes */
|
80
|
+
typedef enum Argon2_ErrorCodes {
|
81
|
+
ARGON2_OK = 0,
|
82
|
+
|
83
|
+
ARGON2_OUTPUT_PTR_NULL = 1,
|
84
|
+
|
85
|
+
ARGON2_OUTPUT_TOO_SHORT = 2,
|
86
|
+
ARGON2_OUTPUT_TOO_LONG = 3,
|
87
|
+
|
88
|
+
ARGON2_PWD_TOO_SHORT = 4,
|
89
|
+
ARGON2_PWD_TOO_LONG = 5,
|
90
|
+
|
91
|
+
ARGON2_SALT_TOO_SHORT = 6,
|
92
|
+
ARGON2_SALT_TOO_LONG = 7,
|
93
|
+
|
94
|
+
ARGON2_AD_TOO_SHORT = 8,
|
95
|
+
ARGON2_AD_TOO_LONG = 9,
|
96
|
+
|
97
|
+
ARGON2_SECRET_TOO_SHORT = 10,
|
98
|
+
ARGON2_SECRET_TOO_LONG = 11,
|
99
|
+
|
100
|
+
ARGON2_TIME_TOO_SMALL = 12,
|
101
|
+
ARGON2_TIME_TOO_LARGE = 13,
|
102
|
+
|
103
|
+
ARGON2_MEMORY_TOO_LITTLE = 14,
|
104
|
+
ARGON2_MEMORY_TOO_MUCH = 15,
|
105
|
+
|
106
|
+
ARGON2_LANES_TOO_FEW = 16,
|
107
|
+
ARGON2_LANES_TOO_MANY = 17,
|
108
|
+
|
109
|
+
ARGON2_PWD_PTR_MISMATCH = 18, /* NULL ptr with non-zero length */
|
110
|
+
ARGON2_SALT_PTR_MISMATCH = 19, /* NULL ptr with non-zero length */
|
111
|
+
ARGON2_SECRET_PTR_MISMATCH = 20, /* NULL ptr with non-zero length */
|
112
|
+
ARGON2_AD_PTR_MISMATCH = 21, /* NULL ptr with non-zero length */
|
113
|
+
|
114
|
+
ARGON2_MEMORY_ALLOCATION_ERROR = 22,
|
115
|
+
|
116
|
+
ARGON2_FREE_MEMORY_CBK_NULL = 23,
|
117
|
+
ARGON2_ALLOCATE_MEMORY_CBK_NULL = 24,
|
118
|
+
|
119
|
+
ARGON2_INCORRECT_PARAMETER = 25,
|
120
|
+
ARGON2_INCORRECT_TYPE = 26,
|
121
|
+
|
122
|
+
ARGON2_OUT_PTR_MISMATCH = 27,
|
123
|
+
|
124
|
+
ARGON2_THREADS_TOO_FEW = 28,
|
125
|
+
ARGON2_THREADS_TOO_MANY = 29,
|
126
|
+
|
127
|
+
ARGON2_MISSING_ARGS = 30,
|
128
|
+
|
129
|
+
ARGON2_ERROR_CODES_LENGTH /* Do NOT remove; Do NOT add error codes after
|
130
|
+
this
|
131
|
+
error code */
|
132
|
+
} argon2_error_codes;
|
133
|
+
|
134
|
+
/* Memory allocator types --- for external allocation */
|
135
|
+
typedef int (*allocate_fptr)(uint8_t **memory, size_t bytes_to_allocate);
|
136
|
+
typedef void (*deallocate_fptr)(uint8_t *memory, size_t bytes_to_allocate);
|
137
|
+
|
138
|
+
/* Argon2 external data structures */
|
139
|
+
|
140
|
+
/*
|
141
|
+
*****Context: structure to hold Argon2 inputs:
|
142
|
+
* output array and its length,
|
143
|
+
* password and its length,
|
144
|
+
* salt and its length,
|
145
|
+
* secret and its length,
|
146
|
+
* associated data and its length,
|
147
|
+
* number of passes, amount of used memory (in KBytes, can be rounded up a bit)
|
148
|
+
* number of parallel threads that will be run.
|
149
|
+
* All the parameters above affect the output hash value.
|
150
|
+
* Additionally, two function pointers can be provided to allocate and
|
151
|
+
deallocate the memory (if NULL, memory will be allocated internally).
|
152
|
+
* Also, three flags indicate whether to erase password, secret as soon as they
|
153
|
+
are pre-hashed (and thus not needed anymore), and the entire memory
|
154
|
+
****************************
|
155
|
+
Simplest situation: you have output array out[8], password is stored in
|
156
|
+
pwd[32], salt is stored in salt[16], you do not have keys nor associated data.
|
157
|
+
You need to spend 1 GB of RAM and you run 5 passes of Argon2d with 4 parallel
|
158
|
+
lanes.
|
159
|
+
You want to erase the password, but you're OK with last pass not being erased.
|
160
|
+
You want to use the default memory allocator.
|
161
|
+
Then you initialize
|
162
|
+
Argon2_Context(out,8,pwd,32,salt,16,NULL,0,NULL,0,5,1<<20,4,4,NULL,NULL,true,false,false,false).
|
163
|
+
*/
|
164
|
+
typedef struct Argon2_Context {
|
165
|
+
uint8_t *out; /* output array */
|
166
|
+
uint32_t outlen; /* digest length */
|
167
|
+
|
168
|
+
uint8_t *pwd; /* password array */
|
169
|
+
uint32_t pwdlen; /* password length */
|
170
|
+
|
171
|
+
uint8_t *salt; /* salt array */
|
172
|
+
uint32_t saltlen; /* salt length */
|
173
|
+
|
174
|
+
uint8_t *secret; /* key array */
|
175
|
+
uint32_t secretlen; /* key length */
|
176
|
+
|
177
|
+
uint8_t *ad; /* associated data array */
|
178
|
+
uint32_t adlen; /* associated data length */
|
179
|
+
|
180
|
+
uint32_t t_cost; /* number of passes */
|
181
|
+
uint32_t m_cost; /* amount of memory requested (KB) */
|
182
|
+
uint32_t lanes; /* number of lanes */
|
183
|
+
uint32_t threads; /* maximum number of threads */
|
184
|
+
|
185
|
+
allocate_fptr allocate_cbk; /* pointer to memory allocator */
|
186
|
+
deallocate_fptr free_cbk; /* pointer to memory deallocator */
|
187
|
+
|
188
|
+
uint32_t flags; /* array of bool options */
|
189
|
+
} argon2_context;
|
190
|
+
|
191
|
+
/**
|
192
|
+
* Function to hash the inputs in the memory-hard fashion (uses Argon2i)
|
193
|
+
* @param out Pointer to the memory where the hash digest will be written
|
194
|
+
* @param outlen Digest length in bytes
|
195
|
+
* @param in Pointer to the input (password)
|
196
|
+
* @param inlen Input length in bytes
|
197
|
+
* @param salt Pointer to the salt
|
198
|
+
* @param saltlen Salt length in bytes
|
199
|
+
* @pre @a out must have at least @a outlen bytes allocated
|
200
|
+
* @pre @a in must be at least @inlen bytes long
|
201
|
+
* @pre @a saltlen must be at least @saltlen bytes long
|
202
|
+
* @return Zero if successful, 1 otherwise.
|
203
|
+
*/
|
204
|
+
int hash_argon2i(void *out, size_t outlen, const void *in, size_t inlen,
|
205
|
+
const void *salt, size_t saltlen, unsigned int t_cost,
|
206
|
+
unsigned int m_cost);
|
207
|
+
|
208
|
+
/* same for argon2d */
|
209
|
+
int hash_argon2d(void *out, size_t outlen, const void *in, size_t inlen,
|
210
|
+
const void *salt, size_t saltlen, unsigned int t_cost,
|
211
|
+
unsigned int m_cost);
|
212
|
+
|
213
|
+
/*
|
214
|
+
* **************Argon2d: Version of Argon2 that picks memory blocks depending
|
215
|
+
* on the password and salt. Only for side-channel-free
|
216
|
+
* environment!!***************
|
217
|
+
* @param context Pointer to current Argon2 context
|
218
|
+
* @return Zero if successful, a non zero error code otherwise
|
219
|
+
*/
|
220
|
+
int argon2d(argon2_context *context);
|
221
|
+
|
222
|
+
/*
|
223
|
+
* * **************Argon2i: Version of Argon2 that picks memory blocks
|
224
|
+
*independent on the password and salt. Good for side-channels,
|
225
|
+
******************* but worse w.r.t. tradeoff attacks if
|
226
|
+
*******************only one pass is used***************
|
227
|
+
* @param context Pointer to current Argon2 context
|
228
|
+
* @return Zero if successful, a non zero error code otherwise
|
229
|
+
*/
|
230
|
+
int argon2i(argon2_context *context);
|
231
|
+
|
232
|
+
/*
|
233
|
+
* * **************Argon2di: Reserved name***************
|
234
|
+
* @param context Pointer to current Argon2 context
|
235
|
+
* @return Zero if successful, a non zero error code otherwise
|
236
|
+
*/
|
237
|
+
int argon2di(argon2_context *context);
|
238
|
+
|
239
|
+
/*
|
240
|
+
* * **************Argon2ds: Argon2d hardened against GPU attacks, 20%
|
241
|
+
* slower***************
|
242
|
+
* @param context Pointer to current Argon2 context
|
243
|
+
* @return Zero if successful, a non zero error code otherwise
|
244
|
+
*/
|
245
|
+
int argon2ds(argon2_context *context);
|
246
|
+
|
247
|
+
/*
|
248
|
+
* * **************Argon2id: First half-pass over memory is
|
249
|
+
*password-independent, the rest are password-dependent
|
250
|
+
********************OK against side channels: they reduce to 1/2-pass
|
251
|
+
*Argon2i***************
|
252
|
+
* @param context Pointer to current Argon2 context
|
253
|
+
* @return Zero if successful, a non zero error code otherwise
|
254
|
+
*/
|
255
|
+
int argon2id(argon2_context *context);
|
256
|
+
|
257
|
+
/*
|
258
|
+
* Verify if a given password is correct for Argon2d hashing
|
259
|
+
* @param context Pointer to current Argon2 context
|
260
|
+
* @param hash The password hash to verify. The length of the hash is
|
261
|
+
* specified by the context outlen member
|
262
|
+
* @return Zero if successful, a non zero error code otherwise
|
263
|
+
*/
|
264
|
+
int verify_d(argon2_context *context, const char *hash);
|
265
|
+
|
266
|
+
/*
|
267
|
+
* Get the associated error message for given error code
|
268
|
+
* @return The error message associated with the given error code
|
269
|
+
*/
|
270
|
+
const char *error_message(int error_code);
|
271
|
+
|
272
|
+
/* ==================================================================== */
|
273
|
+
/*
|
274
|
+
* Code specific to Argon2i.
|
275
|
+
*
|
276
|
+
* The code below applies the following format:
|
277
|
+
*
|
278
|
+
* $argon2i$m=<num>,t=<num>,p=<num>[,keyid=<bin>][,data=<bin>][$<bin>[$<bin>]]
|
279
|
+
*
|
280
|
+
* where <num> is a decimal integer (positive, fits in an 'unsigned long')
|
281
|
+
* and <bin> is Base64-encoded data (no '=' padding characters, no newline
|
282
|
+
* or whitespace). The "keyid" is a binary identifier for a key (up to 8
|
283
|
+
* bytes); "data" is associated data (up to 32 bytes). When the 'keyid'
|
284
|
+
* (resp. the 'data') is empty, then it is ommitted from the output.
|
285
|
+
*
|
286
|
+
* The last two binary chunks (encoded in Base64) are, in that order,
|
287
|
+
* the salt and the output. Both are optional, but you cannot have an
|
288
|
+
* output without a salt. The binary salt length is between 8 and 48 bytes.
|
289
|
+
* The output length is always exactly 32 bytes.
|
290
|
+
*/
|
291
|
+
|
292
|
+
int encode_string(char *dst, size_t dst_len, argon2_context *ctx);
|
293
|
+
|
294
|
+
#if defined(__cplusplus)
|
295
|
+
}
|
296
|
+
#endif
|
297
|
+
|
298
|
+
#endif
|