Welcome to little lamb

Code » limb » commit f577313

Add ccpl.h & related functions

author Olivier Brunel
2023-04-28 19:59:05 UTC
committer Olivier Brunel
2023-05-20 18:06:38 UTC
parent f66014223dffbcdd65fd704c4b468de5c8b3a8a1

Add ccpl.h & related functions

Implement ChaCha20-Poly1305

src/doc/ccpl.h.0.md +44 -0
src/doc/ccpl.h/ccpl_init.3.md +89 -0
src/doc/chacha20.h/chacha20_init.3.md +4 -0
src/doc/poly1305.h/poly1305_init.3.md +1 -1
src/liblimb/ccpl.h/ccpl_aad.c +18 -0
src/liblimb/ccpl.h/ccpl_crypt.c +30 -0
src/liblimb/ccpl.h/ccpl_final.c +28 -0
src/liblimb/ccpl.h/ccpl_init.c +23 -0
src/liblimb/include/limb/ccpl.h +28 -0

diff --git a/src/doc/ccpl.h.0.md b/src/doc/ccpl.h.0.md
new file mode 100644
index 0000000..c79565b
--- /dev/null
+++ b/src/doc/ccpl.h.0.md
@@ -0,0 +1,44 @@
+% limb manual
+% ccpl.h(0)
+
+# NAME
+
+ccpl.h - ChaCha20-Poly1305 AEAD encryption
+
+# SYNOPSIS
+
+    #include <limb/ccpl.h>
+
+# DESCRIPTION
+
+This header defines the required function to encrypt/decrypt messages using the
+ChaCha20-Poly1305 AEAD algorithm.
+
+## Types
+
+The following types are defined :
+
+: *ccpl_ctx*
+:: An opaque structure to be given to the functions below.
+
+## Functions
+
+The following functions/macros are defined :
+
+: [ccpl_init](3)
+:: To initialize a ccpl context.
+
+: [ccpl_aad](3)
+:: To feed additional data into a ccpl context.
+
+: [ccpl_crypt](3)
+:: To crypt data using a ccpl context.
+
+: [ccpl_encrypt](3)
+:: To encrypt data using a ccpl context;
+
+: [ccpl_decrupt](3)
+:: To decrypt data using a ccpl context.
+
+: [ccpl_final](3)
+:: To obtain the MAC from a ccpl context.
diff --git a/src/doc/ccpl.h/ccpl_init.3.md b/src/doc/ccpl.h/ccpl_init.3.md
new file mode 100644
index 0000000..a004d13
--- /dev/null
+++ b/src/doc/ccpl.h/ccpl_init.3.md
@@ -0,0 +1,89 @@
+% limb manual
+% ccpl_init(3)
+
+# NAME
+
+ccpl\_init, ccpl\_aad, ccpl\_crypt, ccpl\_encrypt, ccpl\_decrypt, ccpl\_final -
+encrypt/decrypt data using the ChaCha20-Poly1305 algorithm
+
+# SYNOPSIS
+
+    #include <limb/ccpl.h>
+
+```pre hl
+void ccpl_init(void *<em>key</em>, void *<em>nonce</em>, void *<em>ctx</em>)
+int ccpl_aad(const void *<em>data</em>, size_t <em>dlen</em>, void *<em>ctx</em>)
+void ccpl_crypt(void *<em>dst</em>, const void *<em>data</em>, size_t <em>dlen</em>, int <em>encrypt</em>, void *<em>ctx</em>)
+void ccpl_encrypt(void *<em>dst</em>, const void *<em>data</em>, size_t <em>dlen</em>, void *<em>ctx</em>)
+void ccpl_decrypt(void *<em>dst</em>, const void *<em>data</em>, size_t <em>dlen</em>, void *<em>ctx</em>)
+void ccpl_final(void *<em>dst</em>, void *<em>ctx</em>)
+```
+
+# DESCRIPTION
+
+The `ccpl_init`() function initializes the given ccpl context pointed by `ctx`
+to encrypt/decrypt data using the ChaCha20-Poly1305 authenticated encryption
+with additional data (AEAD) algorithm.
+
+This implementation is conform to [RFC 8439][rfc8439], as such the key pointed
+to by `key` must be 256bit/32 bytes long, and the nonce pointed.by `nonce` must
+be 96bit/12 bytes long.
+
+In order to be secure, the given `nonce` must be different for each invocation
+with the same `key`.
+
+Limitations of message length are the same as described in [chacha20_init](3),
+however an additional limitation, specific to this combined algorithm, also
+applies, and brings the maximum size of both the additional data and the
+encrypted data to 2^64 bytes each.
+
+[rfc8439] (https://datatracker.ietf.org/doc/html/rfc8439)
+
+First, the `ccpl_aad`() function must be used to feed additional data pointed by
+`data` of length `dlen` into the ccpl context pointed by `ctx`. Such data will
+not be encrypted, but will be covered by the authentication code generated using
+the Poly1305 algorithm.
+You can call this function as many times as needed.
+
+Then, the `ccpl_crypt`() function can be used to either encrypt or decrypt data
+pointed by `data` of length `dlen` into the memory pointed by `dst` (which must
+be able to store `dlen` bytes).
+
+As with [chacha20_crypt](3) it is possible to use the same memory area for both
+`data` and `dst`, and have it processed in-place.
+
+Though the data processing is the same for encrypting and decrypting using the
+ChaCha20 cipher, a difference is made regarding the Poly1305 MAC, as it is
+always the /encrypted/ data that must be fed into it.
+This is why the argument `encrypt` is needed, and must be a set to 1 when
+encrypting data (thus feeding it to Poly1305 /after/ processing through
+the ChaCha20 cipher), and set to 0 when decrypting data (thus feeding it to
+Poly1305 /before/ processing through the ChaCha20 cipher).
+
+All calls must be either of encrypting or decrypting, mixing both is invalid.
+However, you can call the function (with the same value for `encrypt`) as many
+times as needed.
+
+As a convenience, the `ccpl_encrypt`() and `ccpl_decrypt`() macros are provided.
+
+! Additional Data First
+! It is required that all additional data - fed through the `ccpl_aad`()
+! function - be fed into the ccpl `ctx` /before/ any call is made to
+! `ccpl_crypt`().
+
+The `ccpl_final`() function stores the computed Poly1305-based MAC from `ctx`
+in binary form into `dst`, which must be able to store 16 bytes.
+
+When decrypting data, the stored MAC should be compared to the one accompanying
+the data. If bitwise identical, both the decrypted data and the additional data
+fed into the ccpl `ctx` have been authenticated.
+
+# RETURN VALUE
+
+The `ccpl_aad`() function returns 1 on success, and 0 on failure. The only
+possible failure case is if a call to `ccpl_crypt`() has already been made for
+the same context.
+
+# SEE ALSO
+
+[chacha20_init](3), [poly1305_init](3)
diff --git a/src/doc/chacha20.h/chacha20_init.3.md b/src/doc/chacha20.h/chacha20_init.3.md
index 64f9e6f..a00a1b8 100644
--- a/src/doc/chacha20.h/chacha20_init.3.md
+++ b/src/doc/chacha20.h/chacha20_init.3.md
@@ -53,3 +53,7 @@ first.
 
 The `chacha20`() function can be used as convenience if the entire message can
 be stored in a continuous memory area, to encrypt/decrypt it in a single call.
+
+# SEE ALSO
+
+[ccpl_init](3)
diff --git a/src/doc/poly1305.h/poly1305_init.3.md b/src/doc/poly1305.h/poly1305_init.3.md
index 2808036..0f5108a 100644
--- a/src/doc/poly1305.h/poly1305_init.3.md
+++ b/src/doc/poly1305.h/poly1305_init.3.md
@@ -36,4 +36,4 @@ form into `dst`, which must be able to store 16 bytes.
 
 # SEE ALSO
 
-[hmac](3)
+[hmac](3), [ccpl_init](3)
diff --git a/src/liblimb/ccpl.h/ccpl_aad.c b/src/liblimb/ccpl.h/ccpl_aad.c
new file mode 100644
index 0000000..4b0f48f
--- /dev/null
+++ b/src/liblimb/ccpl.h/ccpl_aad.c
@@ -0,0 +1,18 @@
+/* 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/ccpl.h>
+
+int
+ccpl_aad(const void *data, size_t dlen, void *ctx_)
+{
+    ccpl_ctx *ctx = ctx_;
+
+    /* can't be called after calls to ccpl_crypt() */
+    if (ctx->w) return 0;
+
+    poly1305_update(data, dlen, &ctx->pl);
+    ctx->alen += dlen;
+
+    return 1;
+}
diff --git a/src/liblimb/ccpl.h/ccpl_crypt.c b/src/liblimb/ccpl.h/ccpl_crypt.c
new file mode 100644
index 0000000..5190378
--- /dev/null
+++ b/src/liblimb/ccpl.h/ccpl_crypt.c
@@ -0,0 +1,30 @@
+/* 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/ccpl.h>
+
+void
+ccpl_crypt(void *dst, const void *data, size_t dlen, int encrypt, void *ctx_)
+{
+    ccpl_ctx *ctx = ctx_;
+
+    if (!ctx->w) {
+        size_t l = 16 - (ctx->alen % 16);
+        if (l) {
+            char pad[l];
+            memset(pad, 0, l);
+            poly1305_update(pad, l, &ctx->pl);
+        }
+    }
+    ctx->w = 1;
+
+    if (!encrypt)
+        poly1305_update(data, dlen, &ctx->pl);
+
+    chacha20_crypt(dst, data, dlen, &ctx->cc);
+    ctx->dlen += dlen;
+
+    if (encrypt)
+        poly1305_update(dst, dlen, &ctx->pl);
+}
diff --git a/src/liblimb/ccpl.h/ccpl_final.c b/src/liblimb/ccpl.h/ccpl_final.c
new file mode 100644
index 0000000..2e8beda
--- /dev/null
+++ b/src/liblimb/ccpl.h/ccpl_final.c
@@ -0,0 +1,28 @@
+/* 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/ccpl.h>
+#include <limb/u64.h>
+
+void
+ccpl_final(void *dst, void *ctx_)
+{
+    ccpl_ctx *ctx = ctx_;
+
+    size_t l = 16 - (((ctx->w) ? ctx->dlen : ctx->alen) % 16);
+    if (l) {
+        char pad[l];
+        memset(pad, 0, l);
+        poly1305_update(pad, l, &ctx->pl);
+    }
+
+    u64p_le(&ctx->alen);
+    poly1305_update(&ctx->alen, sizeof(u64), &ctx->pl);
+
+    u64p_le(&ctx->dlen);
+    poly1305_update(&ctx->dlen, sizeof(u64), &ctx->pl);
+
+    poly1305_final(dst, &ctx->pl);
+    chacha20_clear(&ctx->cc);
+}
diff --git a/src/liblimb/ccpl.h/ccpl_init.c b/src/liblimb/ccpl.h/ccpl_init.c
new file mode 100644
index 0000000..d09634c
--- /dev/null
+++ b/src/liblimb/ccpl.h/ccpl_init.c
@@ -0,0 +1,23 @@
+/* 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/ccpl.h>
+#include <limb/u32.h>
+
+void
+ccpl_init(void *key, void *nonce, void *ctx_)
+{
+    ccpl_ctx *ctx = ctx_;
+
+    char k[32] = { 0 };
+    chacha20_init(key, nonce, &ctx->cc);
+    chacha20_crypt(k, k, sizeof(k), &ctx->cc);
+    poly1305_init(k, &ctx->pl);
+
+    chacha20_init(key, nonce, &ctx->cc);
+    ctx->cc.in[12] = 1;
+    u32p_le(&ctx->cc.in[12]);
+
+    ctx->alen = ctx->dlen = 0;
+    ctx->w = 0;
+}
diff --git a/src/liblimb/include/limb/ccpl.h b/src/liblimb/include/limb/ccpl.h
new file mode 100644
index 0000000..fb7ec6b
--- /dev/null
+++ b/src/liblimb/include/limb/ccpl.h
@@ -0,0 +1,28 @@
+/* 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_CCPL_H
+#define LIMB_CCPL_H
+
+#include <limb/chacha20.h>
+#include <limb/int.h>
+#include <limb/poly1305.h>
+
+struct ccpl_ctx {
+    struct chacha20_ctx cc;
+    struct poly1305_ctx pl;
+    u64 alen;
+    u64 dlen;
+    u8 w;
+};
+
+typedef struct ccpl_ctx ccpl_ctx;
+
+extern void ccpl_init(void *key, void *nonce, void *ctx);
+extern int ccpl_aad(const void *data, size_t dlen, void *ctx);
+extern void ccpl_crypt(void *dst, const void *data, size_t dlen, int encrypt, void *ctx);
+#define ccpl_encrypt(dst,data,dlen,ctx)     ccpl_crypt(dst, data, dlen, 1, ctx)
+#define ccpl_decrypt(dst,data,dlen,ctx)     ccpl_crypt(dst, data, dlen, 0, ctx)
+extern void ccpl_final(void *dst, void *ctx);
+
+#endif /* LIMB_CCPL_H */