From 951926f20b674a0622236a0e331b359df1c02d9b Mon Sep 17 00:00:00 2001 From: Chrono Date: Thu, 13 Jul 2023 22:46:26 +0800 Subject: [PATCH] feat(module): remove page level encryption This feature is unmaintained in upstream LMDB and has known issues that prevents it from being used. --- .gitmodules | 2 +- README.md | 23 --- lmdb | 2 +- src/ngx_lua_resty_lmdb_module.c | 251 ------------------------ src/ngx_lua_resty_lmdb_module.h | 6 - t/05-encrypt_and_find_plaintext.t | 178 ----------------- t/06-open_encrypted_db_with_wrong_key.t | 84 -------- 7 files changed, 2 insertions(+), 544 deletions(-) delete mode 100644 t/05-encrypt_and_find_plaintext.t delete mode 100644 t/06-open_encrypted_db_with_wrong_key.t diff --git a/.gitmodules b/.gitmodules index 2a703b43..83f85fe9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,5 +1,5 @@ [submodule "lmdb"] path = lmdb url = https://github.com/LMDB/lmdb.git - branch = mdb.master3 + branch = LMDB_0.9.31 diff --git a/README.md b/README.md index 54cefa16..e7e2237d 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,6 @@ Table of Contents * [lmdb_environment_path](#lmdb_environment_path) * [lmdb_max_databases](#lmdb_max_databases) * [lmdb_map_size](#lmdb_map_size) - * [lmdb_encryption_key](#lmdb_encryption_key) - * [lmdb_encryption_mode](#lmdb_encryption_mode) * [Copyright and license](#copyright-and-license) ## APIs @@ -230,27 +228,6 @@ Set the size of the memory map, the default value is `1048576`(1MB). [Back to TOC](#table-of-contents) -### lmdb_encryption_key - -**syntax:** *lmdb_encryption_key path/to/keyfile;* - -**context:** *main* - -Encrypt the lmdb database. Encryption is enabled only when the `lmdb_encryption_key` is set. The -content of keyfile will be used to derive a key to encrypt lmdb. - -[Back to TOC](#table-of-contents) - -### lmdb_encryption_mode - -**syntax:** *lmdb_encryption_mode "aes-256-gcm";* - -**context:** *main* - -Set the lmdb database encryption mode. The default encryption mode is "aes-256-gcm". The optional encryption -modes are "chacha20-poly1305" and "aes-256-gcm". Note that `lmdb_encryption_mode` needs to be set only when -`lmdb_encryption_key` is set. - [Back to TOC](#table-of-contents) ## Copyright and license diff --git a/lmdb b/lmdb index b9db2582..ce201088 160000 --- a/lmdb +++ b/lmdb @@ -1 +1 @@ -Subproject commit b9db2582cb31aa0ec88371db388095cc31ceb2f4 +Subproject commit ce201088de95d26fc0da36ba805bf2ddc2ba74ff diff --git a/src/ngx_lua_resty_lmdb_module.c b/src/ngx_lua_resty_lmdb_module.c index 31db7772..c371d8ec 100644 --- a/src/ngx_lua_resty_lmdb_module.c +++ b/src/ngx_lua_resty_lmdb_module.c @@ -1,19 +1,10 @@ #include -#define NGX_LUA_RESTY_LMDB_MAX_BUF_LEN 512 -#define NGX_LUA_RESTY_LMDB_ENC_KEY_LEN 32 - - #define NGX_LUA_RESTY_LMDB_FILE_MODE 0600 #define NGX_LUA_RESTY_LMDB_DIR_MODE 0700 -#ifndef NGX_LUA_RESTY_LMDB_DIGEST_CONSTANT -#define NGX_LUA_RESTY_LMDB_DIGEST_CONSTANT "konglmdb" -#endif - - static ngx_str_t ngx_lua_resty_lmdb_file_names[] = { ngx_string("/data.mdb"), ngx_string("/lock.mdb"), @@ -28,11 +19,6 @@ static ngx_int_t ngx_lua_resty_lmdb_init_worker(ngx_cycle_t *cycle); static void ngx_lua_resty_lmdb_exit_worker(ngx_cycle_t *cycle); -static int ngx_lua_resty_lmdb_digest_key(ngx_str_t *passwd, MDB_val *key); -static int ngx_lua_resty_lmdb_cipher(const MDB_val *src, MDB_val *dst, - const MDB_val *key, int encdec); - - static ngx_command_t ngx_lua_resty_lmdb_commands[] = { { ngx_string("lmdb_environment_path"), @@ -56,20 +42,6 @@ static ngx_command_t ngx_lua_resty_lmdb_commands[] = { offsetof(ngx_lua_resty_lmdb_conf_t, map_size), NULL }, - { ngx_string("lmdb_encryption_key"), - NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, - 0, - offsetof(ngx_lua_resty_lmdb_conf_t, key_file), - NULL }, - - { ngx_string("lmdb_encryption_mode"), - NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, - 0, - offsetof(ngx_lua_resty_lmdb_conf_t, encryption_mode), - NULL }, - ngx_null_command }; @@ -112,7 +84,6 @@ ngx_lua_resty_lmdb_create_conf(ngx_cycle_t *cycle) * * conf->env_path = NULL; * conf->env = NULL; - * conf->cipher = NULL; */ lcf->max_databases = NGX_CONF_UNSET_SIZE; @@ -126,114 +97,12 @@ static char * ngx_lua_resty_lmdb_init_conf(ngx_cycle_t *cycle, void *conf) { ngx_lua_resty_lmdb_conf_t *lcf = conf; - ngx_file_t file; - ngx_file_info_t fi; - size_t size; - ssize_t n; - u_char *buf; ngx_conf_init_size_value(lcf->max_databases, 1); /* same as mdb.c DEFAULT_MAPSIZE */ ngx_conf_init_size_value(lcf->map_size, 1048576); - /* The default encryption mode is aes-256-gcm */ - if (lcf->encryption_mode.data == NULL) { - ngx_str_set(&lcf->encryption_mode, "aes-256-gcm"); - } - - if (ngx_strcasecmp( - lcf->encryption_mode.data, (u_char*)"aes-256-gcm") != 0 && - ngx_strcasecmp( - lcf->encryption_mode.data, (u_char*)"chacha20-poly1305") != 0 ) { - - ngx_log_error(NGX_LOG_CRIT, cycle->log, 0, - "invalid \"lmdb_encryption_mode\": \"%V\"", - &lcf->encryption_mode); - - return NGX_CONF_ERROR; - } - - if (lcf->key_file.data != NULL) { - if (ngx_conf_full_name(cycle, &lcf->key_file, 1) != NGX_OK) { - ngx_log_error(NGX_LOG_CRIT, cycle->log, 0, - "search \"%V\" failed", &lcf->key_file); - return NGX_CONF_ERROR; - } - - ngx_memzero(&file, sizeof(ngx_file_t)); - file.name = lcf->key_file; - file.log = cycle->log; - - file.fd = ngx_open_file(file.name.data, NGX_FILE_RDONLY, - NGX_FILE_OPEN, 0); - - if (file.fd == NGX_INVALID_FILE) { - ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_errno, - ngx_open_file_n " \"%V\" failed", &file.name); - return NGX_CONF_ERROR; - } - - if (ngx_fd_info(file.fd, &fi) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_errno, - ngx_fd_info_n " \"%V\" failed", &file.name); - ngx_close_file(file.fd); - return NGX_CONF_ERROR; - } - - size = ngx_file_size(&fi); - - if (size > NGX_LUA_RESTY_LMDB_MAX_BUF_LEN) { - ngx_log_error(NGX_LOG_CRIT, cycle->log, 0, - "\"%V\" must be less than %d bytes", - &file.name, NGX_LUA_RESTY_LMDB_MAX_BUF_LEN); - ngx_close_file(file.fd); - return NGX_CONF_ERROR; - } - - buf = ngx_pcalloc(cycle->pool, size); - if (buf == NULL) { - ngx_log_error(NGX_LOG_CRIT, cycle->log, 0, - "allocate key memory failed"); - ngx_close_file(file.fd); - return NGX_CONF_ERROR; - } - - n = ngx_read_file(&file, buf, size, 0); - - if (n == NGX_ERROR) { - ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_errno, - ngx_read_file_n " \"%V\" failed", &file.name); - ngx_close_file(file.fd); - return NGX_CONF_ERROR; - } - - if ((size_t) n != size) { - ngx_log_error(NGX_LOG_CRIT, cycle->log, 0, - ngx_read_file_n " \"%V\" returned only " - "%z bytes instead of %uz", &file.name, n, size); - ngx_close_file(file.fd); - return NGX_CONF_ERROR; - } - - lcf->key_data.data = buf; - lcf->key_data.len = size; - - ngx_close_file(file.fd); - } - - if (lcf->key_data.data != NULL) { - lcf->cipher = EVP_get_cipherbyname((char *)lcf->encryption_mode.data); - - if (lcf->cipher == NULL ) { - ngx_log_error(NGX_LOG_CRIT, cycle->log, 0, - "init \"lmdb_encryption\": \"%V\" failed", - &lcf->encryption_mode); - - return NGX_CONF_ERROR; - } - } - return NGX_CONF_OK; } @@ -244,9 +113,6 @@ ngx_lua_resty_lmdb_create_env(ngx_cycle_t *cycle, ngx_flag_t is_master) { int rc; - MDB_val enckey; - int block_size = 0; - u_char keybuf[2048]; rc = mdb_env_create(&lcf->env); if (rc != 0) { @@ -272,47 +138,6 @@ ngx_lua_resty_lmdb_create_env(ngx_cycle_t *cycle, goto failed; } - if (lcf->cipher == NULL) { - return NGX_OK; - } - - /* setup lmdb encryption */ - - enckey.mv_data = keybuf; - enckey.mv_size = NGX_LUA_RESTY_LMDB_ENC_KEY_LEN; - - rc = ngx_lua_resty_lmdb_digest_key(&lcf->key_data, &enckey); - if (rc != 0) { - ngx_log_error(NGX_LOG_CRIT, cycle->log, 0, - "unable to set LMDB encryption key, string to key"); - goto failed; - } - - block_size = EVP_CIPHER_block_size(lcf->cipher); - if (block_size == 0) { - ngx_log_error(NGX_LOG_CRIT, cycle->log, 0, - "unable to set LMDB encryption key, block size"); - goto failed; - } - - rc = mdb_env_set_encrypt(lcf->env, ngx_lua_resty_lmdb_cipher, - &enckey, block_size); - if (rc != 0) { - ngx_log_error(NGX_LOG_CRIT, cycle->log, 0, - "unable to set LMDB encryption key: %s", - mdb_strerror(rc)); - goto failed; - } - - /* worker will destroy secret data */ - if (is_master == 0) { - ngx_explicit_memzero(lcf->key_data.data, lcf->key_data.len); - ngx_explicit_memzero(lcf->encryption_mode.data, lcf->encryption_mode.len); - - ngx_str_null(&lcf->key_data); - ngx_str_null(&lcf->encryption_mode); - } - return NGX_OK; failed: @@ -605,79 +430,3 @@ static void ngx_lua_resty_lmdb_exit_worker(ngx_cycle_t *cycle) } -static int ngx_lua_resty_lmdb_digest_key(ngx_str_t *passwd, MDB_val *key) -{ - unsigned int size; - int rc; - EVP_MD_CTX *mdctx = EVP_MD_CTX_new(); - - rc = EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL); - if (rc) { - rc = EVP_DigestUpdate(mdctx, - NGX_LUA_RESTY_LMDB_DIGEST_CONSTANT, - sizeof(NGX_LUA_RESTY_LMDB_DIGEST_CONSTANT)); - } - - if (rc) { - rc = EVP_DigestUpdate(mdctx, passwd->data, passwd->len); - } - - if (rc) { - rc = EVP_DigestFinal_ex(mdctx, key->mv_data, &size); - } - - EVP_MD_CTX_free(mdctx); - - return rc == 0; -} - - -static int -ngx_lua_resty_lmdb_cipher(const MDB_val *src, MDB_val *dst, - const MDB_val *key, int encdec) -{ - ngx_lua_resty_lmdb_conf_t *lcf; - - u_char iv[12]; - int ivl, outl, rc; - mdb_size_t *ptr; - EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); - - lcf = (ngx_lua_resty_lmdb_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_lua_resty_lmdb_module); - - ngx_lua_resty_lmdb_assert(lcf->cipher != NULL); - - ptr = key[1].mv_data; - ivl = ptr[0] & 0xffffffff; - ngx_memcpy(iv, &ivl, sizeof(int)); - ngx_memcpy(iv + sizeof(int), ptr + 1, sizeof(mdb_size_t)); - - rc = EVP_CipherInit_ex(ctx, lcf->cipher, NULL, key[0].mv_data, iv, encdec); - if (rc) { - EVP_CIPHER_CTX_set_padding(ctx, 0); - } - - if (rc && !encdec) { - rc = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, - key[2].mv_size, key[2].mv_data); - } - - if (rc) { - rc = EVP_CipherUpdate(ctx, dst->mv_data, &outl, - src->mv_data, src->mv_size); - } - - if (rc) { - rc = EVP_CipherFinal_ex(ctx, key[2].mv_data, &outl); - } - - if (rc && encdec) { - rc = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, - key[2].mv_size, key[2].mv_data); - } - - EVP_CIPHER_CTX_free(ctx); - - return rc == 0; -} diff --git a/src/ngx_lua_resty_lmdb_module.h b/src/ngx_lua_resty_lmdb_module.h index 2cac3355..5a7a805d 100644 --- a/src/ngx_lua_resty_lmdb_module.h +++ b/src/ngx_lua_resty_lmdb_module.h @@ -13,12 +13,6 @@ struct ngx_lua_resty_lmdb_conf_s { size_t map_size; MDB_env *env; MDB_txn *ro_txn; - - ngx_str_t key_file; - ngx_str_t key_data; - ngx_str_t encryption_mode; - - const EVP_CIPHER *cipher; }; diff --git a/t/05-encrypt_and_find_plaintext.t b/t/05-encrypt_and_find_plaintext.t deleted file mode 100644 index 4f3f287f..00000000 --- a/t/05-encrypt_and_find_plaintext.t +++ /dev/null @@ -1,178 +0,0 @@ -# vim:set ft= ts=4 sw=4 et: - -use Test::Nginx::Socket::Lua; -use Cwd qw(cwd); - -repeat_each(2); - -plan tests => repeat_each() * blocks() * 5; - -my $pwd = cwd(); - -our $MainConfig = qq{ - lmdb_environment_path /tmp/test5.mdb; - lmdb_map_size 5m; - lmdb_encryption_key /etc/hostname; - lmdb_encryption_mode "chacha20-poly1305"; -}; - -our $MainConfig1 = qq{ - lmdb_environment_path /tmp/test6.mdb; - lmdb_map_size 5m; -}; - -our $HttpConfig = qq{ - lua_package_path "$pwd/lib/?.lua;;"; -}; - -no_shuffle(); -no_long_string(); -#no_diff(); - -run_tests(); - -__DATA__ - -=== TEST 1: simple set() / get() ---- http_config eval: $::HttpConfig ---- main_config eval: $::MainConfig ---- config - location = /t { - content_by_lua_block { - local l = require("resty.lmdb") - - ngx.say(l.set("test", "encrypted")) - - local file1 = io.input("/tmp/test5.mdb/data.mdb") - local str = io.read("*a") - - local _, q = string.find(str, 'test') - if q == nil then - ngx.say("can not find plaintxt key") - else - ngx.say("can find plaintxt key") - end - - local _, p = string.find(str, 'encrypted') - if p == nil then - ngx.say("can not find plaintxt value") - else - ngx.say("can find plaintxt value") - end - - io.close(file1); - - ngx.say(l.get("test")) - ngx.say(l.get("test_not_exist")) - } - } ---- request -GET /t ---- response_body -true -can not find plaintxt key -can not find plaintxt value -encrypted -nil ---- no_error_log -[error] -[warn] -[crit] - - - -=== TEST 2: clear using set() ---- http_config eval: $::HttpConfig ---- main_config eval: $::MainConfig ---- config - location = /t { - content_by_lua_block { - local l = require("resty.lmdb") - - ngx.say(l.set("test", "value")) - ngx.say(l.set("test", nil)) - ngx.say(l.get("test")) - } - } ---- request -GET /t ---- response_body -true -true -nil ---- no_error_log -[error] -[warn] -[crit] - - - -=== TEST 3: db_drop() ---- http_config eval: $::HttpConfig ---- main_config eval: $::MainConfig ---- config - location = /t { - content_by_lua_block { - local l = require("resty.lmdb") - - ngx.say(l.set("test", "value")) - ngx.say(l.db_drop()) - ngx.say(l.get("test")) - } - } ---- request -GET /t ---- response_body -true -true -nil ---- no_error_log -[error] -[warn] -[crit] - -=== TEST 4: simple set() / get() ---- http_config eval: $::HttpConfig ---- main_config eval: $::MainConfig1 ---- config - location = /t { - content_by_lua_block { - local l = require("resty.lmdb") - - ngx.say(l.set("test", "unenc")) - - local file1 = io.input("/tmp/test6.mdb/data.mdb") - local str = io.read("*a") - - local _, q = string.find(str, 'test') - if q == nil then - ngx.say("can not find plaintxt key") - else - ngx.say("can find plaintxt key") - end - - local _, p = string.find(str, 'unenc') - if p == nil then - ngx.say("can not find plaintxt value") - else - ngx.say("can find plaintxt value") - end - - io.close(file1); - - ngx.say(l.get("test")) - ngx.say(l.get("test_not_exist")) - } - } ---- request -GET /t ---- response_body -true -can find plaintxt key -can find plaintxt value -unenc -nil ---- no_error_log -[error] -[warn] -[crit] diff --git a/t/06-open_encrypted_db_with_wrong_key.t b/t/06-open_encrypted_db_with_wrong_key.t deleted file mode 100644 index c6a347f9..00000000 --- a/t/06-open_encrypted_db_with_wrong_key.t +++ /dev/null @@ -1,84 +0,0 @@ -# vim:set ft= ts=4 sw=4 et: - -use Test::Nginx::Socket::Lua; -use Cwd qw(cwd); - -repeat_each(2); - -plan tests => repeat_each() * blocks() * 5; - -my $pwd = cwd(); - -our $MainConfig = qq{ - lmdb_environment_path /tmp/test7.mdb; - lmdb_map_size 5m; - lmdb_encryption_key /etc/hostname; - lmdb_encryption_mode "AES-256-GCM"; -}; - -our $MainConfig1 = qq{ - lmdb_environment_path /tmp/test7.mdb; - lmdb_map_size 5m; - lmdb_encryption_key /etc/hosts; - lmdb_encryption_mode "AES-256-GCM"; -}; - -our $HttpConfig = qq{ - lua_package_path "$pwd/lib/?.lua;;"; -}; - -no_shuffle(); -no_long_string(); -#no_diff(); - -run_tests(); - -__DATA__ - -=== TEST 1: encrypt db with right key ---- http_config eval: $::HttpConfig ---- main_config eval: $::MainConfig ---- config - location = /t { - content_by_lua_block { - local l = require("resty.lmdb") - - ngx.say(l.set("test", "value")) - ngx.say(l.get("test")) - ngx.say(l.get("test_not_exist")) - } - } ---- request -GET /t ---- response_body -true -value -nil ---- no_error_log -[error] -[warn] -[crit] - -=== TEST 2: open db with wrong key ---- http_config eval: $::HttpConfig ---- main_config eval: $::MainConfig1 ---- config - location = /t { - content_by_lua_block { - local l = require("resty.lmdb") - - ngx.say(l.set("test", "value")) - ngx.say(l.get("test")) - ngx.say(l.get("test_not_exist")) - } - } ---- request -GET /t ---- response_body -nilunable to open DB for access: MDB_CRYPTO_FAIL: Page encryption or decryption failed -nilunable to open DB for access: MDB_CRYPTO_FAIL: Page encryption or decryption failed -nilunable to open DB for access: MDB_CRYPTO_FAIL: Page encryption or decryption failed ---- no_error_log -[error] -[warn] -[crit]