argon2id 0.1.0-x86_64-darwin

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,228 @@
1
+ /*
2
+ * Argon2 reference source code package - reference C implementations
3
+ *
4
+ * Copyright 2015
5
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
6
+ *
7
+ * You may use this work under the terms of a Creative Commons CC0 1.0
8
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
9
+ * these licenses can be found at:
10
+ *
11
+ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
12
+ * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
13
+ *
14
+ * You should have received a copy of both of these licenses along with this
15
+ * software. If not, they may be obtained at the above URLs.
16
+ */
17
+
18
+ #ifndef ARGON2_CORE_H
19
+ #define ARGON2_CORE_H
20
+
21
+ #include "argon2.h"
22
+
23
+ #define CONST_CAST(x) (x)(uintptr_t)
24
+
25
+ /**********************Argon2 internal constants*******************************/
26
+
27
+ enum argon2_core_constants {
28
+ /* Memory block size in bytes */
29
+ ARGON2_BLOCK_SIZE = 1024,
30
+ ARGON2_QWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 8,
31
+ ARGON2_OWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 16,
32
+ ARGON2_HWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 32,
33
+ ARGON2_512BIT_WORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 64,
34
+
35
+ /* Number of pseudo-random values generated by one call to Blake in Argon2i
36
+ to
37
+ generate reference block positions */
38
+ ARGON2_ADDRESSES_IN_BLOCK = 128,
39
+
40
+ /* Pre-hashing digest length and its extension*/
41
+ ARGON2_PREHASH_DIGEST_LENGTH = 64,
42
+ ARGON2_PREHASH_SEED_LENGTH = 72
43
+ };
44
+
45
+ /*************************Argon2 internal data types***********************/
46
+
47
+ /*
48
+ * Structure for the (1KB) memory block implemented as 128 64-bit words.
49
+ * Memory blocks can be copied, XORed. Internal words can be accessed by [] (no
50
+ * bounds checking).
51
+ */
52
+ typedef struct block_ { uint64_t v[ARGON2_QWORDS_IN_BLOCK]; } block;
53
+
54
+ /*****************Functions that work with the block******************/
55
+
56
+ /* Initialize each byte of the block with @in */
57
+ void init_block_value(block *b, uint8_t in);
58
+
59
+ /* Copy block @src to block @dst */
60
+ void copy_block(block *dst, const block *src);
61
+
62
+ /* XOR @src onto @dst bytewise */
63
+ void xor_block(block *dst, const block *src);
64
+
65
+ /*
66
+ * Argon2 instance: memory pointer, number of passes, amount of memory, type,
67
+ * and derived values.
68
+ * Used to evaluate the number and location of blocks to construct in each
69
+ * thread
70
+ */
71
+ typedef struct Argon2_instance_t {
72
+ block *memory; /* Memory pointer */
73
+ uint32_t version;
74
+ uint32_t passes; /* Number of passes */
75
+ uint32_t memory_blocks; /* Number of blocks in memory */
76
+ uint32_t segment_length;
77
+ uint32_t lane_length;
78
+ uint32_t lanes;
79
+ uint32_t threads;
80
+ argon2_type type;
81
+ int print_internals; /* whether to print the memory blocks */
82
+ argon2_context *context_ptr; /* points back to original context */
83
+ } argon2_instance_t;
84
+
85
+ /*
86
+ * Argon2 position: where we construct the block right now. Used to distribute
87
+ * work between threads.
88
+ */
89
+ typedef struct Argon2_position_t {
90
+ uint32_t pass;
91
+ uint32_t lane;
92
+ uint8_t slice;
93
+ uint32_t index;
94
+ } argon2_position_t;
95
+
96
+ /*Struct that holds the inputs for thread handling FillSegment*/
97
+ typedef struct Argon2_thread_data {
98
+ argon2_instance_t *instance_ptr;
99
+ argon2_position_t pos;
100
+ } argon2_thread_data;
101
+
102
+ /*************************Argon2 core functions********************************/
103
+
104
+ /* Allocates memory to the given pointer, uses the appropriate allocator as
105
+ * specified in the context. Total allocated memory is num*size.
106
+ * @param context argon2_context which specifies the allocator
107
+ * @param memory pointer to the pointer to the memory
108
+ * @param size the size in bytes for each element to be allocated
109
+ * @param num the number of elements to be allocated
110
+ * @return ARGON2_OK if @memory is a valid pointer and memory is allocated
111
+ */
112
+ int allocate_memory(const argon2_context *context, uint8_t **memory,
113
+ size_t num, size_t size);
114
+
115
+ /*
116
+ * Frees memory at the given pointer, uses the appropriate deallocator as
117
+ * specified in the context. Also cleans the memory using clear_internal_memory.
118
+ * @param context argon2_context which specifies the deallocator
119
+ * @param memory pointer to buffer to be freed
120
+ * @param size the size in bytes for each element to be deallocated
121
+ * @param num the number of elements to be deallocated
122
+ */
123
+ void free_memory(const argon2_context *context, uint8_t *memory,
124
+ size_t num, size_t size);
125
+
126
+ /* Function that securely cleans the memory. This ignores any flags set
127
+ * regarding clearing memory. Usually one just calls clear_internal_memory.
128
+ * @param mem Pointer to the memory
129
+ * @param s Memory size in bytes
130
+ */
131
+ void secure_wipe_memory(void *v, size_t n);
132
+
133
+ /* Function that securely clears the memory if FLAG_clear_internal_memory is
134
+ * set. If the flag isn't set, this function does nothing.
135
+ * @param mem Pointer to the memory
136
+ * @param s Memory size in bytes
137
+ */
138
+ void clear_internal_memory(void *v, size_t n);
139
+
140
+ /*
141
+ * Computes absolute position of reference block in the lane following a skewed
142
+ * distribution and using a pseudo-random value as input
143
+ * @param instance Pointer to the current instance
144
+ * @param position Pointer to the current position
145
+ * @param pseudo_rand 32-bit pseudo-random value used to determine the position
146
+ * @param same_lane Indicates if the block will be taken from the current lane.
147
+ * If so we can reference the current segment
148
+ * @pre All pointers must be valid
149
+ */
150
+ uint32_t index_alpha(const argon2_instance_t *instance,
151
+ const argon2_position_t *position, uint32_t pseudo_rand,
152
+ int same_lane);
153
+
154
+ /*
155
+ * Function that validates all inputs against predefined restrictions and return
156
+ * an error code
157
+ * @param context Pointer to current Argon2 context
158
+ * @return ARGON2_OK if everything is all right, otherwise one of error codes
159
+ * (all defined in <argon2.h>
160
+ */
161
+ int validate_inputs(const argon2_context *context);
162
+
163
+ /*
164
+ * Hashes all the inputs into @a blockhash[PREHASH_DIGEST_LENGTH], clears
165
+ * password and secret if needed
166
+ * @param context Pointer to the Argon2 internal structure containing memory
167
+ * pointer, and parameters for time and space requirements.
168
+ * @param blockhash Buffer for pre-hashing digest
169
+ * @param type Argon2 type
170
+ * @pre @a blockhash must have at least @a PREHASH_DIGEST_LENGTH bytes
171
+ * allocated
172
+ */
173
+ void initial_hash(uint8_t *blockhash, argon2_context *context,
174
+ argon2_type type);
175
+
176
+ /*
177
+ * Function creates first 2 blocks per lane
178
+ * @param instance Pointer to the current instance
179
+ * @param blockhash Pointer to the pre-hashing digest
180
+ * @pre blockhash must point to @a PREHASH_SEED_LENGTH allocated values
181
+ */
182
+ void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance);
183
+
184
+ /*
185
+ * Function allocates memory, hashes the inputs with Blake, and creates first
186
+ * two blocks. Returns the pointer to the main memory with 2 blocks per lane
187
+ * initialized
188
+ * @param context Pointer to the Argon2 internal structure containing memory
189
+ * pointer, and parameters for time and space requirements.
190
+ * @param instance Current Argon2 instance
191
+ * @return Zero if successful, -1 if memory failed to allocate. @context->state
192
+ * will be modified if successful.
193
+ */
194
+ int initialize(argon2_instance_t *instance, argon2_context *context);
195
+
196
+ /*
197
+ * XORing the last block of each lane, hashing it, making the tag. Deallocates
198
+ * the memory.
199
+ * @param context Pointer to current Argon2 context (use only the out parameters
200
+ * from it)
201
+ * @param instance Pointer to current instance of Argon2
202
+ * @pre instance->state must point to necessary amount of memory
203
+ * @pre context->out must point to outlen bytes of memory
204
+ * @pre if context->free_cbk is not NULL, it should point to a function that
205
+ * deallocates memory
206
+ */
207
+ void finalize(const argon2_context *context, argon2_instance_t *instance);
208
+
209
+ /*
210
+ * Function that fills the segment using previous segments also from other
211
+ * threads
212
+ * @param context current context
213
+ * @param instance Pointer to the current instance
214
+ * @param position Current position
215
+ * @pre all block pointers must be valid
216
+ */
217
+ void fill_segment(const argon2_instance_t *instance,
218
+ argon2_position_t position);
219
+
220
+ /*
221
+ * Function that fills the entire memory t_cost times based on the first two
222
+ * blocks in each lane
223
+ * @param instance Pointer to the current instance
224
+ * @return ARGON2_OK if successful, @context->state
225
+ */
226
+ int fill_memory_blocks(argon2_instance_t *instance);
227
+
228
+ #endif
@@ -0,0 +1,463 @@
1
+ /*
2
+ * Argon2 reference source code package - reference C implementations
3
+ *
4
+ * Copyright 2015
5
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
6
+ *
7
+ * You may use this work under the terms of a Creative Commons CC0 1.0
8
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
9
+ * these licenses can be found at:
10
+ *
11
+ * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
12
+ * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
13
+ *
14
+ * You should have received a copy of both of these licenses along with this
15
+ * software. If not, they may be obtained at the above URLs.
16
+ */
17
+
18
+ #include <stdio.h>
19
+ #include <stdlib.h>
20
+ #include <string.h>
21
+ #include <limits.h>
22
+ #include "encoding.h"
23
+ #include "core.h"
24
+
25
+ /*
26
+ * Example code for a decoder and encoder of "hash strings", with Argon2
27
+ * parameters.
28
+ *
29
+ * This code comprises three sections:
30
+ *
31
+ * -- The first section contains generic Base64 encoding and decoding
32
+ * functions. It is conceptually applicable to any hash function
33
+ * implementation that uses Base64 to encode and decode parameters,
34
+ * salts and outputs. It could be made into a library, provided that
35
+ * the relevant functions are made public (non-static) and be given
36
+ * reasonable names to avoid collisions with other functions.
37
+ *
38
+ * -- The second section is specific to Argon2. It encodes and decodes
39
+ * the parameters, salts and outputs. It does not compute the hash
40
+ * itself.
41
+ *
42
+ * The code was originally written by Thomas Pornin <pornin@bolet.org>,
43
+ * to whom comments and remarks may be sent. It is released under what
44
+ * should amount to Public Domain or its closest equivalent; the
45
+ * following mantra is supposed to incarnate that fact with all the
46
+ * proper legal rituals:
47
+ *
48
+ * ---------------------------------------------------------------------
49
+ * This file is provided under the terms of Creative Commons CC0 1.0
50
+ * Public Domain Dedication. To the extent possible under law, the
51
+ * author (Thomas Pornin) has waived all copyright and related or
52
+ * neighboring rights to this file. This work is published from: Canada.
53
+ * ---------------------------------------------------------------------
54
+ *
55
+ * Copyright (c) 2015 Thomas Pornin
56
+ */
57
+
58
+ /* ==================================================================== */
59
+ /*
60
+ * Common code; could be shared between different hash functions.
61
+ *
62
+ * Note: the Base64 functions below assume that uppercase letters (resp.
63
+ * lowercase letters) have consecutive numerical codes, that fit on 8
64
+ * bits. All modern systems use ASCII-compatible charsets, where these
65
+ * properties are true. If you are stuck with a dinosaur of a system
66
+ * that still defaults to EBCDIC then you already have much bigger
67
+ * interoperability issues to deal with.
68
+ */
69
+
70
+ /*
71
+ * Some macros for constant-time comparisons. These work over values in
72
+ * the 0..255 range. Returned value is 0x00 on "false", 0xFF on "true".
73
+ */
74
+ #define EQ(x, y) ((((0U - ((unsigned)(x) ^ (unsigned)(y))) >> 8) & 0xFF) ^ 0xFF)
75
+ #define GT(x, y) ((((unsigned)(y) - (unsigned)(x)) >> 8) & 0xFF)
76
+ #define GE(x, y) (GT(y, x) ^ 0xFF)
77
+ #define LT(x, y) GT(y, x)
78
+ #define LE(x, y) GE(y, x)
79
+
80
+ /*
81
+ * Convert value x (0..63) to corresponding Base64 character.
82
+ */
83
+ static int b64_byte_to_char(unsigned x) {
84
+ return (LT(x, 26) & (x + 'A')) |
85
+ (GE(x, 26) & LT(x, 52) & (x + ('a' - 26))) |
86
+ (GE(x, 52) & LT(x, 62) & (x + ('0' - 52))) | (EQ(x, 62) & '+') |
87
+ (EQ(x, 63) & '/');
88
+ }
89
+
90
+ /*
91
+ * Convert character c to the corresponding 6-bit value. If character c
92
+ * is not a Base64 character, then 0xFF (255) is returned.
93
+ */
94
+ static unsigned b64_char_to_byte(int c) {
95
+ unsigned x;
96
+
97
+ x = (GE(c, 'A') & LE(c, 'Z') & (c - 'A')) |
98
+ (GE(c, 'a') & LE(c, 'z') & (c - ('a' - 26))) |
99
+ (GE(c, '0') & LE(c, '9') & (c - ('0' - 52))) | (EQ(c, '+') & 62) |
100
+ (EQ(c, '/') & 63);
101
+ return x | (EQ(x, 0) & (EQ(c, 'A') ^ 0xFF));
102
+ }
103
+
104
+ /*
105
+ * Convert some bytes to Base64. 'dst_len' is the length (in characters)
106
+ * of the output buffer 'dst'; if that buffer is not large enough to
107
+ * receive the result (including the terminating 0), then (size_t)-1
108
+ * is returned. Otherwise, the zero-terminated Base64 string is written
109
+ * in the buffer, and the output length (counted WITHOUT the terminating
110
+ * zero) is returned.
111
+ */
112
+ static size_t to_base64(char *dst, size_t dst_len, const void *src,
113
+ size_t src_len) {
114
+ size_t olen;
115
+ const unsigned char *buf;
116
+ unsigned acc, acc_len;
117
+
118
+ olen = (src_len / 3) << 2;
119
+ switch (src_len % 3) {
120
+ case 2:
121
+ olen++;
122
+ /* fall through */
123
+ case 1:
124
+ olen += 2;
125
+ break;
126
+ }
127
+ if (dst_len <= olen) {
128
+ return (size_t)-1;
129
+ }
130
+ acc = 0;
131
+ acc_len = 0;
132
+ buf = (const unsigned char *)src;
133
+ while (src_len-- > 0) {
134
+ acc = (acc << 8) + (*buf++);
135
+ acc_len += 8;
136
+ while (acc_len >= 6) {
137
+ acc_len -= 6;
138
+ *dst++ = (char)b64_byte_to_char((acc >> acc_len) & 0x3F);
139
+ }
140
+ }
141
+ if (acc_len > 0) {
142
+ *dst++ = (char)b64_byte_to_char((acc << (6 - acc_len)) & 0x3F);
143
+ }
144
+ *dst++ = 0;
145
+ return olen;
146
+ }
147
+
148
+ /*
149
+ * Decode Base64 chars into bytes. The '*dst_len' value must initially
150
+ * contain the length of the output buffer '*dst'; when the decoding
151
+ * ends, the actual number of decoded bytes is written back in
152
+ * '*dst_len'.
153
+ *
154
+ * Decoding stops when a non-Base64 character is encountered, or when
155
+ * the output buffer capacity is exceeded. If an error occurred (output
156
+ * buffer is too small, invalid last characters leading to unprocessed
157
+ * buffered bits), then NULL is returned; otherwise, the returned value
158
+ * points to the first non-Base64 character in the source stream, which
159
+ * may be the terminating zero.
160
+ */
161
+ static const char *from_base64(void *dst, size_t *dst_len, const char *src) {
162
+ size_t len;
163
+ unsigned char *buf;
164
+ unsigned acc, acc_len;
165
+
166
+ buf = (unsigned char *)dst;
167
+ len = 0;
168
+ acc = 0;
169
+ acc_len = 0;
170
+ for (;;) {
171
+ unsigned d;
172
+
173
+ d = b64_char_to_byte(*src);
174
+ if (d == 0xFF) {
175
+ break;
176
+ }
177
+ src++;
178
+ acc = (acc << 6) + d;
179
+ acc_len += 6;
180
+ if (acc_len >= 8) {
181
+ acc_len -= 8;
182
+ if ((len++) >= *dst_len) {
183
+ return NULL;
184
+ }
185
+ *buf++ = (acc >> acc_len) & 0xFF;
186
+ }
187
+ }
188
+
189
+ /*
190
+ * If the input length is equal to 1 modulo 4 (which is
191
+ * invalid), then there will remain 6 unprocessed bits;
192
+ * otherwise, only 0, 2 or 4 bits are buffered. The buffered
193
+ * bits must also all be zero.
194
+ */
195
+ if (acc_len > 4 || (acc & (((unsigned)1 << acc_len) - 1)) != 0) {
196
+ return NULL;
197
+ }
198
+ *dst_len = len;
199
+ return src;
200
+ }
201
+
202
+ /*
203
+ * Decode decimal integer from 'str'; the value is written in '*v'.
204
+ * Returned value is a pointer to the next non-decimal character in the
205
+ * string. If there is no digit at all, or the value encoding is not
206
+ * minimal (extra leading zeros), or the value does not fit in an
207
+ * 'unsigned long', then NULL is returned.
208
+ */
209
+ static const char *decode_decimal(const char *str, unsigned long *v) {
210
+ const char *orig;
211
+ unsigned long acc;
212
+
213
+ acc = 0;
214
+ for (orig = str;; str++) {
215
+ int c;
216
+
217
+ c = *str;
218
+ if (c < '0' || c > '9') {
219
+ break;
220
+ }
221
+ c -= '0';
222
+ if (acc > (ULONG_MAX / 10)) {
223
+ return NULL;
224
+ }
225
+ acc *= 10;
226
+ if ((unsigned long)c > (ULONG_MAX - acc)) {
227
+ return NULL;
228
+ }
229
+ acc += (unsigned long)c;
230
+ }
231
+ if (str == orig || (*orig == '0' && str != (orig + 1))) {
232
+ return NULL;
233
+ }
234
+ *v = acc;
235
+ return str;
236
+ }
237
+
238
+ /* ==================================================================== */
239
+ /*
240
+ * Code specific to Argon2.
241
+ *
242
+ * The code below applies the following format:
243
+ *
244
+ * $argon2<T>[$v=<num>]$m=<num>,t=<num>,p=<num>$<bin>$<bin>
245
+ *
246
+ * where <T> is either 'd', 'id', or 'i', <num> is a decimal integer (positive,
247
+ * fits in an 'unsigned long'), and <bin> is Base64-encoded data (no '=' padding
248
+ * characters, no newline or whitespace).
249
+ *
250
+ * The last two binary chunks (encoded in Base64) are, in that order,
251
+ * the salt and the output. Both are required. The binary salt length and the
252
+ * output length must be in the allowed ranges defined in argon2.h.
253
+ *
254
+ * The ctx struct must contain buffers large enough to hold the salt and pwd
255
+ * when it is fed into decode_string.
256
+ */
257
+
258
+ int decode_string(argon2_context *ctx, const char *str, argon2_type type) {
259
+
260
+ /* check for prefix */
261
+ #define CC(prefix) \
262
+ do { \
263
+ size_t cc_len = strlen(prefix); \
264
+ if (strncmp(str, prefix, cc_len) != 0) { \
265
+ return ARGON2_DECODING_FAIL; \
266
+ } \
267
+ str += cc_len; \
268
+ } while ((void)0, 0)
269
+
270
+ /* optional prefix checking with supplied code */
271
+ #define CC_opt(prefix, code) \
272
+ do { \
273
+ size_t cc_len = strlen(prefix); \
274
+ if (strncmp(str, prefix, cc_len) == 0) { \
275
+ str += cc_len; \
276
+ { code; } \
277
+ } \
278
+ } while ((void)0, 0)
279
+
280
+ /* Decoding prefix into decimal */
281
+ #define DECIMAL(x) \
282
+ do { \
283
+ unsigned long dec_x; \
284
+ str = decode_decimal(str, &dec_x); \
285
+ if (str == NULL) { \
286
+ return ARGON2_DECODING_FAIL; \
287
+ } \
288
+ (x) = dec_x; \
289
+ } while ((void)0, 0)
290
+
291
+
292
+ /* Decoding prefix into uint32_t decimal */
293
+ #define DECIMAL_U32(x) \
294
+ do { \
295
+ unsigned long dec_x; \
296
+ str = decode_decimal(str, &dec_x); \
297
+ if (str == NULL || dec_x > UINT32_MAX) { \
298
+ return ARGON2_DECODING_FAIL; \
299
+ } \
300
+ (x) = (uint32_t)dec_x; \
301
+ } while ((void)0, 0)
302
+
303
+
304
+ /* Decoding base64 into a binary buffer */
305
+ #define BIN(buf, max_len, len) \
306
+ do { \
307
+ size_t bin_len = (max_len); \
308
+ str = from_base64(buf, &bin_len, str); \
309
+ if (str == NULL || bin_len > UINT32_MAX) { \
310
+ return ARGON2_DECODING_FAIL; \
311
+ } \
312
+ (len) = (uint32_t)bin_len; \
313
+ } while ((void)0, 0)
314
+
315
+ size_t maxsaltlen = ctx->saltlen;
316
+ size_t maxoutlen = ctx->outlen;
317
+ int validation_result;
318
+ const char* type_string;
319
+
320
+ /* We should start with the argon2_type we are using */
321
+ type_string = argon2_type2string(type, 0);
322
+ if (!type_string) {
323
+ return ARGON2_INCORRECT_TYPE;
324
+ }
325
+
326
+ CC("$");
327
+ CC(type_string);
328
+
329
+ /* Reading the version number if the default is suppressed */
330
+ ctx->version = ARGON2_VERSION_10;
331
+ CC_opt("$v=", DECIMAL_U32(ctx->version));
332
+
333
+ CC("$m=");
334
+ DECIMAL_U32(ctx->m_cost);
335
+ CC(",t=");
336
+ DECIMAL_U32(ctx->t_cost);
337
+ CC(",p=");
338
+ DECIMAL_U32(ctx->lanes);
339
+ ctx->threads = ctx->lanes;
340
+
341
+ CC("$");
342
+ BIN(ctx->salt, maxsaltlen, ctx->saltlen);
343
+ CC("$");
344
+ BIN(ctx->out, maxoutlen, ctx->outlen);
345
+
346
+ /* The rest of the fields get the default values */
347
+ ctx->secret = NULL;
348
+ ctx->secretlen = 0;
349
+ ctx->ad = NULL;
350
+ ctx->adlen = 0;
351
+ ctx->allocate_cbk = NULL;
352
+ ctx->free_cbk = NULL;
353
+ ctx->flags = ARGON2_DEFAULT_FLAGS;
354
+
355
+ /* On return, must have valid context */
356
+ validation_result = validate_inputs(ctx);
357
+ if (validation_result != ARGON2_OK) {
358
+ return validation_result;
359
+ }
360
+
361
+ /* Can't have any additional characters */
362
+ if (*str == 0) {
363
+ return ARGON2_OK;
364
+ } else {
365
+ return ARGON2_DECODING_FAIL;
366
+ }
367
+ #undef CC
368
+ #undef CC_opt
369
+ #undef DECIMAL
370
+ #undef BIN
371
+ }
372
+
373
+ int encode_string(char *dst, size_t dst_len, argon2_context *ctx,
374
+ argon2_type type) {
375
+ #define SS(str) \
376
+ do { \
377
+ size_t pp_len = strlen(str); \
378
+ if (pp_len >= dst_len) { \
379
+ return ARGON2_ENCODING_FAIL; \
380
+ } \
381
+ memcpy(dst, str, pp_len + 1); \
382
+ dst += pp_len; \
383
+ dst_len -= pp_len; \
384
+ } while ((void)0, 0)
385
+
386
+ #define SX(x) \
387
+ do { \
388
+ char tmp[30]; \
389
+ sprintf(tmp, "%lu", (unsigned long)(x)); \
390
+ SS(tmp); \
391
+ } while ((void)0, 0)
392
+
393
+ #define SB(buf, len) \
394
+ do { \
395
+ size_t sb_len = to_base64(dst, dst_len, buf, len); \
396
+ if (sb_len == (size_t)-1) { \
397
+ return ARGON2_ENCODING_FAIL; \
398
+ } \
399
+ dst += sb_len; \
400
+ dst_len -= sb_len; \
401
+ } while ((void)0, 0)
402
+
403
+ const char* type_string = argon2_type2string(type, 0);
404
+ int validation_result = validate_inputs(ctx);
405
+
406
+ if (!type_string) {
407
+ return ARGON2_ENCODING_FAIL;
408
+ }
409
+
410
+ if (validation_result != ARGON2_OK) {
411
+ return validation_result;
412
+ }
413
+
414
+
415
+ SS("$");
416
+ SS(type_string);
417
+
418
+ SS("$v=");
419
+ SX(ctx->version);
420
+
421
+ SS("$m=");
422
+ SX(ctx->m_cost);
423
+ SS(",t=");
424
+ SX(ctx->t_cost);
425
+ SS(",p=");
426
+ SX(ctx->lanes);
427
+
428
+ SS("$");
429
+ SB(ctx->salt, ctx->saltlen);
430
+
431
+ SS("$");
432
+ SB(ctx->out, ctx->outlen);
433
+ return ARGON2_OK;
434
+
435
+ #undef SS
436
+ #undef SX
437
+ #undef SB
438
+ }
439
+
440
+ size_t b64len(uint32_t len) {
441
+ size_t olen = ((size_t)len / 3) << 2;
442
+
443
+ switch (len % 3) {
444
+ case 2:
445
+ olen++;
446
+ /* fall through */
447
+ case 1:
448
+ olen += 2;
449
+ break;
450
+ }
451
+
452
+ return olen;
453
+ }
454
+
455
+ size_t numlen(uint32_t num) {
456
+ size_t len = 1;
457
+ while (num >= 10) {
458
+ ++len;
459
+ num = num / 10;
460
+ }
461
+ return len;
462
+ }
463
+