diff options
Diffstat (limited to 'libhashsum_init_hasher_from_string.c')
-rw-r--r-- | libhashsum_init_hasher_from_string.c | 172 |
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(); } |