Welcome to little lamb

Code » limb » commit 0bdbefa

Add memxor() & memxor3() for fast XORing

author Olivier Brunel
2023-04-06 15:03:05 UTC
committer Olivier Brunel
2023-05-20 18:06:35 UTC
parent f935ee30dba410cd4b79e4a23f11e94b533b9c75

Add memxor() & memxor3() for fast XORing

src/doc/memxor.h.0.md +24 -0
src/doc/memxor.h/memxor.3.md +24 -0
src/liblimb/hmac.h/hmac.c +6 -5
src/liblimb/include/limb/memxor.h +22 -0
src/liblimb/memxor.h/memxor.c +82 -0
src/liblimb/memxor.h/memxor3.c +19 -0

diff --git a/src/doc/memxor.h.0.md b/src/doc/memxor.h.0.md
new file mode 100644
index 0000000..dbdcaa2
--- /dev/null
+++ b/src/doc/memxor.h.0.md
@@ -0,0 +1,24 @@
+% limb manual
+% memxor.h(0)
+
+# NAME
+
+memxor.h - XOR memory areas
+
+# SYNOPSIS
+
+    #include <limb/memxor.h>
+
+# DESCRIPTION
+
+This header defines the required functions to XOR memory areas.
+
+## Functions
+
+The following functions are defined :
+
+: [memxor](3)
+:: To XOR one memory area with another.
+
+: [memxor3](3)
+:: To apply XOR of two memory areas, storing the result in a third one.
diff --git a/src/doc/memxor.h/memxor.3.md b/src/doc/memxor.h/memxor.3.md
new file mode 100644
index 0000000..e609c3d
--- /dev/null
+++ b/src/doc/memxor.h/memxor.3.md
@@ -0,0 +1,24 @@
+% limb manual
+% memxor(3)
+
+# NAME
+
+memxor, memxor3 - XOR memory areas
+
+# SYNOPSIS
+
+    #include <limb/memxor.h>
+
+```pre hl
+void memxor(void *<em>dst</em>, const void *<em>src</em>, size_t <em>len</em>)
+void memxor3(void *<em>dst</em>, const void *<em>src1</em>, const void *<em>src2</em>, size_t <em>len</em>)
+```
+
+# DESCRIPTION
+
+The `memxor`() function will XOR the content of memory pointed to by `src` and
+`dst` over `len` bytes, storing the result over the memory area pointed to by
+`dst`.
+
+The `memxor3`() is similar, but the results of XOR-ing areas pointed to by
+`src1` and `src2` will be stored in memory pointed to by `dst`.
diff --git a/src/liblimb/hmac.h/hmac.c b/src/liblimb/hmac.h/hmac.c
index f70576a..15121b5 100644
--- a/src/liblimb/hmac.h/hmac.c
+++ b/src/liblimb/hmac.h/hmac.c
@@ -4,6 +4,7 @@
 #include <string.h>
 #include <skalibs/bytestr.h>
 #include <limb/hmac.h>
+#include <limb/memxor.h>
 
 void
 hmac(char *out, hasher *h, const void *key, size_t klen, const void *msg, size_t mlen)
@@ -23,11 +24,11 @@ hmac(char *out, hasher *h, const void *key, size_t klen, const void *msg, size_t
     memset(secret + l, 0, h->blen - l);
 
     unsigned char buf[h->blen];
-
-    for (size_t i = 0; i < h->blen; ++i) {
-        buf[i] = secret[i] ^ 0x36;
-        secret[i] ^= 0x5c;
-    }
+    memset(buf, 0x36, h->blen);
+    memxor(buf, secret, h->blen);
+    unsigned char tmp[h->blen];
+    memset(tmp, 0x5c, h->blen);
+    memxor(secret, tmp, h->blen);
 
     hinit(h);
     hupdate(buf, h->blen, h);
diff --git a/src/liblimb/include/limb/memxor.h b/src/liblimb/include/limb/memxor.h
new file mode 100644
index 0000000..5d2e538
--- /dev/null
+++ b/src/liblimb/include/limb/memxor.h
@@ -0,0 +1,22 @@
+/* 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_MEMXOR_H
+#define LIMB_MEMXOR_H
+
+#include <stddef.h> /* size_t */
+#include <limb/int.h>
+
+/* The word_t type is intended to be the native word size. */
+#if defined(__x86_64__) || defined(__arch64__)
+typedef u64 word_t;
+#else
+typedef unsigned long int word_t;
+#endif
+
+#define ALIGN_OFFSET(p) ((uintptr_t) (p) % sizeof(word_t))
+
+extern void memxor(void *dst, const void *src, size_t len);
+extern void memxor3(void *dst, const void *src1, const void *src2, size_t len);
+
+#endif /* LIMB_MEMXOR_H */
diff --git a/src/liblimb/memxor.h/memxor.c b/src/liblimb/memxor.h/memxor.c
new file mode 100644
index 0000000..27dac90
--- /dev/null
+++ b/src/liblimb/memxor.h/memxor.c
@@ -0,0 +1,82 @@
+/* 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 <limb/memxor.h>
+
+static void
+xor8(void *dst_, const void *src_, size_t len)
+{
+    u8 *dst = dst_;
+    const u8 *src = src_;
+
+    while (len--) {
+        *dst ^= *src;
+        ++dst;
+        ++src;
+    }
+}
+
+static void
+xor64(void *dst_, const void *src_, size_t len)
+{
+    u64 *dst = dst_;
+    const u64 *src = src_;
+
+    size_t n = len / sizeof(u64);
+    len -= n * sizeof(u64);
+
+    while (n >= 4) {
+        dst[0] ^= src[0];
+        dst[1] ^= src[1];
+        dst[2] ^= src[2];
+        dst[3] ^= src[3];
+        dst += 4;
+        src += 4;
+        n -= 4;
+    }
+
+    while (n >= 1) {
+        *dst ^= *src;
+        ++dst;
+        ++src;
+        --n;
+    }
+
+    xor8(dst, src, len);
+}
+
+void
+memxor(void *dst_, const void *src_, size_t len)
+{
+    u8 *dst = dst_;
+    const u8 *src = src_;
+
+    size_t off = ALIGN_OFFSET(dst);
+    if (off) {
+        off = sizeof(word_t) - off;
+        if (off > len)
+            off = len;
+        xor8(dst, src, off);
+        dst += off;
+        src += off;
+        len -= off;
+    }
+
+    off = ALIGN_OFFSET(src);
+    if (off) {
+        u8 buf[8092];
+        size_t blen = sizeof(buf);
+
+        while (len) {
+            if (blen > len) blen = len;
+            memcpy(buf, src, blen);
+            xor64(dst, buf, blen);
+            dst += blen;
+            src += blen;
+            len -= blen;
+        }
+    } else {
+        xor64(dst, src, len);
+    }
+}
diff --git a/src/liblimb/memxor.h/memxor3.c b/src/liblimb/memxor.h/memxor3.c
new file mode 100644
index 0000000..4c2fa30
--- /dev/null
+++ b/src/liblimb/memxor.h/memxor3.c
@@ -0,0 +1,19 @@
+/* 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 <limb/memxor.h>
+
+void
+memxor3(void *dst, const void *src1, const void *src2, size_t len)
+{
+    size_t off = ALIGN_OFFSET(src1);
+
+    if (off) {
+        memcpy(dst, src1, len);
+        memxor(dst, src2, len);
+    } else {
+        memcpy(dst, src2, len);
+        memxor(dst, src1, len);
+    }
+}