Welcome to little lamb

Code » limb » commit 4a3a229

Add hasher.h & hasher_hash()

author Olivier Brunel
2023-03-26 13:07:56 UTC
committer Olivier Brunel
2023-03-26 14:03:03 UTC
parent 2e3d09c11ae56fd1f65f9c061a1bfedd1cd9c913

Add hasher.h & hasher_hash()

A generic interface to compute message digests. To help harmonize our
different hash functions, as well as allow the use of a hasher, which
can hold all the necessary information.

It will be simple then to create a function using a hasher, unaware of
which algorithm is used, and switch it simply by using a different
hasher.

doc/hasher.h.0.md +52 -0
doc/hasher_hash.3.md +87 -0
include/limb/hasher.h +31 -0
meta/libs/limb +2 -0
src/hasher_hash.c +12 -0

diff --git a/doc/hasher.h.0.md b/doc/hasher.h.0.md
new file mode 100644
index 0000000..a6b2369
--- /dev/null
+++ b/doc/hasher.h.0.md
@@ -0,0 +1,52 @@
+% limb manual
+% hasher.h(0)
+
+# NAME
+
+hasher.h - generic message digest interface
+
+# SYNOPSIS
+
+    #include <limb/hasher.h>
+
+# DESCRIPTION
+
+This header defines the required functions to compute message digests through a
+generic interface.
+
+## Types
+
+The following types are defined :
+
+: *hasher_init*
+:: Generic pointer function for context initialization
+
+: *hasher_upate*
+:: Generic pointer function for feeding data into a hashing context
+
+: *hasher_final*
+:: Generic pointer function for computing/obtaining the message digest
+
+## Structures
+
+The following structures are defined :
+
+: *struct hasher*, *hasher*
+:: A structure representing a hasher, allowing to compute a message digest
+:: through the algorithm of said hasher.
+
+## Functions
+
+The following functions/macros are defined :
+
+: [hasher_hash](3)
+:: To compute the message digest through a given hasher
+
+: [hinit](3)
+:: To initialize a hasher.
+
+: [hupdate](3)
+:: To feed data into a hasher.
+
+: [hfinal](3)
+:: To obtain the hash from a hasher.
diff --git a/doc/hasher_hash.3.md b/doc/hasher_hash.3.md
new file mode 100644
index 0000000..457c1fd
--- /dev/null
+++ b/doc/hasher_hash.3.md
@@ -0,0 +1,87 @@
+% limb manual
+% hasher_hash(3)
+
+# NAME
+
+hasher\_hash, hinit, hupdate, hfinal - compute a message digest using a given hasher
+
+# SYNOPSIS
+
+    #include <limb/hasher.h>
+
+```pre hl
+void hinit (hasher *<em>hasher</em>)
+void hupdate (const void *<em>msg</em>, size_t <em>mlen</em>, hasher *<em>hasher</em>)
+void hfinal (void *<em>digest</em>, hasher *<em>hasher</em>)
+
+void hasher_hash(void *<em>digest</em>, const void *<em>msg</em>, size_t <em>mlen</em>, hasher *<em>hasher</em>)
+```
+
+# DESCRIPTION
+
+A hasher is a structure containing all required information to compute a message
+digest for a given algorithm. It is defined as such :
+
+    typedef void (*hasher_init)   (void *ctx);
+    typedef void (*hasher_update) (const void *msg, size_t mlen, void *ctx);
+    typedef void (*hasher_final)  (void *digest, void *ctx);
+
+    struct hasher {
+        size_t hlen;
+        size_t blen;
+        hasher_init init;
+        hasher_update update;
+        hasher_final final;
+        void *ctx;
+    };
+
+The members are the following :
+
+: `hlen`
+:: Length (in bytes) of the generated hash/message digest.
+
+: `blen`
+:: Length (in bytes) of the internal block size for the algorithm.
+
+: `init`
+:: Function to call to initialize the hasher's context.
+
+: `update`
+:: Function to call to feed data into the hasher.
+
+: `final`
+:: Function to call to obtain the hash/message digest from the hasher.
+
+: `ctx`
+:: The hasher's (opaque) context.
+
+Though it is possible to call the previously mentioned functions directly, some
+macros are available to make things easier.
+
+The `hinit`() macro initializes the hasher `hasher` to calculate a new message
+digest.
+
+The `hupdate`() macro feeds the specified chunk of data pointed by `msg` of
+length `mlen` to be hashed into the given `hasher`. You can call this function
+repeatedly as many times as needed.
+
+The `hfinal`() macro stores the calculated hash from `hasher` in binary form
+into `digest`, which must be able to store as many bytes as needed, available
+through `hasher->hlen`.
+
+Finally, the `hasher_hash`() function is there for convenience, allowing to
+compute into `digest` the message digest for message `msg` of length `mlen`
+using `hasher` all in a single call, when the entire message is available in
+a single continuous memory area.
+
+# EXAMPLE
+
+To compute the SHA1 of a given message, and show it on *stdout*, one could do :
+
+```c
+const char *msg = "The quick brown fox jumps over the lazy dog";
+char digest[sha1->hlen];
+
+hasher_hash(digest, msg, strlen(msg), sha1);
+out("The SHA1 of ", ESC, msg, ESC, " is ", HEX(digest, sizeof(digest)));
+```
diff --git a/include/limb/hasher.h b/include/limb/hasher.h
new file mode 100644
index 0000000..af7aa1a
--- /dev/null
+++ b/include/limb/hasher.h
@@ -0,0 +1,31 @@
+/* This file is part of limb                           https://lila.oss/limb
+ * Copyright (C) 2023 Olivier Brunel                          jjk@jjacky.com */
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef LIMB_HASHER_H
+#define LIMB_HASHER_H
+
+#include <stddef.h> /* size_t */
+#include "limb/int.h"
+
+typedef void (*hasher_init)   (void *ctx);
+typedef void (*hasher_update) (const void *msg, size_t mlen, void *ctx);
+typedef void (*hasher_final)  (void *digest, void *ctx);
+
+typedef struct hasher hasher;
+
+struct hasher {
+    size_t hlen;
+    size_t blen;
+    hasher_init init;
+    hasher_update update;
+    hasher_final final;
+    u8 ctx[];
+};
+
+#define hinit(h)            h->init(h->ctx)
+#define hupdate(d,l,h)      h->update(d, l, h->ctx)
+#define hfinal(o,h)         h->final(o, h->ctx)
+
+extern void hasher_hash(void *digest, const void *msg, size_t mlen, hasher *hasher);
+
+#endif /* LIMB_HASHER_H */
diff --git a/meta/libs/limb b/meta/libs/limb
index b26bf93..a0508a9 100644
--- a/meta/libs/limb
+++ b/meta/libs/limb
@@ -85,6 +85,8 @@ obj/hmap/hmap_init.o
 obj/hmap/hmap_set.o
 obj/hmap/hmap_get.o
 obj/hmap/hmap_free.o
+# hasher.h
+obj/hasher_hash.o
 # SHA3
 obj/sha3/byte_order.o
 obj/sha3/rhash_sha3_process_block.o
diff --git a/src/hasher_hash.c b/src/hasher_hash.c
new file mode 100644
index 0000000..2259a84
--- /dev/null
+++ b/src/hasher_hash.c
@@ -0,0 +1,12 @@
+/* This file is part of limb                           https://lila.oss/limb
+ * Copyright (C) 2023 Olivier Brunel                          jjk@jjacky.com */
+/* SPDX-License-Identifier: GPL-2.0-only */
+#include "limb/hasher.h"
+
+void
+hasher_hash(void *md, const void *msg, size_t mlen, hasher *h)
+{
+    hinit(h);
+    hupdate(msg, mlen, h);
+    hfinal(md, h);
+}