argon2 0.0.2 → 0.1.0
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/.rubocop.yml +66 -0
- data/.travis.yml +4 -0
- data/README.md +60 -5
- data/Rakefile +3 -0
- data/argon2.gemspec +10 -12
- data/ext/argon2_wrap/Makefile +4 -4
- data/ext/argon2_wrap/argon_wrap.c +57 -5
- data/ext/argon2_wrap/test.c +84 -12
- data/ext/phc-winner-argon2/.gitignore +1 -0
- data/ext/phc-winner-argon2/Makefile +1 -1
- data/ext/phc-winner-argon2/README.md +31 -26
- data/ext/phc-winner-argon2/src/argon2.c +133 -188
- data/ext/phc-winner-argon2/src/argon2.h +76 -42
- data/ext/phc-winner-argon2/src/core.c +0 -1
- data/ext/phc-winner-argon2/src/core.h +2 -3
- data/ext/phc-winner-argon2/src/encoding.c +435 -0
- data/ext/phc-winner-argon2/src/encoding.h +7 -0
- data/ext/phc-winner-argon2/src/run.c +43 -58
- data/lib/argon2.rb +21 -2
- data/lib/argon2/constants.rb +3 -0
- data/lib/argon2/engine.rb +1 -1
- data/lib/argon2/errors.rb +35 -30
- data/lib/argon2/ffi_engine.rb +43 -21
- data/lib/argon2/version.rb +2 -2
- metadata +51 -7
@@ -73,8 +73,7 @@ extern "C" {
|
|
73
73
|
#define ARGON2_FLAG_CLEAR_PASSWORD (UINT32_C(1) << 0)
|
74
74
|
#define ARGON2_FLAG_CLEAR_SECRET (UINT32_C(1) << 1)
|
75
75
|
#define ARGON2_FLAG_CLEAR_MEMORY (UINT32_C(1) << 2)
|
76
|
-
#define ARGON2_DEFAULT_FLAGS
|
77
|
-
(ARGON2_FLAG_CLEAR_PASSWORD | ARGON2_FLAG_CLEAR_MEMORY)
|
76
|
+
#define ARGON2_DEFAULT_FLAGS (ARGON2_FLAG_CLEAR_MEMORY)
|
78
77
|
|
79
78
|
/* Error codes */
|
80
79
|
typedef enum Argon2_ErrorCodes {
|
@@ -126,6 +125,10 @@ typedef enum Argon2_ErrorCodes {
|
|
126
125
|
|
127
126
|
ARGON2_MISSING_ARGS = 30,
|
128
127
|
|
128
|
+
ARGON2_ENCODING_FAIL = 31,
|
129
|
+
|
130
|
+
ARGON2_DECODING_FAIL = 32,
|
131
|
+
|
129
132
|
ARGON2_ERROR_CODES_LENGTH /* Do NOT remove; Do NOT add error codes after
|
130
133
|
this
|
131
134
|
error code */
|
@@ -188,27 +191,80 @@ typedef struct Argon2_Context {
|
|
188
191
|
uint32_t flags; /* array of bool options */
|
189
192
|
} argon2_context;
|
190
193
|
|
194
|
+
/* Argon2 primitive type */
|
195
|
+
typedef enum Argon2_type { Argon2_d = 0, Argon2_i = 1 } argon2_type;
|
196
|
+
|
197
|
+
/**
|
198
|
+
* Hashes a password with Argon2i, producing an encoded hash
|
199
|
+
* @param t_cost Number of iterations
|
200
|
+
* @param m_cost Sets memory usage to 2^m_cost kibibytes
|
201
|
+
* @param parallelism Number of threads and compute lanes
|
202
|
+
* @param pwd Pointer to password
|
203
|
+
* @param pwdlen Password size in bytes
|
204
|
+
* @param salt Pointer to salt
|
205
|
+
* @param saltlen Salt size in bytes
|
206
|
+
* @param hashlen Desired length of the hash in bytes
|
207
|
+
* @param encoded Buffer where to write the encoded hash
|
208
|
+
* @param encodedlen Size of the buffer (thus max size of the encoded hash)
|
209
|
+
* @pre Different parallelism levels will give different results
|
210
|
+
* @pre Returns ARGON2_OK if successful
|
211
|
+
*/
|
212
|
+
int argon2i_hash_encoded(const uint32_t t_cost, const uint32_t m_cost,
|
213
|
+
const uint32_t parallelism, const void *pwd,
|
214
|
+
const size_t pwdlen, const void *salt,
|
215
|
+
const size_t saltlen, const size_t hashlen,
|
216
|
+
char *encoded, const size_t encodedlen);
|
217
|
+
|
218
|
+
/**
|
219
|
+
* Hashes a password with Argon2i, producing a raw hash
|
220
|
+
* @param t_cost Number of iterations
|
221
|
+
* @param m_cost Sets memory usage to 2^m_cost kibibytes
|
222
|
+
* @param parallelism Number of threads and compute lanes
|
223
|
+
* @param pwd Pointer to password
|
224
|
+
* @param pwdlen Password size in bytes
|
225
|
+
* @param salt Pointer to salt
|
226
|
+
* @param saltlen Salt size in bytes
|
227
|
+
* @param hash Buffer where to write the raw hash
|
228
|
+
* @param hashlen Desired length of the hash in bytes
|
229
|
+
* @pre Different parallelism levels will give different results
|
230
|
+
* @pre Returns ARGON2_OK if successful
|
231
|
+
*/
|
232
|
+
int argon2i_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
|
233
|
+
const uint32_t parallelism, const void *pwd,
|
234
|
+
const size_t pwdlen, const void *salt,
|
235
|
+
const size_t saltlen, void *hash, const size_t hashlen);
|
236
|
+
|
237
|
+
int argon2d_hash_encoded(const uint32_t t_cost, const uint32_t m_cost,
|
238
|
+
const uint32_t parallelism, const void *pwd,
|
239
|
+
const size_t pwdlen, const void *salt,
|
240
|
+
const size_t saltlen, const size_t hashlen,
|
241
|
+
char *encoded, const size_t encodedlen);
|
242
|
+
|
243
|
+
int argon2d_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
|
244
|
+
const uint32_t parallelism, const void *pwd,
|
245
|
+
const size_t pwdlen, const void *salt,
|
246
|
+
const size_t saltlen, void *hash, const size_t hashlen);
|
247
|
+
|
248
|
+
/* generic function underlying the above ones */
|
249
|
+
int argon2_hash(const uint32_t t_cost, const uint32_t m_cost,
|
250
|
+
const uint32_t parallelism, const void *pwd,
|
251
|
+
const size_t pwdlen, const void *salt, const size_t saltlen,
|
252
|
+
void *hash, const size_t hashlen, char *encoded,
|
253
|
+
const size_t encodedlen, argon2_type type);
|
254
|
+
|
191
255
|
/**
|
192
|
-
*
|
193
|
-
* @param
|
194
|
-
* @param
|
195
|
-
* @
|
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.
|
256
|
+
* Verifies a password against an encoded string
|
257
|
+
* @param encoded String encoding parameters, salt, hash
|
258
|
+
* @param pwd Pointer to password
|
259
|
+
* @pre Returns ARGON2_OK if successful
|
203
260
|
*/
|
204
|
-
int
|
205
|
-
const void *salt, size_t saltlen, unsigned int t_cost,
|
206
|
-
unsigned int m_cost);
|
261
|
+
int argon2i_verify(const char *encoded, const void *pwd, const size_t pwdlen);
|
207
262
|
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
263
|
+
int argon2d_verify(const char *encoded, const void *pwd, const size_t pwdlen);
|
264
|
+
|
265
|
+
/* generic function underlying the above ones */
|
266
|
+
int argon2_verify(const char *encoded, const void *pwd, const size_t pwdlen,
|
267
|
+
argon2_type type);
|
212
268
|
|
213
269
|
/*
|
214
270
|
* **************Argon2d: Version of Argon2 that picks memory blocks depending
|
@@ -269,28 +325,6 @@ int verify_d(argon2_context *context, const char *hash);
|
|
269
325
|
*/
|
270
326
|
const char *error_message(int error_code);
|
271
327
|
|
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
328
|
#if defined(__cplusplus)
|
295
329
|
}
|
296
330
|
#endif
|
@@ -14,6 +14,8 @@
|
|
14
14
|
#ifndef ARGON2_CORE_H
|
15
15
|
#define ARGON2_CORE_H
|
16
16
|
|
17
|
+
#include "argon2.h"
|
18
|
+
|
17
19
|
#if defined(_MSC_VER)
|
18
20
|
#define ALIGN(n) __declspec(align(16))
|
19
21
|
#elif defined(__GNUC__) || defined(__clang)
|
@@ -44,9 +46,6 @@ enum argon2_core_constants {
|
|
44
46
|
ARGON2_PREHASH_SEED_LENGTH = 72
|
45
47
|
};
|
46
48
|
|
47
|
-
/* Argon2 primitive type */
|
48
|
-
typedef enum Argon2_type { Argon2_d = 0, Argon2_i = 1 } argon2_type;
|
49
|
-
|
50
49
|
/*************************Argon2 internal data
|
51
50
|
* types**************************************************/
|
52
51
|
|
@@ -0,0 +1,435 @@
|
|
1
|
+
#include <stdio.h>
|
2
|
+
#include <stdlib.h>
|
3
|
+
#include <string.h>
|
4
|
+
#include <limits.h>
|
5
|
+
#include "encoding.h"
|
6
|
+
|
7
|
+
#/*
|
8
|
+
* Example code for a decoder and encoder of "hash strings", with Argon2i
|
9
|
+
* parameters.
|
10
|
+
*
|
11
|
+
* This code comprises three sections:
|
12
|
+
*
|
13
|
+
* -- The first section contains generic Base64 encoding and decoding
|
14
|
+
* functions. It is conceptually applicable to any hash function
|
15
|
+
* implementation that uses Base64 to encode and decode parameters,
|
16
|
+
* salts and outputs. It could be made into a library, provided that
|
17
|
+
* the relevant functions are made public (non-static) and be given
|
18
|
+
* reasonable names to avoid collisions with other functions.
|
19
|
+
*
|
20
|
+
* -- The second section is specific to Argon2i. It encodes and decodes
|
21
|
+
* the parameters, salts and outputs. It does not compute the hash
|
22
|
+
* itself.
|
23
|
+
*
|
24
|
+
* -- The third section is test code, with a main() function. With
|
25
|
+
* this section, the whole file compiles as a stand-alone program
|
26
|
+
* that exercises the encoding and decoding functions with some
|
27
|
+
* test vectors.
|
28
|
+
*
|
29
|
+
* The code was originally written by Thomas Pornin <pornin@bolet.org>,
|
30
|
+
* to whom comments and remarks may be sent. It is released under what
|
31
|
+
* should amount to Public Domain or its closest equivalent; the
|
32
|
+
* following mantra is supposed to incarnate that fact with all the
|
33
|
+
* proper legal rituals:
|
34
|
+
*
|
35
|
+
* ---------------------------------------------------------------------
|
36
|
+
* This file is provided under the terms of Creative Commons CC0 1.0
|
37
|
+
* Public Domain Dedication. To the extent possible under law, the
|
38
|
+
* author (Thomas Pornin) has waived all copyright and related or
|
39
|
+
* neighboring rights to this file. This work is published from: Canada.
|
40
|
+
* ---------------------------------------------------------------------
|
41
|
+
*
|
42
|
+
* Copyright (c) 2015 Thomas Pornin
|
43
|
+
*/
|
44
|
+
|
45
|
+
/* ==================================================================== */
|
46
|
+
/*
|
47
|
+
* Common code; could be shared between different hash functions.
|
48
|
+
*
|
49
|
+
* Note: the Base64 functions below assume that uppercase letters (resp.
|
50
|
+
* lowercase letters) have consecutive numerical codes, that fit on 8
|
51
|
+
* bits. All modern systems use ASCII-compatible charsets, where these
|
52
|
+
* properties are true. If you are stuck with a dinosaur of a system
|
53
|
+
* that still defaults to EBCDIC then you already have much bigger
|
54
|
+
* interoperability issues to deal with.
|
55
|
+
*/
|
56
|
+
|
57
|
+
/*
|
58
|
+
* Some macros for constant-time comparisons. These work over values in
|
59
|
+
* the 0..255 range. Returned value is 0x00 on "false", 0xFF on "true".
|
60
|
+
*/
|
61
|
+
#define EQ(x, y) ((((-((unsigned)(x) ^ (unsigned)(y))) >> 8) & 0xFF) ^ 0xFF)
|
62
|
+
#define GT(x, y) ((((unsigned)(y) - (unsigned)(x)) >> 8) & 0xFF)
|
63
|
+
#define GE(x, y) (GT(y, x) ^ 0xFF)
|
64
|
+
#define LT(x, y) GT(y, x)
|
65
|
+
#define LE(x, y) GE(y, x)
|
66
|
+
|
67
|
+
/*
|
68
|
+
* Convert value x (0..63) to corresponding Base64 character.
|
69
|
+
*/
|
70
|
+
static int b64_byte_to_char(unsigned x) {
|
71
|
+
return (LT(x, 26) & (x + 'A')) |
|
72
|
+
(GE(x, 26) & LT(x, 52) & (x + ('a' - 26))) |
|
73
|
+
(GE(x, 52) & LT(x, 62) & (x + ('0' - 52))) | (EQ(x, 62) & '+') |
|
74
|
+
(EQ(x, 63) & '/');
|
75
|
+
}
|
76
|
+
|
77
|
+
/*
|
78
|
+
* Convert character c to the corresponding 6-bit value. If character c
|
79
|
+
* is not a Base64 character, then 0xFF (255) is returned.
|
80
|
+
*/
|
81
|
+
static unsigned b64_char_to_byte(int c) {
|
82
|
+
unsigned x;
|
83
|
+
|
84
|
+
x = (GE(c, 'A') & LE(c, 'Z') & (c - 'A')) |
|
85
|
+
(GE(c, 'a') & LE(c, 'z') & (c - ('a' - 26))) |
|
86
|
+
(GE(c, '0') & LE(c, '9') & (c - ('0' - 52))) | (EQ(c, '+') & 62) |
|
87
|
+
(EQ(c, '/') & 63);
|
88
|
+
return x | (EQ(x, 0) & (EQ(c, 'A') ^ 0xFF));
|
89
|
+
}
|
90
|
+
|
91
|
+
/*
|
92
|
+
* Convert some bytes to Base64. 'dst_len' is the length (in characters)
|
93
|
+
* of the output buffer 'dst'; if that buffer is not large enough to
|
94
|
+
* receive the result (including the terminating 0), then (size_t)-1
|
95
|
+
* is returned. Otherwise, the zero-terminated Base64 string is written
|
96
|
+
* in the buffer, and the output length (counted WITHOUT the terminating
|
97
|
+
* zero) is returned.
|
98
|
+
*/
|
99
|
+
static size_t to_base64(char *dst, size_t dst_len, const void *src,
|
100
|
+
size_t src_len) {
|
101
|
+
size_t olen;
|
102
|
+
const unsigned char *buf;
|
103
|
+
unsigned acc, acc_len;
|
104
|
+
|
105
|
+
olen = (src_len / 3) << 2;
|
106
|
+
switch (src_len % 3) {
|
107
|
+
case 2:
|
108
|
+
olen++;
|
109
|
+
/* fall through */
|
110
|
+
case 1:
|
111
|
+
olen += 2;
|
112
|
+
break;
|
113
|
+
}
|
114
|
+
if (dst_len <= olen) {
|
115
|
+
return (size_t)-1;
|
116
|
+
}
|
117
|
+
acc = 0;
|
118
|
+
acc_len = 0;
|
119
|
+
buf = (const unsigned char *)src;
|
120
|
+
while (src_len-- > 0) {
|
121
|
+
acc = (acc << 8) + (*buf++);
|
122
|
+
acc_len += 8;
|
123
|
+
while (acc_len >= 6) {
|
124
|
+
acc_len -= 6;
|
125
|
+
*dst++ = b64_byte_to_char((acc >> acc_len) & 0x3F);
|
126
|
+
}
|
127
|
+
}
|
128
|
+
if (acc_len > 0) {
|
129
|
+
*dst++ = b64_byte_to_char((acc << (6 - acc_len)) & 0x3F);
|
130
|
+
}
|
131
|
+
*dst++ = 0;
|
132
|
+
return olen;
|
133
|
+
}
|
134
|
+
|
135
|
+
/*
|
136
|
+
* Decode Base64 chars into bytes. The '*dst_len' value must initially
|
137
|
+
* contain the length of the output buffer '*dst'; when the decoding
|
138
|
+
* ends, the actual number of decoded bytes is written back in
|
139
|
+
* '*dst_len'.
|
140
|
+
*
|
141
|
+
* Decoding stops when a non-Base64 character is encountered, or when
|
142
|
+
* the output buffer capacity is exceeded. If an error occurred (output
|
143
|
+
* buffer is too small, invalid last characters leading to unprocessed
|
144
|
+
* buffered bits), then NULL is returned; otherwise, the returned value
|
145
|
+
* points to the first non-Base64 character in the source stream, which
|
146
|
+
* may be the terminating zero.
|
147
|
+
*/
|
148
|
+
static const char *from_base64(void *dst, size_t *dst_len, const char *src) {
|
149
|
+
size_t len;
|
150
|
+
unsigned char *buf;
|
151
|
+
unsigned acc, acc_len;
|
152
|
+
|
153
|
+
buf = (unsigned char *)dst;
|
154
|
+
len = 0;
|
155
|
+
acc = 0;
|
156
|
+
acc_len = 0;
|
157
|
+
for (;;) {
|
158
|
+
unsigned d;
|
159
|
+
|
160
|
+
d = b64_char_to_byte(*src);
|
161
|
+
if (d == 0xFF) {
|
162
|
+
break;
|
163
|
+
}
|
164
|
+
src++;
|
165
|
+
acc = (acc << 6) + d;
|
166
|
+
acc_len += 6;
|
167
|
+
if (acc_len >= 8) {
|
168
|
+
acc_len -= 8;
|
169
|
+
if ((len++) >= *dst_len) {
|
170
|
+
return NULL;
|
171
|
+
}
|
172
|
+
*buf++ = (acc >> acc_len) & 0xFF;
|
173
|
+
}
|
174
|
+
}
|
175
|
+
|
176
|
+
/*
|
177
|
+
* If the input length is equal to 1 modulo 4 (which is
|
178
|
+
* invalid), then there will remain 6 unprocessed bits;
|
179
|
+
* otherwise, only 0, 2 or 4 bits are buffered. The buffered
|
180
|
+
* bits must also all be zero.
|
181
|
+
*/
|
182
|
+
if (acc_len > 4 || (acc & (((unsigned)1 << acc_len) - 1)) != 0) {
|
183
|
+
return NULL;
|
184
|
+
}
|
185
|
+
*dst_len = len;
|
186
|
+
return src;
|
187
|
+
}
|
188
|
+
|
189
|
+
/*
|
190
|
+
* Decode decimal integer from 'str'; the value is written in '*v'.
|
191
|
+
* Returned value is a pointer to the next non-decimal character in the
|
192
|
+
* string. If there is no digit at all, or the value encoding is not
|
193
|
+
* minimal (extra leading zeros), or the value does not fit in an
|
194
|
+
* 'unsigned long', then NULL is returned.
|
195
|
+
*/
|
196
|
+
static const char *decode_decimal(const char *str, unsigned long *v) {
|
197
|
+
const char *orig;
|
198
|
+
unsigned long acc;
|
199
|
+
|
200
|
+
orig = str;
|
201
|
+
acc = 0;
|
202
|
+
for (orig = str;; str++) {
|
203
|
+
int c;
|
204
|
+
|
205
|
+
c = *str;
|
206
|
+
if (c < '0' || c > '9') {
|
207
|
+
break;
|
208
|
+
}
|
209
|
+
c -= '0';
|
210
|
+
if (acc > (ULONG_MAX / 10)) {
|
211
|
+
return NULL;
|
212
|
+
}
|
213
|
+
acc *= 10;
|
214
|
+
if ((unsigned long)c > (ULONG_MAX - acc)) {
|
215
|
+
return NULL;
|
216
|
+
}
|
217
|
+
acc += (unsigned long)c;
|
218
|
+
}
|
219
|
+
if (str == orig || (*orig == '0' && str != (orig + 1))) {
|
220
|
+
return NULL;
|
221
|
+
}
|
222
|
+
*v = acc;
|
223
|
+
return str;
|
224
|
+
}
|
225
|
+
|
226
|
+
/* ==================================================================== */
|
227
|
+
/*
|
228
|
+
* Code specific to Argon2i.
|
229
|
+
*
|
230
|
+
* The code below applies the following format:
|
231
|
+
*
|
232
|
+
* $argon2i$m=<num>,t=<num>,p=<num>[,keyid=<bin>][,data=<bin>][$<bin>[$<bin>]]
|
233
|
+
*
|
234
|
+
* where <num> is a decimal integer (positive, fits in an 'unsigned long')
|
235
|
+
* and <bin> is Base64-encoded data (no '=' padding characters, no newline
|
236
|
+
* or whitespace). The "keyid" is a binary identifier for a key (up to 8
|
237
|
+
* bytes); "data" is associated data (up to 32 bytes). When the 'keyid'
|
238
|
+
* (resp. the 'data') is empty, then it is ommitted from the output.
|
239
|
+
*
|
240
|
+
* The last two binary chunks (encoded in Base64) are, in that order,
|
241
|
+
* the salt and the output. Both are optional, but you cannot have an
|
242
|
+
* output without a salt. The binary salt length is between 8 and 48 bytes.
|
243
|
+
* The output length is always exactly 32 bytes.
|
244
|
+
*/
|
245
|
+
|
246
|
+
/*
|
247
|
+
* Decode an Argon2i hash string into the provided structure 'ctx'.
|
248
|
+
* Returned value is 1 on success, 0 on error.
|
249
|
+
*/
|
250
|
+
int decode_string(argon2_context *ctx, const char *str, argon2_type type) {
|
251
|
+
#define CC(prefix) \
|
252
|
+
do { \
|
253
|
+
size_t cc_len = strlen(prefix); \
|
254
|
+
if (strncmp(str, prefix, cc_len) != 0) { \
|
255
|
+
return 0; \
|
256
|
+
} \
|
257
|
+
str += cc_len; \
|
258
|
+
} while (0)
|
259
|
+
|
260
|
+
#define CC_opt(prefix, code) \
|
261
|
+
do { \
|
262
|
+
size_t cc_len = strlen(prefix); \
|
263
|
+
if (strncmp(str, prefix, cc_len) == 0) { \
|
264
|
+
str += cc_len; \
|
265
|
+
{ code; } \
|
266
|
+
} \
|
267
|
+
} while (0)
|
268
|
+
|
269
|
+
#define DECIMAL(x) \
|
270
|
+
do { \
|
271
|
+
unsigned long dec_x; \
|
272
|
+
str = decode_decimal(str, &dec_x); \
|
273
|
+
if (str == NULL) { \
|
274
|
+
return 0; \
|
275
|
+
} \
|
276
|
+
(x) = dec_x; \
|
277
|
+
} while (0)
|
278
|
+
|
279
|
+
#define BIN(buf, max_len, len) \
|
280
|
+
do { \
|
281
|
+
size_t bin_len = (max_len); \
|
282
|
+
str = from_base64(buf, &bin_len, str); \
|
283
|
+
if (str == NULL) { \
|
284
|
+
return 0; \
|
285
|
+
} \
|
286
|
+
(len) = bin_len; \
|
287
|
+
} while (0)
|
288
|
+
|
289
|
+
size_t maxadlen = ctx->adlen;
|
290
|
+
size_t maxsaltlen = ctx->saltlen;
|
291
|
+
size_t maxoutlen = ctx->outlen;
|
292
|
+
|
293
|
+
ctx->adlen = 0;
|
294
|
+
ctx->saltlen = 0;
|
295
|
+
ctx->outlen = 0;
|
296
|
+
if (type == Argon2_i)
|
297
|
+
CC("$argon2i");
|
298
|
+
else if (type == Argon2_d)
|
299
|
+
CC("$argon2d");
|
300
|
+
else
|
301
|
+
return 0;
|
302
|
+
CC("$m=");
|
303
|
+
DECIMAL(ctx->m_cost);
|
304
|
+
CC(",t=");
|
305
|
+
DECIMAL(ctx->t_cost);
|
306
|
+
CC(",p=");
|
307
|
+
DECIMAL(ctx->lanes);
|
308
|
+
ctx->threads = ctx->lanes;
|
309
|
+
|
310
|
+
/*
|
311
|
+
* Both m and t must be no more than 2^32-1. The tests below
|
312
|
+
* use a shift by 30 bits to avoid a direct comparison with
|
313
|
+
* 0xFFFFFFFF, which may trigger a spurious compiler warning
|
314
|
+
* on machines where 'unsigned long' is a 32-bit type.
|
315
|
+
*/
|
316
|
+
if (ctx->m_cost < 1 || (ctx->m_cost >> 30) > 3) {
|
317
|
+
return 0;
|
318
|
+
}
|
319
|
+
if (ctx->t_cost < 1 || (ctx->t_cost >> 30) > 3) {
|
320
|
+
return 0;
|
321
|
+
}
|
322
|
+
|
323
|
+
/*
|
324
|
+
* The parallelism p must be between 1 and 255. The memory cost
|
325
|
+
* parameter, expressed in kilobytes, must be at least 8 times
|
326
|
+
* the value of p.
|
327
|
+
*/
|
328
|
+
if (ctx->lanes < 1 || ctx->lanes > 255) {
|
329
|
+
return 0;
|
330
|
+
}
|
331
|
+
if (ctx->m_cost < (ctx->lanes << 3)) {
|
332
|
+
return 0;
|
333
|
+
}
|
334
|
+
|
335
|
+
CC_opt(",data=", BIN(ctx->ad, maxadlen, ctx->adlen));
|
336
|
+
if (*str == 0) {
|
337
|
+
return 1;
|
338
|
+
}
|
339
|
+
CC("$");
|
340
|
+
BIN(ctx->salt, maxsaltlen, ctx->saltlen);
|
341
|
+
if (ctx->saltlen < 8) {
|
342
|
+
return 0;
|
343
|
+
}
|
344
|
+
if (*str == 0) {
|
345
|
+
return 1;
|
346
|
+
}
|
347
|
+
CC("$");
|
348
|
+
BIN(ctx->out, maxoutlen, ctx->outlen);
|
349
|
+
if (ctx->outlen < 12) {
|
350
|
+
return 0;
|
351
|
+
}
|
352
|
+
return *str == 0;
|
353
|
+
|
354
|
+
#undef CC
|
355
|
+
#undef CC_opt
|
356
|
+
#undef DECIMAL
|
357
|
+
#undef BIN
|
358
|
+
}
|
359
|
+
|
360
|
+
/*
|
361
|
+
* encode an argon2i hash string into the provided buffer. 'dst_len'
|
362
|
+
* contains the size, in characters, of the 'dst' buffer; if 'dst_len'
|
363
|
+
* is less than the number of required characters (including the
|
364
|
+
* terminating 0), then this function returns 0.
|
365
|
+
*
|
366
|
+
* if pp->output_len is 0, then the hash string will be a salt string
|
367
|
+
* (no output). if pp->salt_len is also 0, then the string will be a
|
368
|
+
* parameter-only string (no salt and no output).
|
369
|
+
*
|
370
|
+
* on success, 1 is returned.
|
371
|
+
*/
|
372
|
+
int encode_string(char *dst, size_t dst_len, argon2_context *ctx,
|
373
|
+
argon2_type type) {
|
374
|
+
#define SS(str) \
|
375
|
+
do { \
|
376
|
+
size_t pp_len = strlen(str); \
|
377
|
+
if (pp_len >= dst_len) { \
|
378
|
+
return 0; \
|
379
|
+
} \
|
380
|
+
memcpy(dst, str, pp_len + 1); \
|
381
|
+
dst += pp_len; \
|
382
|
+
dst_len -= pp_len; \
|
383
|
+
} while (0)
|
384
|
+
|
385
|
+
#define SX(x) \
|
386
|
+
do { \
|
387
|
+
char tmp[30]; \
|
388
|
+
sprintf(tmp, "%lu", (unsigned long)(x)); \
|
389
|
+
SS(tmp); \
|
390
|
+
} while (0);
|
391
|
+
|
392
|
+
#define SB(buf, len) \
|
393
|
+
do { \
|
394
|
+
size_t sb_len = to_base64(dst, dst_len, buf, len); \
|
395
|
+
if (sb_len == (size_t)-1) { \
|
396
|
+
return 0; \
|
397
|
+
} \
|
398
|
+
dst += sb_len; \
|
399
|
+
dst_len -= sb_len; \
|
400
|
+
} while (0);
|
401
|
+
|
402
|
+
if (type == Argon2_i)
|
403
|
+
SS("$argon2i$m=");
|
404
|
+
else if (type == Argon2_d)
|
405
|
+
SS("$argon2d$m=");
|
406
|
+
else
|
407
|
+
return 0;
|
408
|
+
SX(ctx->m_cost);
|
409
|
+
SS(",t=");
|
410
|
+
SX(ctx->t_cost);
|
411
|
+
SS(",p=");
|
412
|
+
SX(ctx->lanes);
|
413
|
+
|
414
|
+
if (ctx->adlen > 0) {
|
415
|
+
SS(",data=");
|
416
|
+
SB(ctx->ad, ctx->adlen);
|
417
|
+
}
|
418
|
+
|
419
|
+
if (ctx->saltlen == 0)
|
420
|
+
return 1;
|
421
|
+
|
422
|
+
SS("$");
|
423
|
+
SB(ctx->salt, ctx->saltlen);
|
424
|
+
|
425
|
+
if (ctx->outlen == 0)
|
426
|
+
return 1;
|
427
|
+
|
428
|
+
SS("$");
|
429
|
+
SB(ctx->out, ctx->outlen);
|
430
|
+
return 1;
|
431
|
+
|
432
|
+
#undef SS
|
433
|
+
#undef SX
|
434
|
+
#undef SB
|
435
|
+
}
|