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.c129
1 files changed, 127 insertions, 2 deletions
diff --git a/libhashsum_init_hasher_from_string.c b/libhashsum_init_hasher_from_string.c
index e41c8b1..30526da 100644
--- a/libhashsum_init_hasher_from_string.c
+++ b/libhashsum_init_hasher_from_string.c
@@ -8,7 +8,7 @@ __attribute__((__pure__))
static int
equiv(const char *a, const char *b)
{
- while (*a && *b) {
+ while (*a && *b && *b != '[') {
if (tolower(*a) == tolower(*b)) {
a++;
b++;
@@ -18,7 +18,102 @@ equiv(const char *a, const char *b)
return 0;
}
}
- return !*a && !*b;
+ return !*a && (!*b || *b == '[');
+}
+
+
+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;
+
+ p = strchr(algorithm, '[');
+ if (!p || *++p == ']')
+ return initfunc(this, 0);
+
+ if ((*p++ != 'n' && *p++ != 'N'))
+ goto einval;
+ if (*p++ != '=' || !('1' <= *p && *p <= '9'))
+ 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;
+
+ return initfunc(this, n);
+
+einval:
+ errno = EINVAL;
+ return -1;
+}
+
+
+static int
+parse_value(size_t *valp, const char *p, const char **end_out)
+{
+ size_t digit;
+ if (*valp)
+ return -1;
+ p++;
+ 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_rcn(int (*initfunc)(struct libhashsum_hasher *, size_t, size_t, size_t),
+ struct libhashsum_hasher *this, const char *algorithm)
+{
+ const char *p;
+ size_t r = 0, c = 0, n = 0;
+
+ p = strchr(algorithm, '[');
+ if (!p || *++p == ']')
+ return initfunc(this, 0, 0, 0);
+
+ for (;;) {
+ if (*p == 'r' || *p == 'R') {
+ if (parse_value(&r, p, &p))
+ goto einval;
+ } else if (*p == 'c' || *p == 'C') {
+ if (parse_value(&c, p, &p))
+ goto einval;
+ } else if (*p == 'n' || *p == 'N') {
+ if (parse_value(&n, p, &p))
+ goto einval;
+ } else if (*p == ']') {
+ break;
+ } else {
+ goto einval;
+ }
+ if (*p == ']')
+ break;
+ if (*p++ != ',')
+ goto einval;
+ }
+ if (p[1])
+ goto einval;
+
+ return initfunc(this, r, c, n);
+
+einval:
+ errno = EINVAL;
+ return -1;
}
@@ -55,6 +150,36 @@ libhashsum_init_hasher_from_string(struct libhashsum_hasher *this, const char *a
return libhashsum_init_sha_512_224_hasher(this);
if (equiv(algorithm, "SHA-512/256") || !strcasecmp(algorithm, "SHA2-512/256"))
return libhashsum_init_sha_512_256_hasher(this);
+ if (equiv(algorithm, "Keccak-224"))
+ return libhashsum_init_keccak_224_hasher(this);
+ if (equiv(algorithm, "Keccak-256"))
+ return libhashsum_init_keccak_256_hasher(this);
+ if (equiv(algorithm, "Keccak-384"))
+ return libhashsum_init_keccak_384_hasher(this);
+ if (equiv(algorithm, "Keccak-512"))
+ return libhashsum_init_keccak_512_hasher(this);
+ if (!strcasecmp(algorithm, "SHA3-224"))
+ return libhashsum_init_sha3_224_hasher(this);
+ if (!strcasecmp(algorithm, "SHA3-256"))
+ return libhashsum_init_sha3_256_hasher(this);
+ if (!strcasecmp(algorithm, "SHA3-384"))
+ return libhashsum_init_sha3_384_hasher(this);
+ if (!strcasecmp(algorithm, "SHA3-512"))
+ return libhashsum_init_sha3_512_hasher(this);
+ if (equiv(algorithm, "SHAKE-128["))
+ return with_n(&libhashsum_init_shake128_hasher, this, algorithm);
+ if (equiv(algorithm, "SHAKE-256["))
+ return with_n(&libhashsum_init_shake256_hasher, this, algorithm);
+ if (equiv(algorithm, "SHAKE-512["))
+ return with_n(&libhashsum_init_shake512_hasher, this, algorithm);
+ if (equiv(algorithm, "RawSHAKE-128["))
+ return with_n(&libhashsum_init_rawshake128_hasher, this, algorithm);
+ if (equiv(algorithm, "RawSHAKE-256["))
+ return with_n(&libhashsum_init_rawshake256_hasher, this, algorithm);
+ if (equiv(algorithm, "RawSHAKE-512["))
+ return with_n(&libhashsum_init_rawshake512_hasher, this, algorithm);
+ if (equiv(algorithm, "Keccak["))
+ return with_rcn(&libhashsum_init_keccak_hasher, this, algorithm);
errno = EINVAL;
return -1;