THREADS = -pthread
OPT = -O2 -g
CFLAGS = $(THREADS) $(OPT) $(W) $(XCFLAGS)
+LDFLAGS = $(THREADS)
LDLIBS =
SOLIBS =
SOEXT = .so
+LDL = -ldl
prefix = /usr/local
exec_prefix = $(prefix)
bindir = $(exec_prefix)/bin
# $(CC) $(LDFLAGS) -pthread -shared -Wl,-Bsymbolic -o $@ mdb.o midl.o $(SOLIBS)
$(CC) $(LDFLAGS) -pthread -shared -o $@ mdb.lo midl.lo $(SOLIBS)
-mdb_stat: mdb_stat.o liblmdb.a
-mdb_copy: mdb_copy.o liblmdb.a
-mdb_dump: mdb_dump.o liblmdb.a
-mdb_load: mdb_load.o liblmdb.a
-mdb_drop: mdb_drop.o liblmdb.a
+mdb_stat: mdb_stat.o module.o liblmdb.a
+ $(CC) $(LDFLAGS) -o $@ $^ $(LDL)
+mdb_copy: mdb_copy.o module.o liblmdb.a
+ $(CC) $(LDFLAGS) -o $@ $^ $(LDL)
+mdb_dump: mdb_dump.o module.o liblmdb.a
+ $(CC) $(LDFLAGS) -o $@ $^ $(LDL)
+mdb_load: mdb_load.o module.o liblmdb.a
+ $(CC) $(LDFLAGS) -o $@ $^ $(LDL)
+mdb_drop: mdb_drop.o module.o liblmdb.a
+ $(CC) $(LDFLAGS) -o $@ $^ $(LDL)
mtest: mtest.o liblmdb.a
mtest2: mtest2.o liblmdb.a
mtest3: mtest3.o liblmdb.a
mtest6: mtest6.o liblmdb.a
mtest_remap: mtest_remap.o liblmdb.a
mtest_enc: mtest_enc.o chacha8.o liblmdb.a
-mtest_enc2: mtest_enc2.o crypto.o liblmdb.a
- $(CC) $(LDFLAGS) -pthread -o $@ $^ -lcrypto
+mtest_enc2: mtest_enc2.o module.o liblmdb.a crypto.lm
+ $(CC) $(LDFLAGS) -pthread -o $@ mtest_enc2.o module.o liblmdb.a $(LDL)
+crypto.lm: crypto.c
+ $(CC) -shared -o $@ -lcrypto
mdb.o: mdb.c lmdb.h midl.h
$(CC) $(CFLAGS) $(CPPFLAGS) -c mdb.c
+/* crypto.c - LMDB encryption helper module */
+/*
+ * Copyright 2020 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 <openssl/engine.h>
static EVP_CIPHER *cipher;
-static int str2key(const char *passwd, MDB_val *key)
+static int mcf_str2key(const char *passwd, MDB_val *key)
{
unsigned int size;
EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
size_t tls_payload_length;
} EVP_CHACHA_AEAD_CTX;
-static int encfunc(const MDB_val *src, MDB_val *dst, const MDB_val *key, int encdec)
+static int mcf_encfunc(const MDB_val *src, MDB_val *dst, const MDB_val *key, int encdec)
{
unsigned char iv[12];
int ivl, outl, rc;
return rc == 0;
}
-static const MDB_crypto_funcs table = {
- str2key,
- encfunc,
+static const MDB_crypto_funcs mcf_table = {
+ mcf_str2key,
+ mcf_encfunc,
NULL,
- 32,
- 16,
+ CHACHA_KEY_SIZE,
+ POLY1305_BLOCK_SIZE,
0
};
MDB_crypto_funcs *MDB_crypto()
{
cipher = (EVP_CIPHER *)EVP_chacha20_poly1305();
- return (MDB_crypto_funcs *)&table;
+ return (MDB_crypto_funcs *)&mcf_table;
}
#include <stdlib.h>
#include <signal.h>
#include "lmdb.h"
+#include "module.h"
static void
sighandle(int sig)
const char *progname = argv[0], *act;
unsigned flags = MDB_RDONLY;
unsigned cpflags = 0;
+ char *module = NULL, *password = NULL;
+ void *mlm = NULL;
+ char *errmsg;
for (; argc > 1 && argv[1][0] == '-'; argc--, argv++) {
if (argv[1][1] == 'n' && argv[1][2] == '\0')
else if (argv[1][1] == 'V' && argv[1][2] == '\0') {
printf("%s\n", MDB_VERSION_STRING);
exit(0);
+ } else if (argv[1][1] == 'm' && argv[1][2] == '\0') {
+ module = argv[2];
+ argc--;
+ argv++;
+ } else if (argv[1][1] == 'w' && argv[1][2] == '\0') {
+ password = argv[2];
+ argc--;
+ argv++;
} else
argc = 0;
}
if (argc<2 || argc>3) {
- fprintf(stderr, "usage: %s [-V] [-c] [-n] [-v] srcpath [dstpath]\n", progname);
+ fprintf(stderr, "usage: %s [-V] [-c] [-n] [-v] [-m module [-w password]] srcpath [dstpath]\n", progname);
exit(EXIT_FAILURE);
}
+
#ifdef SIGPIPE
signal(SIGPIPE, sighandle);
#endif
act = "opening environment";
rc = mdb_env_create(&env);
if (rc == MDB_SUCCESS) {
+ if (module) {
+ mlm = mlm_setup(env, module, password, &errmsg);
+ if (!mlm) {
+ fprintf(stderr, "Failed to load crypto module: %s\n", errmsg);
+ exit(EXIT_FAILURE);
+ }
+ }
rc = mdb_env_open(env, argv[1], flags, 0600);
}
if (rc == MDB_SUCCESS) {
fprintf(stderr, "%s: %s failed, error %d (%s)\n",
progname, act, rc, mdb_strerror(rc));
mdb_env_close(env);
+ if (mlm)
+ mlm_unload(mlm);
return rc ? EXIT_FAILURE : EXIT_SUCCESS;
}
#include <unistd.h>
#include <signal.h>
#include "lmdb.h"
+#include "module.h"
static volatile sig_atomic_t gotsig;
static void usage(char *prog)
{
- fprintf(stderr, "usage: %s [-V] [-n] [-d] [-s subdb] dbpath\n", prog);
+ fprintf(stderr, "usage: %s [-V] [-n] [-d] [-m module [-w password]] [-s subdb] dbpath\n", prog);
exit(EXIT_FAILURE);
}
char *envname;
char *subname = NULL;
int envflags = 0, delete = 0;
+ char *module = NULL, *password = NULL;
+ void *mlm = NULL;
+ char *errmsg;
if (argc < 2) {
usage(prog);
* -V: print version and exit
* (default) empty the main DB
*/
- while ((i = getopt(argc, argv, "dns:V")) != EOF) {
+ while ((i = getopt(argc, argv, "dm:ns:w:V")) != EOF) {
switch(i) {
case 'V':
printf("%s\n", MDB_VERSION_STRING);
case 's':
subname = optarg;
break;
+ case 'm':
+ module = optarg;
+ break;
+ case 'w':
+ password = optarg;
+ break;
default:
usage(prog);
}
fprintf(stderr, "mdb_env_create failed, error %d %s\n", rc, mdb_strerror(rc));
return EXIT_FAILURE;
}
+ if (module) {
+ mlm = mlm_setup(env, module, password, &errmsg);
+ if (!mlm) {
+ fprintf(stderr, "Failed to load crypto module: %s\n", errmsg);
+ goto env_close;
+ }
+ }
mdb_env_set_maxdbs(env, 2);
mdb_txn_abort(txn);
env_close:
mdb_env_close(env);
+ if (mlm)
+ mlm_unload(mlm);
return rc ? EXIT_FAILURE : EXIT_SUCCESS;
}
#include <unistd.h>
#include <signal.h>
#include "lmdb.h"
+#include "module.h"
#define Yu MDB_PRIy(u)
static void usage(char *prog)
{
- fprintf(stderr, "usage: %s [-V] [-f output] [-l] [-n] [-p] [-v] [-a|-s subdb] dbpath\n", prog);
+ fprintf(stderr, "usage: %s [-V] [-f output] [-l] [-n] [-p] [-v] [-m module [-w password]] [-a|-s subdb] dbpath\n", prog);
exit(EXIT_FAILURE);
}
char *envname;
char *subname = NULL;
int alldbs = 0, envflags = 0, list = 0;
+ char *module = NULL, *password = NULL, *errmsg;
+ void *mlm = NULL;
if (argc < 2) {
usage(prog);
* -V: print version and exit
* (default) dump only the main DB
*/
- while ((i = getopt(argc, argv, "af:lnps:vV")) != EOF) {
+ while ((i = getopt(argc, argv, "af:lm:nps:vw:V")) != EOF) {
switch(i) {
case 'V':
printf("%s\n", MDB_VERSION_STRING);
usage(prog);
subname = optarg;
break;
+ case 'm':
+ module = optarg;
+ break;
+ case 'w':
+ password = optarg;
+ break;
default:
usage(prog);
}
return EXIT_FAILURE;
}
+ if (module) {
+ mlm = mlm_setup(env, module, password, &errmsg);
+ if (!mlm) {
+ fprintf(stderr, "Failed to load crypto module: %s\n", errmsg);
+ goto env_close;
+ }
+ }
+
if (alldbs || subname) {
mdb_env_set_maxdbs(env, 2);
}
#include <ctype.h>
#include <unistd.h>
#include "lmdb.h"
+#include "module.h"
#define PRINT 1
#define NOHDR 2
static void usage(void)
{
- fprintf(stderr, "usage: %s [-V] [-a] [-f input] [-n] [-s name] [-N] [-T] dbpath\n", prog);
+ fprintf(stderr, "usage: %s [-V] [-a] [-f input] [-n] [-m module [-w password]] [-s name] [-N] [-T] dbpath\n", prog);
exit(EXIT_FAILURE);
}
int envflags = MDB_NOSYNC, putflags = 0;
int dohdr = 0, append = 0;
MDB_val prevk;
+ char *module = NULL, *password = NULL, *errmsg;
+ void *mlm = NULL;
prog = argv[0];
* -T: read plaintext
* -V: print version and exit
*/
- while ((i = getopt(argc, argv, "af:ns:NTV")) != EOF) {
+ while ((i = getopt(argc, argv, "af:m:ns:w:NTV")) != EOF) {
switch(i) {
case 'V':
printf("%s\n", MDB_VERSION_STRING);
case 'T':
mode |= NOHDR | PRINT;
break;
+ case 'm':
+ module = optarg;
+ break;
+ case 'w':
+ password = optarg;
+ break;
default:
usage();
}
fprintf(stderr, "mdb_env_create failed, error %d %s\n", rc, mdb_strerror(rc));
return EXIT_FAILURE;
}
+ if (module) {
+ mlm = mlm_setup(env, module, password, &errmsg);
+ if (!mlm) {
+ fprintf(stderr, "Failed to load crypto module: %s\n", errmsg);
+ goto env_close;
+ }
+ }
mdb_env_set_maxdbs(env, 2);
mdb_txn_abort(txn);
env_close:
mdb_env_close(env);
+ if (mlm)
+ mlm_unload(mlm);
return rc ? EXIT_FAILURE : EXIT_SUCCESS;
}
#include <string.h>
#include <unistd.h>
#include "lmdb.h"
+#include "module.h"
#define Z MDB_FMT_Z
#define Yu MDB_PRIy(u)
static void prstat(MDB_stat *ms)
{
-#if 0
printf(" Page size: %u\n", ms->ms_psize);
-#endif
printf(" Tree depth: %u\n", ms->ms_depth);
printf(" Branch pages: %"Yu"\n", ms->ms_branch_pages);
printf(" Leaf pages: %"Yu"\n", ms->ms_leaf_pages);
static void usage(char *prog)
{
- fprintf(stderr, "usage: %s [-V] [-n] [-e] [-r[r]] [-f[f[f]]] [-v] [-a|-s subdb] dbpath\n", prog);
+ fprintf(stderr, "usage: %s [-V] [-n] [-e] [-r[r]] [-f[f[f]]] [-v] [-m module [-w password]] [-a|-s subdb] dbpath\n", prog);
exit(EXIT_FAILURE);
}
char *envname;
char *subname = NULL;
int alldbs = 0, envinfo = 0, envflags = 0, freinfo = 0, rdrinfo = 0;
+ char *module = NULL, *password = NULL, *errmsg;
+ void *mlm = NULL;
if (argc < 2) {
usage(prog);
* -V: print version and exit
* (default) print stat of only the main DB
*/
- while ((i = getopt(argc, argv, "Vaefnrs:v")) != EOF) {
+ while ((i = getopt(argc, argv, "Vaefm:nrs:vw:")) != EOF) {
switch(i) {
case 'V':
printf("%s\n", MDB_VERSION_STRING);
usage(prog);
subname = optarg;
break;
+ case 'm':
+ module = optarg;
+ break;
+ case 'w':
+ password = optarg;
+ break;
default:
usage(prog);
}
return EXIT_FAILURE;
}
+ if (module) {
+ mlm = mlm_setup(env, module, password, &errmsg);
+ if (!mlm) {
+ fprintf(stderr, "Failed to load crypto module: %s\n", errmsg);
+ goto env_close;
+ }
+ }
+
if (alldbs || subname) {
mdb_env_set_maxdbs(env, 4);
}
--- /dev/null
+/* module.c - helper for dynamically loading crypto module */
+/*
+ * Copyright 2020 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.
+ */
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <dlfcn.h>
+#endif
+
+#include <stddef.h>
+#include <string.h>
+
+#include "lmdb.h"
+#include "module.h"
+
+void *mlm_load(const char *file, const char *name, MDB_crypto_funcs **mcf_ptr, char **errmsg)
+{
+ MDB_crypto_hooks *hookfunc;
+ void *ret = NULL;
+ if (!name)
+ name = "MDB_crypto";
+
+#ifdef _WIN32
+ {
+ HINSTANCE mlm = LoadLibrary(file);
+ if (mlm) {
+ hookfunc = GetProcAddress(mlm, name);
+ if (hookfunc)
+ *mcf_ptr = hookfunc();
+ else {
+ *errmsg = "Crypto hook function not found";
+ FreeLibrary(mlm);
+ mlm = NULL;
+ }
+ } else {
+ *errmsg = GetLastError();
+ }
+ ret = (void *)mlm;
+ }
+#else
+ {
+ void *mlm = dlopen(file, RTLD_NOW);
+ if (mlm) {
+ hookfunc = dlsym(mlm, name);
+ if (hookfunc)
+ *mcf_ptr = hookfunc();
+ else {
+ *errmsg = "Crypto hook function not found";
+ dlclose(mlm);
+ mlm = NULL;
+ }
+ } else {
+ *errmsg = dlerror();
+ }
+ ret = mlm;
+ }
+#endif
+ return ret;
+}
+
+void mlm_unload(void *mlm)
+{
+#ifdef _WIN32
+ FreeLibrary((HINSTANCE)mlm);
+#else
+ dlclose(mlm);
+#endif
+}
+
+void *mlm_setup(MDB_env *env, const char *file, const char *password, char **errmsg)
+{
+ MDB_crypto_funcs *cf;
+ MDB_val enckey = {0};
+ void *mlm = mlm_load(file, NULL, &cf, errmsg);
+ if (mlm) {
+ if (cf->mcf_sumfunc) {
+ mdb_env_set_checksum(env, cf->mcf_sumfunc, cf->mcf_sumsize);
+ }
+ if (cf->mcf_encfunc && password) {
+ char keybuf[2048];
+ enckey.mv_data = keybuf;
+ enckey.mv_size = cf->mcf_keysize;
+ if (cf->mcf_str2key)
+ cf->mcf_str2key(password, &enckey);
+ else
+ strncpy(enckey.mv_data, password, enckey.mv_size);
+ mdb_env_set_encrypt(env, cf->mcf_encfunc, &enckey, cf->mcf_esumsize);
+ memset(enckey.mv_data, 0, enckey.mv_size);
+ }
+ }
+ return mlm;
+}
--- /dev/null
+/* module.h - helper for dynamically loading crypto module */
+/*
+ * Copyright 2020 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.
+ */
+
+void *mlm_load(const char *file, const char *name, MDB_crypto_funcs **mcf_ptr, char **errmsg);
+void mlm_unload(void *lm);
+void *mlm_setup(MDB_env *env, const char *file, const char *password, char **errmsg);
#include <stdlib.h>
#include <time.h>
#include "lmdb.h"
+#include "module.h"
#define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr)
#define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0))
#define CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \
"%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(rc)), abort()))
-extern MDB_crypto_hooks MDB_crypto;
MDB_crypto_funcs *cf;
int main(int argc,char * argv[])
char sval[32] = "";
char password[] = "This is my passphrase for now...";
char *ekey;
+ void *lm;
+ char *errmsg;
srand(time(NULL));
values[i] = rand()%1024;
}
- cf = MDB_crypto();
+ lm = lm_load("./crypto.lm", NULL, &cf, &errmsg);
+ if (!lm) {
+ fprintf(stderr,"Failed to load crypto module: %s\n", errmsg);
+ exit(1);
+ }
E(mdb_env_create(&env));
E(mdb_env_set_maxreaders(env, 1));
mdb_dbi_close(env, dbi);
mdb_env_close(env);
+ lm_unload(lm);
return 0;
}