Skip to content

Commit

Permalink
Merge pull request #47 from dutow/empty_config
Browse files Browse the repository at this point in the history
Encrypt fork files with master key and improve tests
  • Loading branch information
dutow authored Oct 18, 2023
2 parents b8b02b7 + 4c95782 commit e954b6b
Show file tree
Hide file tree
Showing 24 changed files with 338 additions and 55 deletions.
10 changes: 9 additions & 1 deletion .github/workflows/postgresql-16-pgdg-package-pgxs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,14 @@ jobs:
sudo make USE_PGXS=1 install
working-directory: src/postgres-tde-ext

- name: Start pg_stat_monitor_tests
- name: Start postgres-tde-ext tests
run: |
sudo service postgresql stop
echo "shared_preload_libraries = 'pg_tde'" |
sudo tee -a /etc/postgresql/16/main/postgresql.conf
echo "pg_tde.keyringConfigFile = '/tmp/keyring.json'" |
sudo tee -a /etc/postgresql/16/main/postgresql.conf
cp keyring.json /tmp/keyring.json
sudo service postgresql start
sudo psql -V
sudo -u postgres bash -c 'make installcheck USE_PGXS=1'
Expand All @@ -74,6 +77,11 @@ jobs:
src/postgres-tde-ext/logfile
retention-days: 3

- name: Report on test fail 2
if: ${{ failure() }}
run: |
cat src/postgres-tde-ext/regression.diffs
- name: Create release directory
run: |
sudo mkdir pgtde-pgdg16
Expand Down
14 changes: 11 additions & 3 deletions .github/workflows/postgresql-16-src-make.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,12 @@ jobs:
initdb -D /opt/pgsql/data
echo "shared_preload_libraries = 'pg_tde'" >> \
/opt/pgsql/data/postgresql.conf
echo "pg_tde.keyringConfigFile = '/tmp/keyring.json'" >> \
/opt/pgsql/data/postgresql.conf
cp src/contrib/postgres-tde-ext/keyring.json /tmp/keyring.json
pg_ctl -D /opt/pgsql/data -l logfile start
- name: Build postgres-tde-ext
- name: Test postgres-tde-ext
run: |
make installcheck
working-directory: src/contrib/postgres-tde-ext
Expand All @@ -78,6 +81,11 @@ jobs:
with:
name: Regressions diff and postgresql log
path: |
src/postgres-tde-ext/regression.diffs
src/postgres-tde-ext/logfile
src/contrib/postgres-tde-ext/regression.diffs
logfile
retention-days: 3

- name: Report on test fail 2
if: ${{ failure() }}
run: |
cat src/contrib/postgres-tde-ext/regression.diffs
15 changes: 4 additions & 11 deletions .github/workflows/postgresql-16-src-meson.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,21 +48,14 @@ jobs:
- name: Build postgres
run: |
meson setup build
cd build && ninja && sudo ninja install
meson setup build --prefix `pwd`/../inst
cd build && ninja && ninja install
working-directory: src

- name: Start postgresql cluster with pg_tde
run: |
export PATH="/usr/local/pgsql/bin:$PATH"
sudo cp /usr/local/pgsql/bin/pg_config /usr/bin
initdb -D /opt/pgsql/data
echo "shared_preload_libraries = 'pg_tde'" >> /opt/pgsql/data/postgresql.conf
pg_ctl -D /opt/pgsql/data -l logfile start
- name: Test postgres-tde-ext
run: |
export PATH="/usr/local/pgsql/bin:$PATH"
cp ../contrib/postgres-tde-ext/keyring.json /tmp/keyring.json
meson test --suite setup -v
meson test --suite postgres-tde-ext -v
working-directory: src/build

Expand Down
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ MODULE_big = pg_tde
EXTENSION = pg_tde
DATA = pg_tde--1.0.sql

REGRESS_OPTS = --temp-config $(top_srcdir)/contrib/postgres-tde-ext/postgres-tde-ext.conf --inputdir=regression
REGRESS_OPTS = --temp-config $(top_srcdir)/contrib/postgres-tde-ext/postgres-tde-ext.conf
REGRESS = non_sorted_off_compact update_compare_indexes pgtde_is_encrypted
TAP_TESTS = 1

OBJS = src/encryption/enc_tuple.o \
src/encryption/enc_aes.o \
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
4 changes: 4 additions & 0 deletions keyring.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
'provider': 'file',
'datafile': '/tmp/pgkeyring',
}
9 changes: 7 additions & 2 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ install_data(

tests += {
'name': 'postgres-tde-ext',
'sd': meson.current_source_dir() + '/regression/',
'bd': meson.current_build_dir() + '/regression/',
'sd': meson.current_source_dir(),
'bd': meson.current_build_dir(),
'regress': {
'sql': [
'non_sorted_off_compact',
Expand All @@ -72,4 +72,9 @@ tests += {
'regress_args': ['--temp-config', files('postgres-tde-ext.conf')],
'runningcheck': false,
},
'tap': {
'tests': [
't/001_basic.pl',
],
},
}
1 change: 1 addition & 0 deletions postgres-tde-ext.conf
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
shared_preload_libraries = 'pg_tde'
pg_tde.keyringConfigFile = '/tmp/keyring.json'
File renamed without changes.
File renamed without changes.
File renamed without changes.
72 changes: 65 additions & 7 deletions src/access/pg_tde_tdemap.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include "utils/memutils.h"

#include "access/pg_tde_tdemap.h"
#include "encryption/enc_aes.h"
#include "keyring/keyring_api.h"

#include <openssl/rand.h>
#include <openssl/err.h>
Expand All @@ -33,8 +35,10 @@ pg_tde_delete_key_fork(Relation rel)
/* TODO: delete related internal keys from cache */
char *key_file_path = pg_tde_get_key_file_path(&rel->rd_locator);
if (!key_file_path)
{
ereport(ERROR,
(errmsg("failed to get key file path")));
}
RegisterFileForDeletion(key_file_path, true);
pfree(key_file_path);
}
Expand All @@ -52,26 +56,48 @@ pg_tde_create_key_fork(const RelFileLocator *newrlocator, Relation rel)
File file = -1;
InternalKey int_key = {0};
RelKeysData *data;
unsigned char dataEnc[1024];
size_t sz;
int encsz;
const keyInfo *master_key_info;
// TODO: use proper iv stored in the file!
unsigned char iv[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

master_key_info = keyringGetLatestKey(MasterKeyName);
if(master_key_info == NULL)
{
master_key_info = keyringGenerateKey(MasterKeyName, 16);
}
if(master_key_info == NULL)
{
ereport(ERROR,
(errmsg("failed to retrieve master key")));
}

key_file_path = pg_tde_get_key_file_path(newrlocator);
if (!key_file_path)
{
ereport(ERROR,
(errmsg("failed to get key file path")));
}

file = PathNameOpenFile(key_file_path, O_RDWR | O_CREAT | PG_BINARY);
if (file < 0)
{
ereport(FATAL,
(errcode_for_file_access(),
errmsg("could not open tde key file \"%s\": %m",
key_file_path)));
}


if (!RAND_bytes(int_key.key, INTERNAL_KEY_LEN))
{
ereport(FATAL,
(errcode(ERRCODE_INTERNAL_ERROR),
errmsg("could not generate internal key for relation \"%s\": %s",
RelationGetRelationName(rel), ERR_error_string(ERR_get_error(), NULL))));
}

#if TDE_FORK_DEBUG
ereport(DEBUG2,
Expand All @@ -87,14 +113,19 @@ pg_tde_create_key_fork(const RelFileLocator *newrlocator, Relation rel)
data->internal_keys_len = 1;

sz = SizeOfRelKeysData(data->internal_keys_len);
/*
* TODO: internal key(s) should be encrypted
*/
if (FileWrite(file, data, sz, 0, WAIT_EVENT_DATA_FILE_WRITE) != sz)

memcpy(dataEnc, data, sz);
AesEncrypt(master_key_info->data.data, iv, (unsigned char*)data + SizeOfRelKeysDataHeader, 16, dataEnc + SizeOfRelKeysDataHeader, &encsz);

Assert(encsz == sz - SizeOfRelKeysDataHeader);

if (FileWrite(file, dataEnc, sz, 0, WAIT_EVENT_DATA_FILE_WRITE) != sz)
{
ereport(FATAL,
(errcode_for_file_access(),
errmsg("could not write key data to file \"%s\": %m",
key_file_path)));
}

/* Register the file for delete in case transaction Aborts */
RegisterFileForDeletion(key_file_path, false);
Expand All @@ -120,15 +151,19 @@ pg_tde_get_keys_from_fork(const RelFileLocator *rlocator)

key_file_path = pg_tde_get_key_file_path(rlocator);
if (!key_file_path)
{
ereport(ERROR,
(errmsg("failed to get key file path")));
}

file = PathNameOpenFile(key_file_path, O_RDONLY | PG_BINARY);
if (file < 0)
{
ereport(FATAL,
(errcode_for_file_access(),
errmsg("could not open tde key file \"%s\": %m",
key_file_path)));
}


sz = (Size) FileSize(file);
Expand All @@ -145,10 +180,36 @@ pg_tde_get_keys_from_fork(const RelFileLocator *rlocator)
key_file_path)));
else if (nbytes < SizeOfRelKeysData(1) ||
(nbytes - SizeOfRelKeysDataHeader) % sizeof(InternalKey) != 0)
{
ereport(FATAL,
(errcode(ERRCODE_DATA_CORRUPTED),
errmsg("corrupted key data in file \"%s\"",
key_file_path)));
}

{
const keyInfo *master_key_info;
unsigned char dataDec[1024];
int encsz;
// TODO: use proper iv stored in the file!
unsigned char iv[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

master_key_info = keyringGetLatestKey(keys->master_key_name);
if(master_key_info == NULL)
{
master_key_info = keyringGenerateKey(keys->master_key_name, 16);
}
if(master_key_info == NULL)
{
ereport(ERROR,
(errmsg("failed to retrieve master key")));
}

AesDecrypt(master_key_info->data.data, iv, (unsigned char*) keys->internal_key , 16, dataDec, &encsz);
memcpy(keys->internal_key, dataDec, encsz);

}


#if TDE_FORK_DEBUG
for (Size i = 0; i < keys->internal_keys_len; i++)
Expand All @@ -175,8 +236,6 @@ RelKeysData *
GetRelationKeys(RelFileLocator rel)
{
RelKeys *curr;
RelKeys *prev = NULL;
RelKeys *new;
RelKeysData *keys;

Oid rel_id = rel.relNumber;
Expand All @@ -192,7 +251,6 @@ GetRelationKeys(RelFileLocator rel)
#endif
return curr->keys;
}
prev = curr;
}

keys = pg_tde_get_keys_from_fork(&rel);
Expand Down
17 changes: 7 additions & 10 deletions src/encryption/enc_aes.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <unistd.h>
#include <assert.h>

#include <openssl/ssl.h>
#include <openssl/crypto.h>
#include <openssl/evp.h>
#include <openssl/err.h>
Expand Down Expand Up @@ -37,23 +38,21 @@
*/


const EVP_CIPHER* cipher;
const EVP_CIPHER* cipher2;
int cipher_block_size;
const EVP_CIPHER* cipher = NULL;
const EVP_CIPHER* cipher2 = NULL;
int cipher_block_size = 0;

void AesInit(void)
{
static int initialized = 0;

if(!initialized) {
// Not sure if we need this 2, does postgres already call them somewhere?
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();

cipher = EVP_get_cipherbyname("aes-128-ctr");
cipher = EVP_aes_128_cbc();
cipher_block_size = EVP_CIPHER_block_size(cipher); // == buffer size
//
cipher2 = EVP_get_cipherbyname("aes-128-ecb");
cipher2 = EVP_aes_128_ecb();

initialized = 1;
}
Expand Down Expand Up @@ -82,7 +81,6 @@ static void AesRun2(EVP_CIPHER_CTX** ctxPtr, int enc, const unsigned char* key,
static void AesRun(int enc, const unsigned char* key, const unsigned char* iv, const unsigned char* in, int in_len, unsigned char* out, int* out_len)
{
EVP_CIPHER_CTX* ctx = NULL;
int f_len; // todo: what to do with this?
ctx = EVP_CIPHER_CTX_new();
EVP_CIPHER_CTX_init(ctx);

Expand All @@ -97,11 +95,10 @@ static void AesRun(int enc, const unsigned char* key, const unsigned char* iv, c
goto cleanup;
}

if(EVP_CipherFinal_ex(ctx, out, &f_len) == 0) {
if(EVP_CipherFinal_ex(ctx, out, out_len) == 0) {
fprintf(stderr, "ERROR: EVP_CipherFinal_ex failed. OpenSSL error: %s\n", ERR_error_string(ERR_get_error(), NULL));
goto cleanup;
}
assert(f_len == 0);

cleanup:
EVP_CIPHER_CTX_cleanup(ctx);
Expand Down
15 changes: 0 additions & 15 deletions src/encryption/enc_aes.h

This file was deleted.

2 changes: 0 additions & 2 deletions src/encryption/enc_tuple.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ void PGTdeCryptTupInternal(Oid tableOid, BlockNumber bn, unsigned long offsetInP
unsigned char encKey[16 * (aesBlockNumber2 - aesBlockNumber1 + 1)];
#pragma GCC diagnostic pop

AesInit(); // TODO: where to move this?

// TODO: verify key length!
Aes128EncryptedZeroBlocks2(&(keys->internal_key[0].ctx), keys->internal_key[0].key, aesBlockNumber1, aesBlockNumber2, encKey);

Expand Down
2 changes: 1 addition & 1 deletion src/include/pg_tde_defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
*/

#define ENCRYPTION_DEBUG 0
#define KEYRING_DEBUG 0
#define KEYRING_DEBUG 1
#define TDE_FORK_DEBUG 0

#define pg_tde_fill_tuple heap_fill_tuple
Expand Down
5 changes: 4 additions & 1 deletion src/keyring/keyring_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@ const keyInfo* keyringStoreKey(keyName name, keyData data)
#if KEYRING_DEBUG
fprintf(stderr, "Storing key: %s\n", name.name);
#endif
keyringFileStoreKey(ki);
if(!keyringFileStoreKey(ki))
{
return NULL;
}
return ki;
}

Expand Down
Loading

0 comments on commit e954b6b

Please sign in to comment.