]> git.ipfire.org Git - thirdparty/openldap.git/commitdiff
ITS#10523 LMDB: add sample for checksum plus authenticated encryption mdb.RE/1.0
authorHoward Chu <hyc@openldap.org>
Tue, 16 Jun 2026 14:24:22 +0000 (15:24 +0100)
committerHoward Chu <hyc@openldap.org>
Tue, 16 Jun 2026 14:24:58 +0000 (15:24 +0100)
libraries/liblmdb/cryptoc.c [new file with mode: 0644]

diff --git a/libraries/liblmdb/cryptoc.c b/libraries/liblmdb/cryptoc.c
new file mode 100644 (file)
index 0000000..4403fe4
--- /dev/null
@@ -0,0 +1,97 @@
+/* crypto.c - LMDB encryption helper module */
+/*
+ * Copyright 2020-2024 Howard Chu, Symas Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the Symas
+ * Dual-Use License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * source distribution.
+ */
+#include <string.h>
+
+#include <sodium.h>
+
+#include "lmdb.h"
+
+#define KEYBYTES       crypto_aead_chacha20poly1305_ietf_KEYBYTES
+#define NONCEBYTES     crypto_aead_chacha20poly1305_ietf_NPUBBYTES
+#define MACBYTES       crypto_aead_chacha20poly1305_ietf_ABYTES
+#define SUMBYTES       crypto_hash_sha256_BYTES
+
+MDB_crypto_hooks MDB_crypto;
+
+static int mcf_str2key(const char *passwd, MDB_val *key)
+{
+       crypto_hash_sha256_state state;
+
+       crypto_hash_sha256_init(&state);
+       crypto_hash_sha256_update(&state, (const unsigned char *)"Just a Constant", sizeof("Just a Constant"));
+       crypto_hash_sha256_update(&state, (const unsigned char *)passwd, strlen(passwd));
+       crypto_hash_sha256_final(&state, key->mv_data);
+       return 0;
+}
+
+static void mcf_sumfunc(const MDB_val *src, MDB_val *dst, const MDB_val *key)
+{
+       crypto_hash_sha256_state state;
+
+       crypto_hash_sha256_init(&state);
+       if (key)
+               crypto_hash_sha256_update(&state, (const unsigned char *)key->mv_data, key->mv_size);
+       crypto_hash_sha256_update(&state, (const unsigned char *)src->mv_data, src->mv_size);
+       crypto_hash_sha256_final(&state, dst->mv_data);
+}
+
+#define ENC(dst, src, mac, key, iv) \
+       crypto_aead_chacha20poly1305_ietf_encrypt_detached(dst->mv_data, mac, &mlen, \
+               src->mv_data, src->mv_size, NULL, 0, NULL, iv, key)
+
+#define DEC(dst, src, mac, key, iv) \
+       crypto_aead_chacha20poly1305_ietf_decrypt_detached(dst->mv_data, NULL, src->mv_data, \
+               src->mv_size, mac, NULL, 0, iv, key)
+
+static int mcf_encfunc(const MDB_val *src, MDB_val *dst, const MDB_val *key, int encdec)
+{
+       unsigned char iv[NONCEBYTES];
+       mdb_size_t *ptr;
+       int ivl, rc;
+       unsigned long long mlen;
+
+       /* the nonce is only 12 bytes */
+       ptr = key[1].mv_data;
+       ivl = ptr[0] & 0xffffffff;
+       memcpy(iv, &ivl, 4);
+       memcpy(iv+4, ptr+1, sizeof(mdb_size_t));
+
+       if (encdec) {
+               rc = ENC(dst, src, key[2].mv_data, key[0].mv_data, iv);
+       } else {
+               if (key[2].mv_size)
+                       rc = DEC(dst, src, key[2].mv_data, key[0].mv_data, iv);
+               else {
+                       /* Decrypting without MAC check: only used when decrypting page
+                        * headers during incremental load.
+                        */
+                       rc = crypto_stream_chacha20_ietf_xor_ic(dst->mv_data, src->mv_data,
+                               src->mv_size, iv, 1, key[0].mv_data);
+               }
+       }
+       return rc;
+}
+
+static const MDB_crypto_funcs mcf_table = {
+       mcf_str2key,
+       mcf_encfunc,
+       mcf_sumfunc,
+       KEYBYTES,
+       MACBYTES,
+       SUMBYTES
+};
+
+MDB_crypto_funcs *MDB_crypto()
+{
+       return (MDB_crypto_funcs *)&mcf_table;
+}