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 @@
|
|
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
|