aboutsummaryrefslogtreecommitdiffstats
path: root/libar2simplified_decode.c
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2022-02-15 16:21:36 +0100
committerMattias Andrée <maandree@kth.se>2022-02-15 16:21:36 +0100
commitf74764136b8b0564aa0e75e5c667b9d11158a2a9 (patch)
tree4b21592981aa6e06ecd4b336e2ad940cc8957613 /libar2simplified_decode.c
parentAdd libar2simplified_init_context (diff)
downloadlibar2simplified-f74764136b8b0564aa0e75e5c667b9d11158a2a9.tar.gz
libar2simplified-f74764136b8b0564aa0e75e5c667b9d11158a2a9.tar.bz2
libar2simplified-f74764136b8b0564aa0e75e5c667b9d11158a2a9.tar.xz
Add libar2simplified_decode_r
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to '')
-rw-r--r--libar2simplified_decode.c188
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, &params, &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, &params, 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;
}