argon2 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
- * 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.
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 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);
261
+ int argon2i_verify(const char *encoded, const void *pwd, const size_t pwdlen);
207
262
 
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);
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
@@ -26,7 +26,6 @@
26
26
  #include <stdlib.h>
27
27
  #include <string.h>
28
28
 
29
- #include "argon2.h"
30
29
  #include "core.h"
31
30
  #include "thread.h"
32
31
  #include "blake2/blake2.h"
@@ -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
+ }