diff options
Diffstat (limited to 'libar2simplified_decode.c')
-rw-r--r-- | libar2simplified_decode.c | 188 |
1 files changed, 11 insertions, 177 deletions
diff --git a/libar2simplified_decode.c b/libar2simplified_decode.c index 2c2f38e..eb3d3ee 100644 --- a/libar2simplified_decode.c +++ b/libar2simplified_decode.c @@ -1,194 +1,28 @@ /* See LICENSE file for copyright and license details. */ #include "common.h" -#ifdef __linux__ -#include <sys/random.h> -#endif -#include <time.h> -static size_t -decode_u32(const char *s, uint_least32_t *outp) -{ - uint_least32_t digit; - size_t i; - - if ((s[0] == '0' && s[1] == '0') || !isdigit(s[0])) { - errno = EINVAL; - return 0; - } - - *outp = 0; - for (i = 0; isdigit(s[i]); i++) { - digit = (uint_least32_t)(s[i] & 15); - if (*outp > ((uint_least32_t)0xFFFFffffUL - digit) / 10) { - errno = ERANGE; - return 0; - } - *outp = *outp * 10 + digit; - } - - return i; -} +union function { + int (*func)(char *out, size_t n); +}; static int -random_salt(char *out, size_t n, int (*random_byte_generator)(char *out, size_t n)) -{ -#define ALPHABET "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" - static int srand_called = 0; - - double x; - size_t i; - int xi; -#ifdef __linux__ - ssize_t r; -#endif - - if (random_byte_generator) { - if (random_byte_generator(out, n)) - return -1; - } else { - i = 0; -#ifdef __linux__ - for(; i < n; i += (size_t)r) { - r = getrandom(&out[i], n - i, GRND_NONBLOCK); - if(r < 0) - break; - } -#endif - if (!srand_called) { - srand((unsigned int)time(NULL) ^ (unsigned int)rand()); - srand_called = 1; - } - for(; i < n; i++) { - xi = rand(); - x = (double)xi; - x /= (double)RAND_MAX; - x *= 63; - out[i] = (char)x; - } - } - - for (i = 0; i < n; i++) - out[i] = ALPHABET[out[i] % 64]; - return 0; -} - - -static void * -allocate(size_t num, size_t size, size_t alignment, struct libar2_context *ctx) -{ - (void) ctx; - (void) alignment; - return malloc(num * size); -} - - -static void -deallocate(void *ptr, struct libar2_context *ctx) +function_wrapper(char *out, size_t n, void *function) { - (void) ctx; - free(ptr); + union function *func = function; + return func->func(out, n); } struct libar2_argon2_parameters * libar2simplified_decode(const char *str, char **tagp, char **endp, int (*random_byte_generator)(char *out, size_t n)) { - struct libar2_argon2_parameters params, *ret; - const char *p = str; - const char *end; - char *str_free = NULL; - char *buf = NULL; - size_t n, saltsize, offset; - uint_least32_t saltlen, hashlen; - struct libar2_context ctx; - - if (*p != '$') - goto einval; - p = strchr(&p[1], '$'); - if (!p) - goto einval; - if (p[1] == 'v' && p[2] == '=') { - p = strchr(&p[1], '$'); - if (!p) - goto einval; - } - p = strchr(&p[1], '$'); - if (!p) - goto einval; - p++; - end = strchr(p, '$'); - if (!end) - goto einval; - - if (*p == '*') { - n = decode_u32(&p[1], &saltlen); - if (!n++) - goto fail; - if (&p[n] != end) - goto einval; - params.saltlen = (size_t)saltlen; - saltsize = libar2_encode_base64(NULL, NULL, saltlen) - 1; - offset = (size_t)(p - str); - str_free = malloc(offset + saltsize + strlen(&p[n]) + 1); - if (!str_free) - goto enomem; - memcpy(str_free, str, offset); - if (random_salt(&str_free[offset], saltsize, random_byte_generator)) - goto fail; - offset += saltsize; - stpcpy(&str_free[offset], &p[n]); - str = str_free; - } - end++; - - ctx.allocate = allocate; - ctx.deallocate = deallocate; - - if (!libar2_decode_params(str, ¶ms, &buf, &ctx)) - goto fail; - - if (*end == '*') { - n = decode_u32(&end[1], &hashlen); - if (!n++) - goto fail; - end = &end[n]; - params.hashlen = (size_t)hashlen; - if (tagp) - *tagp = NULL; + union function func; + if (random_byte_generator) { + func.func = random_byte_generator; + return libar2simplified_decode_r(str, tagp, endp, function_wrapper, &func); } else { - if (tagp) - *tagp = *(void **)(void *)&end; - end = &end[libar2_encode_base64(NULL, NULL, params.hashlen) - 1]; + return libar2simplified_decode_r(str, tagp, endp, NULL, NULL); } - - ret = malloc(sizeof(params) + params.saltlen); - if (!ret) - goto enomem; - memcpy(ret, ¶ms, sizeof(params)); - if (buf) { - memcpy(&((char *)ret)[sizeof(params)], buf, params.saltlen); - ret->salt = &((unsigned char *)ret)[sizeof(params)]; - deallocate(buf, &ctx); - } - - if (endp) - *endp = *(void **)(void *)&end; - - free(str_free); - return ret; - -einval: - errno = EINVAL; - return NULL; - -fail: - free(str_free); - return NULL; - -enomem: - free(str_free); - errno = ENOMEM; - return NULL; } |