/work/workdir/UnpackedTarball/argon2/src/encoding.c
Line | Count | Source (jump to first uncovered line) |
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 | 0 | #define EQ(x, y) ((((0U - ((unsigned)(x) ^ (unsigned)(y))) >> 8) & 0xFF) ^ 0xFF) |
75 | 0 | #define GT(x, y) ((((unsigned)(y) - (unsigned)(x)) >> 8) & 0xFF) |
76 | 0 | #define GE(x, y) (GT(y, x) ^ 0xFF) |
77 | 0 | #define LT(x, y) GT(y, x) |
78 | 0 | #define LE(x, y) GE(y, x) |
79 | | |
80 | | /* |
81 | | * Convert value x (0..63) to corresponding Base64 character. |
82 | | */ |
83 | 0 | static int b64_byte_to_char(unsigned x) { |
84 | 0 | return (LT(x, 26) & (x + 'A')) | |
85 | 0 | (GE(x, 26) & LT(x, 52) & (x + ('a' - 26))) | |
86 | 0 | (GE(x, 52) & LT(x, 62) & (x + ('0' - 52))) | (EQ(x, 62) & '+') | |
87 | 0 | (EQ(x, 63) & '/'); |
88 | 0 | } |
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 | 0 | static unsigned b64_char_to_byte(int c) { |
95 | 0 | unsigned x; |
96 | |
|
97 | 0 | x = (GE(c, 'A') & LE(c, 'Z') & (c - 'A')) | |
98 | 0 | (GE(c, 'a') & LE(c, 'z') & (c - ('a' - 26))) | |
99 | 0 | (GE(c, '0') & LE(c, '9') & (c - ('0' - 52))) | (EQ(c, '+') & 62) | |
100 | 0 | (EQ(c, '/') & 63); |
101 | 0 | return x | (EQ(x, 0) & (EQ(c, 'A') ^ 0xFF)); |
102 | 0 | } |
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 | 0 | size_t src_len) { |
114 | 0 | size_t olen; |
115 | 0 | const unsigned char *buf; |
116 | 0 | unsigned acc, acc_len; |
117 | |
|
118 | 0 | olen = (src_len / 3) << 2; |
119 | 0 | switch (src_len % 3) { |
120 | 0 | case 2: |
121 | 0 | olen++; |
122 | | /* fall through */ |
123 | 0 | case 1: |
124 | 0 | olen += 2; |
125 | 0 | break; |
126 | 0 | } |
127 | 0 | if (dst_len <= olen) { |
128 | 0 | return (size_t)-1; |
129 | 0 | } |
130 | 0 | acc = 0; |
131 | 0 | acc_len = 0; |
132 | 0 | buf = (const unsigned char *)src; |
133 | 0 | while (src_len-- > 0) { |
134 | 0 | acc = (acc << 8) + (*buf++); |
135 | 0 | acc_len += 8; |
136 | 0 | while (acc_len >= 6) { |
137 | 0 | acc_len -= 6; |
138 | 0 | *dst++ = (char)b64_byte_to_char((acc >> acc_len) & 0x3F); |
139 | 0 | } |
140 | 0 | } |
141 | 0 | if (acc_len > 0) { |
142 | 0 | *dst++ = (char)b64_byte_to_char((acc << (6 - acc_len)) & 0x3F); |
143 | 0 | } |
144 | 0 | *dst++ = 0; |
145 | 0 | return olen; |
146 | 0 | } |
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 | 0 | static const char *from_base64(void *dst, size_t *dst_len, const char *src) { |
162 | 0 | size_t len; |
163 | 0 | unsigned char *buf; |
164 | 0 | unsigned acc, acc_len; |
165 | |
|
166 | 0 | buf = (unsigned char *)dst; |
167 | 0 | len = 0; |
168 | 0 | acc = 0; |
169 | 0 | acc_len = 0; |
170 | 0 | for (;;) { |
171 | 0 | unsigned d; |
172 | |
|
173 | 0 | d = b64_char_to_byte(*src); |
174 | 0 | if (d == 0xFF) { |
175 | 0 | break; |
176 | 0 | } |
177 | 0 | src++; |
178 | 0 | acc = (acc << 6) + d; |
179 | 0 | acc_len += 6; |
180 | 0 | if (acc_len >= 8) { |
181 | 0 | acc_len -= 8; |
182 | 0 | if ((len++) >= *dst_len) { |
183 | 0 | return NULL; |
184 | 0 | } |
185 | 0 | *buf++ = (acc >> acc_len) & 0xFF; |
186 | 0 | } |
187 | 0 | } |
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 | 0 | if (acc_len > 4 || (acc & (((unsigned)1 << acc_len) - 1)) != 0) { |
196 | 0 | return NULL; |
197 | 0 | } |
198 | 0 | *dst_len = len; |
199 | 0 | return src; |
200 | 0 | } |
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 | 0 | static const char *decode_decimal(const char *str, unsigned long *v) { |
210 | 0 | const char *orig; |
211 | 0 | unsigned long acc; |
212 | |
|
213 | 0 | acc = 0; |
214 | 0 | for (orig = str;; str++) { |
215 | 0 | int c; |
216 | |
|
217 | 0 | c = *str; |
218 | 0 | if (c < '0' || c > '9') { |
219 | 0 | break; |
220 | 0 | } |
221 | 0 | c -= '0'; |
222 | 0 | if (acc > (ULONG_MAX / 10)) { |
223 | 0 | return NULL; |
224 | 0 | } |
225 | 0 | acc *= 10; |
226 | 0 | if ((unsigned long)c > (ULONG_MAX - acc)) { |
227 | 0 | return NULL; |
228 | 0 | } |
229 | 0 | acc += (unsigned long)c; |
230 | 0 | } |
231 | 0 | if (str == orig || (*orig == '0' && str != (orig + 1))) { |
232 | 0 | return NULL; |
233 | 0 | } |
234 | 0 | *v = acc; |
235 | 0 | return str; |
236 | 0 | } |
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 | 0 | int decode_string(argon2_context *ctx, const char *str, argon2_type type) { |
259 | | |
260 | | /* check for prefix */ |
261 | 0 | #define CC(prefix) \ |
262 | 0 | do { \ |
263 | 0 | size_t cc_len = strlen(prefix); \ |
264 | 0 | if (strncmp(str, prefix, cc_len) != 0) { \ |
265 | 0 | return ARGON2_DECODING_FAIL; \ |
266 | 0 | } \ |
267 | 0 | str += cc_len; \ |
268 | 0 | } while ((void)0, 0) |
269 | | |
270 | | /* optional prefix checking with supplied code */ |
271 | 0 | #define CC_opt(prefix, code) \ |
272 | 0 | do { \ |
273 | 0 | size_t cc_len = strlen(prefix); \ |
274 | 0 | if (strncmp(str, prefix, cc_len) == 0) { \ |
275 | 0 | str += cc_len; \ |
276 | 0 | { code; } \ |
277 | 0 | } \ |
278 | 0 | } while ((void)0, 0) |
279 | | |
280 | | /* Decoding prefix into decimal */ |
281 | 0 | #define DECIMAL(x) \ |
282 | 0 | do { \ |
283 | 0 | unsigned long dec_x; \ |
284 | 0 | str = decode_decimal(str, &dec_x); \ |
285 | 0 | if (str == NULL) { \ |
286 | 0 | return ARGON2_DECODING_FAIL; \ |
287 | 0 | } \ |
288 | 0 | (x) = dec_x; \ |
289 | 0 | } while ((void)0, 0) |
290 | | |
291 | | |
292 | | /* Decoding prefix into uint32_t decimal */ |
293 | 0 | #define DECIMAL_U32(x) \ |
294 | 0 | do { \ |
295 | 0 | unsigned long dec_x; \ |
296 | 0 | str = decode_decimal(str, &dec_x); \ |
297 | 0 | if (str == NULL || dec_x > UINT32_MAX) { \ |
298 | 0 | return ARGON2_DECODING_FAIL; \ |
299 | 0 | } \ |
300 | 0 | (x) = (uint32_t)dec_x; \ |
301 | 0 | } while ((void)0, 0) |
302 | | |
303 | | |
304 | | /* Decoding base64 into a binary buffer */ |
305 | 0 | #define BIN(buf, max_len, len) \ |
306 | 0 | do { \ |
307 | 0 | size_t bin_len = (max_len); \ |
308 | 0 | str = from_base64(buf, &bin_len, str); \ |
309 | 0 | if (str == NULL || bin_len > UINT32_MAX) { \ |
310 | 0 | return ARGON2_DECODING_FAIL; \ |
311 | 0 | } \ |
312 | 0 | (len) = (uint32_t)bin_len; \ |
313 | 0 | } while ((void)0, 0) |
314 | |
|
315 | 0 | size_t maxsaltlen = ctx->saltlen; |
316 | 0 | size_t maxoutlen = ctx->outlen; |
317 | 0 | int validation_result; |
318 | 0 | const char* type_string; |
319 | | |
320 | | /* We should start with the argon2_type we are using */ |
321 | 0 | type_string = argon2_type2string(type, 0); |
322 | 0 | if (!type_string) { |
323 | 0 | return ARGON2_INCORRECT_TYPE; |
324 | 0 | } |
325 | | |
326 | 0 | CC("$"); |
327 | 0 | CC(type_string); |
328 | | |
329 | | /* Reading the version number if the default is suppressed */ |
330 | 0 | ctx->version = ARGON2_VERSION_10; |
331 | 0 | CC_opt("$v=", DECIMAL_U32(ctx->version)); |
332 | | |
333 | 0 | CC("$m="); |
334 | 0 | DECIMAL_U32(ctx->m_cost); |
335 | 0 | CC(",t="); |
336 | 0 | DECIMAL_U32(ctx->t_cost); |
337 | 0 | CC(",p="); |
338 | 0 | DECIMAL_U32(ctx->lanes); |
339 | 0 | ctx->threads = ctx->lanes; |
340 | |
|
341 | 0 | CC("$"); |
342 | 0 | BIN(ctx->salt, maxsaltlen, ctx->saltlen); |
343 | 0 | CC("$"); |
344 | 0 | BIN(ctx->out, maxoutlen, ctx->outlen); |
345 | | |
346 | | /* The rest of the fields get the default values */ |
347 | 0 | ctx->secret = NULL; |
348 | 0 | ctx->secretlen = 0; |
349 | 0 | ctx->ad = NULL; |
350 | 0 | ctx->adlen = 0; |
351 | 0 | ctx->allocate_cbk = NULL; |
352 | 0 | ctx->free_cbk = NULL; |
353 | 0 | ctx->flags = ARGON2_DEFAULT_FLAGS; |
354 | | |
355 | | /* On return, must have valid context */ |
356 | 0 | validation_result = validate_inputs(ctx); |
357 | 0 | if (validation_result != ARGON2_OK) { |
358 | 0 | return validation_result; |
359 | 0 | } |
360 | | |
361 | | /* Can't have any additional characters */ |
362 | 0 | if (*str == 0) { |
363 | 0 | return ARGON2_OK; |
364 | 0 | } else { |
365 | 0 | return ARGON2_DECODING_FAIL; |
366 | 0 | } |
367 | 0 | #undef CC |
368 | 0 | #undef CC_opt |
369 | 0 | #undef DECIMAL |
370 | 0 | #undef BIN |
371 | 0 | } |
372 | | |
373 | | int encode_string(char *dst, size_t dst_len, argon2_context *ctx, |
374 | 0 | argon2_type type) { |
375 | 0 | #define SS(str) \ |
376 | 0 | do { \ |
377 | 0 | size_t pp_len = strlen(str); \ |
378 | 0 | if (pp_len >= dst_len) { \ |
379 | 0 | return ARGON2_ENCODING_FAIL; \ |
380 | 0 | } \ |
381 | 0 | memcpy(dst, str, pp_len + 1); \ |
382 | 0 | dst += pp_len; \ |
383 | 0 | dst_len -= pp_len; \ |
384 | 0 | } while ((void)0, 0) |
385 | |
|
386 | 0 | #define SX(x) \ |
387 | 0 | do { \ |
388 | 0 | char tmp[30]; \ |
389 | 0 | sprintf(tmp, "%lu", (unsigned long)(x)); \ |
390 | 0 | SS(tmp); \ |
391 | 0 | } while ((void)0, 0) |
392 | |
|
393 | 0 | #define SB(buf, len) \ |
394 | 0 | do { \ |
395 | 0 | size_t sb_len = to_base64(dst, dst_len, buf, len); \ |
396 | 0 | if (sb_len == (size_t)-1) { \ |
397 | 0 | return ARGON2_ENCODING_FAIL; \ |
398 | 0 | } \ |
399 | 0 | dst += sb_len; \ |
400 | 0 | dst_len -= sb_len; \ |
401 | 0 | } while ((void)0, 0) |
402 | |
|
403 | 0 | const char* type_string = argon2_type2string(type, 0); |
404 | 0 | int validation_result = validate_inputs(ctx); |
405 | |
|
406 | 0 | if (!type_string) { |
407 | 0 | return ARGON2_ENCODING_FAIL; |
408 | 0 | } |
409 | | |
410 | 0 | if (validation_result != ARGON2_OK) { |
411 | 0 | return validation_result; |
412 | 0 | } |
413 | | |
414 | | |
415 | 0 | SS("$"); |
416 | 0 | SS(type_string); |
417 | | |
418 | 0 | SS("$v="); |
419 | 0 | SX(ctx->version); |
420 | | |
421 | 0 | SS("$m="); |
422 | 0 | SX(ctx->m_cost); |
423 | 0 | SS(",t="); |
424 | 0 | SX(ctx->t_cost); |
425 | 0 | SS(",p="); |
426 | 0 | SX(ctx->lanes); |
427 | | |
428 | 0 | SS("$"); |
429 | 0 | SB(ctx->salt, ctx->saltlen); |
430 | | |
431 | 0 | SS("$"); |
432 | 0 | SB(ctx->out, ctx->outlen); |
433 | 0 | return ARGON2_OK; |
434 | |
|
435 | 0 | #undef SS |
436 | 0 | #undef SX |
437 | 0 | #undef SB |
438 | 0 | } |
439 | | |
440 | 0 | size_t b64len(uint32_t len) { |
441 | 0 | size_t olen = ((size_t)len / 3) << 2; |
442 | |
|
443 | 0 | switch (len % 3) { |
444 | 0 | case 2: |
445 | 0 | olen++; |
446 | | /* fall through */ |
447 | 0 | case 1: |
448 | 0 | olen += 2; |
449 | 0 | break; |
450 | 0 | } |
451 | | |
452 | 0 | return olen; |
453 | 0 | } |
454 | | |
455 | 0 | size_t numlen(uint32_t num) { |
456 | 0 | size_t len = 1; |
457 | 0 | while (num >= 10) { |
458 | 0 | ++len; |
459 | 0 | num = num / 10; |
460 | 0 | } |
461 | 0 | return len; |
462 | 0 | } |
463 | | |