Welcome to little lamb

Code » limb » commit ce7f4e4

Add hmac.h & hmac()

author Olivier Brunel
2023-03-26 17:17:18 UTC
committer Olivier Brunel
2023-05-20 18:05:20 UTC
parent 5c9b41ae08bc7474aca50db29d2e1786414ac388

Add hmac.h & hmac()

Function to compute the HMAC of a message, using any of the available
hashers, e.g. HMAC-SHA1, HMAC-SHA3-224, HMAC-BLAKE3, etc

doc/hasher.h.0.md +4 -0
doc/hasher_hash.3.md +1 -1
doc/hmac.3.md +45 -0
doc/hmac.h.0.md +25 -0
include/limb/hmac.h +11 -0
meta/libs/limb +2 -0
src/hmac.c +43 -0

diff --git a/doc/hasher.h.0.md b/doc/hasher.h.0.md
index a6b2369..1b2fae4 100644
--- a/doc/hasher.h.0.md
+++ b/doc/hasher.h.0.md
@@ -50,3 +50,7 @@ The following functions/macros are defined :
 
 : [hfinal](3)
 :: To obtain the hash from a hasher.
+
+# SEE ALSO
+
+[hmac.h](0)
diff --git a/doc/hasher_hash.3.md b/doc/hasher_hash.3.md
index a6d5f74..01b60f2 100644
--- a/doc/hasher_hash.3.md
+++ b/doc/hasher_hash.3.md
@@ -130,4 +130,4 @@ out("The SHA1 of ", ESC, msg, ESC, " is ", HEX(digest, sizeof(digest)));
 
 # SEE ALSO
 
-[blake3_init](3), [sha3_224_init](3)
+[hmac](3), [blake3_init](3), [sha3_224_init](3)
diff --git a/doc/hmac.3.md b/doc/hmac.3.md
new file mode 100644
index 0000000..b9d1c0b
--- /dev/null
+++ b/doc/hmac.3.md
@@ -0,0 +1,45 @@
+% limb manual
+% hmac(3)
+
+# NAME
+
+hmac - compute the HMAC of a given message using given hasher and key
+
+# SYNOPSIS
+
+    #include <limb/hmac.h>
+
+```pre hl
+void hmac(char *<em>out</em>, hasher *<em>hr</em>, const void *<em>key</em>, size_t <em>klen</em>, const void *<em>msg</em>, size_t <em>mlen</em>)
+```
+
+# DESCRIPTION
+
+The `hmac`() function calculates the HMAC of message `msg` of length `mlen`,
+using the secret key `key` of length `klen` and the cryptographic hasher `hr`.
+
+The results if then copied into the buffer pointed by `out` which must be able
+to hold at least the length of a message digest from the hash function used,
+i.e. `hr->hlen` bytes.
+
+For a list of available hashers, refer to [hasher_hash](3).
+
+# EXAMPLE
+
+```c
+#include <limb/hmac.h>
+#include <limb/hasher_sha1.h>
+#include <limb/output.h>
+
+int main(void)
+{
+    const char *msg = "The quick brown fox jumps over the lazy dog";
+    const char *key = "key";
+    char out[sha1->hlen];
+
+    hmac(out, sha1, key, 3, msg, strlen(msg));
+    out("HMAC-SHA1(\"key\", \"", msg, "\") = ", HEX(out, sizeof(out)));
+
+    return 0;
+}
+```
diff --git a/doc/hmac.h.0.md b/doc/hmac.h.0.md
new file mode 100644
index 0000000..bdc21ad
--- /dev/null
+++ b/doc/hmac.h.0.md
@@ -0,0 +1,25 @@
+% limb manual
+% hmac.h(0)
+
+# NAME
+
+hmac.h - computing HMACs
+
+# SYNOPSIS
+
+    #include <limb/hmac.h>
+
+# DESCRIPTION
+
+This header defines the required functions to compute HMACs of messages.
+
+## Functions
+
+The following functions are defined :
+
+: [hmac](3)
+:: Compute the HMAC of a given message using given hasher and key
+
+# SEE ALSO
+
+[hasher.h](0)
diff --git a/include/limb/hmac.h b/include/limb/hmac.h
new file mode 100644
index 0000000..7f02ac1
--- /dev/null
+++ b/include/limb/hmac.h
@@ -0,0 +1,11 @@
+/* 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_HMAC_H
+#define LIMB_HMAC_H
+
+#include "limb/hasher.h"
+
+extern void hmac(char *out, hasher *h, const void *key, size_t klen, const void *msg, size_t mlen);
+
+#endif /* LIMB_HMAC_H */
diff --git a/meta/libs/limb b/meta/libs/limb
index d57a6eb..5910f3c 100644
--- a/meta/libs/limb
+++ b/meta/libs/limb
@@ -111,5 +111,7 @@ obj/hasher_sha3_224.o
 obj/hasher_sha3_256.o
 obj/hasher_sha3_384.o
 obj/hasher_sha3_512.o
+# hmac.h
+obj/hmac.o
 # skalibs dependency
 skalibs
diff --git a/src/hmac.c b/src/hmac.c
new file mode 100644
index 0000000..5c2b926
--- /dev/null
+++ b/src/hmac.c
@@ -0,0 +1,43 @@
+/* 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 <string.h>
+#include <skalibs/bytestr.h>
+#include "limb/hmac.h"
+
+void
+hmac(char *out, hasher *h, const void *key, size_t klen, const void *msg, size_t mlen)
+{
+    unsigned char secret[h->blen];
+    size_t l;
+
+    if (klen > h->blen) {
+        hinit(h);
+        hupdate(key, klen, h);
+        hfinal(secret, h);
+        l = h->hlen;
+    } else {
+        memcpy(secret, key, klen);
+        l = klen;
+    }
+    memset(secret + l, 0, h->blen - l);
+
+    unsigned char buf[h->blen];
+
+    for (int i = 0; i < h->blen; ++i) {
+        buf[i] = secret[i] ^ 0x36;
+        secret[i] ^= 0x5c;
+    }
+
+    hinit(h);
+    hupdate(buf, h->blen, h);
+    hupdate(msg, mlen, h);
+    hfinal(buf, h);
+
+    hinit(h);
+    hupdate(secret, h->blen, h);
+    hupdate(buf, h->hlen, h);
+    hfinal(out, h);
+
+    byte_zero(secret, h->blen);
+}