aboutsummaryrefslogtreecommitdiffstats
path: root/libhashsum_init_hasher_from_string.c
diff options
context:
space:
mode:
Diffstat (limited to 'libhashsum_init_hasher_from_string.c')
-rw-r--r--libhashsum_init_hasher_from_string.c172
1 files changed, 139 insertions, 33 deletions
diff --git a/libhashsum_init_hasher_from_string.c b/libhashsum_init_hasher_from_string.c
index a1ee827..ffd23eb 100644
--- a/libhashsum_init_hasher_from_string.c
+++ b/libhashsum_init_hasher_from_string.c
@@ -3,28 +3,42 @@
static int
+parse_value(size_t *valp, const char *p, const char **end_out)
+{
+ size_t digit;
+ if (*valp)
+ return -1;
+ if (*p++ != '=' || !('1' <= *p && *p <= '9'))
+ return -1;
+ while (isdigit(*p)) {
+ digit = (size_t)(*p++ & 15);
+ if (*valp > (SIZE_MAX - digit) / 10U)
+ return -1;
+ *valp = *valp * 10U + digit;
+ }
+ *end_out = p;
+ return 0;
+}
+
+
+static int
with_n(int (*initfunc)(struct libhashsum_hasher *, size_t), struct libhashsum_hasher *this, const char *algorithm)
{
const char *p;
- size_t n = 0, digit;
+ size_t n = 0;
p = strchr(algorithm, '[');
- if (!p || *++p == ']')
+ if (!p || *++p == ']') {
+ if (p && *++p)
+ goto einval;
return initfunc(this, 0);
+ }
if (*p != 'n' && *p != 'N')
goto einval;
- p++;
- if (*p++ != '=' || !('1' <= *p && *p <= '9'))
+ if (parse_value(&n, &p[1], &p))
goto einval;
- while (isdigit(*p)) {
- digit = (size_t)(*p++ & 15);
- if (n > (SIZE_MAX - digit) / 10U)
- goto einval;
- n = n * 10U + digit;
- }
-
if (*p++ != ']' || *p)
goto einval;
@@ -37,25 +51,6 @@ einval:
static int
-parse_value(size_t *valp, const char *p, const char **end_out)
-{
- size_t digit;
- if (*valp)
- return -1;
- if (*p++ != '=' || !('1' <= *p && *p <= '9'))
- return -1;
- while (isdigit(*p)) {
- digit = (size_t)(*p++ & 15);
- if (*valp > (SIZE_MAX - digit) / 10U)
- return -1;
- *valp = *valp * 10U + digit;
- }
- *end_out = p;
- return 0;
-}
-
-
-static int
with_rcnz(int (*initfunc)(struct libhashsum_hasher *, size_t, size_t, size_t, size_t),
struct libhashsum_hasher *this, const char *algorithm)
{
@@ -64,7 +59,7 @@ with_rcnz(int (*initfunc)(struct libhashsum_hasher *, size_t, size_t, size_t, si
p = strchr(algorithm, '[');
if (!p || *++p == ']') {
- if (p && *p)
+ if (p && *++p)
goto einval;
return initfunc(this, 0, 0, 0, 0);
}
@@ -112,8 +107,11 @@ with_salt(int (*initfunc)(struct libhashsum_hasher *, const void *),
size_t salti = 0;
p = strchr(algorithm, '[');
- if (!p || *++p == ']')
+ if (!p || *++p == ']') {
+ if (p && *++p)
+ goto einval;
return initfunc(this, NULL);
+ }
if (*p != 's' && *p != 'S')
goto einval;
@@ -156,10 +154,116 @@ with_salt(int (*initfunc)(struct libhashsum_hasher *, const void *),
if (*p++ != ']' || *p)
goto einval;
- return initfunc(this, salt);
+ return initfunc(this, salti ? salt : NULL);
+
+einval:
+ errno = EINVAL;
+ return -1;
+}
+
+
+static int
+blake2(int (*initfunc)(struct libhashsum_hasher *, size_t, const void *, const void *, const void *, size_t),
+ struct libhashsum_hasher *this, const char *algorithm, size_t saltbytes, size_t pepperbytes)
+{
+ const char *p;
+ uint8_t a, b, salt[16], pepper[16], *key = NULL;
+ size_t n = 0, salti = 0, pepperi = 0, keyi = 0, i;
+ int r;
+
+ p = strchr(algorithm, '[');
+ if (!p || *++p == ']') {
+ if (p && *++p)
+ goto einval;
+ return initfunc(this, 0, NULL, NULL, NULL, 0);
+ }
+
+next:
+ if (!salti && !strncasecmp(p, "salt=", 5U)) {
+ p = &p[5];
+ if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X'))
+ p = &p[2];
+ for (;;) {
+ if (isxdigit(p[0]) && isxdigit(p[1])) {
+ if (!saltbytes)
+ goto einval;
+ saltbytes--;
+ } else if (isxdigit(p[0])) {
+ goto einval;
+ } else if (saltbytes) {
+ goto einval;
+ } else {
+ break;
+ }
+ a = (uint8_t)(((p[0] & 15) + (p[0] > '9' ? 9 : 0)) << 4);
+ b = (uint8_t)(((p[1] & 15) + (p[1] > '9' ? 9 : 0)) << 0);
+ salt[salti++] = (uint8_t)(a | b);
+ p = &p[2];
+ }
+ } else if (!pepperi && !strncasecmp(p, "pepper=", 7U)) {
+ p = &p[7];
+ if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X'))
+ p = &p[2];
+ for (;;) {
+ if (isxdigit(p[0]) && isxdigit(p[1])) {
+ if (!pepperbytes)
+ goto einval;
+ pepperbytes--;
+ } else if (isxdigit(p[0])) {
+ goto einval;
+ } else if (pepperbytes) {
+ goto einval;
+ } else {
+ break;
+ }
+ a = (uint8_t)(((p[0] & 15) + (p[0] > '9' ? 9 : 0)) << 4);
+ b = (uint8_t)(((p[1] & 15) + (p[1] > '9' ? 9 : 0)) << 0);
+ pepper[pepperi++] = (uint8_t)(a | b);
+ p = &p[2];
+ }
+ } else if (!keyi && !strncasecmp(p, "key=", 4U)) {
+ p = &p[4];
+ if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X'))
+ p = &p[2];
+ while (isxdigit(p[keyi | 0]) && isxdigit(p[keyi | 1]))
+ keyi += 2U;
+ if (isxdigit(p[keyi]))
+ goto einval;
+ keyi /= 2U;
+ if (keyi) {
+ key = malloc(keyi);
+ if (!key)
+ goto fail;
+ }
+ for (i = 0; i < keyi; i++) {
+ a = (uint8_t)(((p[0] & 15) + (p[0] > '9' ? 9 : 0)) << 4);
+ b = (uint8_t)(((p[1] & 15) + (p[1] > '9' ? 9 : 0)) << 0);
+ key[i] = (uint8_t)(a | b);
+ p = &p[2];
+ }
+ } else if (*p == 'n' || *p == 'N') {
+ if (parse_value(&n, &p[1], &p))
+ goto einval;
+ } else {
+ goto einval;
+ }
+
+ if (*p == ',') {
+ p++;
+ goto next;
+ }
+
+ if (*p++ != ']' || *p)
+ goto einval;
+
+ r = initfunc(this, n, salti ? salt : NULL, pepperi ? pepper : NULL, key, keyi);
+ free(key);
+ return r;
einval:
errno = EINVAL;
+fail:
+ free(key);
return -1;
}
@@ -207,6 +311,8 @@ libhashsum_init_hasher_from_string(struct libhashsum_hasher *this, const char *a
case LIBHASHSUM_BLAKE256: return with_salt(&libhashsum_init_blake256_hasher, this, algorithm, 16U);
case LIBHASHSUM_BLAKE384: return with_salt(&libhashsum_init_blake384_hasher, this, algorithm, 32U);
case LIBHASHSUM_BLAKE512: return with_salt(&libhashsum_init_blake512_hasher, this, algorithm, 32U);
+ case LIBHASHSUM_BLAKE2S: return blake2(&libhashsum_init_blake2s_hasher, this, algorithm, 8U, 8U);
+ case LIBHASHSUM_BLAKE2B: return blake2(&libhashsum_init_blake2b_hasher, this, algorithm, 16U, 16U);
default:
abort();
}