PG-1095 Add format validation CI workflow and format sources (#308)

* PG-1095 Add code format validation to CI

* PG-1095 Manually fix some codestyle

* PG-1095 Add comment to pgindent_exclude file

* PG-1095 Format sources

* PG-1095 Fix makefile

* PG-1095 Remove accidentally commited file

* PG-1094 Update gitignore

* PG-1094 Update pgindent_exclude

* PG-1095 Update typedefs list

* PG-1095 Manual code formatting

* PG-1095 Update typedefs list

* PG-1095 More manual code formatting

* PG-1095 More manual code formatting

* PG-1095 More fixes

* PG-1095 Fix
pull/209/head
Artem Gavrilov 10 months ago committed by GitHub
parent 2f31c0ed45
commit d2237acde5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 57
      .github/workflows/check.yaml
  2. 4
      .gitignore
  3. 11
      Makefile.in
  4. 9
      pgindent_excludes
  5. 6
      src/access/pg_tde_ddl.c
  6. 28
      src/access/pg_tde_slot.c
  7. 100
      src/access/pg_tde_tdemap.c
  8. 9
      src/access/pg_tde_xlog.c
  9. 39
      src/access/pg_tde_xlog_encrypt.c
  10. 7
      src/catalog/tde_global_space.c
  11. 87
      src/catalog/tde_keyring.c
  12. 4
      src/catalog/tde_keyring_parse_opts.c
  13. 75
      src/catalog/tde_principal_key.c
  14. 46
      src/common/pg_tde_shmem.c
  15. 15
      src/common/pg_tde_utils.c
  16. 93
      src/encryption/enc_aes.c
  17. 118
      src/encryption/enc_tde.c
  18. 4
      src/include/access/pg_tde_tdemap.h
  19. 7
      src/include/catalog/tde_keyring.h
  20. 6
      src/include/catalog/tde_principal_key.h
  21. 31
      src/include/common/pg_tde_shmem.h
  22. 2
      src/include/common/pg_tde_utils.h
  23. 8
      src/include/encryption/enc_aes.h
  24. 8
      src/include/encryption/enc_tde.h
  25. 6
      src/include/keyring/keyring_api.h
  26. 9
      src/include/keyring/keyring_curl.h
  27. 2
      src/include/keyring/keyring_file.h
  28. 2
      src/include/keyring/keyring_vault.h
  29. 6
      src/include/pg_tde.h
  30. 8
      src/include/pg_tde_defines.h
  31. 2
      src/include/pg_tde_defs.h
  32. 2
      src/include/pg_tde_event_capture.h
  33. 22
      src/keyring/keyring_api.c
  34. 69
      src/keyring/keyring_curl.c
  35. 31
      src/keyring/keyring_file.c
  36. 52
      src/keyring/keyring_vault.c
  37. 27
      src/pg_tde.c
  38. 4
      src/pg_tde_defs.c
  39. 12
      src/pg_tde_event_capture.c
  40. 111
      src/smgr/pg_tde_smgr.c
  41. 6
      src/transam/pg_tde_xact_handler.c
  42. 113
      typedefs.list

@ -0,0 +1,57 @@
name: Checks
on:
pull_request:
jobs:
format:
name: Format
runs-on: ubuntu-22.04
timeout-minutes: 5
steps:
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y libcurl4-openssl-dev
- name: Clone postgres repository
uses: actions/checkout@v4
with:
repository: 'postgres/postgres'
ref: 'REL_17_STABLE'
- name: Checkout sources
uses: actions/checkout@v4
with:
path: 'contrib/pg_tde'
- name: Configure postgres
run: ./configure
- name: Configure pg_tde
run: ./configure
working-directory: contrib/pg_tde
- name: Install perltidy
run: sudo cpan -T SHANCOCK/Perl-Tidy-20230309.tar.gz
- name: Install pg_bsd_indent
working-directory: src/tools/pg_bsd_indent
run: sudo make install
- name: Add pg_bsd_indent and pgindent to path
run: |
echo "/usr/local/pgsql/bin" >> $GITHUB_PATH
echo "${{ github.workspace }}/src/tools/pgindent" >> $GITHUB_PATH
- name: Format sources
working-directory: contrib/pg_tde
run: |
make update-typedefs
make indent
- name: Check files are formatted and no source code changes
working-directory: contrib/pg_tde
run: |
git status
git diff --exit-code

4
.gitignore vendored

@ -9,3 +9,7 @@ __pycache__
/autom4te.cache /autom4te.cache
/configure~ /configure~
t/results t/results
src/include/config.h
# tools files
typedefs-full.list

@ -74,3 +74,14 @@ include $(top_srcdir)/contrib/contrib-global.mk
endif endif
override SHLIB_LINK += @tde_LDFLAGS@ -lcrypto -lssl override SHLIB_LINK += @tde_LDFLAGS@ -lcrypto -lssl
# Fetches typedefs list for PostgreSQL core and merges it with typedefs defined in this project.
# https://wiki.postgresql.org/wiki/Running_pgindent_on_non-core_code_or_development_code
update-typedefs:
wget -q -O - "https://buildfarm.postgresql.org/cgi-bin/typedefs.pl?branch=REL_17_STABLE" | cat - typedefs.list | sort | uniq > typedefs-full.list
# Indents projects sources.
indent:
pgindent --typedefs=typedefs-full.list --excludes=pgindent_excludes .
.PHONY: update-typedefs indent

@ -0,0 +1,9 @@
# List of filename patterns to exclude from pgindent runs
#
# This contains code copied from postgres tree as is and slightly modified.
# We don't want to run pgindent on these files to avoid unnecessary conflicts.
src\d\d/
# This file is generated by configure and should not be formatted
src/include/config.h

@ -22,7 +22,8 @@ static object_access_hook_type prev_object_access_hook = NULL;
static void tdeheap_object_access_hook(ObjectAccessType access, Oid classId, static void tdeheap_object_access_hook(ObjectAccessType access, Oid classId,
Oid objectId, int subId, void *arg); Oid objectId, int subId, void *arg);
void SetupTdeDDLHooks(void) void
SetupTdeDDLHooks(void)
{ {
prev_object_access_hook = object_access_hook; prev_object_access_hook = object_access_hook;
object_access_hook = tdeheap_object_access_hook; object_access_hook = tdeheap_object_access_hook;
@ -31,7 +32,7 @@ void SetupTdeDDLHooks(void)
static void static void
tdeheap_object_access_hook(ObjectAccessType access, Oid classId, Oid objectId, tdeheap_object_access_hook(ObjectAccessType access, Oid classId, Oid objectId,
int subId, void *arg) int subId, void *arg)
{ {
Relation rel = NULL; Relation rel = NULL;
if (prev_object_access_hook) if (prev_object_access_hook)
@ -40,6 +41,7 @@ tdeheap_object_access_hook(ObjectAccessType access, Oid classId, Oid objectId,
if (access == OAT_DROP && classId == RelationRelationId) if (access == OAT_DROP && classId == RelationRelationId)
{ {
ObjectAccessDrop *drop_arg = (ObjectAccessDrop *) arg; ObjectAccessDrop *drop_arg = (ObjectAccessDrop *) arg;
rel = relation_open(objectId, AccessShareLock); rel = relation_open(objectId, AccessShareLock);
} }
if (rel != NULL) if (rel != NULL)

@ -49,6 +49,7 @@ static void
tdeheap_tts_buffer_heap_init(TupleTableSlot *slot) tdeheap_tts_buffer_heap_init(TupleTableSlot *slot)
{ {
TDEBufferHeapTupleTableSlot *bslot = (TDEBufferHeapTupleTableSlot *) slot; TDEBufferHeapTupleTableSlot *bslot = (TDEBufferHeapTupleTableSlot *) slot;
bslot->cached_relation_key = NULL; bslot->cached_relation_key = NULL;
} }
@ -254,6 +255,7 @@ static HeapTuple
tdeheap_tts_buffer_heap_get_heap_tuple(TupleTableSlot *slot) tdeheap_tts_buffer_heap_get_heap_tuple(TupleTableSlot *slot)
{ {
BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot; BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
Assert(!TTS_EMPTY(slot)); Assert(!TTS_EMPTY(slot));
if (!bslot->base.tuple) if (!bslot->base.tuple)
@ -367,6 +369,7 @@ tdeheap_slot_deform_heap_tuple(TupleTableSlot *slot, HeapTuple tuple, uint32 *of
uint32 off; /* offset in tuple data */ uint32 off; /* offset in tuple data */
bits8 *bp = tup->t_bits; /* ptr to null bitmap in tuple */ bits8 *bp = tup->t_bits; /* ptr to null bitmap in tuple */
bool slow; /* can we use/set attcacheoff? */ bool slow; /* can we use/set attcacheoff? */
/* We can only fetch as many attributes as the tuple has. */ /* We can only fetch as many attributes as the tuple has. */
natts = Min(HeapTupleHeaderGetNatts(tuple->t_data), natts); natts = Min(HeapTupleHeaderGetNatts(tuple->t_data), natts);
@ -453,7 +456,7 @@ tdeheap_slot_deform_heap_tuple(TupleTableSlot *slot, HeapTuple tuple, uint32 *of
} }
static HeapTuple static HeapTuple
slot_copytuple(void* buffer, HeapTuple tuple) slot_copytuple(void *buffer, HeapTuple tuple)
{ {
HeapTuple newTuple; HeapTuple newTuple;
@ -465,7 +468,7 @@ slot_copytuple(void* buffer, HeapTuple tuple)
newTuple->t_self = tuple->t_self; newTuple->t_self = tuple->t_self;
newTuple->t_tableOid = tuple->t_tableOid; newTuple->t_tableOid = tuple->t_tableOid;
newTuple->t_data = (HeapTupleHeader) ((char *) newTuple + HEAPTUPLESIZE); newTuple->t_data = (HeapTupleHeader) ((char *) newTuple + HEAPTUPLESIZE);
// We don't copy the data, it will be copied by the decryption code /* We don't copy the data, it will be copied by the decryption code */
memcpy((char *) newTuple->t_data, (char *) tuple->t_data, tuple->t_data->t_hoff); memcpy((char *) newTuple->t_data, (char *) tuple->t_data, tuple->t_data->t_hoff);
return newTuple; return newTuple;
} }
@ -487,7 +490,8 @@ const TupleTableSlotOps TTSOpsTDEBufferHeapTuple = {
/* A buffer heap tuple table slot can not "own" a minimal tuple. */ /* A buffer heap tuple table slot can not "own" a minimal tuple. */
.get_minimal_tuple = NULL, .get_minimal_tuple = NULL,
.copy_heap_tuple = tdeheap_tts_buffer_heap_copy_heap_tuple, .copy_heap_tuple = tdeheap_tts_buffer_heap_copy_heap_tuple,
.copy_minimal_tuple = tdeheap_tts_buffer_heap_copy_minimal_tuple}; .copy_minimal_tuple = tdeheap_tts_buffer_heap_copy_minimal_tuple
};
/* -------------------------------- /* --------------------------------
* ExecStoreBufferHeapTuple * ExecStoreBufferHeapTuple
@ -515,7 +519,8 @@ PGTdeExecStoreBufferHeapTuple(Relation rel,
Buffer buffer) Buffer buffer)
{ {
TDEBufferHeapTupleTableSlot *bslot = (TDEBufferHeapTupleTableSlot *)slot; TDEBufferHeapTupleTableSlot *bslot = (TDEBufferHeapTupleTableSlot *) slot;
/* /*
* sanity checks * sanity checks
*/ */
@ -535,8 +540,8 @@ PGTdeExecStoreBufferHeapTuple(Relation rel,
Assert(key != NULL); Assert(key != NULL);
slot_copytuple(bslot->decrypted_buffer, tuple); slot_copytuple(bslot->decrypted_buffer, tuple);
PG_TDE_DECRYPT_TUPLE_EX(tuple, (HeapTuple)bslot->decrypted_buffer, key, "ExecStoreBuffer"); PG_TDE_DECRYPT_TUPLE_EX(tuple, (HeapTuple) bslot->decrypted_buffer, key, "ExecStoreBuffer");
tuple->t_data = ((HeapTuple)bslot->decrypted_buffer)->t_data; tuple->t_data = ((HeapTuple) bslot->decrypted_buffer)->t_data;
} }
tdeheap_tts_buffer_heap_store_tuple(slot, tuple, buffer, false); tdeheap_tts_buffer_heap_store_tuple(slot, tuple, buffer, false);
@ -556,7 +561,8 @@ PGTdeExecStorePinnedBufferHeapTuple(Relation rel,
TupleTableSlot *slot, TupleTableSlot *slot,
Buffer buffer) Buffer buffer)
{ {
TDEBufferHeapTupleTableSlot *bslot = (TDEBufferHeapTupleTableSlot *)slot; TDEBufferHeapTupleTableSlot *bslot = (TDEBufferHeapTupleTableSlot *) slot;
/* /*
* sanity checks * sanity checks
*/ */
@ -571,12 +577,12 @@ PGTdeExecStorePinnedBufferHeapTuple(Relation rel,
if (rel->rd_rel->relkind != RELKIND_TOASTVALUE) if (rel->rd_rel->relkind != RELKIND_TOASTVALUE)
{ {
RelKeyData *key = get_current_slot_relation_key(bslot,rel); RelKeyData *key = get_current_slot_relation_key(bslot, rel);
slot_copytuple(bslot->decrypted_buffer, tuple); slot_copytuple(bslot->decrypted_buffer, tuple);
PG_TDE_DECRYPT_TUPLE_EX(tuple, (HeapTuple)bslot->decrypted_buffer, key, "ExecStorePinnedBuffer"); PG_TDE_DECRYPT_TUPLE_EX(tuple, (HeapTuple) bslot->decrypted_buffer, key, "ExecStorePinnedBuffer");
/* TODO: revisit this */ /* TODO: revisit this */
tuple->t_data = ((HeapTuple)bslot->decrypted_buffer)->t_data; tuple->t_data = ((HeapTuple) bslot->decrypted_buffer)->t_data;
} }
tdeheap_tts_buffer_heap_store_tuple(slot, tuple, buffer, true); tdeheap_tts_buffer_heap_store_tuple(slot, tuple, buffer, true);
@ -586,7 +592,7 @@ PGTdeExecStorePinnedBufferHeapTuple(Relation rel,
return slot; return slot;
} }
static inline RelKeyData* static inline RelKeyData *
get_current_slot_relation_key(TDEBufferHeapTupleTableSlot *bslot, Relation rel) get_current_slot_relation_key(TDEBufferHeapTupleTableSlot *bslot, Relation rel)
{ {
Assert(bslot != NULL); Assert(bslot != NULL);

@ -113,11 +113,11 @@ typedef struct RelKeyCache
RelKeyCache *tde_rel_key_cache = NULL; RelKeyCache *tde_rel_key_cache = NULL;
static int32 pg_tde_process_map_entry(const RelFileLocator *rlocator, uint32 key_type, char *db_map_path, off_t *offset, bool should_delete); static int32 pg_tde_process_map_entry(const RelFileLocator *rlocator, uint32 key_type, char *db_map_path, off_t *offset, bool should_delete);
static RelKeyData* pg_tde_read_keydata(char *db_keydata_path, int32 key_index, TDEPrincipalKey *principal_key); static RelKeyData *pg_tde_read_keydata(char *db_keydata_path, int32 key_index, TDEPrincipalKey *principal_key);
static int pg_tde_open_file_basic(char *tde_filename, int fileFlags, bool ignore_missing); static int pg_tde_open_file_basic(char *tde_filename, int fileFlags, bool ignore_missing);
static int pg_tde_file_header_read(char *tde_filename, int fd, TDEFileHeader *fheader, bool *is_new_file, off_t *bytes_read); static int pg_tde_file_header_read(char *tde_filename, int fd, TDEFileHeader *fheader, bool *is_new_file, off_t *bytes_read);
static bool pg_tde_read_one_map_entry(int fd, const RelFileLocator *rlocator, int flags, TDEMapEntry *map_entry, off_t *offset); static bool pg_tde_read_one_map_entry(int fd, const RelFileLocator *rlocator, int flags, TDEMapEntry *map_entry, off_t *offset);
static RelKeyData* pg_tde_read_one_keydata(int keydata_fd, int32 key_index, TDEPrincipalKey *principal_key); static RelKeyData *pg_tde_read_one_keydata(int keydata_fd, int32 key_index, TDEPrincipalKey *principal_key);
static int pg_tde_open_file(char *tde_filename, TDEPrincipalKeyInfo *principal_key_info, bool should_fill_info, int fileFlags, bool *is_new_file, off_t *offset); static int pg_tde_open_file(char *tde_filename, TDEPrincipalKeyInfo *principal_key_info, bool should_fill_info, int fileFlags, bool *is_new_file, off_t *offset);
static RelKeyData *pg_tde_get_key_from_cache(RelFileNumber rel_number, uint32 key_type); static RelKeyData *pg_tde_get_key_from_cache(RelFileNumber rel_number, uint32 key_type);
@ -218,7 +218,7 @@ tde_sprint_key(InternalKey *k)
int i; int i;
for (i = 0; i < sizeof(k->key); i++) for (i = 0; i < sizeof(k->key); i++)
sprintf(buf+i, "%02X", k->key[i]); sprintf(buf + i, "%02X", k->key[i]);
return buf; return buf;
} }
@ -231,6 +231,7 @@ RelKeyData *
tde_create_rel_key(RelFileNumber rel_num, InternalKey *key, TDEPrincipalKeyInfo *principal_key_info) tde_create_rel_key(RelFileNumber rel_num, InternalKey *key, TDEPrincipalKeyInfo *principal_key_info)
{ {
RelKeyData rel_key_data; RelKeyData rel_key_data;
memcpy(&rel_key_data.principal_key_id, &principal_key_info->keyId, sizeof(TDEPrincipalKeyId)); memcpy(&rel_key_data.principal_key_id, &principal_key_info->keyId, sizeof(TDEPrincipalKeyId));
memcpy(&rel_key_data.internal_key, key, sizeof(InternalKey)); memcpy(&rel_key_data.internal_key, key, sizeof(InternalKey));
rel_key_data.internal_key.ctx = NULL; rel_key_data.internal_key.ctx = NULL;
@ -238,6 +239,7 @@ tde_create_rel_key(RelFileNumber rel_num, InternalKey *key, TDEPrincipalKeyInfo
/* Add to the decrypted key to cache */ /* Add to the decrypted key to cache */
return pg_tde_put_key_into_cache(rel_num, &rel_key_data); return pg_tde_put_key_into_cache(rel_num, &rel_key_data);
} }
/* /*
* Encrypts a given key and returns the encrypted one. * Encrypts a given key and returns the encrypted one.
*/ */
@ -373,15 +375,18 @@ pg_tde_write_map_entry(const RelFileLocator *rlocator, uint32 entry_type, char *
/* /*
* Read until we find an empty slot. Otherwise, read until end. This seems * Read until we find an empty slot. Otherwise, read until end. This seems
* to be less frequent than vacuum. So let's keep this function here rather * to be less frequent than vacuum. So let's keep this function here
* than overloading the vacuum process. * rather than overloading the vacuum process.
*/ */
while(1) while (1)
{ {
prev_pos = curr_pos; prev_pos = curr_pos;
found = pg_tde_read_one_map_entry(map_fd, NULL, MAP_ENTRY_EMPTY, &map_entry, &curr_pos); found = pg_tde_read_one_map_entry(map_fd, NULL, MAP_ENTRY_EMPTY, &map_entry, &curr_pos);
/* We either reach EOF or found an empty slot in the middle of the file */ /*
* We either reach EOF or found an empty slot in the middle of the
* file
*/
if (prev_pos == curr_pos || found) if (prev_pos == curr_pos || found)
break; break;
@ -389,7 +394,10 @@ pg_tde_write_map_entry(const RelFileLocator *rlocator, uint32 entry_type, char *
key_index++; key_index++;
} }
/* Write the given entry at the location pointed by prev_pos; i.e. the free entry */ /*
* Write the given entry at the location pointed by prev_pos; i.e. the
* free entry
*/
curr_pos = prev_pos; curr_pos = prev_pos;
pg_tde_write_one_map_entry(map_fd, rlocator, entry_type, key_index, &map_entry, &prev_pos); pg_tde_write_one_map_entry(map_fd, rlocator, entry_type, key_index, &map_entry, &prev_pos);
@ -425,6 +433,7 @@ pg_tde_write_one_map_entry(int fd, const RelFileLocator *rlocator, uint32 flags,
if (bytes_written != MAP_ENTRY_SIZE) if (bytes_written != MAP_ENTRY_SIZE)
{ {
char db_map_path[MAXPGPATH] = {0}; char db_map_path[MAXPGPATH] = {0};
pg_tde_set_db_file_paths(rlocator->dbOid, rlocator->spcOid, db_map_path, NULL); pg_tde_set_db_file_paths(rlocator->dbOid, rlocator->spcOid, db_map_path, NULL);
ereport(FATAL, ereport(FATAL,
(errcode_for_file_access(), (errcode_for_file_access(),
@ -434,6 +443,7 @@ pg_tde_write_one_map_entry(int fd, const RelFileLocator *rlocator, uint32 flags,
if (pg_fsync(fd) != 0) if (pg_fsync(fd) != 0)
{ {
char db_map_path[MAXPGPATH] = {0}; char db_map_path[MAXPGPATH] = {0};
pg_tde_set_db_file_paths(rlocator->dbOid, rlocator->spcOid, db_map_path, NULL); pg_tde_set_db_file_paths(rlocator->dbOid, rlocator->spcOid, db_map_path, NULL);
ereport(data_sync_elevel(ERROR), ereport(data_sync_elevel(ERROR),
(errcode_for_file_access(), (errcode_for_file_access(),
@ -528,7 +538,8 @@ pg_tde_write_key_map_entry(const RelFileLocator *rlocator, RelKeyData *enc_rel_k
* Deletes a map entry by setting marking it as unused. We don't have to delete * Deletes a map entry by setting marking it as unused. We don't have to delete
* the actual key data as valid key data entries are identify by valid map entries. * the actual key data as valid key data entries are identify by valid map entries.
*/ */
void pg_tde_delete_key_map_entry(const RelFileLocator *rlocator, uint32 key_type) void
pg_tde_delete_key_map_entry(const RelFileLocator *rlocator, uint32 key_type)
{ {
int32 key_index = 0; int32 key_index = 0;
off_t offset = 0; off_t offset = 0;
@ -575,7 +586,8 @@ void pg_tde_delete_key_map_entry(const RelFileLocator *rlocator, uint32 key_type
* *
* A caller should hold an EXCLUSIVE tde_lwlock_enc_keys lock. * A caller should hold an EXCLUSIVE tde_lwlock_enc_keys lock.
*/ */
void pg_tde_free_key_map_entry(const RelFileLocator *rlocator, uint32 key_type, off_t offset) void
pg_tde_free_key_map_entry(const RelFileLocator *rlocator, uint32 key_type, off_t offset)
{ {
int32 key_index = 0; int32 key_index = 0;
char db_map_path[MAXPGPATH] = {0}; char db_map_path[MAXPGPATH] = {0};
@ -621,7 +633,10 @@ void pg_tde_free_key_map_entry(const RelFileLocator *rlocator, uint32 key_type,
static File static File
keyrotation_init_file(TDEPrincipalKeyInfo *new_principal_key_info, char *rotated_filename, char *filename, bool *is_new_file, off_t *curr_pos) keyrotation_init_file(TDEPrincipalKeyInfo *new_principal_key_info, char *rotated_filename, char *filename, bool *is_new_file, off_t *curr_pos)
{ {
/* Set the new filenames for the key rotation process - temporary at the moment */ /*
* Set the new filenames for the key rotation process - temporary at the
* moment
*/
snprintf(rotated_filename, MAXPGPATH, "%s.r", filename); snprintf(rotated_filename, MAXPGPATH, "%s.r", filename);
/* Create file, truncate if the rotate file already exits */ /* Create file, truncate if the rotate file already exits */
@ -677,11 +692,17 @@ pg_tde_perform_rotate_key(TDEPrincipalKey *principal_key, TDEPrincipalKey *new_p
principal_key->keyInfo.tablespaceId, principal_key->keyInfo.tablespaceId,
db_map_path, db_keydata_path); db_map_path, db_keydata_path);
/* Let's update the pathnames in the local variable for ease of use/readability */ /*
* Let's update the pathnames in the local variable for ease of
* use/readability
*/
strncpy(m_path[OLD_PRINCIPAL_KEY], db_map_path, MAXPGPATH); strncpy(m_path[OLD_PRINCIPAL_KEY], db_map_path, MAXPGPATH);
strncpy(k_path[OLD_PRINCIPAL_KEY], db_keydata_path, MAXPGPATH); strncpy(k_path[OLD_PRINCIPAL_KEY], db_keydata_path, MAXPGPATH);
/* Open both files in read only mode. We don't need to track the current position of the keydata file. We always use the key index */ /*
* Open both files in read only mode. We don't need to track the current
* position of the keydata file. We always use the key index
*/
m_fd[OLD_PRINCIPAL_KEY] = pg_tde_open_file(m_path[OLD_PRINCIPAL_KEY], &principal_key->keyInfo, false, O_RDONLY, &is_new_file, &curr_pos[OLD_PRINCIPAL_KEY]); m_fd[OLD_PRINCIPAL_KEY] = pg_tde_open_file(m_path[OLD_PRINCIPAL_KEY], &principal_key->keyInfo, false, O_RDONLY, &is_new_file, &curr_pos[OLD_PRINCIPAL_KEY]);
k_fd[OLD_PRINCIPAL_KEY] = pg_tde_open_file(k_path[OLD_PRINCIPAL_KEY], &principal_key->keyInfo, false, O_RDONLY, &is_new_file, &read_pos_tmp); k_fd[OLD_PRINCIPAL_KEY] = pg_tde_open_file(k_path[OLD_PRINCIPAL_KEY], &principal_key->keyInfo, false, O_RDONLY, &is_new_file, &read_pos_tmp);
@ -689,9 +710,10 @@ pg_tde_perform_rotate_key(TDEPrincipalKey *principal_key, TDEPrincipalKey *new_p
k_fd[NEW_PRINCIPAL_KEY] = keyrotation_init_file(&new_principal_key->keyInfo, k_path[NEW_PRINCIPAL_KEY], k_path[OLD_PRINCIPAL_KEY], &is_new_file, &read_pos_tmp); k_fd[NEW_PRINCIPAL_KEY] = keyrotation_init_file(&new_principal_key->keyInfo, k_path[NEW_PRINCIPAL_KEY], k_path[OLD_PRINCIPAL_KEY], &is_new_file, &read_pos_tmp);
/* Read all entries until EOF */ /* Read all entries until EOF */
for(key_index[OLD_PRINCIPAL_KEY] = 0; ; key_index[OLD_PRINCIPAL_KEY]++) for (key_index[OLD_PRINCIPAL_KEY] = 0;; key_index[OLD_PRINCIPAL_KEY]++)
{ {
TDEMapEntry read_map_entry, write_map_entry; TDEMapEntry read_map_entry,
write_map_entry;
RelFileLocator rloc; RelFileLocator rloc;
prev_pos[OLD_PRINCIPAL_KEY] = curr_pos[OLD_PRINCIPAL_KEY]; prev_pos[OLD_PRINCIPAL_KEY] = curr_pos[OLD_PRINCIPAL_KEY];
@ -705,10 +727,13 @@ pg_tde_perform_rotate_key(TDEPrincipalKey *principal_key, TDEPrincipalKey *new_p
if (found == false) if (found == false)
continue; continue;
/* Set the relNumber of rlocator. Ignore the tablespace Oid since we only place our files under the default. */ /*
* Set the relNumber of rlocator. Ignore the tablespace Oid since we
* only place our files under the default.
*/
rloc.relNumber = read_map_entry.relNumber; rloc.relNumber = read_map_entry.relNumber;
rloc.dbOid = principal_key->keyInfo.databaseId; rloc.dbOid = principal_key->keyInfo.databaseId;
rloc.spcOid = DEFAULTTABLESPACE_OID; /* TODO. Revisit*/ rloc.spcOid = DEFAULTTABLESPACE_OID; /* TODO. Revisit */
/* Let's get the decrypted key and re-encrypt it with the new key. */ /* Let's get the decrypted key and re-encrypt it with the new key. */
enc_rel_key_data[OLD_PRINCIPAL_KEY] = pg_tde_read_one_keydata(k_fd[OLD_PRINCIPAL_KEY], key_index[OLD_PRINCIPAL_KEY], principal_key); enc_rel_key_data[OLD_PRINCIPAL_KEY] = pg_tde_read_one_keydata(k_fd[OLD_PRINCIPAL_KEY], key_index[OLD_PRINCIPAL_KEY], principal_key);
@ -955,12 +980,11 @@ pg_tde_get_key_from_file(const RelFileLocator *rlocator, uint32 key_type, bool n
* *
* We should hold the lock until the internal key is loaded to be sure the * We should hold the lock until the internal key is loaded to be sure the
* retrieved key was encrypted with the obtained principal key. Otherwise, * retrieved key was encrypted with the obtained principal key. Otherwise,
* the next may happen: * the next may happen: - GetPrincipalKey returns key "PKey_1". - Some
* - GetPrincipalKey returns key "PKey_1". * other process rotates the Principal key and re-encrypt an Internal key
* - Some other process rotates the Principal key and re-encrypt an * with "PKey_2". - We read the Internal key and decrypt it with "PKey_1"
* Internal key with "PKey_2". * (that's what we've got). As the result we return an invalid Internal
* - We read the Internal key and decrypt it with "PKey_1" (that's what * key.
* we've got). As the result we return an invalid Internal key.
*/ */
LWLockAcquire(lock_pk, LW_SHARED); LWLockAcquire(lock_pk, LW_SHARED);
principal_key = GetPrincipalKey(rlocator->dbOid, rlocator->spcOid, LW_SHARED); principal_key = GetPrincipalKey(rlocator->dbOid, rlocator->spcOid, LW_SHARED);
@ -1031,8 +1055,8 @@ pg_tde_process_map_entry(const RelFileLocator *rlocator, uint32 key_type, char *
Assert(offset); Assert(offset);
/* /*
* Open and validate file for basic correctness. DO NOT create it. * Open and validate file for basic correctness. DO NOT create it. The
* The file should pre-exist otherwise we should never be here. * file should pre-exist otherwise we should never be here.
*/ */
map_fd = pg_tde_open_file(db_map_path, NULL, false, O_RDWR, &is_new_file, &curr_pos); map_fd = pg_tde_open_file(db_map_path, NULL, false, O_RDWR, &is_new_file, &curr_pos);
@ -1061,10 +1085,10 @@ pg_tde_process_map_entry(const RelFileLocator *rlocator, uint32 key_type, char *
/* /*
* Read until we find an empty slot. Otherwise, read until end. This seems * Read until we find an empty slot. Otherwise, read until end. This seems
* to be less frequent than vacuum. So let's keep this function here rather * to be less frequent than vacuum. So let's keep this function here
* than overloading the vacuum process. * rather than overloading the vacuum process.
*/ */
while(1) while (1)
{ {
prev_pos = curr_pos; prev_pos = curr_pos;
found = pg_tde_read_one_map_entry(map_fd, rlocator, key_type, &map_entry, &curr_pos); found = pg_tde_read_one_map_entry(map_fd, rlocator, key_type, &map_entry, &curr_pos);
@ -1300,6 +1324,7 @@ pg_tde_read_one_keydata(int keydata_fd, int32 key_index, TDEPrincipalKey *princi
if ((read_pos + INTERNAL_KEY_DAT_LEN) > lseek(keydata_fd, 0, SEEK_END)) if ((read_pos + INTERNAL_KEY_DAT_LEN) > lseek(keydata_fd, 0, SEEK_END))
{ {
char db_keydata_path[MAXPGPATH] = {0}; char db_keydata_path[MAXPGPATH] = {0};
pg_tde_set_db_file_paths(principal_key->keyInfo.databaseId, principal_key->keyInfo.tablespaceId, NULL, db_keydata_path); pg_tde_set_db_file_paths(principal_key->keyInfo.databaseId, principal_key->keyInfo.tablespaceId, NULL, db_keydata_path);
ereport(FATAL, ereport(FATAL,
(errcode(ERRCODE_NO_DATA_FOUND), (errcode(ERRCODE_NO_DATA_FOUND),
@ -1313,6 +1338,7 @@ pg_tde_read_one_keydata(int keydata_fd, int32 key_index, TDEPrincipalKey *princi
if (pg_pread(keydata_fd, &(enc_rel_key_data->internal_key), INTERNAL_KEY_DAT_LEN, read_pos) != INTERNAL_KEY_DAT_LEN) if (pg_pread(keydata_fd, &(enc_rel_key_data->internal_key), INTERNAL_KEY_DAT_LEN, read_pos) != INTERNAL_KEY_DAT_LEN)
{ {
char db_keydata_path[MAXPGPATH] = {0}; char db_keydata_path[MAXPGPATH] = {0};
pg_tde_set_db_file_paths(principal_key->keyInfo.databaseId, principal_key->keyInfo.tablespaceId, NULL, db_keydata_path); pg_tde_set_db_file_paths(principal_key->keyInfo.databaseId, principal_key->keyInfo.tablespaceId, NULL, db_keydata_path);
ereport(FATAL, ereport(FATAL,
(errcode_for_file_access(), (errcode_for_file_access(),
@ -1356,7 +1382,10 @@ pg_tde_get_principal_key_info(Oid dbOid, Oid spcOid)
close(fd); close(fd);
/* It's not a new file. So we can memcpy the principal key info from the header */ /*
* It's not a new file. So we can memcpy the principal key info from the
* header
*/
if (!is_new_file) if (!is_new_file)
{ {
size_t sz = sizeof(TDEPrincipalKeyInfo); size_t sz = sizeof(TDEPrincipalKeyInfo);
@ -1427,7 +1456,7 @@ pg_tde_get_key_from_cache(RelFileNumber rel_number, uint32 key_type)
for (int i = 0; i < tde_rel_key_cache->len; i++) for (int i = 0; i < tde_rel_key_cache->len; i++)
{ {
rec = tde_rel_key_cache->data+i; rec = tde_rel_key_cache->data + i;
if (rec != NULL && if (rec != NULL &&
(rel_number == InvalidOid || (rec->rel_number == rel_number)) && (rel_number == InvalidOid || (rec->rel_number == rel_number)) &&
rec->key.internal_key.rel_type & key_type) rec->key.internal_key.rel_type & key_type)
@ -1454,9 +1483,9 @@ pg_tde_put_key_into_cache(RelFileNumber rel_num, RelKeyData *key)
{ {
#ifndef _SC_PAGESIZE #ifndef _SC_PAGESIZE
pageSize = getpagesize(); pageSize = getpagesize();
#else #else
pageSize = sysconf(_SC_PAGESIZE); pageSize = sysconf(_SC_PAGESIZE);
#endif #endif
} }
if (tde_rel_key_cache == NULL) if (tde_rel_key_cache == NULL)
@ -1479,17 +1508,18 @@ pg_tde_put_key_into_cache(RelFileNumber rel_num, RelKeyData *key)
tde_rel_key_cache->cap = pageSize / sizeof(RelKeyCacheRec); tde_rel_key_cache->cap = pageSize / sizeof(RelKeyCacheRec);
} }
/* Add another mem page if there is no more room left for another key. We /*
* Add another mem page if there is no more room left for another key. We
* allocate `current_memory_size` + 1 page and copy data there. * allocate `current_memory_size` + 1 page and copy data there.
*/ */
if (tde_rel_key_cache->len+1 > if (tde_rel_key_cache->len + 1 >
(tde_rel_key_cache->cap * sizeof(RelKeyCacheRec)) / sizeof(RelKeyCacheRec)) (tde_rel_key_cache->cap * sizeof(RelKeyCacheRec)) / sizeof(RelKeyCacheRec))
{ {
size_t size; size_t size;
size_t old_size; size_t old_size;
RelKeyCacheRec *chachePage; RelKeyCacheRec *chachePage;
size = TYPEALIGN(pageSize, (tde_rel_key_cache->cap+1) * sizeof(RelKeyCacheRec)); size = TYPEALIGN(pageSize, (tde_rel_key_cache->cap + 1) * sizeof(RelKeyCacheRec));
old_size = TYPEALIGN(pageSize, (tde_rel_key_cache->cap) * sizeof(RelKeyCacheRec)); old_size = TYPEALIGN(pageSize, (tde_rel_key_cache->cap) * sizeof(RelKeyCacheRec));
#ifndef FRONTEND #ifndef FRONTEND

@ -57,14 +57,15 @@ tdeheap_rmgr_redo(XLogReaderState *record)
} }
else if (info == XLOG_TDE_EXTENSION_INSTALL_KEY) else if (info == XLOG_TDE_EXTENSION_INSTALL_KEY)
{ {
XLogExtensionInstall *xlrec = (XLogExtensionInstall *)XLogRecGetData(record); XLogExtensionInstall *xlrec = (XLogExtensionInstall *) XLogRecGetData(record);
extension_install_redo(xlrec); extension_install_redo(xlrec);
} }
else if (info == XLOG_TDE_ADD_KEY_PROVIDER_KEY) else if (info == XLOG_TDE_ADD_KEY_PROVIDER_KEY)
{ {
KeyringProviderXLRecord *xlrec = (KeyringProviderXLRecord *)XLogRecGetData(record); KeyringProviderXLRecord *xlrec = (KeyringProviderXLRecord *) XLogRecGetData(record);
redo_key_provider_info(xlrec); redo_key_provider_info(xlrec);
} }
@ -111,7 +112,7 @@ tdeheap_rmgr_desc(StringInfo buf, XLogReaderState *record)
} }
if (info == XLOG_TDE_EXTENSION_INSTALL_KEY) if (info == XLOG_TDE_EXTENSION_INSTALL_KEY)
{ {
XLogExtensionInstall *xlrec = (XLogExtensionInstall *)XLogRecGetData(record); XLogExtensionInstall *xlrec = (XLogExtensionInstall *) XLogRecGetData(record);
appendStringInfo(buf, "tde extension install for db %u/%u", xlrec->database_id, xlrec->tablespace_id); appendStringInfo(buf, "tde extension install for db %u/%u", xlrec->database_id, xlrec->tablespace_id);
} }
@ -123,7 +124,7 @@ tdeheap_rmgr_desc(StringInfo buf, XLogReaderState *record)
} }
if (info == XLOG_TDE_ADD_KEY_PROVIDER_KEY) if (info == XLOG_TDE_ADD_KEY_PROVIDER_KEY)
{ {
KeyringProviderXLRecord *xlrec = (KeyringProviderXLRecord *)XLogRecGetData(record); KeyringProviderXLRecord *xlrec = (KeyringProviderXLRecord *) XLogRecGetData(record);
appendStringInfo(buf, "add key provider %s for %u", xlrec->provider.provider_name, xlrec->database_id); appendStringInfo(buf, "add key provider %s for %u", xlrec->provider.provider_name, xlrec->database_id);
} }

@ -34,7 +34,7 @@
static XLogPageHeaderData DecryptCurrentPageHrd; static XLogPageHeaderData DecryptCurrentPageHrd;
static void SetXLogPageIVPrefix(TimeLineID tli, XLogRecPtr lsn, char* iv_prefix); static void SetXLogPageIVPrefix(TimeLineID tli, XLogRecPtr lsn, char *iv_prefix);
#ifndef FRONTEND #ifndef FRONTEND
/* GUC */ /* GUC */
@ -134,13 +134,13 @@ TDEXLogWriteEncryptedPages(int fd, const void *buf, size_t count, off_t offset)
#endif #endif
/* /*
* Go through the buf page-by-page and encrypt them. * Go through the buf page-by-page and encrypt them. We may start or
* We may start or finish writing from/in the middle of the page * finish writing from/in the middle of the page (walsender or
* (walsender or `full_page_writes = off`). So preserve a page header * `full_page_writes = off`). So preserve a page header for the IV init
* for the IV init data. * data.
* *
* TODO: check if walsender restarts form the beggining of the page * TODO: check if walsender restarts form the beggining of the page in
* in case of the crash. * case of the crash.
*/ */
for (enc_off = 0; enc_off < count;) for (enc_off = 0; enc_off < count;)
{ {
@ -151,8 +151,9 @@ TDEXLogWriteEncryptedPages(int fd, const void *buf, size_t count, off_t offset)
memcpy((char *) curr_page_hdr, (char *) buf + enc_off, SizeOfXLogShortPHD); memcpy((char *) curr_page_hdr, (char *) buf + enc_off, SizeOfXLogShortPHD);
/* /*
* Need to use a separate buf for the encryption so the page remains non-crypted * Need to use a separate buf for the encryption so the page
* in the XLog buf (XLogInsert has to have access to records' lsn). * remains non-crypted in the XLog buf (XLogInsert has to have
* access to records' lsn).
*/ */
enc_buf_page = (XLogPageHeader) (TDEXLogEncryptBuf + enc_off); enc_buf_page = (XLogPageHeader) (TDEXLogEncryptBuf + enc_off);
memcpy((char *) enc_buf_page, (char *) buf + enc_off, (Size) XLogPageHeaderSize(curr_page_hdr)); memcpy((char *) enc_buf_page, (char *) buf + enc_off, (Size) XLogPageHeaderSize(curr_page_hdr));
@ -175,9 +176,9 @@ TDEXLogWriteEncryptedPages(int fd, const void *buf, size_t count, off_t offset)
} }
/* /*
* The page is zeroed (no data), no sense to enctypt. * The page is zeroed (no data), no sense to enctypt. This may happen
* This may happen when base_backup or other requests XLOG SWITCH and * when base_backup or other requests XLOG SWITCH and some pages in
* some pages in XLog buffer still not used. * XLog buffer still not used.
*/ */
if (curr_page_hdr->xlp_magic == 0) if (curr_page_hdr->xlp_magic == 0)
{ {
@ -241,13 +242,13 @@ tdeheap_xlog_seg_read(int fd, void *buf, size_t count, off_t offset)
readsz = pg_pread(fd, buf, count, offset); readsz = pg_pread(fd, buf, count, offset);
/* /*
* Read the buf page by page and decypt ecnrypted pages. * Read the buf page by page and decypt ecnrypted pages. We may start or
* We may start or fihish reading from/in the middle of the page (walreceiver) * fihish reading from/in the middle of the page (walreceiver) in such a
* in such a case we should preserve the last read page header for * case we should preserve the last read page header for the IV data and
* the IV data and the encryption state. * the encryption state.
* *
* TODO: check if walsender/receiver restarts form the beggining of the page * TODO: check if walsender/receiver restarts form the beggining of the
* in case of the crash. * page in case of the crash.
*/ */
for (dec_off = 0; dec_off < readsz;) for (dec_off = 0; dec_off < readsz;)
{ {
@ -294,7 +295,7 @@ tdeheap_xlog_seg_read(int fd, void *buf, size_t count, off_t offset)
/* IV: TLI(uint32) + XLogRecPtr(uint64)*/ /* IV: TLI(uint32) + XLogRecPtr(uint64)*/
static void static void
SetXLogPageIVPrefix(TimeLineID tli, XLogRecPtr lsn, char* iv_prefix) SetXLogPageIVPrefix(TimeLineID tli, XLogRecPtr lsn, char *iv_prefix)
{ {
iv_prefix[0] = (tli >> 24); iv_prefix[0] = (tli >> 24);
iv_prefix[1] = ((tli >> 16) & 0xFF); iv_prefix[1] = ((tli >> 16) & 0xFF);

@ -41,8 +41,8 @@
#ifndef FRONTEND #ifndef FRONTEND
static void init_keys(void); static void init_keys(void);
static void init_default_keyring(void); static void init_default_keyring(void);
static TDEPrincipalKey * create_principal_key(const char *key_name, static TDEPrincipalKey *create_principal_key(const char *key_name,
GenericKeyring * keyring, Oid dbOid, GenericKeyring *keyring, Oid dbOid,
Oid spcOid); Oid spcOid);
#endif /* !FRONTEND */ #endif /* !FRONTEND */
@ -175,7 +175,7 @@ init_keys(void)
* first. * first.
*/ */
static TDEPrincipalKey * static TDEPrincipalKey *
create_principal_key(const char *key_name, GenericKeyring * keyring, create_principal_key(const char *key_name, GenericKeyring *keyring,
Oid dbOid, Oid spcOid) Oid dbOid, Oid spcOid)
{ {
TDEPrincipalKey *principalKey; TDEPrincipalKey *principalKey;
@ -200,6 +200,7 @@ create_principal_key(const char *key_name, GenericKeyring * keyring,
} }
principalKey->keyLength = keyInfo->data.len; principalKey->keyLength = keyInfo->data.len;
memcpy(principalKey->keyData, keyInfo->data.data, keyInfo->data.len); memcpy(principalKey->keyData, keyInfo->data.data, keyInfo->data.len);
return principalKey; return principalKey;

@ -55,7 +55,7 @@ static VaultV2Keyring *load_vaultV2_keyring_provider_options(char *keyring_optio
static void debug_print_kerying(GenericKeyring *keyring); static void debug_print_kerying(GenericKeyring *keyring);
static GenericKeyring *load_keyring_provider_from_record(KeyringProvideRecord *provider); static GenericKeyring *load_keyring_provider_from_record(KeyringProvideRecord *provider);
static char *get_keyring_infofile_path(char *resPath, Oid dbOid, Oid spcOid); static char *get_keyring_infofile_path(char *resPath, Oid dbOid, Oid spcOid);
static bool fetch_next_key_provider(int fd, off_t* curr_pos, KeyringProvideRecord *provider); static bool fetch_next_key_provider(int fd, off_t *curr_pos, KeyringProvideRecord *provider);
#ifdef FRONTEND #ifdef FRONTEND
@ -89,14 +89,14 @@ typedef struct TdeKeyProviderInfoSharedState
LWLockPadded *Locks; LWLockPadded *Locks;
} TdeKeyProviderInfoSharedState; } TdeKeyProviderInfoSharedState;
TdeKeyProviderInfoSharedState* sharedPrincipalKeyState = NULL; /* Lives in shared state */ TdeKeyProviderInfoSharedState *sharedPrincipalKeyState = NULL; /* Lives in shared state */
static const TDEShmemSetupRoutine key_provider_info_shmem_routine = { static const TDEShmemSetupRoutine key_provider_info_shmem_routine = {
.init_shared_state = initialize_shared_state, .init_shared_state = initialize_shared_state,
.init_dsa_area_objects = NULL, .init_dsa_area_objects = NULL,
.required_shared_mem_size = required_shared_mem_size, .required_shared_mem_size = required_shared_mem_size,
.shmem_kill = NULL .shmem_kill = NULL
}; };
static Size static Size
required_shared_mem_size(void) required_shared_mem_size(void)
@ -107,7 +107,7 @@ required_shared_mem_size(void)
static Size static Size
initialize_shared_state(void *start_address) initialize_shared_state(void *start_address)
{ {
sharedPrincipalKeyState = (TdeKeyProviderInfoSharedState *)start_address; sharedPrincipalKeyState = (TdeKeyProviderInfoSharedState *) start_address;
sharedPrincipalKeyState->Locks = GetNamedLWLockTranche(TDE_TRANCHE_NAME); sharedPrincipalKeyState->Locks = GetNamedLWLockTranche(TDE_TRANCHE_NAME);
return sizeof(TdeKeyProviderInfoSharedState); return sizeof(TdeKeyProviderInfoSharedState);
@ -120,7 +120,8 @@ tde_provider_info_lock(void)
return &sharedPrincipalKeyState->Locks[TDE_LWLOCK_PI_FILES].lock; return &sharedPrincipalKeyState->Locks[TDE_LWLOCK_PI_FILES].lock;
} }
void InitializeKeyProviderInfo(void) void
InitializeKeyProviderInfo(void)
{ {
ereport(LOG, (errmsg("initializing TDE key provider info"))); ereport(LOG, (errmsg("initializing TDE key provider info")));
RegisterShmemRequest(&key_provider_info_shmem_routine); RegisterShmemRequest(&key_provider_info_shmem_routine);
@ -177,10 +178,11 @@ GenericKeyring *
GetKeyProviderByName(const char *provider_name, Oid dbOid, Oid spcOid) GetKeyProviderByName(const char *provider_name, Oid dbOid, Oid spcOid)
{ {
GenericKeyring *keyring = NULL; GenericKeyring *keyring = NULL;
List *providers = scan_key_provider_file(PROVIDER_SCAN_BY_NAME, (void*)provider_name, dbOid, spcOid); List *providers = scan_key_provider_file(PROVIDER_SCAN_BY_NAME, (void *) provider_name, dbOid, spcOid);
if (providers != NIL) if (providers != NIL)
{ {
keyring = (GenericKeyring *)linitial(providers); keyring = (GenericKeyring *) linitial(providers);
list_free(providers); list_free(providers);
} }
else else
@ -221,7 +223,10 @@ write_key_provider_info(KeyringProvideRecord *provider, Oid database_id,
} }
if (position == -1) if (position == -1)
{ {
/* we also need to verify the name conflict and generate the next provider ID */ /*
* we also need to verify the name conflict and generate the next
* provider ID
*/
while (fetch_next_key_provider(fd, &curr_pos, &existing_provider)) while (fetch_next_key_provider(fd, &curr_pos, &existing_provider))
{ {
if (strcmp(existing_provider.provider_name, provider->provider_name) == 0) if (strcmp(existing_provider.provider_name, provider->provider_name) == 0)
@ -244,7 +249,8 @@ write_key_provider_info(KeyringProvideRecord *provider, Oid database_id,
provider->provider_id = max_provider_id + 1; provider->provider_id = max_provider_id + 1;
curr_pos = lseek(fd, 0, SEEK_END); curr_pos = lseek(fd, 0, SEEK_END);
/* emit the xlog here. So that we can handle partial file write errors /*
* emit the xlog here. So that we can handle partial file write errors
* but cannot make new WAL entries during recovery. * but cannot make new WAL entries during recovery.
*/ */
if (write_xlog) if (write_xlog)
@ -257,18 +263,20 @@ write_key_provider_info(KeyringProvideRecord *provider, Oid database_id,
memcpy(&xlrec.provider, provider, sizeof(KeyringProvideRecord)); memcpy(&xlrec.provider, provider, sizeof(KeyringProvideRecord));
XLogBeginInsert(); XLogBeginInsert();
XLogRegisterData((char *)&xlrec, sizeof(KeyringProviderXLRecord)); XLogRegisterData((char *) &xlrec, sizeof(KeyringProviderXLRecord));
XLogInsert(RM_TDERMGR_ID, XLOG_TDE_ADD_KEY_PROVIDER_KEY); XLogInsert(RM_TDERMGR_ID, XLOG_TDE_ADD_KEY_PROVIDER_KEY);
} }
} }
else else
{ {
/* we are performing redo, just go to the position received from the /*
* xlog and write the record there. * we are performing redo, just go to the position received from the
* No need to verify the name conflict and generate the provider ID * xlog and write the record there. No need to verify the name
* conflict and generate the provider ID
*/ */
curr_pos = lseek(fd, position, SEEK_SET); curr_pos = lseek(fd, position, SEEK_SET);
} }
/* /*
* All good, Just add a new provider * All good, Just add a new provider
*/ */
@ -315,7 +323,7 @@ copy_key_provider_info(KeyringProvideRecord* provider, Oid newdatabaseId, Oid ne
} }
uint32 uint32
redo_key_provider_info(KeyringProviderXLRecord* xlrec) redo_key_provider_info(KeyringProviderXLRecord *xlrec)
{ {
return write_key_provider_info(&xlrec->provider, xlrec->database_id, xlrec->tablespace_id, xlrec->offset_in_file, true, false); return write_key_provider_info(&xlrec->provider, xlrec->database_id, xlrec->tablespace_id, xlrec->offset_in_file, true, false);
} }
@ -358,13 +366,14 @@ pg_tde_add_key_provider_internal(PG_FUNCTION_ARGS)
Datum Datum
pg_tde_list_all_key_providers(PG_FUNCTION_ARGS) pg_tde_list_all_key_providers(PG_FUNCTION_ARGS)
{ {
List* all_providers = GetAllKeyringProviders(MyDatabaseId, MyDatabaseTableSpace); List *all_providers = GetAllKeyringProviders(MyDatabaseId, MyDatabaseTableSpace);
ListCell *lc; ListCell *lc;
Tuplestorestate *tupstore; Tuplestorestate *tupstore;
TupleDesc tupdesc; TupleDesc tupdesc;
MemoryContext per_query_ctx; MemoryContext per_query_ctx;
MemoryContext oldcontext; MemoryContext oldcontext;
ReturnSetInfo *rsinfo = (ReturnSetInfo *)fcinfo->resultinfo; ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
/* check to see if caller supports us returning a tuplestore */ /* check to see if caller supports us returning a tuplestore */
if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo)) if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
ereport(ERROR, ereport(ERROR,
@ -390,11 +399,11 @@ pg_tde_list_all_key_providers(PG_FUNCTION_ARGS)
MemoryContextSwitchTo(oldcontext); MemoryContextSwitchTo(oldcontext);
foreach (lc, all_providers) foreach(lc, all_providers)
{ {
Datum values[PG_TDE_LIST_PROVIDERS_COLS] = {0}; Datum values[PG_TDE_LIST_PROVIDERS_COLS] = {0};
bool nulls[PG_TDE_LIST_PROVIDERS_COLS] = {0}; bool nulls[PG_TDE_LIST_PROVIDERS_COLS] = {0};
GenericKeyring *keyring = (GenericKeyring *)lfirst(lc); GenericKeyring *keyring = (GenericKeyring *) lfirst(lc);
int i = 0; int i = 0;
values[i++] = Int32GetDatum(keyring->key_id); values[i++] = Int32GetDatum(keyring->key_id);
@ -406,7 +415,7 @@ pg_tde_list_all_key_providers(PG_FUNCTION_ARGS)
debug_print_kerying(keyring); debug_print_kerying(keyring);
} }
list_free_deep(all_providers); list_free_deep(all_providers);
return (Datum)0; return (Datum) 0;
} }
GenericKeyring * GenericKeyring *
@ -414,9 +423,10 @@ GetKeyProviderByID(int provider_id, Oid dbOid, Oid spcOid)
{ {
GenericKeyring *keyring = NULL; GenericKeyring *keyring = NULL;
List *providers = scan_key_provider_file(PROVIDER_SCAN_BY_ID, &provider_id, dbOid, spcOid); List *providers = scan_key_provider_file(PROVIDER_SCAN_BY_ID, &provider_id, dbOid, spcOid);
if (providers != NIL) if (providers != NIL)
{ {
keyring = (GenericKeyring *)linitial(providers); keyring = (GenericKeyring *) linitial(providers);
list_free(providers); list_free(providers);
} }
return keyring; return keyring;
@ -430,6 +440,7 @@ GetKeyProviderByID(int provider_id, Oid dbOid, Oid spcOid)
{ {
GenericKeyring *keyring = NULL; GenericKeyring *keyring = NULL;
SimplePtrList *providers = scan_key_provider_file(PROVIDER_SCAN_BY_ID, &provider_id, dbOid, spcOid); SimplePtrList *providers = scan_key_provider_file(PROVIDER_SCAN_BY_ID, &provider_id, dbOid, spcOid);
if (providers != NULL) if (providers != NULL)
{ {
keyring = (GenericKeyring *) providers->head->ptr; keyring = (GenericKeyring *) providers->head->ptr;
@ -494,22 +505,23 @@ scan_key_provider_file(ProviderScanType scanType, void *scanKey, Oid dbOid, Oid
while (fetch_next_key_provider(fd, &curr_pos, &provider)) while (fetch_next_key_provider(fd, &curr_pos, &provider))
{ {
bool match = false; bool match = false;
ereport(DEBUG2, ereport(DEBUG2,
(errmsg("read key provider ID=%d %s", provider.provider_id, provider.provider_name))); (errmsg("read key provider ID=%d %s", provider.provider_id, provider.provider_name)));
if (scanType == PROVIDER_SCAN_BY_NAME) if (scanType == PROVIDER_SCAN_BY_NAME)
{ {
if (strcasecmp(provider.provider_name, (char*)scanKey) == 0) if (strcasecmp(provider.provider_name, (char *) scanKey) == 0)
match = true; match = true;
} }
else if (scanType == PROVIDER_SCAN_BY_ID) else if (scanType == PROVIDER_SCAN_BY_ID)
{ {
if (provider.provider_id == *(int *)scanKey) if (provider.provider_id == *(int *) scanKey)
match = true; match = true;
} }
else if (scanType == PROVIDER_SCAN_BY_TYPE) else if (scanType == PROVIDER_SCAN_BY_TYPE)
{ {
if (provider.provider_type == *(ProviderType*)scanKey) if (provider.provider_type == *(ProviderType *) scanKey)
match = true; match = true;
} }
else if (scanType == PROVIDER_SCAN_ALL) else if (scanType == PROVIDER_SCAN_ALL)
@ -518,6 +530,7 @@ scan_key_provider_file(ProviderScanType scanType, void *scanKey, Oid dbOid, Oid
if (match) if (match)
{ {
GenericKeyring *keyring = load_keyring_provider_from_record(&provider); GenericKeyring *keyring = load_keyring_provider_from_record(&provider);
if (keyring) if (keyring)
{ {
#ifndef FRONTEND #ifndef FRONTEND
@ -559,10 +572,10 @@ load_keyring_provider_options(ProviderType provider_type, char *keyring_options)
switch (provider_type) switch (provider_type)
{ {
case FILE_KEY_PROVIDER: case FILE_KEY_PROVIDER:
return (GenericKeyring *)load_file_keyring_provider_options(keyring_options); return (GenericKeyring *) load_file_keyring_provider_options(keyring_options);
break; break;
case VAULT_V2_KEY_PROVIDER: case VAULT_V2_KEY_PROVIDER:
return (GenericKeyring *)load_vaultV2_keyring_provider_options(keyring_options); return (GenericKeyring *) load_vaultV2_keyring_provider_options(keyring_options);
break; break;
default: default:
break; break;
@ -583,7 +596,7 @@ load_file_keyring_provider_options(char *keyring_options)
return NULL; return NULL;
} }
if(strlen(file_keyring->file_name) == 0) if (strlen(file_keyring->file_name) == 0)
{ {
ereport(WARNING, ereport(WARNING,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE), (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@ -607,7 +620,7 @@ load_vaultV2_keyring_provider_options(char *keyring_options)
return NULL; return NULL;
} }
if(strlen(vaultV2_keyring->vault_token) == 0 || if (strlen(vaultV2_keyring->vault_token) == 0 ||
strlen(vaultV2_keyring->vault_url) == 0 || strlen(vaultV2_keyring->vault_url) == 0 ||
strlen(vaultV2_keyring->vault_mount_path) == 0) strlen(vaultV2_keyring->vault_mount_path) == 0)
{ {
@ -627,19 +640,20 @@ static void
debug_print_kerying(GenericKeyring *keyring) debug_print_kerying(GenericKeyring *keyring)
{ {
int debug_level = DEBUG2; int debug_level = DEBUG2;
elog(debug_level, "Keyring type: %d", keyring->type); elog(debug_level, "Keyring type: %d", keyring->type);
elog(debug_level, "Keyring name: %s", keyring->provider_name); elog(debug_level, "Keyring name: %s", keyring->provider_name);
elog(debug_level, "Keyring id: %d", keyring->key_id); elog(debug_level, "Keyring id: %d", keyring->key_id);
switch (keyring->type) switch (keyring->type)
{ {
case FILE_KEY_PROVIDER: case FILE_KEY_PROVIDER:
elog(debug_level, "File Keyring Path: %s", ((FileKeyring *)keyring)->file_name); elog(debug_level, "File Keyring Path: %s", ((FileKeyring *) keyring)->file_name);
break; break;
case VAULT_V2_KEY_PROVIDER: case VAULT_V2_KEY_PROVIDER:
elog(debug_level, "Vault Keyring Token: %s", ((VaultV2Keyring *)keyring)->vault_token); elog(debug_level, "Vault Keyring Token: %s", ((VaultV2Keyring *) keyring)->vault_token);
elog(debug_level, "Vault Keyring URL: %s", ((VaultV2Keyring *)keyring)->vault_url); elog(debug_level, "Vault Keyring URL: %s", ((VaultV2Keyring *) keyring)->vault_url);
elog(debug_level, "Vault Keyring Mount Path: %s", ((VaultV2Keyring *)keyring)->vault_mount_path); elog(debug_level, "Vault Keyring Mount Path: %s", ((VaultV2Keyring *) keyring)->vault_mount_path);
elog(debug_level, "Vault Keyring CA Path: %s", ((VaultV2Keyring *)keyring)->vault_ca_path); elog(debug_level, "Vault Keyring CA Path: %s", ((VaultV2Keyring *) keyring)->vault_ca_path);
break; break;
case UNKNOWN_KEY_PROVIDER: case UNKNOWN_KEY_PROVIDER:
elog(debug_level, "Unknown Keyring "); elog(debug_level, "Unknown Keyring ");
@ -647,10 +661,11 @@ debug_print_kerying(GenericKeyring *keyring)
} }
} }
static char* static char *
get_keyring_infofile_path(char* resPath, Oid dbOid, Oid spcOid) get_keyring_infofile_path(char *resPath, Oid dbOid, Oid spcOid)
{ {
char *db_path = pg_tde_get_tde_file_dir(dbOid, spcOid); char *db_path = pg_tde_get_tde_file_dir(dbOid, spcOid);
Assert(db_path != NULL); Assert(db_path != NULL);
join_path_components(resPath, db_path, PG_TDE_KEYRING_FILENAME); join_path_components(resPath, db_path, PG_TDE_KEYRING_FILENAME);
pfree(db_path); pfree(db_path);
@ -661,7 +676,7 @@ get_keyring_infofile_path(char* resPath, Oid dbOid, Oid spcOid)
* Fetch the next key provider from the file and update the curr_pos * Fetch the next key provider from the file and update the curr_pos
*/ */
static bool static bool
fetch_next_key_provider(int fd, off_t* curr_pos, KeyringProvideRecord *provider) fetch_next_key_provider(int fd, off_t *curr_pos, KeyringProvideRecord *provider)
{ {
off_t bytes_read = 0; off_t bytes_read = 0;
@ -680,7 +695,7 @@ fetch_next_key_provider(int fd, off_t* curr_pos, KeyringProvideRecord *provider)
ereport(ERROR, ereport(ERROR,
(errcode_for_file_access(), (errcode_for_file_access(),
errmsg("key provider info file is corrupted: %m"), errmsg("key provider info file is corrupted: %m"),
errdetail("invalid key provider record size %lld expected %lu", bytes_read, sizeof(KeyringProvideRecord) ))); errdetail("invalid key provider record size %lld expected %lu", bytes_read, sizeof(KeyringProvideRecord))));
} }
return true; return true;
} }

@ -127,7 +127,7 @@ static JsonParseErrorType json_kring_object_field_start(void *state, char *fname
static JsonParseErrorType json_kring_object_start(void *state); static JsonParseErrorType json_kring_object_start(void *state);
static JsonParseErrorType json_kring_object_end(void *state); static JsonParseErrorType json_kring_object_end(void *state);
static void json_kring_assign_scalar(JsonKeyringState * parse, JsonKeyringField field, char *value); static void json_kring_assign_scalar(JsonKeyringState *parse, JsonKeyringField field, char *value);
static char *get_remote_kring_value(const char *url, const char *field_name); static char *get_remote_kring_value(const char *url, const char *field_name);
static char *get_file_kring_value(const char *path, const char *field_name); static char *get_file_kring_value(const char *path, const char *field_name);
@ -364,7 +364,7 @@ json_kring_scalar(void *state, char *token, JsonTokenType tokentype)
} }
static void static void
json_kring_assign_scalar(JsonKeyringState * parse, JsonKeyringField field, char *value) json_kring_assign_scalar(JsonKeyringState *parse, JsonKeyringField field, char *value)
{ {
VaultV2Keyring *vault = parse->provider_opts; VaultV2Keyring *vault = parse->provider_opts;
FileKeyring *file = parse->provider_opts; FileKeyring *file = parse->provider_opts;

@ -53,8 +53,7 @@ typedef struct TdePrincipalKeylocalState
{ {
TdePrincipalKeySharedState *sharedPrincipalKeyState; TdePrincipalKeySharedState *sharedPrincipalKeyState;
dsa_area *dsa; /* local dsa area for backend attached to the dsa_area *dsa; /* local dsa area for backend attached to the
* dsa area created by postmaster at startup. * dsa area created by postmaster at startup. */
*/
dshash_table *sharedHash; dshash_table *sharedHash;
} TdePrincipalKeylocalState; } TdePrincipalKeylocalState;
@ -63,7 +62,7 @@ static dshash_parameters principal_key_dsh_params = {
sizeof(Oid), sizeof(Oid),
sizeof(TDEPrincipalKey), sizeof(TDEPrincipalKey),
dshash_memcmp, /* TODO use int compare instead */ dshash_memcmp, /* TODO use int compare instead */
dshash_memhash}; dshash_memhash};
TdePrincipalKeylocalState principalKeyLocalState; TdePrincipalKeylocalState principalKeyLocalState;
@ -74,7 +73,7 @@ static Size cache_area_size(void);
static Size required_shared_mem_size(void); static Size required_shared_mem_size(void);
static void shared_memory_shutdown(int code, Datum arg); static void shared_memory_shutdown(int code, Datum arg);
static void principal_key_startup_cleanup(int tde_tbl_count, XLogExtensionInstall *ext_info, bool redo, void *arg); static void principal_key_startup_cleanup(int tde_tbl_count, XLogExtensionInstall *ext_info, bool redo, void *arg);
static void clear_principal_key_cache(Oid databaseId) ; static void clear_principal_key_cache(Oid databaseId);
static inline dshash_table *get_principal_key_Hash(void); static inline dshash_table *get_principal_key_Hash(void);
static TDEPrincipalKey *get_principal_key_from_keyring(Oid dbOid, Oid spcOid); static TDEPrincipalKey *get_principal_key_from_keyring(Oid dbOid, Oid spcOid);
static TDEPrincipalKey *get_principal_key_from_cache(Oid dbOid); static TDEPrincipalKey *get_principal_key_from_cache(Oid dbOid);
@ -93,9 +92,10 @@ static const TDEShmemSetupRoutine principal_key_info_shmem_routine = {
.init_dsa_area_objects = initialize_objects_in_dsa_area, .init_dsa_area_objects = initialize_objects_in_dsa_area,
.required_shared_mem_size = required_shared_mem_size, .required_shared_mem_size = required_shared_mem_size,
.shmem_kill = shared_memory_shutdown .shmem_kill = shared_memory_shutdown
}; };
void InitializePrincipalKeyInfo(void) void
InitializePrincipalKeyInfo(void)
{ {
ereport(LOG, (errmsg("Initializing TDE principal key info"))); ereport(LOG, (errmsg("Initializing TDE principal key info")));
RegisterShmemRequest(&principal_key_info_shmem_routine); RegisterShmemRequest(&principal_key_info_shmem_routine);
@ -124,6 +124,7 @@ static Size
required_shared_mem_size(void) required_shared_mem_size(void)
{ {
Size sz = cache_area_size(); Size sz = cache_area_size();
sz = add_size(sz, sizeof(TdePrincipalKeySharedState)); sz = add_size(sz, sizeof(TdePrincipalKeySharedState));
return MAXALIGN(sz); return MAXALIGN(sz);
} }
@ -136,7 +137,8 @@ required_shared_mem_size(void)
static Size static Size
initialize_shared_state(void *start_address) initialize_shared_state(void *start_address)
{ {
TdePrincipalKeySharedState *sharedState = (TdePrincipalKeySharedState *)start_address; TdePrincipalKeySharedState *sharedState = (TdePrincipalKeySharedState *) start_address;
ereport(LOG, (errmsg("initializing shared state for principal key"))); ereport(LOG, (errmsg("initializing shared state for principal key")));
principalKeyLocalState.dsa = NULL; principalKeyLocalState.dsa = NULL;
principalKeyLocalState.sharedHash = NULL; principalKeyLocalState.sharedHash = NULL;
@ -147,7 +149,8 @@ initialize_shared_state(void *start_address)
return sizeof(TdePrincipalKeySharedState); return sizeof(TdePrincipalKeySharedState);
} }
void initialize_objects_in_dsa_area(dsa_area *dsa, void *raw_dsa_area) void
initialize_objects_in_dsa_area(dsa_area *dsa, void *raw_dsa_area)
{ {
dshash_table *dsh; dshash_table *dsh;
TdePrincipalKeySharedState *sharedState = principalKeyLocalState.sharedPrincipalKeyState; TdePrincipalKeySharedState *sharedState = principalKeyLocalState.sharedPrincipalKeyState;
@ -263,11 +266,12 @@ set_principal_key_with_keyring(const char *key_name, GenericKeyring *keyring,
} }
principalKey->keyLength = keyInfo->data.len; principalKey->keyLength = keyInfo->data.len;
memcpy(principalKey->keyData, keyInfo->data.data, keyInfo->data.len); memcpy(principalKey->keyData, keyInfo->data.data, keyInfo->data.len);
save_principal_key_info(&principalKey->keyInfo); save_principal_key_info(&principalKey->keyInfo);
/* XLog the new key*/ /* XLog the new key */
XLogBeginInsert(); XLogBeginInsert();
XLogRegisterData((char *) &principalKey->keyInfo, sizeof(TDEPrincipalKeyInfo)); XLogRegisterData((char *) &principalKey->keyInfo, sizeof(TDEPrincipalKeyInfo));
XLogInsert(RM_TDERMGR_ID, XLOG_TDE_ADD_PRINCIPAL_KEY); XLogInsert(RM_TDERMGR_ID, XLOG_TDE_ADD_PRINCIPAL_KEY);
@ -280,8 +284,8 @@ set_principal_key_with_keyring(const char *key_name, GenericKeyring *keyring,
if (is_dup_key) if (is_dup_key)
{ {
/* /*
* Seems like just before we got the lock, the key was installed by some other caller * Seems like just before we got the lock, the key was installed by
* Throw an error and mover no * some other caller Throw an error and mover no
*/ */
ereport(ERROR, ereport(ERROR,
@ -322,9 +326,9 @@ RotatePrincipalKey(TDEPrincipalKey *current_key, const char *new_key_name, const
oldCtx = MemoryContextSwitchTo(keyRotateCtx); oldCtx = MemoryContextSwitchTo(keyRotateCtx);
/* /*
* Let's set everything the same as the older principal key and * Let's set everything the same as the older principal key and update
* update only the required attributes. * only the required attributes.
* */ */
memcpy(&new_principal_key, current_key, sizeof(TDEPrincipalKey)); memcpy(&new_principal_key, current_key, sizeof(TDEPrincipalKey));
if (new_key_name == NULL) if (new_key_name == NULL)
@ -361,9 +365,11 @@ RotatePrincipalKey(TDEPrincipalKey *current_key, const char *new_key_name, const
} }
new_principal_key.keyLength = keyInfo->data.len; new_principal_key.keyLength = keyInfo->data.len;
memcpy(new_principal_key.keyData, keyInfo->data.data, keyInfo->data.len); memcpy(new_principal_key.keyData, keyInfo->data.data, keyInfo->data.len);
is_rotated = pg_tde_perform_rotate_key(current_key, &new_principal_key); is_rotated = pg_tde_perform_rotate_key(current_key, &new_principal_key);
if (is_rotated && current_key->keyInfo.tablespaceId != GLOBALTABLESPACE_OID) { if (is_rotated && current_key->keyInfo.tablespaceId != GLOBALTABLESPACE_OID)
{
clear_principal_key_cache(current_key->keyInfo.databaseId); clear_principal_key_cache(current_key->keyInfo.databaseId);
push_principal_key_to_cache(&new_principal_key); push_principal_key_to_cache(&new_principal_key);
} }
@ -399,12 +405,15 @@ load_latest_versioned_key_name(TDEPrincipalKeyInfo *principal_key_info, GenericK
KeyringReturnCodes kr_ret; KeyringReturnCodes kr_ret;
keyInfo *keyInfo = NULL; keyInfo *keyInfo = NULL;
int base_version = principal_key_info->keyId.version; int base_version = principal_key_info->keyId.version;
Assert(principal_key_info != NULL); Assert(principal_key_info != NULL);
Assert(keyring != NULL); Assert(keyring != NULL);
Assert(strlen(principal_key_info->keyId.name) > 0); Assert(strlen(principal_key_info->keyId.name) > 0);
/* Start with the passed in version number
* We expect the name and the version number are already properly initialized /*
* and contain the correct values * Start with the passed in version number We expect the name and the
* version number are already properly initialized and contain the correct
* values
*/ */
snprintf(principal_key_info->keyId.versioned_name, TDE_KEY_NAME_LEN, snprintf(principal_key_info->keyId.versioned_name, TDE_KEY_NAME_LEN,
"%s_%d", principal_key_info->keyId.name, principal_key_info->keyId.version); "%s_%d", principal_key_info->keyId.name, principal_key_info->keyId.version);
@ -412,7 +421,11 @@ load_latest_versioned_key_name(TDEPrincipalKeyInfo *principal_key_info, GenericK
while (true) while (true)
{ {
keyInfo = KeyringGetKey(keyring, principal_key_info->keyId.versioned_name, false, &kr_ret); keyInfo = KeyringGetKey(keyring, principal_key_info->keyId.versioned_name, false, &kr_ret);
/* vault-v2 returns 404 (KEYRING_CODE_RESOURCE_NOT_AVAILABLE) when key is not found */
/*
* vault-v2 returns 404 (KEYRING_CODE_RESOURCE_NOT_AVAILABLE) when key
* is not found
*/
if (kr_ret != KEYRING_CODE_SUCCESS && kr_ret != KEYRING_CODE_RESOURCE_NOT_AVAILABLE) if (kr_ret != KEYRING_CODE_SUCCESS && kr_ret != KEYRING_CODE_RESOURCE_NOT_AVAILABLE)
{ {
ereport(FATAL, ereport(FATAL,
@ -443,7 +456,8 @@ load_latest_versioned_key_name(TDEPrincipalKeyInfo *principal_key_info, GenericK
snprintf(principal_key_info->keyId.versioned_name, TDE_KEY_NAME_LEN, "%s_%d", principal_key_info->keyId.name, principal_key_info->keyId.version); snprintf(principal_key_info->keyId.versioned_name, TDE_KEY_NAME_LEN, "%s_%d", principal_key_info->keyId.name, principal_key_info->keyId.version);
/* /*
* Not really required. Just to break the infinite loop in case the key provider is not behaving sane. * Not really required. Just to break the infinite loop in case the
* key provider is not behaving sane.
*/ */
if (principal_key_info->keyId.version > MAX_PRINCIPAL_KEY_VERSION_NUM) if (principal_key_info->keyId.version > MAX_PRINCIPAL_KEY_VERSION_NUM)
{ {
@ -453,6 +467,7 @@ load_latest_versioned_key_name(TDEPrincipalKeyInfo *principal_key_info, GenericK
} }
return NULL; /* Just to keep compiler quite */ return NULL; /* Just to keep compiler quite */
} }
/* /*
* Returns the provider ID of the keyring that holds the principal key * Returns the provider ID of the keyring that holds the principal key
* Return InvalidOid if the principal key is not set for the database * Return InvalidOid if the principal key is not set for the database
@ -474,7 +489,10 @@ GetPrincipalKeyProviderId(void)
keyringId = principalKey->keyInfo.keyringId; keyringId = principalKey->keyInfo.keyringId;
} }
{ {
/* Principal key not present in cache. Try Loading it from the info file */ /*
* Principal key not present in cache. Try Loading it from the info
* file
*/
principalKeyInfo = pg_tde_get_principal_key_info(dbOid, MyDatabaseTableSpace); principalKeyInfo = pg_tde_get_principal_key_info(dbOid, MyDatabaseTableSpace);
if (principalKeyInfo) if (principalKeyInfo)
{ {
@ -508,7 +526,7 @@ get_principal_key_from_cache(Oid dbOid)
{ {
TDEPrincipalKey *cacheEntry = NULL; TDEPrincipalKey *cacheEntry = NULL;
cacheEntry = (TDEPrincipalKey *)dshash_find(get_principal_key_Hash(), cacheEntry = (TDEPrincipalKey *) dshash_find(get_principal_key_Hash(),
&dbOid, false); &dbOid, false);
if (cacheEntry) if (cacheEntry)
dshash_release_lock(get_principal_key_Hash(), cacheEntry); dshash_release_lock(get_principal_key_Hash(), cacheEntry);
@ -532,6 +550,7 @@ push_principal_key_to_cache(TDEPrincipalKey *principalKey)
TDEPrincipalKey *cacheEntry = NULL; TDEPrincipalKey *cacheEntry = NULL;
Oid databaseId = principalKey->keyInfo.databaseId; Oid databaseId = principalKey->keyInfo.databaseId;
bool found = false; bool found = false;
cacheEntry = dshash_find_or_insert(get_principal_key_Hash(), cacheEntry = dshash_find_or_insert(get_principal_key_Hash(),
&databaseId, &found); &databaseId, &found);
if (!found) if (!found)
@ -570,6 +589,7 @@ void
cleanup_principal_key_info(Oid databaseId, Oid tablespaceId) cleanup_principal_key_info(Oid databaseId, Oid tablespaceId)
{ {
clear_principal_key_cache(databaseId); clear_principal_key_cache(databaseId);
/* /*
* TODO: Although should never happen. Still verify if any table in the * TODO: Although should never happen. Still verify if any table in the
* database is using tde * database is using tde
@ -585,7 +605,7 @@ clear_principal_key_cache(Oid databaseId)
TDEPrincipalKey *cache_entry; TDEPrincipalKey *cache_entry;
/* Start with deleting the cache entry for the database */ /* Start with deleting the cache entry for the database */
cache_entry = (TDEPrincipalKey *)dshash_find(get_principal_key_Hash(), cache_entry = (TDEPrincipalKey *) dshash_find(get_principal_key_Hash(),
&databaseId, true); &databaseId, true);
if (cache_entry) if (cache_entry)
{ {
@ -599,7 +619,8 @@ clear_principal_key_cache(Oid databaseId)
PG_FUNCTION_INFO_V1(pg_tde_set_principal_key); PG_FUNCTION_INFO_V1(pg_tde_set_principal_key);
Datum pg_tde_set_principal_key(PG_FUNCTION_ARGS); Datum pg_tde_set_principal_key(PG_FUNCTION_ARGS);
Datum pg_tde_set_principal_key(PG_FUNCTION_ARGS) Datum
pg_tde_set_principal_key(PG_FUNCTION_ARGS)
{ {
char *principal_key_name = text_to_cstring(PG_GETARG_TEXT_PP(0)); char *principal_key_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
char *provider_name = text_to_cstring(PG_GETARG_TEXT_PP(1)); char *provider_name = text_to_cstring(PG_GETARG_TEXT_PP(1));
@ -656,7 +677,8 @@ pg_tde_rotate_principal_key_internal(PG_FUNCTION_ARGS)
} }
PG_FUNCTION_INFO_V1(pg_tde_principal_key_info_internal); PG_FUNCTION_INFO_V1(pg_tde_principal_key_info_internal);
Datum pg_tde_principal_key_info_internal(PG_FUNCTION_ARGS) Datum
pg_tde_principal_key_info_internal(PG_FUNCTION_ARGS)
{ {
Oid dbOid = MyDatabaseId; Oid dbOid = MyDatabaseId;
Oid spcOid = MyDatabaseTableSpace; Oid spcOid = MyDatabaseTableSpace;
@ -727,7 +749,7 @@ pg_tde_get_key_info(PG_FUNCTION_ARGS, Oid dbOid, Oid spcOid)
values[4] = Int32GetDatum(principal_key->keyInfo.keyId.version); values[4] = Int32GetDatum(principal_key->keyInfo.keyId.version);
isnull[4] = false; isnull[4] = false;
/* TIMESTAMP TZ: Principal key creation time */ /* TIMESTAMP TZ: Principal key creation time */
ts = (TimestampTz)principal_key->keyInfo.creationTime.tv_sec - ((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY); ts = (TimestampTz) principal_key->keyInfo.creationTime.tv_sec - ((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY);
ts = (ts * USECS_PER_SEC) + principal_key->keyInfo.creationTime.tv_usec; ts = (ts * USECS_PER_SEC) + principal_key->keyInfo.creationTime.tv_usec;
values[5] = TimestampTzGetDatum(ts); values[5] = TimestampTzGetDatum(ts);
isnull[5] = false; isnull[5] = false;
@ -770,6 +792,7 @@ get_principal_key_from_keyring(Oid dbOid, Oid spcOid)
} }
keyInfo = KeyringGetKey(keyring, principalKeyInfo->keyId.versioned_name, false, &keyring_ret); keyInfo = KeyringGetKey(keyring, principalKeyInfo->keyId.versioned_name, false, &keyring_ret);
if (keyInfo == NULL) if (keyInfo == NULL)
{ {
return NULL; return NULL;

@ -27,8 +27,7 @@ typedef struct TDELocalState
{ {
TdeSharedState *sharedTdeState; TdeSharedState *sharedTdeState;
dsa_area **dsa; /* local dsa area for backend attached to the dsa_area **dsa; /* local dsa area for backend attached to the
* dsa area created by postmaster at startup. * dsa area created by postmaster at startup. */
*/
dshash_table *principalKeySharedHash; dshash_table *principalKeySharedHash;
} TDELocalState; } TDELocalState;
@ -37,19 +36,23 @@ static void tde_shmem_shutdown(int code, Datum arg);
List *registeredShmemRequests = NIL; List *registeredShmemRequests = NIL;
bool shmemInited = false; bool shmemInited = false;
void RegisterShmemRequest(const TDEShmemSetupRoutine *routine) void
RegisterShmemRequest(const TDEShmemSetupRoutine *routine)
{ {
Assert(shmemInited == false); Assert(shmemInited == false);
registeredShmemRequests = lappend(registeredShmemRequests, (void *)routine); registeredShmemRequests = lappend(registeredShmemRequests, (void *) routine);
} }
Size TdeRequiredSharedMemorySize(void) Size
TdeRequiredSharedMemorySize(void)
{ {
Size sz = 0; Size sz = 0;
ListCell *lc; ListCell *lc;
foreach (lc, registeredShmemRequests)
foreach(lc, registeredShmemRequests)
{ {
TDEShmemSetupRoutine *routine = (TDEShmemSetupRoutine *)lfirst(lc); TDEShmemSetupRoutine *routine = (TDEShmemSetupRoutine *) lfirst(lc);
if (routine->required_shared_mem_size) if (routine->required_shared_mem_size)
sz = add_size(sz, routine->required_shared_mem_size()); sz = add_size(sz, routine->required_shared_mem_size());
} }
@ -57,12 +60,14 @@ Size TdeRequiredSharedMemorySize(void)
return MAXALIGN(sz); return MAXALIGN(sz);
} }
int TdeRequiredLocksCount(void) int
TdeRequiredLocksCount(void)
{ {
return TDE_LWLOCK_COUNT; return TDE_LWLOCK_COUNT;
} }
void TdeShmemInit(void) void
TdeShmemInit(void)
{ {
bool found; bool found;
TdeSharedState *tdeState; TdeSharedState *tdeState;
@ -76,7 +81,7 @@ void TdeShmemInit(void)
if (!found) if (!found)
{ {
/* First time through ... */ /* First time through ... */
char *p = (char *)tdeState; char *p = (char *) tdeState;
dsa_area *dsa; dsa_area *dsa;
ListCell *lc; ListCell *lc;
Size used_size = 0; Size used_size = 0;
@ -85,10 +90,11 @@ void TdeShmemInit(void)
p += MAXALIGN(sizeof(TdeSharedState)); p += MAXALIGN(sizeof(TdeSharedState));
used_size += MAXALIGN(sizeof(TdeSharedState)); used_size += MAXALIGN(sizeof(TdeSharedState));
/* Now place all shared state structures */ /* Now place all shared state structures */
foreach (lc, registeredShmemRequests) foreach(lc, registeredShmemRequests)
{ {
Size sz = 0; Size sz = 0;
TDEShmemSetupRoutine *routine = (TDEShmemSetupRoutine *)lfirst(lc); TDEShmemSetupRoutine *routine = (TDEShmemSetupRoutine *) lfirst(lc);
if (routine->init_shared_state) if (routine->init_shared_state)
{ {
sz = routine->init_shared_state(p); sz = routine->init_shared_state(p);
@ -110,29 +116,33 @@ void TdeShmemInit(void)
dsa_set_size_limit(dsa, dsa_area_size); dsa_set_size_limit(dsa, dsa_area_size);
/* Initialize all DSA area objects */ /* Initialize all DSA area objects */
foreach (lc, registeredShmemRequests) foreach(lc, registeredShmemRequests)
{ {
TDEShmemSetupRoutine *routine = (TDEShmemSetupRoutine *)lfirst(lc); TDEShmemSetupRoutine *routine = (TDEShmemSetupRoutine *) lfirst(lc);
if (routine->init_dsa_area_objects) if (routine->init_dsa_area_objects)
routine->init_dsa_area_objects(dsa, tdeState->rawDsaArea); routine->init_dsa_area_objects(dsa, tdeState->rawDsaArea);
} }
ereport(LOG, (errmsg("setting no limit to DSA area of size %lu", dsa_area_size))); ereport(LOG, (errmsg("setting no limit to DSA area of size %lu", dsa_area_size)));
dsa_set_size_limit(dsa, -1); /* Let it grow outside the shared memory */ dsa_set_size_limit(dsa, -1); /* Let it grow outside the shared
* memory */
shmemInited = true; shmemInited = true;
} }
LWLockRelease(AddinShmemInitLock); LWLockRelease(AddinShmemInitLock);
on_shmem_exit(tde_shmem_shutdown, (Datum)0); on_shmem_exit(tde_shmem_shutdown, (Datum) 0);
} }
static void static void
tde_shmem_shutdown(int code, Datum arg) tde_shmem_shutdown(int code, Datum arg)
{ {
ListCell *lc; ListCell *lc;
foreach (lc, registeredShmemRequests)
foreach(lc, registeredShmemRequests)
{ {
TDEShmemSetupRoutine *routine = (TDEShmemSetupRoutine *)lfirst(lc); TDEShmemSetupRoutine *routine = (TDEShmemSetupRoutine *) lfirst(lc);
if (routine->shmem_kill) if (routine->shmem_kill)
routine->shmem_kill(code, arg); routine->shmem_kill(code, arg);
} }

@ -35,13 +35,13 @@ get_tde_table_am_oid(void)
/* /*
* Returns the list of OIDs for all TDE tables in a database * Returns the list of OIDs for all TDE tables in a database
*/ */
List* List *
get_all_tde_tables(void) get_all_tde_tables(void)
{ {
Relation pg_class; Relation pg_class;
SysScanDesc scan; SysScanDesc scan;
HeapTuple tuple; HeapTuple tuple;
List* tde_tables = NIL; List *tde_tables = NIL;
Oid am_oid = get_tde_basic_table_am_oid(); Oid am_oid = get_tde_basic_table_am_oid();
/* Open the pg_class table */ /* Open the pg_class table */
@ -54,7 +54,7 @@ get_all_tde_tables(void)
/* Iterate over all tuples in the table */ /* Iterate over all tuples in the table */
while ((tuple = systable_getnext(scan)) != NULL) while ((tuple = systable_getnext(scan)) != NULL)
{ {
Form_pg_class classForm = (Form_pg_class)GETSTRUCT(tuple); Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple);
/* Check if the table uses the specified access method */ /* Check if the table uses the specified access method */
if (classForm->relam == am_oid) if (classForm->relam == am_oid)
@ -76,8 +76,9 @@ get_all_tde_tables(void)
int int
get_tde_tables_count(void) get_tde_tables_count(void)
{ {
List* tde_tables = get_all_tde_tables(); List *tde_tables = get_all_tde_tables();
int count = list_length(tde_tables); int count = list_length(tde_tables);
list_free(tde_tables); list_free(tde_tables);
return count; return count;
} }
@ -97,8 +98,10 @@ pg_tde_set_globalspace_dir(const char *dir)
char * char *
pg_tde_get_tde_file_dir(Oid dbOid, Oid spcOid) pg_tde_get_tde_file_dir(Oid dbOid, Oid spcOid)
{ {
/* `dbOid` is set to a value for the XLog keys caching but GetDatabasePath() /*
* expects it (`dbOid`) to be `0` if this is a global space. * `dbOid` is set to a value for the XLog keys caching but
* GetDatabasePath() expects it (`dbOid`) to be `0` if this is a global
* space.
*/ */
if (spcOid == GLOBALTABLESPACE_OID) if (spcOid == GLOBALTABLESPACE_OID)
{ {

@ -44,43 +44,46 @@
*/ */
const EVP_CIPHER* cipher = NULL; const EVP_CIPHER *cipher = NULL;
const EVP_CIPHER* cipher2 = NULL; const EVP_CIPHER *cipher2 = NULL;
int cipher_block_size = 0; int cipher_block_size = 0;
void AesInit(void) void
AesInit(void)
{ {
static int initialized = 0; static int initialized = 0;
if(!initialized) { if (!initialized)
{
OpenSSL_add_all_algorithms(); OpenSSL_add_all_algorithms();
ERR_load_crypto_strings(); ERR_load_crypto_strings();
cipher = EVP_aes_128_cbc(); cipher = EVP_aes_128_cbc();
cipher_block_size = EVP_CIPHER_block_size(cipher); // == buffer size cipher_block_size = EVP_CIPHER_block_size(cipher);
//== buffer size
cipher2 = EVP_aes_128_ecb(); cipher2 = EVP_aes_128_ecb();
initialized = 1; initialized = 1;
} }
} }
// TODO: a few things could be optimized in this. It's good enough for a prototype. /* TODO: a few things could be optimized in this. It's good enough for a prototype. */
static void static void
AesRunCtr(EVP_CIPHER_CTX** ctxPtr, int enc, const unsigned char* key, const unsigned char* iv, const unsigned char* in, int in_len, unsigned char* out, int* out_len) AesRunCtr(EVP_CIPHER_CTX **ctxPtr, int enc, const unsigned char *key, const unsigned char *iv, const unsigned char *in, int in_len, unsigned char *out, int *out_len)
{ {
if (*ctxPtr == NULL) if (*ctxPtr == NULL)
{ {
*ctxPtr = EVP_CIPHER_CTX_new(); *ctxPtr = EVP_CIPHER_CTX_new();
EVP_CIPHER_CTX_init(*ctxPtr); EVP_CIPHER_CTX_init(*ctxPtr);
if(EVP_CipherInit_ex(*ctxPtr, cipher2, NULL, key, iv, enc) == 0) if (EVP_CipherInit_ex(*ctxPtr, cipher2, NULL, key, iv, enc) == 0)
{ {
#ifdef FRONTEND #ifdef FRONTEND
fprintf(stderr, "ERROR: EVP_CipherInit_ex failed. OpenSSL error: %s\n", ERR_error_string(ERR_get_error(), NULL)); fprintf(stderr, "ERROR: EVP_CipherInit_ex failed. OpenSSL error: %s\n", ERR_error_string(ERR_get_error(), NULL));
#else #else
ereport(ERROR, ereport(ERROR,
(errmsg("EVP_CipherInit_ex failed. OpenSSL error: %s", ERR_error_string(ERR_get_error(), NULL)))); (errmsg("EVP_CipherInit_ex failed. OpenSSL error: %s", ERR_error_string(ERR_get_error(), NULL))));
#endif #endif
return; return;
} }
@ -88,63 +91,66 @@ AesRunCtr(EVP_CIPHER_CTX** ctxPtr, int enc, const unsigned char* key, const unsi
EVP_CIPHER_CTX_set_padding(*ctxPtr, 0); EVP_CIPHER_CTX_set_padding(*ctxPtr, 0);
} }
if(EVP_CipherUpdate(*ctxPtr, out, out_len, in, in_len) == 0) if (EVP_CipherUpdate(*ctxPtr, out, out_len, in, in_len) == 0)
{ {
#ifdef FRONTEND #ifdef FRONTEND
fprintf(stderr, "ERROR: EVP_CipherUpdate failed. OpenSSL error: %s\n", ERR_error_string(ERR_get_error(), NULL)); fprintf(stderr, "ERROR: EVP_CipherUpdate failed. OpenSSL error: %s\n", ERR_error_string(ERR_get_error(), NULL));
#else #else
ereport(ERROR, ereport(ERROR,
(errmsg("EVP_CipherUpdate failed. OpenSSL error: %s", ERR_error_string(ERR_get_error(), NULL)))); (errmsg("EVP_CipherUpdate failed. OpenSSL error: %s", ERR_error_string(ERR_get_error(), NULL))));
#endif #endif
return; return;
} }
} }
static void AesRunCbc(int enc, const unsigned char* key, const unsigned char* iv, const unsigned char* in, int in_len, unsigned char* out, int* out_len) static void
AesRunCbc(int enc, const unsigned char *key, const unsigned char *iv, const unsigned char *in, int in_len, unsigned char *out, int *out_len)
{ {
int out_len_final = 0; int out_len_final = 0;
EVP_CIPHER_CTX* ctx = NULL; EVP_CIPHER_CTX *ctx = NULL;
ctx = EVP_CIPHER_CTX_new(); ctx = EVP_CIPHER_CTX_new();
EVP_CIPHER_CTX_init(ctx); EVP_CIPHER_CTX_init(ctx);
if(EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, enc) == 0) if (EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, enc) == 0)
{ {
#ifdef FRONTEND #ifdef FRONTEND
fprintf(stderr, "ERROR: EVP_CipherInit_ex failed. OpenSSL error: %s\n", ERR_error_string(ERR_get_error(), NULL)); fprintf(stderr, "ERROR: EVP_CipherInit_ex failed. OpenSSL error: %s\n", ERR_error_string(ERR_get_error(), NULL));
#else #else
ereport(ERROR, ereport(ERROR,
(errmsg("EVP_CipherInit_ex failed. OpenSSL error: %s", ERR_error_string(ERR_get_error(), NULL)))); (errmsg("EVP_CipherInit_ex failed. OpenSSL error: %s", ERR_error_string(ERR_get_error(), NULL))));
#endif #endif
goto cleanup; goto cleanup;
} }
EVP_CIPHER_CTX_set_padding(ctx, 0); EVP_CIPHER_CTX_set_padding(ctx, 0);
Assert(in_len % cipher_block_size == 0); Assert(in_len % cipher_block_size == 0);
if(EVP_CipherUpdate(ctx, out, out_len, in, in_len) == 0) if (EVP_CipherUpdate(ctx, out, out_len, in, in_len) == 0)
{ {
#ifdef FRONTEND #ifdef FRONTEND
fprintf(stderr, "ERROR: EVP_CipherUpdate failed. OpenSSL error: %s\n", ERR_error_string(ERR_get_error(), NULL)); fprintf(stderr, "ERROR: EVP_CipherUpdate failed. OpenSSL error: %s\n", ERR_error_string(ERR_get_error(), NULL));
#else #else
ereport(ERROR, ereport(ERROR,
(errmsg("EVP_CipherUpdate failed. OpenSSL error: %s", ERR_error_string(ERR_get_error(), NULL)))); (errmsg("EVP_CipherUpdate failed. OpenSSL error: %s", ERR_error_string(ERR_get_error(), NULL))));
#endif #endif
goto cleanup; goto cleanup;
} }
if(EVP_CipherFinal_ex(ctx, out + *out_len, &out_len_final) == 0) if (EVP_CipherFinal_ex(ctx, out + *out_len, &out_len_final) == 0)
{ {
#ifdef FRONTEND #ifdef FRONTEND
fprintf(stderr, "ERROR: EVP_CipherFinal_ex failed. OpenSSL error: %s\n", ERR_error_string(ERR_get_error(), NULL)); fprintf(stderr, "ERROR: EVP_CipherFinal_ex failed. OpenSSL error: %s\n", ERR_error_string(ERR_get_error(), NULL));
#else #else
ereport(ERROR, ereport(ERROR,
(errmsg("EVP_CipherFinal_ex failed. OpenSSL error: %s", ERR_error_string(ERR_get_error(), NULL)))); (errmsg("EVP_CipherFinal_ex failed. OpenSSL error: %s", ERR_error_string(ERR_get_error(), NULL))));
#endif #endif
goto cleanup; goto cleanup;
} }
/* We encrypt one block (16 bytes) /*
* Our expectation is that the result should also be 16 bytes, without any additional padding * We encrypt one block (16 bytes) Our expectation is that the result
* should also be 16 bytes, without any additional padding
*/ */
*out_len += out_len_final; *out_len += out_len_final;
Assert(in_len == *out_len); Assert(in_len == *out_len);
@ -154,37 +160,40 @@ cleanup:
EVP_CIPHER_CTX_free(ctx); EVP_CIPHER_CTX_free(ctx);
} }
void AesEncrypt(const unsigned char* key, const unsigned char* iv, const unsigned char* in, int in_len, unsigned char* out, int* out_len) void
AesEncrypt(const unsigned char *key, const unsigned char *iv, const unsigned char *in, int in_len, unsigned char *out, int *out_len)
{ {
AesRunCbc(1, key, iv, in, in_len, out, out_len); AesRunCbc(1, key, iv, in, in_len, out, out_len);
} }
void AesDecrypt(const unsigned char* key, const unsigned char* iv, const unsigned char* in, int in_len, unsigned char* out, int* out_len) void
AesDecrypt(const unsigned char *key, const unsigned char *iv, const unsigned char *in, int in_len, unsigned char *out, int *out_len)
{ {
AesRunCbc(0, key, iv, in, in_len, out, out_len); AesRunCbc(0, key, iv, in, in_len, out, out_len);
} }
/* This function assumes that the out buffer is big enough: at least (blockNumber2 - blockNumber1) * 16 bytes /* This function assumes that the out buffer is big enough: at least (blockNumber2 - blockNumber1) * 16 bytes
*/ */
void Aes128EncryptedZeroBlocks(void* ctxPtr, const unsigned char* key, const char* iv_prefix, uint64_t blockNumber1, uint64_t blockNumber2, unsigned char* out) void
Aes128EncryptedZeroBlocks(void *ctxPtr, const unsigned char *key, const char *iv_prefix, uint64_t blockNumber1, uint64_t blockNumber2, unsigned char *out)
{ {
const unsigned char iv[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; const unsigned char iv[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const unsigned dataLen = (blockNumber2 - blockNumber1) * 16; const unsigned dataLen = (blockNumber2 - blockNumber1) * 16;
int outLen; int outLen;
Assert(blockNumber2 >= blockNumber1); Assert(blockNumber2 >= blockNumber1);
for(int j=blockNumber1;j<blockNumber2;++j) for (int j = blockNumber1; j < blockNumber2; ++j)
{ {
/* /*
* We have 16 bytes, and a 4 byte counter. The counter is the last 4 bytes. * We have 16 bytes, and a 4 byte counter. The counter is the last 4
* Technically, this isn't correct: the byte order of the counter depends * bytes. Technically, this isn't correct: the byte order of the
* on the endianness of the CPU running it. * counter depends on the endianness of the CPU running it. As this is
* As this is a generic limitation of Postgres, it's fine. * a generic limitation of Postgres, it's fine.
*/ */
memcpy(out + (16*(j-blockNumber1)), iv_prefix, 12); memcpy(out + (16 * (j - blockNumber1)), iv_prefix, 12);
memcpy(out + (16*(j-blockNumber1)) + 12, (char*)&j, 4); memcpy(out + (16 * (j - blockNumber1)) + 12, (char *) &j, 4);
} }
AesRunCtr(ctxPtr, 1, key, iv, out, dataLen, out, &outLen); AesRunCtr(ctxPtr, 1, key, iv, out, dataLen, out, &outLen);

@ -11,23 +11,26 @@
#include "keyring/keyring_api.h" #include "keyring/keyring_api.h"
#ifdef ENCRYPTION_DEBUG #ifdef ENCRYPTION_DEBUG
static void iv_prefix_debug(const char* iv_prefix, char* out_hex) static void
iv_prefix_debug(const char *iv_prefix, char *out_hex)
{ {
for(int i =0;i<16;++i) { for (int i = 0; i < 16; ++i)
sprintf(out_hex + i*2, "%02x", (int)*(iv_prefix + i)); {
sprintf(out_hex + i * 2, "%02x", (int) *(iv_prefix + i));
} }
out_hex[32] = 0; out_hex[32] = 0;
} }
#endif #endif
static void static void
SetIVPrefix(ItemPointerData* ip, char* iv_prefix) SetIVPrefix(ItemPointerData *ip, char *iv_prefix)
{ {
/* We have up to 16 bytes for the entire IV /*
* The higher bytes (starting with 15) are used for the incrementing counter * We have up to 16 bytes for the entire IV The higher bytes (starting
* The lower bytes (in this case, 0..5) are used for the tuple identification * with 15) are used for the incrementing counter The lower bytes (in this
* Tuple identification is based on CTID, which currently is 48 bytes in * case, 0..5) are used for the tuple identification Tuple identification
* postgres: 4 bytes for the block id and 2 bytes for the position id * is based on CTID, which currently is 48 bytes in postgres: 4 bytes for
* the block id and 2 bytes for the position id
*/ */
iv_prefix[0] = ip->ip_blkid.bi_hi / 256; iv_prefix[0] = ip->ip_blkid.bi_hi / 256;
iv_prefix[1] = ip->ip_blkid.bi_hi % 256; iv_prefix[1] = ip->ip_blkid.bi_hi % 256;
@ -50,7 +53,7 @@ SetIVPrefix(ItemPointerData* ip, char* iv_prefix)
* This function assumes that everything is in a single block, and has an assertion ensuring this * This function assumes that everything is in a single block, and has an assertion ensuring this
*/ */
static void static void
pg_tde_crypt_simple(const char* iv_prefix, uint32 start_offset, const char* data, uint32 data_len, char* out, RelKeyData* key, const char* context) pg_tde_crypt_simple(const char *iv_prefix, uint32 start_offset, const char *data, uint32 data_len, char *out, RelKeyData *key, const char *context)
{ {
const uint64 aes_start_block = start_offset / AES_BLOCK_SIZE; const uint64 aes_start_block = start_offset / AES_BLOCK_SIZE;
const uint64 aes_end_block = (start_offset + data_len + (AES_BLOCK_SIZE - 1)) / AES_BLOCK_SIZE; const uint64 aes_end_block = (start_offset + data_len + (AES_BLOCK_SIZE - 1)) / AES_BLOCK_SIZE;
@ -63,16 +66,17 @@ pg_tde_crypt_simple(const char* iv_prefix, uint32 start_offset, const char* data
Aes128EncryptedZeroBlocks(&(key->internal_key.ctx), key->internal_key.key, iv_prefix, aes_start_block, aes_end_block, enc_key); Aes128EncryptedZeroBlocks(&(key->internal_key.ctx), key->internal_key.key, iv_prefix, aes_start_block, aes_end_block, enc_key);
#ifdef ENCRYPTION_DEBUG #ifdef ENCRYPTION_DEBUG
{ {
char ivp_debug[33]; char ivp_debug[33];
iv_prefix_debug(iv_prefix, ivp_debug); iv_prefix_debug(iv_prefix, ivp_debug);
ereport(LOG, ereport(LOG,
(errmsg("%s: Start offset: %lu Data_Len: %u, aes_start_block: %lu, aes_end_block: %lu, IV prefix: %s", (errmsg("%s: Start offset: %lu Data_Len: %u, aes_start_block: %lu, aes_end_block: %lu, IV prefix: %s",
context?context:"", start_offset, data_len, aes_start_block, aes_end_block, ivp_debug))); context ? context : "", start_offset, data_len, aes_start_block, aes_end_block, ivp_debug)));
} }
#endif #endif
for(uint32 i = 0; i < data_len; ++i) for (uint32 i = 0; i < data_len; ++i)
{ {
out[i] = data[i] ^ enc_key[i + aes_block_no]; out[i] = data[i] ^ enc_key[i + aes_block_no];
} }
@ -86,10 +90,10 @@ pg_tde_crypt_simple(const char* iv_prefix, uint32 start_offset, const char* data
* This is a generic function intended for large data, that do not fit into a single block * This is a generic function intended for large data, that do not fit into a single block
*/ */
static void static void
pg_tde_crypt_complex(const char* iv_prefix, uint32 start_offset, const char* data, uint32 data_len, char* out, RelKeyData* key, const char* context) pg_tde_crypt_complex(const char *iv_prefix, uint32 start_offset, const char *data, uint32 data_len, char *out, RelKeyData *key, const char *context)
{ {
const uint64 aes_start_block = start_offset / AES_BLOCK_SIZE; const uint64 aes_start_block = start_offset / AES_BLOCK_SIZE;
const uint64 aes_end_block = (start_offset + data_len + (AES_BLOCK_SIZE -1)) / AES_BLOCK_SIZE; const uint64 aes_end_block = (start_offset + data_len + (AES_BLOCK_SIZE - 1)) / AES_BLOCK_SIZE;
const uint64 aes_block_no = start_offset % AES_BLOCK_SIZE; const uint64 aes_block_no = start_offset % AES_BLOCK_SIZE;
uint32 batch_no = 0; uint32 batch_no = 0;
uint32 data_index = 0; uint32 data_index = 0;
@ -104,39 +108,42 @@ pg_tde_crypt_complex(const char* iv_prefix, uint32 start_offset, const char* dat
Aes128EncryptedZeroBlocks(&(key->internal_key.ctx), key->internal_key.key, iv_prefix, batch_start_block, batch_end_block, enc_key); Aes128EncryptedZeroBlocks(&(key->internal_key.ctx), key->internal_key.key, iv_prefix, batch_start_block, batch_end_block, enc_key);
#ifdef ENCRYPTION_DEBUG #ifdef ENCRYPTION_DEBUG
{ {
char ivp_debug[33]; char ivp_debug[33];
iv_prefix_debug(iv_prefix, ivp_debug); iv_prefix_debug(iv_prefix, ivp_debug);
ereport(LOG, ereport(LOG,
(errmsg("%s: Batch-No:%d Start offset: %lu Data_Len: %u, batch_start_block: %lu, batch_end_block: %lu, IV prefix: %s", (errmsg("%s: Batch-No:%d Start offset: %lu Data_Len: %u, batch_start_block: %lu, batch_end_block: %lu, IV prefix: %s",
context?context:"", batch_no, start_offset, data_len, batch_start_block, batch_end_block, ivp_debug))); context ? context : "", batch_no, start_offset, data_len, batch_start_block, batch_end_block, ivp_debug)));
} }
#endif #endif
current_batch_bytes = ((batch_end_block - batch_start_block) * AES_BLOCK_SIZE) current_batch_bytes = ((batch_end_block - batch_start_block) * AES_BLOCK_SIZE)
- (batch_no > 0 ? 0 : aes_block_no); /* first batch skips `aes_block_no`-th bytes of enc_key */ - (batch_no > 0 ? 0 : aes_block_no); /* first batch skips
* `aes_block_no`-th bytes
* of enc_key */
if ((data_index + current_batch_bytes) > data_len) if ((data_index + current_batch_bytes) > data_len)
current_batch_bytes = data_len - data_index; current_batch_bytes = data_len - data_index;
for(uint32 i = 0; i < current_batch_bytes; ++i) for (uint32 i = 0; i < current_batch_bytes; ++i)
{ {
/* /*
* As the size of enc_key always is a multiple of 16 we * As the size of enc_key always is a multiple of 16 we start from
* start from `aes_block_no`-th index of the enc_key[] * `aes_block_no`-th index of the enc_key[] so N-th will be
* so N-th will be crypted with the same enc_key byte despite * crypted with the same enc_key byte despite what start_offset
* what start_offset the function was called with. * the function was called with. For example start_offset = 10;
* For example start_offset = 10; MAX_AES_ENC_BATCH_KEY_SIZE = 6: * MAX_AES_ENC_BATCH_KEY_SIZE = 6: data: [10 11 12
* data: [10 11 12 13 14 15 16] * 13 14 15 16] encKey: [...][0 1 2 3 4 5][0 1 2 3 4 5] so
* encKey: [...][0 1 2 3 4 5][0 1 2 3 4 5] * the 10th data byte is encoded with the 4th byte of the 2nd
* so the 10th data byte is encoded with the 4th byte of the 2nd enc_key etc. * enc_key etc. We need this shift so each byte will be coded the
* We need this shift so each byte will be coded the same despite * same despite the initial offset. Let's see the same data but
* the initial offset. * sent to the func starting from the offset 0: data: [0 1 2 3
* Let's see the same data but sent to the func starting from the offset 0: * 4 5 6 7 8 9 10 11 12 13 14 15 16] encKey: [0 1 2 3 4 5][0 1 2 3
* data: [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16] * 4 5][ 0 1 2 3 4 5] again, the 10th data byte is encoded
* encKey: [0 1 2 3 4 5][0 1 2 3 4 5][ 0 1 2 3 4 5] * with the 4th byte of the 2nd enc_key etc.
* again, the 10th data byte is encoded with the 4th byte of the 2nd enc_key etc.
*/ */
uint32 enc_key_index = i + (batch_no > 0 ? 0 : aes_block_no); uint32 enc_key_index = i + (batch_no > 0 ? 0 : aes_block_no);
out[data_index] = data[data_index] ^ enc_key[enc_key_index]; out[data_index] = data[data_index] ^ enc_key[enc_key_index];
data_index++; data_index++;
@ -152,12 +159,13 @@ pg_tde_crypt_complex(const char* iv_prefix, uint32 start_offset, const char* dat
* This function simply selects between the two above variations based on the data length * This function simply selects between the two above variations based on the data length
*/ */
void void
pg_tde_crypt(const char* iv_prefix, uint32 start_offset, const char* data, uint32 data_len, char* out, RelKeyData* key, const char* context) pg_tde_crypt(const char *iv_prefix, uint32 start_offset, const char *data, uint32 data_len, char *out, RelKeyData *key, const char *context)
{ {
if(data_len >= DATA_BYTES_PER_AES_BATCH) if (data_len >= DATA_BYTES_PER_AES_BATCH)
{ {
pg_tde_crypt_complex(iv_prefix, start_offset, data, data_len, out, key, context); pg_tde_crypt_complex(iv_prefix, start_offset, data, data_len, out, key, context);
} else }
else
{ {
pg_tde_crypt_simple(iv_prefix, start_offset, data, data_len, out, key, context); pg_tde_crypt_simple(iv_prefix, start_offset, data, data_len, out, key, context);
} }
@ -172,28 +180,28 @@ pg_tde_crypt(const char* iv_prefix, uint32 start_offset, const char* data, uint3
* context: Optional context message to be used in debug log * context: Optional context message to be used in debug log
* */ * */
void void
pg_tde_crypt_tuple(HeapTuple tuple, HeapTuple out_tuple, RelKeyData* key, const char* context) pg_tde_crypt_tuple(HeapTuple tuple, HeapTuple out_tuple, RelKeyData *key, const char *context)
{ {
char iv_prefix[16] = {0}; char iv_prefix[16] = {0};
uint32 data_len = tuple->t_len - tuple->t_data->t_hoff; uint32 data_len = tuple->t_len - tuple->t_data->t_hoff;
char *tup_data = (char*)tuple->t_data + tuple->t_data->t_hoff; char *tup_data = (char *) tuple->t_data + tuple->t_data->t_hoff;
char *out_data = (char*)out_tuple->t_data + out_tuple->t_data->t_hoff; char *out_data = (char *) out_tuple->t_data + out_tuple->t_data->t_hoff;
SetIVPrefix(&tuple->t_self, iv_prefix); SetIVPrefix(&tuple->t_self, iv_prefix);
#ifdef ENCRYPTION_DEBUG #ifdef ENCRYPTION_DEBUG
ereport(LOG, ereport(LOG,
(errmsg("%s: table Oid: %u data size: %u", (errmsg("%s: table Oid: %u data size: %u",
context?context:"", tuple->t_tableOid, context ? context : "", tuple->t_tableOid,
data_len))); data_len)));
#endif #endif
pg_tde_crypt(iv_prefix, 0, tup_data, data_len, out_data, key, context); pg_tde_crypt(iv_prefix, 0, tup_data, data_len, out_data, key, context);
} }
// ================================================================ /* ================================================================ */
// HELPER FUNCTIONS FOR ENCRYPTION /* HELPER FUNCTIONS FOR ENCRYPTION */
// ================================================================ /* ================================================================ */
OffsetNumber OffsetNumber
PGTdePageAddItemExtended(RelFileLocator rel, PGTdePageAddItemExtended(RelFileLocator rel,
@ -205,13 +213,14 @@ PGTdePageAddItemExtended(RelFileLocator rel,
OffsetNumber offsetNumber, OffsetNumber offsetNumber,
int flags) int flags)
{ {
OffsetNumber off = PageAddItemExtended(page,item,size,offsetNumber,flags); OffsetNumber off = PageAddItemExtended(page, item, size, offsetNumber, flags);
PageHeader phdr = (PageHeader) page; PageHeader phdr = (PageHeader) page;
unsigned long header_size = ((HeapTupleHeader)item)->t_hoff; unsigned long header_size = ((HeapTupleHeader) item)->t_hoff;
char iv_prefix[16] = {0,}; char iv_prefix[16] = {0,};
char* toAddr = ((char*)phdr) + phdr->pd_upper + header_size; char *toAddr = ((char *) phdr) + phdr->pd_upper + header_size;
char* data = item + header_size; char *data = item + header_size;
uint32 data_len = size - header_size; uint32 data_len = size - header_size;
/* ctid stored in item is incorrect (not set) at this point */ /* ctid stored in item is incorrect (not set) at this point */
ItemPointerData ip; ItemPointerData ip;
RelKeyData *key = GetHeapBaiscRelationKey(rel); RelKeyData *key = GetHeapBaiscRelationKey(rel);
@ -234,7 +243,7 @@ PGTdePageAddItemExtended(RelFileLocator rel,
void void
AesEncryptKey(const TDEPrincipalKey *principal_key, const RelFileLocator *rlocator, RelKeyData *rel_key_data, RelKeyData **p_enc_rel_key_data, size_t *enc_key_bytes) AesEncryptKey(const TDEPrincipalKey *principal_key, const RelFileLocator *rlocator, RelKeyData *rel_key_data, RelKeyData **p_enc_rel_key_data, size_t *enc_key_bytes)
{ {
unsigned char iv[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; unsigned char iv[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
/* Ensure we are getting a valid pointer here */ /* Ensure we are getting a valid pointer here */
Assert(principal_key); Assert(principal_key);
@ -245,7 +254,7 @@ AesEncryptKey(const TDEPrincipalKey *principal_key, const RelFileLocator *rlocat
*p_enc_rel_key_data = (RelKeyData *) palloc(sizeof(RelKeyData)); *p_enc_rel_key_data = (RelKeyData *) palloc(sizeof(RelKeyData));
memcpy(*p_enc_rel_key_data, rel_key_data, sizeof(RelKeyData)); memcpy(*p_enc_rel_key_data, rel_key_data, sizeof(RelKeyData));
AesEncrypt(principal_key->keyData, iv, ((unsigned char*)&rel_key_data->internal_key), INTERNAL_KEY_LEN, ((unsigned char *)&(*p_enc_rel_key_data)->internal_key), (int *)enc_key_bytes); AesEncrypt(principal_key->keyData, iv, ((unsigned char *) &rel_key_data->internal_key), INTERNAL_KEY_LEN, ((unsigned char *) &(*p_enc_rel_key_data)->internal_key), (int *) enc_key_bytes);
} }
#endif /* FRONTEND */ #endif /* FRONTEND */
@ -257,9 +266,10 @@ AesEncryptKey(const TDEPrincipalKey *principal_key, const RelFileLocator *rlocat
* to note that memory is allocated in the TopMemoryContext so we expect this to be added * to note that memory is allocated in the TopMemoryContext so we expect this to be added
* to our key cache. * to our key cache.
*/ */
void AesDecryptKey(const TDEPrincipalKey *principal_key, const RelFileLocator *rlocator, RelKeyData **p_rel_key_data, RelKeyData *enc_rel_key_data, size_t *key_bytes) void
AesDecryptKey(const TDEPrincipalKey *principal_key, const RelFileLocator *rlocator, RelKeyData **p_rel_key_data, RelKeyData *enc_rel_key_data, size_t *key_bytes)
{ {
unsigned char iv[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; unsigned char iv[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
/* Ensure we are getting a valid pointer here */ /* Ensure we are getting a valid pointer here */
Assert(principal_key); Assert(principal_key);
@ -283,5 +293,5 @@ void AesDecryptKey(const TDEPrincipalKey *principal_key, const RelFileLocator *r
memcpy(*p_rel_key_data, enc_rel_key_data, sizeof(RelKeyData)); memcpy(*p_rel_key_data, enc_rel_key_data, sizeof(RelKeyData));
(*p_rel_key_data)->internal_key.ctx = NULL; (*p_rel_key_data)->internal_key.ctx = NULL;
AesDecrypt(principal_key->keyData, iv, ((unsigned char*) &enc_rel_key_data->internal_key), INTERNAL_KEY_LEN, ((unsigned char *)&(*p_rel_key_data)->internal_key) , (int *)key_bytes); AesDecrypt(principal_key->keyData, iv, ((unsigned char *) &enc_rel_key_data->internal_key), INTERNAL_KEY_LEN, ((unsigned char *) &(*p_rel_key_data)->internal_key), (int *) key_bytes);
} }

@ -76,8 +76,8 @@ extern bool pg_tde_move_rel_key(const RelFileLocator *newrlocator, const RelFile
extern void pg_tde_set_db_file_paths(Oid dbOid, Oid spcOid, char *map_path, char *keydata_path); extern void pg_tde_set_db_file_paths(Oid dbOid, Oid spcOid, char *map_path, char *keydata_path);
const char * tde_sprint_key(InternalKey *k); const char *tde_sprint_key(InternalKey *k);
extern RelKeyData *pg_tde_put_key_into_cache(RelFileNumber rel_num, RelKeyData *key); extern RelKeyData *pg_tde_put_key_into_cache(RelFileNumber rel_num, RelKeyData *key);
#endif /*PG_TDE_MAP_H*/ #endif /* PG_TDE_MAP_H */

@ -22,7 +22,8 @@
#define FILE_KEYRING_TYPE "file" #define FILE_KEYRING_TYPE "file"
#define VAULTV2_KEYRING_TYPE "vault-v2" #define VAULTV2_KEYRING_TYPE "vault-v2"
#define MAX_PROVIDER_NAME_LEN 128 /* pg_tde_key_provider's provider_name size*/ #define MAX_PROVIDER_NAME_LEN 128 /* pg_tde_key_provider's provider_name
* size */
#define MAX_VAULT_V2_KEY_LEN 128 /* From hashi corp docs */ #define MAX_VAULT_V2_KEY_LEN 128 /* From hashi corp docs */
#define MAX_KEYRING_OPTION_LEN 1024 #define MAX_KEYRING_OPTION_LEN 1024
typedef enum ProviderType typedef enum ProviderType
@ -38,7 +39,7 @@ typedef struct GenericKeyring
ProviderType type; /* Must be the first field */ ProviderType type; /* Must be the first field */
Oid key_id; Oid key_id;
char provider_name[MAX_PROVIDER_NAME_LEN]; char provider_name[MAX_PROVIDER_NAME_LEN];
char options[MAX_KEYRING_OPTION_LEN]; /* User provided options string*/ char options[MAX_KEYRING_OPTION_LEN]; /* User provided options string */
} GenericKeyring; } GenericKeyring;
typedef struct FileKeyring typedef struct FileKeyring
@ -88,4 +89,4 @@ extern uint32 redo_key_provider_info(KeyringProviderXLRecord *xlrec);
extern bool ParseKeyringJSONOptions(ProviderType provider_type, void *out_opts, extern bool ParseKeyringJSONOptions(ProviderType provider_type, void *out_opts,
char *in_buf, int buf_len); char *in_buf, int buf_len);
#endif /*TDE_KEYRING_H*/ #endif /* TDE_KEYRING_H */

@ -62,9 +62,9 @@ extern void cleanup_principal_key_info(Oid databaseId, Oid tablespaceId);
#ifndef FRONTEND #ifndef FRONTEND
extern LWLock *tde_lwlock_enc_keys(void); extern LWLock *tde_lwlock_enc_keys(void);
extern TDEPrincipalKey* GetPrincipalKey(Oid dbOid, Oid spcOid, LWLockMode lockMode); extern TDEPrincipalKey *GetPrincipalKey(Oid dbOid, Oid spcOid, LWLockMode lockMode);
#else #else
extern TDEPrincipalKey* GetPrincipalKey(Oid dbOid, Oid spcOid, void *lockMode); extern TDEPrincipalKey *GetPrincipalKey(Oid dbOid, Oid spcOid, void *lockMode);
#endif #endif
extern bool save_principal_key_info(TDEPrincipalKeyInfo *principalKeyInfo); extern bool save_principal_key_info(TDEPrincipalKeyInfo *principalKeyInfo);
@ -74,4 +74,4 @@ extern bool SetPrincipalKey(const char *key_name, const char *provider_name, boo
extern bool RotatePrincipalKey(TDEPrincipalKey *current_key, const char *new_key_name, const char *new_provider_name, bool ensure_new_key); extern bool RotatePrincipalKey(TDEPrincipalKey *current_key, const char *new_key_name, const char *new_provider_name, bool ensure_new_key);
extern bool xl_tde_perform_rotate_key(XLogPrincipalKeyRotate *xlrec); extern bool xl_tde_perform_rotate_key(XLogPrincipalKeyRotate *xlrec);
#endif /*PG_TDE_PRINCIPAL_KEY_H*/ #endif /* PG_TDE_PRINCIPAL_KEY_H */

@ -27,28 +27,31 @@ typedef enum
typedef struct TDEShmemSetupRoutine typedef struct TDEShmemSetupRoutine
{ {
/* init_shared_state gets called at the time of extension load /*
* you can initialize the data structures required to be placed in * init_shared_state gets called at the time of extension load you can
* shared memory in this callback * initialize the data structures required to be placed in shared memory
* The callback must return the size of the shared memory area acquired. * in this callback The callback must return the size of the shared memory
* The argument to the function is the start of the shared memory address * area acquired. The argument to the function is the start of the shared
* that can be used to store the shared data structures. * memory address that can be used to store the shared data structures.
*/ */
Size (*init_shared_state)(void *raw_dsa_area); Size (*init_shared_state) (void *raw_dsa_area);
/* /*
* shmem_startup gets called at the time of postmaster shutdown * shmem_startup gets called at the time of postmaster shutdown
*/ */
void (*shmem_kill)(int code, Datum arg); void (*shmem_kill) (int code, Datum arg);
/* /*
* The callback must return the size of the shared memory acquired. * The callback must return the size of the shared memory acquired.
*/ */
Size (*required_shared_mem_size)(void); Size (*required_shared_mem_size) (void);
/* /*
* Gets called after all shared memory structures are initialized and * Gets called after all shared memory structures are initialized and here
* here you can create shared memory hash tables or any other shared * you can create shared memory hash tables or any other shared objects
* objects that needs to live in DSA area. * that needs to live in DSA area.
*/ */
void (*init_dsa_area_objects)(dsa_area *dsa, void *raw_dsa_area); void (*init_dsa_area_objects) (dsa_area *dsa, void *raw_dsa_area);
} TDEShmemSetupRoutine; } TDEShmemSetupRoutine;
/* Interface to register the shared memory requests */ /* Interface to register the shared memory requests */
@ -57,4 +60,4 @@ extern void TdeShmemInit(void);
extern Size TdeRequiredSharedMemorySize(void); extern Size TdeRequiredSharedMemorySize(void);
extern int TdeRequiredLocksCount(void); extern int TdeRequiredLocksCount(void);
#endif /*PG_TDE_SHMEM_H*/ #endif /* PG_TDE_SHMEM_H */

@ -21,4 +21,4 @@ extern int get_tde_tables_count(void);
extern char *pg_tde_get_tde_file_dir(Oid dbOid, Oid spcOid); extern char *pg_tde_get_tde_file_dir(Oid dbOid, Oid spcOid);
extern void pg_tde_set_globalspace_dir(const char *dir); extern void pg_tde_set_globalspace_dir(const char *dir);
#endif /*PG_TDE_UTILS_H*/ #endif /* PG_TDE_UTILS_H */

@ -17,10 +17,10 @@
#define DATA_BYTES_PER_AES_BATCH (NUM_AES_BLOCKS_IN_BATCH * AES_BLOCK_SIZE) #define DATA_BYTES_PER_AES_BATCH (NUM_AES_BLOCKS_IN_BATCH * AES_BLOCK_SIZE)
void AesInit(void); void AesInit(void);
extern void Aes128EncryptedZeroBlocks(void* ctxPtr, const unsigned char* key, const char* iv_prefix, uint64_t blockNumber1, uint64_t blockNumber2, unsigned char* out); extern void Aes128EncryptedZeroBlocks(void *ctxPtr, const unsigned char *key, const char *iv_prefix, uint64_t blockNumber1, uint64_t blockNumber2, unsigned char *out);
/* Only used for testing */ /* Only used for testing */
extern void AesEncrypt(const unsigned char* key, const unsigned char* iv, const unsigned char* in, int in_len, unsigned char* out, int* out_len); extern void AesEncrypt(const unsigned char *key, const unsigned char *iv, const unsigned char *in, int in_len, unsigned char *out, int *out_len);
extern void AesDecrypt(const unsigned char* key, const unsigned char* iv, const unsigned char* in, int in_len, unsigned char* out, int* out_len); extern void AesDecrypt(const unsigned char *key, const unsigned char *iv, const unsigned char *in, int in_len, unsigned char *out, int *out_len);
#endif /*ENC_AES_H*/ #endif /* ENC_AES_H */

@ -18,13 +18,13 @@
#include "keyring/keyring_api.h" #include "keyring/keyring_api.h"
extern void extern void
pg_tde_crypt(const char* iv_prefix, uint32 start_offset, const char* data, uint32 data_len, char* out, RelKeyData* key, const char* context); pg_tde_crypt(const char *iv_prefix, uint32 start_offset, const char *data, uint32 data_len, char *out, RelKeyData *key, const char *context);
extern void extern void
pg_tde_crypt_tuple(HeapTuple tuple, HeapTuple out_tuple, RelKeyData* key, const char* context); pg_tde_crypt_tuple(HeapTuple tuple, HeapTuple out_tuple, RelKeyData *key, const char *context);
/* A wrapper to encrypt a tuple before adding it to the buffer */ /* A wrapper to encrypt a tuple before adding it to the buffer */
extern OffsetNumber extern OffsetNumber
PGTdePageAddItemExtended(RelFileLocator rel, Oid oid, BlockNumber bn, Page page, PGTdePageAddItemExtended(RelFileLocator rel, Oid oid, BlockNumber bn, Page page,
Item item, Item item,
Size size, Size size,
OffsetNumber offsetNumber, OffsetNumber offsetNumber,
@ -55,4 +55,4 @@ PGTdePageAddItemExtended(RelFileLocator rel, Oid oid, BlockNumber bn, Page page,
extern void AesEncryptKey(const TDEPrincipalKey *principal_key, const RelFileLocator *rlocator, RelKeyData *rel_key_data, RelKeyData **p_enc_rel_key_data, size_t *enc_key_bytes); extern void AesEncryptKey(const TDEPrincipalKey *principal_key, const RelFileLocator *rlocator, RelKeyData *rel_key_data, RelKeyData **p_enc_rel_key_data, size_t *enc_key_bytes);
extern void AesDecryptKey(const TDEPrincipalKey *principal_key, const RelFileLocator *rlocator, RelKeyData **p_rel_key_data, RelKeyData *enc_rel_key_data, size_t *key_bytes); extern void AesDecryptKey(const TDEPrincipalKey *principal_key, const RelFileLocator *rlocator, RelKeyData **p_rel_key_data, RelKeyData *enc_rel_key_data, size_t *key_bytes);
#endif /*ENC_TDE_H*/ #endif /* ENC_TDE_H */

@ -46,14 +46,14 @@ typedef enum KeyringReturnCodes
typedef struct TDEKeyringRoutine typedef struct TDEKeyringRoutine
{ {
keyInfo *(*keyring_get_key)(GenericKeyring *keyring, const char *key_name, bool throw_error, KeyringReturnCodes *returnCode); keyInfo *(*keyring_get_key) (GenericKeyring *keyring, const char *key_name, bool throw_error, KeyringReturnCodes * returnCode);
KeyringReturnCodes (*keyring_store_key)(GenericKeyring *keyring, keyInfo *key, bool throw_error); KeyringReturnCodes(*keyring_store_key) (GenericKeyring *keyring, keyInfo *key, bool throw_error);
} TDEKeyringRoutine; } TDEKeyringRoutine;
extern bool RegisterKeyProvider(const TDEKeyringRoutine *routine, ProviderType type); extern bool RegisterKeyProvider(const TDEKeyringRoutine *routine, ProviderType type);
extern KeyringReturnCodes KeyringStoreKey(GenericKeyring *keyring, keyInfo *key, bool throw_error); extern KeyringReturnCodes KeyringStoreKey(GenericKeyring *keyring, keyInfo *key, bool throw_error);
extern keyInfo *KeyringGetKey(GenericKeyring *keyring, const char *key_name, bool throw_error, KeyringReturnCodes *returnCode); extern keyInfo *KeyringGetKey(GenericKeyring *keyring, const char *key_name, bool throw_error, KeyringReturnCodes * returnCode);
extern keyInfo *KeyringGenerateNewKeyAndStore(GenericKeyring *keyring, const char *key_name, unsigned key_len, bool throw_error); extern keyInfo *KeyringGenerateNewKeyAndStore(GenericKeyring *keyring, const char *key_name, unsigned key_len, bool throw_error);
extern keyInfo *KeyringGenerateNewKey(const char *key_name, unsigned key_len); extern keyInfo *KeyringGenerateNewKey(const char *key_name, unsigned key_len);

@ -19,13 +19,14 @@
#include <stdbool.h> #include <stdbool.h>
#include <curl/curl.h> #include <curl/curl.h>
typedef struct CurlString { typedef struct CurlString
{
char *ptr; char *ptr;
size_t len; size_t len;
} CurlString; } CurlString;
extern CURL* keyringCurl; extern CURL * keyringCurl;
bool curlSetupSession(const char* url, const char* caFile, CurlString* outStr); bool curlSetupSession(const char *url, const char *caFile, CurlString *outStr);
#endif //KEYRING_CURL_H #endif /* //KEYRING_CURL_H */

@ -14,4 +14,4 @@
extern bool InstallFileKeyring(void); extern bool InstallFileKeyring(void);
#endif /*KEYRING_FILE_H*/ #endif /* KEYRING_FILE_H */

@ -14,4 +14,4 @@
extern bool InstallVaultV2Keyring(void); extern bool InstallVaultV2Keyring(void);
#endif // KEYRING_FILE_H #endif /* KEYRING_FILE_H */

@ -14,9 +14,9 @@ typedef struct XLogExtensionInstall
Oid tablespace_id; Oid tablespace_id;
} XLogExtensionInstall; } XLogExtensionInstall;
typedef void (*pg_tde_on_ext_install_callback)(int tde_tbl_count, XLogExtensionInstall* ext_info, bool redo, void *arg); typedef void (*pg_tde_on_ext_install_callback) (int tde_tbl_count, XLogExtensionInstall *ext_info, bool redo, void *arg);
extern void on_ext_install(pg_tde_on_ext_install_callback function, void* arg); extern void on_ext_install(pg_tde_on_ext_install_callback function, void *arg);
extern void extension_install_redo(XLogExtensionInstall *xlrec); extern void extension_install_redo(XLogExtensionInstall *xlrec);
#endif /*PG_TDE_H*/ #endif /* PG_TDE_H */

@ -19,10 +19,10 @@
* ---------- * ----------
*/ */
//#define ENCRYPTION_DEBUG 1 /* #define ENCRYPTION_DEBUG 1 */
//#define KEYRING_DEBUG 1 /* #define KEYRING_DEBUG 1 */
//#define TDE_FORK_DEBUG 1 /* #define TDE_FORK_DEBUG 1 */
// #define TDE_XLOG_DEBUG 1 /* #define TDE_XLOG_DEBUG 1 */
#define tdeheap_fill_tuple heap_fill_tuple #define tdeheap_fill_tuple heap_fill_tuple
#define tdeheap_form_tuple heap_form_tuple #define tdeheap_form_tuple heap_form_tuple

@ -13,4 +13,4 @@ extern const char *pg_tde_package_string(void);
extern const char *pg_tde_package_name(void); extern const char *pg_tde_package_name(void);
extern const char *pg_tde_package_version(void); extern const char *pg_tde_package_version(void);
#endif /*PG_TDE_DEFS_H*/ #endif /* PG_TDE_DEFS_H */

@ -28,6 +28,6 @@ typedef struct TdeCreateEvent
* create statement */ * create statement */
} TdeCreateEvent; } TdeCreateEvent;
extern TdeCreateEvent * GetCurrentTdeCreateEvent(void); extern TdeCreateEvent *GetCurrentTdeCreateEvent(void);
#endif #endif

@ -34,9 +34,11 @@ static KeyProviders *
find_key_provider(ProviderType type) find_key_provider(ProviderType type)
{ {
ListCell *lc; ListCell *lc;
foreach (lc, registeredKeyProviders)
foreach(lc, registeredKeyProviders)
{ {
KeyProviders *kp = (KeyProviders *)lfirst(lc); KeyProviders *kp = (KeyProviders *) lfirst(lc);
if (kp->type == type) if (kp->type == type)
{ {
return kp; return kp;
@ -49,9 +51,11 @@ static KeyProviders *
find_key_provider(ProviderType type) find_key_provider(ProviderType type)
{ {
SimplePtrListCell *lc; SimplePtrListCell *lc;
for (lc = registeredKeyProviders.head; lc; lc = lc->next) for (lc = registeredKeyProviders.head; lc; lc = lc->next)
{ {
KeyProviders *kp = (KeyProviders *) lc->ptr; KeyProviders *kp = (KeyProviders *) lc->ptr;
if (kp->type == type) if (kp->type == type)
{ {
return kp; return kp;
@ -61,7 +65,8 @@ find_key_provider(ProviderType type)
} }
#endif /* !FRONTEND */ #endif /* !FRONTEND */
bool RegisterKeyProvider(const TDEKeyringRoutine *routine, ProviderType type) bool
RegisterKeyProvider(const TDEKeyringRoutine *routine, ProviderType type)
{ {
KeyProviders *kp; KeyProviders *kp;
@ -79,10 +84,11 @@ bool RegisterKeyProvider(const TDEKeyringRoutine *routine, ProviderType type)
#ifndef FRONTEND #ifndef FRONTEND
MemoryContext oldcontext; MemoryContext oldcontext;
oldcontext = MemoryContextSwitchTo(TopMemoryContext); oldcontext = MemoryContextSwitchTo(TopMemoryContext);
#endif #endif
kp = palloc(sizeof(KeyProviders)); kp = palloc(sizeof(KeyProviders));
kp->routine = (TDEKeyringRoutine *)routine; kp->routine = (TDEKeyringRoutine *) routine;
kp->type = type; kp->type = type;
#ifndef FRONTEND #ifndef FRONTEND
registeredKeyProviders = lappend(registeredKeyProviders, kp); registeredKeyProviders = lappend(registeredKeyProviders, kp);
@ -95,9 +101,10 @@ bool RegisterKeyProvider(const TDEKeyringRoutine *routine, ProviderType type)
} }
keyInfo * keyInfo *
KeyringGetKey(GenericKeyring *keyring, const char *key_name, bool throw_error, KeyringReturnCodes *returnCode) KeyringGetKey(GenericKeyring *keyring, const char *key_name, bool throw_error, KeyringReturnCodes * returnCode)
{ {
KeyProviders *kp = find_key_provider(keyring->type); KeyProviders *kp = find_key_provider(keyring->type);
if (kp == NULL) if (kp == NULL)
{ {
ereport(throw_error ? ERROR : WARNING, ereport(throw_error ? ERROR : WARNING,
@ -112,6 +119,7 @@ KeyringReturnCodes
KeyringStoreKey(GenericKeyring *keyring, keyInfo *key, bool throw_error) KeyringStoreKey(GenericKeyring *keyring, keyInfo *key, bool throw_error)
{ {
KeyProviders *kp = find_key_provider(keyring->type); KeyProviders *kp = find_key_provider(keyring->type);
if (kp == NULL) if (kp == NULL)
{ {
ereport(throw_error ? ERROR : WARNING, ereport(throw_error ? ERROR : WARNING,
@ -125,13 +133,14 @@ keyInfo *
KeyringGenerateNewKey(const char *key_name, unsigned key_len) KeyringGenerateNewKey(const char *key_name, unsigned key_len)
{ {
keyInfo *key; keyInfo *key;
Assert(key_len <= 32); Assert(key_len <= 32);
key = palloc(sizeof(keyInfo)); key = palloc(sizeof(keyInfo));
key->data.len = key_len; key->data.len = key_len;
if (!RAND_bytes(key->data.data, key_len)) if (!RAND_bytes(key->data.data, key_len))
{ {
pfree(key); pfree(key);
return NULL; /*openssl error*/ return NULL; /* openssl error */
} }
strncpy(key->name.name, key_name, sizeof(key->name.name)); strncpy(key->name.name, key_name, sizeof(key->name.name));
return key; return key;
@ -141,6 +150,7 @@ keyInfo *
KeyringGenerateNewKeyAndStore(GenericKeyring *keyring, const char *key_name, unsigned key_len, bool throw_error) KeyringGenerateNewKeyAndStore(GenericKeyring *keyring, const char *key_name, unsigned key_len, bool throw_error)
{ {
keyInfo *key = KeyringGenerateNewKey(key_name, key_len); keyInfo *key = KeyringGenerateNewKey(key_name, key_len);
if (key == NULL) if (key == NULL)
{ {
ereport(throw_error ? ERROR : WARNING, ereport(throw_error ? ERROR : WARNING,

@ -14,50 +14,69 @@
#include "keyring/keyring_curl.h" #include "keyring/keyring_curl.h"
#include "pg_tde_defines.h" #include "pg_tde_defines.h"
CURL* keyringCurl = NULL; CURL *keyringCurl = NULL;
static static
size_t write_func(void *ptr, size_t size, size_t nmemb, struct CurlString *s) size_t
write_func(void *ptr, size_t size, size_t nmemb, struct CurlString *s)
{ {
size_t new_len = s->len + size*nmemb; size_t new_len = s->len + size * nmemb;
s->ptr = repalloc(s->ptr, new_len+1);
if (s->ptr == NULL) { s->ptr = repalloc(s->ptr, new_len + 1);
if (s->ptr == NULL)
{
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
memcpy(s->ptr+s->len, ptr, size*nmemb); memcpy(s->ptr + s->len, ptr, size * nmemb);
s->ptr[new_len] = '\0'; s->ptr[new_len] = '\0';
s->len = new_len; s->len = new_len;
return size*nmemb; return size * nmemb;
} }
bool curlSetupSession(const char* url, const char* caFile, CurlString* outStr) bool
curlSetupSession(const char *url, const char *caFile, CurlString *outStr)
{ {
if(keyringCurl == NULL) if (keyringCurl == NULL)
{ {
keyringCurl = curl_easy_init(); keyringCurl = curl_easy_init();
if(keyringCurl == NULL) return 0; if (keyringCurl == NULL)
} else { return 0;
}
else
{
curl_easy_reset(keyringCurl); curl_easy_reset(keyringCurl);
} }
if(curl_easy_setopt(keyringCurl, CURLOPT_SSL_VERIFYPEER, 1) != CURLE_OK) return 0; if (curl_easy_setopt(keyringCurl, CURLOPT_SSL_VERIFYPEER, 1) != CURLE_OK)
if(curl_easy_setopt(keyringCurl, CURLOPT_USE_SSL, CURLUSESSL_ALL) != CURLE_OK) return 0; return 0;
if(caFile != NULL && strlen(caFile) != 0) if (curl_easy_setopt(keyringCurl, CURLOPT_USE_SSL, CURLUSESSL_ALL) != CURLE_OK)
return 0;
if (caFile != NULL && strlen(caFile) != 0)
{ {
if(curl_easy_setopt(keyringCurl, CURLOPT_CAINFO, caFile) != CURLE_OK) return 0; if (curl_easy_setopt(keyringCurl, CURLOPT_CAINFO, caFile) != CURLE_OK)
return 0;
} }
if(curl_easy_setopt(keyringCurl, CURLOPT_FOLLOWLOCATION, 1L) != CURLE_OK) return 0; if (curl_easy_setopt(keyringCurl, CURLOPT_FOLLOWLOCATION, 1L) != CURLE_OK)
if(curl_easy_setopt(keyringCurl, CURLOPT_CONNECTTIMEOUT, 3) != CURLE_OK) return 0; return 0;
if(curl_easy_setopt(keyringCurl, CURLOPT_TIMEOUT, 10) != CURLE_OK) return 0; if (curl_easy_setopt(keyringCurl, CURLOPT_CONNECTTIMEOUT, 3) != CURLE_OK)
if(curl_easy_setopt(keyringCurl, CURLOPT_HTTP_VERSION,(long)CURL_HTTP_VERSION_1_1) != CURLE_OK) return 0; return 0;
if(curl_easy_setopt(keyringCurl, CURLOPT_WRITEFUNCTION,write_func) != CURLE_OK) return 0; if (curl_easy_setopt(keyringCurl, CURLOPT_TIMEOUT, 10) != CURLE_OK)
if(curl_easy_setopt(keyringCurl, CURLOPT_WRITEDATA,outStr) != CURLE_OK) return 0; return 0;
if(curl_easy_setopt(keyringCurl, CURLOPT_URL, url) != CURLE_OK) return 0; if (curl_easy_setopt(keyringCurl, CURLOPT_HTTP_VERSION, (long) CURL_HTTP_VERSION_1_1) != CURLE_OK)
return 0;
if(curl_easy_setopt(keyringCurl, CURLOPT_POSTFIELDS, NULL) != CURLE_OK) return 0; if (curl_easy_setopt(keyringCurl, CURLOPT_WRITEFUNCTION, write_func) != CURLE_OK)
if(curl_easy_setopt(keyringCurl, CURLOPT_POST, 0) != CURLE_OK) return 0; return 0;
if (curl_easy_setopt(keyringCurl, CURLOPT_WRITEDATA, outStr) != CURLE_OK)
return 0;
if (curl_easy_setopt(keyringCurl, CURLOPT_URL, url) != CURLE_OK)
return 0;
if (curl_easy_setopt(keyringCurl, CURLOPT_POSTFIELDS, NULL) != CURLE_OK)
return 0;
if (curl_easy_setopt(keyringCurl, CURLOPT_POST, 0) != CURLE_OK)
return 0;
return 1; return 1;
} }

@ -26,8 +26,8 @@
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
static keyInfo* get_key_by_name(GenericKeyring* keyring, const char* key_name, bool throw_error, KeyringReturnCodes *return_code); static keyInfo *get_key_by_name(GenericKeyring *keyring, const char *key_name, bool throw_error, KeyringReturnCodes * return_code);
static KeyringReturnCodes set_key_by_name(GenericKeyring* keyring, keyInfo *key, bool throw_error); static KeyringReturnCodes set_key_by_name(GenericKeyring *keyring, keyInfo *key, bool throw_error);
const TDEKeyringRoutine keyringFileRoutine = { const TDEKeyringRoutine keyringFileRoutine = {
.keyring_get_key = get_key_by_name, .keyring_get_key = get_key_by_name,
@ -41,12 +41,12 @@ InstallFileKeyring(void)
} }
static keyInfo* static keyInfo *
get_key_by_name(GenericKeyring* keyring, const char* key_name, bool throw_error, KeyringReturnCodes *return_code) get_key_by_name(GenericKeyring *keyring, const char *key_name, bool throw_error, KeyringReturnCodes * return_code)
{ {
keyInfo* key = NULL; keyInfo *key = NULL;
int fd = -1; int fd = -1;
FileKeyring* file_keyring = (FileKeyring*)keyring; FileKeyring *file_keyring = (FileKeyring *) keyring;
off_t bytes_read = 0; off_t bytes_read = 0;
off_t curr_pos = 0; off_t curr_pos = 0;
@ -57,15 +57,16 @@ get_key_by_name(GenericKeyring* keyring, const char* key_name, bool throw_error,
return NULL; return NULL;
key = palloc(sizeof(keyInfo)); key = palloc(sizeof(keyInfo));
while(true) while (true)
{ {
bytes_read = pg_pread(fd, key, sizeof(keyInfo), curr_pos); bytes_read = pg_pread(fd, key, sizeof(keyInfo), curr_pos);
curr_pos += bytes_read; curr_pos += bytes_read;
if (bytes_read == 0 ) if (bytes_read == 0)
{ {
/* /*
* Empty keyring file is considered as a valid keyring file that has no keys * Empty keyring file is considered as a valid keyring file that
* has no keys
*/ */
close(fd); close(fd);
pfree(key); pfree(key);
@ -77,7 +78,7 @@ get_key_by_name(GenericKeyring* keyring, const char* key_name, bool throw_error,
pfree(key); pfree(key);
/* Corrupt file */ /* Corrupt file */
*return_code = KEYRING_CODE_DATA_CORRUPTED; *return_code = KEYRING_CODE_DATA_CORRUPTED;
ereport(throw_error?ERROR:WARNING, ereport(throw_error ? ERROR : WARNING,
(errcode_for_file_access(), (errcode_for_file_access(),
errmsg("keyring file \"%s\" is corrupted: %m", errmsg("keyring file \"%s\" is corrupted: %m",
file_keyring->file_name), file_keyring->file_name),
@ -96,12 +97,12 @@ get_key_by_name(GenericKeyring* keyring, const char* key_name, bool throw_error,
} }
static KeyringReturnCodes static KeyringReturnCodes
set_key_by_name(GenericKeyring* keyring, keyInfo *key, bool throw_error) set_key_by_name(GenericKeyring *keyring, keyInfo *key, bool throw_error)
{ {
off_t bytes_written = 0; off_t bytes_written = 0;
off_t curr_pos = 0; off_t curr_pos = 0;
int fd; int fd;
FileKeyring* file_keyring = (FileKeyring*)keyring; FileKeyring *file_keyring = (FileKeyring *) keyring;
keyInfo *existing_key; keyInfo *existing_key;
KeyringReturnCodes return_code = KEYRING_CODE_SUCCESS; KeyringReturnCodes return_code = KEYRING_CODE_SUCCESS;
@ -119,7 +120,7 @@ set_key_by_name(GenericKeyring* keyring, keyInfo *key, bool throw_error)
fd = BasicOpenFile(file_keyring->file_name, O_CREAT | O_RDWR | PG_BINARY); fd = BasicOpenFile(file_keyring->file_name, O_CREAT | O_RDWR | PG_BINARY);
if (fd < 0) if (fd < 0)
{ {
ereport(throw_error?ERROR:WARNING, ereport(throw_error ? ERROR : WARNING,
(errcode_for_file_access(), (errcode_for_file_access(),
errmsg("Failed to open keyring file %s :%m", file_keyring->file_name))); errmsg("Failed to open keyring file %s :%m", file_keyring->file_name)));
return KEYRING_CODE_RESOURCE_NOT_ACCESSABLE; return KEYRING_CODE_RESOURCE_NOT_ACCESSABLE;
@ -130,7 +131,7 @@ set_key_by_name(GenericKeyring* keyring, keyInfo *key, bool throw_error)
if (bytes_written != sizeof(keyInfo)) if (bytes_written != sizeof(keyInfo))
{ {
close(fd); close(fd);
ereport(throw_error?ERROR:WARNING, ereport(throw_error ? ERROR : WARNING,
(errcode_for_file_access(), (errcode_for_file_access(),
errmsg("keyring file \"%s\" can't be written: %m", errmsg("keyring file \"%s\" can't be written: %m",
file_keyring->file_name))); file_keyring->file_name)));
@ -140,7 +141,7 @@ set_key_by_name(GenericKeyring* keyring, keyInfo *key, bool throw_error)
if (pg_fsync(fd) != 0) if (pg_fsync(fd) != 0)
{ {
close(fd); close(fd);
ereport(throw_error?ERROR:WARNING, ereport(throw_error ? ERROR : WARNING,
(errcode_for_file_access(), (errcode_for_file_access(),
errmsg("could not fsync file \"%s\": %m", errmsg("could not fsync file \"%s\": %m",
file_keyring->file_name))); file_keyring->file_name)));

@ -69,7 +69,7 @@ static char *get_keyring_vault_url(VaultV2Keyring *keyring, const char *key_name
static bool curl_perform(VaultV2Keyring *keyring, const char *url, CurlString *outStr, long *httpCode, const char *postData); static bool curl_perform(VaultV2Keyring *keyring, const char *url, CurlString *outStr, long *httpCode, const char *postData);
static KeyringReturnCodes set_key_by_name(GenericKeyring *keyring, keyInfo *key, bool throw_error); static KeyringReturnCodes set_key_by_name(GenericKeyring *keyring, keyInfo *key, bool throw_error);
static keyInfo *get_key_by_name(GenericKeyring *keyring, const char *key_name, bool throw_error, KeyringReturnCodes *return_code); static keyInfo *get_key_by_name(GenericKeyring *keyring, const char *key_name, bool throw_error, KeyringReturnCodes * return_code);
const TDEKeyringRoutine keyringVaultV2Routine = { const TDEKeyringRoutine keyringVaultV2Routine = {
.keyring_get_key = get_key_by_name, .keyring_get_key = get_key_by_name,
@ -77,7 +77,8 @@ const TDEKeyringRoutine keyringVaultV2Routine = {
}; };
bool InstallVaultV2Keyring(void) bool
InstallVaultV2Keyring(void)
{ {
return RegisterKeyProvider(&keyringVaultV2Routine, VAULT_V2_KEY_PROVIDER); return RegisterKeyProvider(&keyringVaultV2Routine, VAULT_V2_KEY_PROVIDER);
} }
@ -85,20 +86,24 @@ bool InstallVaultV2Keyring(void)
static bool static bool
curl_setup_token(VaultV2Keyring *keyring) curl_setup_token(VaultV2Keyring *keyring)
{ {
if(curlList == NULL) if (curlList == NULL)
{ {
char tokenHeader[256]; char tokenHeader[256];
strcpy(tokenHeader, "X-Vault-Token:"); strcpy(tokenHeader, "X-Vault-Token:");
strcat(tokenHeader, keyring->vault_token); strcat(tokenHeader, keyring->vault_token);
curlList = curl_slist_append(curlList, tokenHeader); curlList = curl_slist_append(curlList, tokenHeader);
if(curlList == NULL) return 0; if (curlList == NULL)
return 0;
curlList = curl_slist_append(curlList, "Content-Type: application/json"); curlList = curl_slist_append(curlList, "Content-Type: application/json");
if(curlList == NULL) return 0; if (curlList == NULL)
return 0;
} }
if(curl_easy_setopt(keyringCurl, CURLOPT_HTTPHEADER, curlList) != CURLE_OK) return 0; if (curl_easy_setopt(keyringCurl, CURLOPT_HTTPHEADER, curlList) != CURLE_OK)
return 0;
return 1; return 1;
} }
@ -109,7 +114,7 @@ curl_perform(VaultV2Keyring *keyring, const char *url, CurlString *outStr, long
CURLcode ret; CURLcode ret;
#if KEYRING_DEBUG #if KEYRING_DEBUG
elog(DEBUG1, "Performing Vault HTTP [%s] request to '%s'", postData != NULL ? "POST" : "GET", url); elog(DEBUG1, "Performing Vault HTTP [%s] request to '%s'", postData != NULL ? "POST" : "GET", url);
if(postData != NULL) if (postData != NULL)
{ {
elog(DEBUG2, "Postdata: '%s'", postData); elog(DEBUG2, "Postdata: '%s'", postData);
} }
@ -123,9 +128,10 @@ curl_perform(VaultV2Keyring *keyring, const char *url, CurlString *outStr, long
if (!curl_setup_token(keyring)) if (!curl_setup_token(keyring))
return 0; return 0;
if(postData != NULL) if (postData != NULL)
{ {
if(curl_easy_setopt(keyringCurl, CURLOPT_POSTFIELDS, postData) != CURLE_OK) return 0; if (curl_easy_setopt(keyringCurl, CURLOPT_POSTFIELDS, postData) != CURLE_OK)
return 0;
} }
ret = curl_easy_perform(keyringCurl); ret = curl_easy_perform(keyringCurl);
@ -135,7 +141,8 @@ curl_perform(VaultV2Keyring *keyring, const char *url, CurlString *outStr, long
return 0; return 0;
} }
if(curl_easy_getinfo(keyringCurl, CURLINFO_RESPONSE_CODE, httpCode) != CURLE_OK) return 0; if (curl_easy_getinfo(keyringCurl, CURLINFO_RESPONSE_CODE, httpCode) != CURLE_OK)
return 0;
#if KEYRING_DEBUG #if KEYRING_DEBUG
elog(DEBUG2, "Vault response [%li] '%s'", *httpCode, outStr->ptr != NULL ? outStr->ptr : ""); elog(DEBUG2, "Vault response [%li] '%s'", *httpCode, outStr->ptr != NULL ? outStr->ptr : "");
@ -160,9 +167,9 @@ get_keyring_vault_url(VaultV2Keyring *keyring, const char *key_name, char *out,
} }
static KeyringReturnCodes static KeyringReturnCodes
set_key_by_name(GenericKeyring* keyring, keyInfo *key, bool throw_error) set_key_by_name(GenericKeyring *keyring, keyInfo *key, bool throw_error)
{ {
VaultV2Keyring *vault_keyring = (VaultV2Keyring *)keyring; VaultV2Keyring *vault_keyring = (VaultV2Keyring *) keyring;
char url[VAULT_URL_MAX_LEN]; char url[VAULT_URL_MAX_LEN];
CurlString str; CurlString str;
long httpCode = 0; long httpCode = 0;
@ -172,9 +179,12 @@ set_key_by_name(GenericKeyring* keyring, keyInfo *key, bool throw_error)
Assert(key != NULL); Assert(key != NULL);
// Since we are only building a very limited JSON with a single base64 string, we build it by hand /*
// Simpler than using the limited pg json api * Since we are only building a very limited JSON with a single base64
keyLen = pg_b64_encode((char *)key->data.data, key->data.len, keyData, 64); * string, we build it by hand
*/
/* Simpler than using the limited pg json api */
keyLen = pg_b64_encode((char *) key->data.data, key->data.len, keyData, 64);
keyData[keyLen] = 0; keyData[keyLen] = 0;
snprintf(jsonText, 512, "{\"data\":{\"key\":\"%s\"}}", keyData); snprintf(jsonText, 512, "{\"data\":{\"key\":\"%s\"}}", keyData);
@ -207,10 +217,10 @@ set_key_by_name(GenericKeyring* keyring, keyInfo *key, bool throw_error)
} }
static keyInfo * static keyInfo *
get_key_by_name(GenericKeyring *keyring, const char *key_name, bool throw_error, KeyringReturnCodes *return_code) get_key_by_name(GenericKeyring *keyring, const char *key_name, bool throw_error, KeyringReturnCodes * return_code)
{ {
VaultV2Keyring *vault_keyring = (VaultV2Keyring *)keyring; VaultV2Keyring *vault_keyring = (VaultV2Keyring *) keyring;
keyInfo* key = NULL; keyInfo *key = NULL;
char url[VAULT_URL_MAX_LEN]; char url[VAULT_URL_MAX_LEN];
CurlString str; CurlString str;
long httpCode = 0; long httpCode = 0;
@ -218,7 +228,7 @@ get_key_by_name(GenericKeyring *keyring, const char *key_name, bool throw_error,
JsonLexContext *jlex = NULL; JsonLexContext *jlex = NULL;
JsonVaultRespState parse; JsonVaultRespState parse;
const char* responseKey; const char *responseKey;
*return_code = KEYRING_CODE_SUCCESS; *return_code = KEYRING_CODE_SUCCESS;
@ -271,7 +281,7 @@ get_key_by_name(GenericKeyring *keyring, const char *key_name, bool throw_error,
#endif #endif
key = palloc(sizeof(keyInfo)); key = palloc(sizeof(keyInfo));
key->data.len = pg_b64_decode(responseKey, strlen(responseKey), (char *)key->data.data, MAX_KEY_DATA_SIZE); key->data.len = pg_b64_decode(responseKey, strlen(responseKey), (char *) key->data.data, MAX_KEY_DATA_SIZE);
if (key->data.len > MAX_KEY_DATA_SIZE) if (key->data.len > MAX_KEY_DATA_SIZE)
{ {
@ -285,7 +295,7 @@ get_key_by_name(GenericKeyring *keyring, const char *key_name, bool throw_error,
} }
cleanup: cleanup:
if(str.ptr != NULL) if (str.ptr != NULL)
pfree(str.ptr); pfree(str.ptr);
#if PG_VERSION_NUM >= 170000 #if PG_VERSION_NUM >= 170000
if (jlex != NULL) if (jlex != NULL)

@ -45,7 +45,7 @@ PG_MODULE_MAGIC;
struct OnExtInstall struct OnExtInstall
{ {
pg_tde_on_ext_install_callback function; pg_tde_on_ext_install_callback function;
void* arg; void *arg;
}; };
static struct OnExtInstall on_ext_install_list[MAX_ON_INSTALLS]; static struct OnExtInstall on_ext_install_list[MAX_ON_INSTALLS];
@ -122,16 +122,22 @@ _PG_init(void)
RegisterStorageMgr(); RegisterStorageMgr();
} }
Datum pg_tde_extension_initialize(PG_FUNCTION_ARGS) Datum
pg_tde_extension_initialize(PG_FUNCTION_ARGS)
{ {
/* Initialize the TDE map */ /* Initialize the TDE map */
XLogExtensionInstall xlrec; XLogExtensionInstall xlrec;
xlrec.database_id = MyDatabaseId; xlrec.database_id = MyDatabaseId;
xlrec.tablespace_id = MyDatabaseTableSpace; xlrec.tablespace_id = MyDatabaseTableSpace;
run_extension_install_callbacks(&xlrec, false); run_extension_install_callbacks(&xlrec, false);
/* Also put this info in xlog, so we can replicate the same on the other side */
/*
* Also put this info in xlog, so we can replicate the same on the other
* side
*/
XLogBeginInsert(); XLogBeginInsert();
XLogRegisterData((char *)&xlrec, sizeof(XLogExtensionInstall)); XLogRegisterData((char *) &xlrec, sizeof(XLogExtensionInstall));
XLogInsert(RM_TDERMGR_ID, XLOG_TDE_EXTENSION_INSTALL_KEY); XLogInsert(RM_TDERMGR_ID, XLOG_TDE_EXTENSION_INSTALL_KEY);
PG_RETURN_NULL(); PG_RETURN_NULL();
@ -149,7 +155,8 @@ extension_install_redo(XLogExtensionInstall *xlrec)
* run at the time of pg_tde extension installs. * run at the time of pg_tde extension installs.
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void on_ext_install(pg_tde_on_ext_install_callback function, void *arg) void
on_ext_install(pg_tde_on_ext_install_callback function, void *arg)
{ {
if (on_ext_install_index >= MAX_ON_INSTALLS) if (on_ext_install_index >= MAX_ON_INSTALLS)
ereport(FATAL, ereport(FATAL,
@ -167,14 +174,14 @@ void on_ext_install(pg_tde_on_ext_install_callback function, void *arg)
* ------------------ * ------------------
*/ */
static void static void
run_extension_install_callbacks(XLogExtensionInstall* xlrec , bool redo) run_extension_install_callbacks(XLogExtensionInstall *xlrec, bool redo)
{ {
int i; int i;
int tde_table_count =0; int tde_table_count = 0;
/* /*
* Get the number of tde tables in this database * Get the number of tde tables in this database should always be zero.
* should always be zero. But still, it prevents * But still, it prevents the cleanup if someone explicitly calls this
* the cleanup if someone explicitly calls this
* function. * function.
*/ */
if (!redo) if (!redo)

@ -18,7 +18,7 @@
/* Returns package version */ /* Returns package version */
const char* const char *
pg_tde_package_string(void) pg_tde_package_string(void)
{ {
return PACKAGE_STRING; return PACKAGE_STRING;
@ -29,7 +29,7 @@ pg_tde_package_name(void)
{ {
return PACKAGE_NAME; return PACKAGE_NAME;
} }
const char* const char *
pg_tde_package_version(void) pg_tde_package_version(void)
{ {
return PACKAGE_VERSION; return PACKAGE_VERSION;

@ -101,7 +101,7 @@ pg_tde_ddl_command_start_capture(PG_FUNCTION_ARGS)
else if (IsA(parsetree, CreateStmt)) else if (IsA(parsetree, CreateStmt))
{ {
CreateStmt *stmt = (CreateStmt *) parsetree; CreateStmt *stmt = (CreateStmt *) parsetree;
TDEPrincipalKey * principal_key; TDEPrincipalKey *principal_key;
Oid tablespace_oid; Oid tablespace_oid;
tdeCurrentCreateEvent.eventType = TDE_TABLE_CREATE_EVENT; tdeCurrentCreateEvent.eventType = TDE_TABLE_CREATE_EVENT;
@ -110,12 +110,13 @@ pg_tde_ddl_command_start_capture(PG_FUNCTION_ARGS)
if (stmt->accessMethod && strcmp(stmt->accessMethod, "tde_heap") == 0) if (stmt->accessMethod && strcmp(stmt->accessMethod, "tde_heap") == 0)
{ {
tdeCurrentCreateEvent.encryptMode = true; tdeCurrentCreateEvent.encryptMode = true;
} else if ((stmt->accessMethod == NULL || stmt->accessMethod[0] ==0) && strcmp(default_table_access_method, "tde_heap") == 0) }
else if ((stmt->accessMethod == NULL || stmt->accessMethod[0] == 0) && strcmp(default_table_access_method, "tde_heap") == 0)
{ {
tdeCurrentCreateEvent.encryptMode = true; tdeCurrentCreateEvent.encryptMode = true;
} }
if(tdeCurrentCreateEvent.encryptMode) if (tdeCurrentCreateEvent.encryptMode)
{ {
tablespace_oid = stmt->tablespacename != NULL ? get_tablespace_oid(stmt->tablespacename, false) tablespace_oid = stmt->tablespacename != NULL ? get_tablespace_oid(stmt->tablespacename, false)
: MyDatabaseTableSpace; : MyDatabaseTableSpace;
@ -151,7 +152,10 @@ pg_tde_ddl_command_start_capture(PG_FUNCTION_ARGS)
} }
} }
// TODO: also check for tablespace change, if current or new AM is tde_heap! /*
* TODO: also check for tablespace change, if current or new AM is
* tde_heap!
*/
if (tdeCurrentCreateEvent.encryptMode) if (tdeCurrentCreateEvent.encryptMode)
{ {

@ -14,6 +14,7 @@ typedef struct TDESMgrRelationData
{ {
/* parent data */ /* parent data */
SMgrRelationData reln; SMgrRelationData reln;
/* /*
* for md.c; per-fork arrays of the number of open segments * for md.c; per-fork arrays of the number of open segments
* (md_num_open_segs) and the segments themselves (md_seg_fds). * (md_num_open_segs) and the segments themselves (md_seg_fds).
@ -25,7 +26,7 @@ typedef struct TDESMgrRelationData
RelKeyData relKey; RelKeyData relKey;
} TDESMgrRelationData; } TDESMgrRelationData;
typedef TDESMgrRelationData *TDESMgrRelation; typedef TDESMgrRelationData * TDESMgrRelation;
/* /*
* we only encrypt main and init forks * we only encrypt main and init forks
@ -36,48 +37,51 @@ tde_is_encryption_required(TDESMgrRelation tdereln, ForkNumber forknum)
return (tdereln->encrypted_relation && (forknum == MAIN_FORKNUM || forknum == INIT_FORKNUM)); return (tdereln->encrypted_relation && (forknum == MAIN_FORKNUM || forknum == INIT_FORKNUM));
} }
static RelKeyData* static RelKeyData *
tde_smgr_get_key(SMgrRelation reln) tde_smgr_get_key(SMgrRelation reln)
{ {
TdeCreateEvent *event; TdeCreateEvent *event;
RelKeyData *rkd; RelKeyData *rkd;
TDEPrincipalKey *pk; TDEPrincipalKey *pk;
if(IsCatalogRelationOid(reln->smgr_rlocator.locator.relNumber)) if (IsCatalogRelationOid(reln->smgr_rlocator.locator.relNumber))
{ {
// do not try to encrypt/decrypt catalog tables /* do not try to encrypt/decrypt catalog tables */
return NULL; return NULL;
} }
LWLockAcquire(tde_lwlock_enc_keys(), LW_SHARED); LWLockAcquire(tde_lwlock_enc_keys(), LW_SHARED);
pk = GetPrincipalKey(reln->smgr_rlocator.locator.dbOid, reln->smgr_rlocator.locator.spcOid, LW_SHARED); pk = GetPrincipalKey(reln->smgr_rlocator.locator.dbOid, reln->smgr_rlocator.locator.spcOid, LW_SHARED);
LWLockRelease(tde_lwlock_enc_keys()); LWLockRelease(tde_lwlock_enc_keys());
if(pk == NULL) if (pk == NULL)
{ {
return NULL; return NULL;
} }
event = GetCurrentTdeCreateEvent(); event = GetCurrentTdeCreateEvent();
// see if we have a key for the relation, and return if yes /* see if we have a key for the relation, and return if yes */
rkd = GetSMGRRelationKey(reln->smgr_rlocator.locator); rkd = GetSMGRRelationKey(reln->smgr_rlocator.locator);
if(rkd != NULL) if (rkd != NULL)
{ {
return rkd; return rkd;
} }
// if this is a CREATE TABLE, we have to generate the key /* if this is a CREATE TABLE, we have to generate the key */
if(event->encryptMode == true && event->eventType == TDE_TABLE_CREATE_EVENT) if (event->encryptMode == true && event->eventType == TDE_TABLE_CREATE_EVENT)
{ {
return pg_tde_create_smgr_key(&reln->smgr_rlocator.locator); return pg_tde_create_smgr_key(&reln->smgr_rlocator.locator);
} }
// if this is a CREATE INDEX, we have to load the key based on the table /* if this is a CREATE INDEX, we have to load the key based on the table */
if(event->encryptMode == true && event->eventType == TDE_INDEX_CREATE_EVENT) if (event->encryptMode == true && event->eventType == TDE_INDEX_CREATE_EVENT)
{ {
// For now keep it simple and create separate key for indexes /* For now keep it simple and create separate key for indexes */
// Later we might modify the map infrastructure to support the same keys /*
* Later we might modify the map infrastructure to support the same
* keys
*/
return pg_tde_create_smgr_key(&reln->smgr_rlocator.locator); return pg_tde_create_smgr_key(&reln->smgr_rlocator.locator);
} }
@ -88,7 +92,7 @@ static void
tde_mdwritev(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, tde_mdwritev(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
const void **buffers, BlockNumber nblocks, bool skipFsync) const void **buffers, BlockNumber nblocks, bool skipFsync)
{ {
TDESMgrRelation tdereln = (TDESMgrRelation)reln; TDESMgrRelation tdereln = (TDESMgrRelation) reln;
RelKeyData *rkd = &tdereln->relKey; RelKeyData *rkd = &tdereln->relKey;
if (!tde_is_encryption_required(tdereln, forknum)) if (!tde_is_encryption_required(tdereln, forknum))
@ -98,21 +102,23 @@ tde_mdwritev(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
else else
{ {
char *local_blocks = palloc(BLCKSZ * (nblocks + 1)); char *local_blocks = palloc(BLCKSZ * (nblocks + 1));
char *local_blocks_aligned = (char *)TYPEALIGN(PG_IO_ALIGN_SIZE, local_blocks); char *local_blocks_aligned = (char *) TYPEALIGN(PG_IO_ALIGN_SIZE, local_blocks);
const void **local_buffers = palloc(sizeof(void *) * nblocks); const void **local_buffers = palloc(sizeof(void *) * nblocks);
AesInit(); AesInit();
for(int i = 0; i < nblocks; ++i ) for (int i = 0; i < nblocks; ++i)
{ {
int out_len = BLCKSZ; int out_len = BLCKSZ;
local_buffers[i] = &local_blocks_aligned[i * BLCKSZ]; local_buffers[i] = &local_blocks_aligned[i * BLCKSZ];
BlockNumber bn = blocknum + i; BlockNumber bn = blocknum + i;
unsigned char iv[16] = {0,}; unsigned char iv[16] = {0,};
memcpy(iv+4, &bn, sizeof(BlockNumber));
AesEncrypt(rkd->internal_key.key, iv, ((char**)buffers)[i], BLCKSZ, local_buffers[i], &out_len); memcpy(iv + 4, &bn, sizeof(BlockNumber));
AesEncrypt(rkd->internal_key.key, iv, ((char **) buffers)[i], BLCKSZ, local_buffers[i], &out_len);
} }
mdwritev(reln, forknum, blocknum, mdwritev(reln, forknum, blocknum,
@ -127,7 +133,7 @@ static void
tde_mdextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, tde_mdextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
const void *buffer, bool skipFsync) const void *buffer, bool skipFsync)
{ {
TDESMgrRelation tdereln = (TDESMgrRelation)reln; TDESMgrRelation tdereln = (TDESMgrRelation) reln;
RelKeyData *rkd = &tdereln->relKey; RelKeyData *rkd = &tdereln->relKey;
if (!tde_is_encryption_required(tdereln, forknum)) if (!tde_is_encryption_required(tdereln, forknum))
@ -137,7 +143,7 @@ tde_mdextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
else else
{ {
char *local_blocks = palloc(BLCKSZ * (1 + 1)); char *local_blocks = palloc(BLCKSZ * (1 + 1));
char *local_blocks_aligned = (char *)TYPEALIGN(PG_IO_ALIGN_SIZE, local_blocks); char *local_blocks_aligned = (char *) TYPEALIGN(PG_IO_ALIGN_SIZE, local_blocks);
int out_len = BLCKSZ; int out_len = BLCKSZ;
unsigned char iv[16] = { unsigned char iv[16] = {
0, 0,
@ -146,7 +152,7 @@ tde_mdextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
AesInit(); AesInit();
memcpy(iv + 4, &blocknum, sizeof(BlockNumber)); memcpy(iv + 4, &blocknum, sizeof(BlockNumber));
AesEncrypt(rkd->internal_key.key, iv, ((char *)buffer), BLCKSZ, local_blocks_aligned, &out_len); AesEncrypt(rkd->internal_key.key, iv, ((char *) buffer), BLCKSZ, local_blocks_aligned, &out_len);
mdextend(reln, forknum, blocknum, local_blocks_aligned, skipFsync); mdextend(reln, forknum, blocknum, local_blocks_aligned, skipFsync);
@ -159,7 +165,7 @@ tde_mdreadv(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
void **buffers, BlockNumber nblocks) void **buffers, BlockNumber nblocks)
{ {
int out_len = BLCKSZ; int out_len = BLCKSZ;
TDESMgrRelation tdereln = (TDESMgrRelation)reln; TDESMgrRelation tdereln = (TDESMgrRelation) reln;
RelKeyData *rkd = &tdereln->relKey; RelKeyData *rkd = &tdereln->relKey;
mdreadv(reln, forknum, blocknum, buffers, nblocks); mdreadv(reln, forknum, blocknum, buffers, nblocks);
@ -169,42 +175,60 @@ tde_mdreadv(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
AesInit(); AesInit();
for(int i = 0; i < nblocks; ++i) for (int i = 0; i < nblocks; ++i)
{ {
bool allZero = true; bool allZero = true;
BlockNumber bn = blocknum + i; BlockNumber bn = blocknum + i;
unsigned char iv[16] = {0,}; unsigned char iv[16] = {0,};
for(int j = 0; j < 32; ++j) for (int j = 0; j < 32; ++j)
{ {
if(((char**)buffers)[i][j] != 0) if (((char **) buffers)[i][j] != 0)
{ {
// Postgres creates all zero blocks in an optimized route, which we do not try /*
// to encrypt. * Postgres creates all zero blocks in an optimized route,
// Instead we detect if a block is all zero at decryption time, and * which we do not try
// leave it as is. */
// This could be a security issue later, but it is a good first prototype /* to encrypt. */
/*
* Instead we detect if a block is all zero at decryption
* time, and
*/
/* leave it as is. */
/*
* This could be a security issue later, but it is a good
* first prototype
*/
allZero = false; allZero = false;
break; break;
} }
} }
if(allZero) if (allZero)
continue; continue;
memcpy(iv+4, &bn, sizeof(BlockNumber)); memcpy(iv + 4, &bn, sizeof(BlockNumber));
AesDecrypt(rkd->internal_key.key, iv, ((char **)buffers)[i], BLCKSZ, ((char **)buffers)[i], &out_len); AesDecrypt(rkd->internal_key.key, iv, ((char **) buffers)[i], BLCKSZ, ((char **) buffers)[i], &out_len);
} }
} }
static void static void
tde_mdcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo) tde_mdcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
{ {
TDESMgrRelation tdereln = (TDESMgrRelation)reln; TDESMgrRelation tdereln = (TDESMgrRelation) reln;
// This is the only function that gets called during actual CREATE TABLE/INDEX (EVENT TRIGGER)
// so we create the key here by loading it /*
// Later calls then decide to encrypt or not based on the existence of the key * This is the only function that gets called during actual CREATE
RelKeyData* key = tde_smgr_get_key(reln); * TABLE/INDEX (EVENT TRIGGER)
*/
/* so we create the key here by loading it */
/*
* Later calls then decide to encrypt or not based on the existence of the
* key
*/
RelKeyData *key = tde_smgr_get_key(reln);
if (key) if (key)
{ {
tdereln->encrypted_relation = true; tdereln->encrypted_relation = true;
@ -224,8 +248,9 @@ tde_mdcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
static void static void
tde_mdopen(SMgrRelation reln) tde_mdopen(SMgrRelation reln)
{ {
TDESMgrRelation tdereln = (TDESMgrRelation)reln; TDESMgrRelation tdereln = (TDESMgrRelation) reln;
RelKeyData *key = tde_smgr_get_key(reln); RelKeyData *key = tde_smgr_get_key(reln);
if (key) if (key)
{ {
tdereln->encrypted_relation = true; tdereln->encrypted_relation = true;
@ -260,16 +285,18 @@ static const struct f_smgr tde_smgr = {
.smgr_registersync = mdregistersync, .smgr_registersync = mdregistersync,
}; };
void RegisterStorageMgr(void) void
RegisterStorageMgr(void)
{ {
tde_smgr_id = smgr_register(&tde_smgr, sizeof(TDESMgrRelationData)); tde_smgr_id = smgr_register(&tde_smgr, sizeof(TDESMgrRelationData));
// TODO: figure out how this part should work in a real extension /* TODO: figure out how this part should work in a real extension */
storage_manager_id = tde_smgr_id; storage_manager_id = tde_smgr_id;
} }
#else #else
void RegisterStorageMgr(void) void
RegisterStorageMgr(void)
{ {
} }
#endif /* PERCONA_EXT */ #endif /* PERCONA_EXT */

@ -65,7 +65,8 @@ pg_tde_subxact_callback(SubXactEvent event, SubTransactionId mySubid,
ereport(DEBUG2, ereport(DEBUG2,
(errmsg("pg_tde_subxact_callback: aborting subtransaction"))); (errmsg("pg_tde_subxact_callback: aborting subtransaction")));
do_pending_deletes(false); do_pending_deletes(false);
} else if (event == SUBXACT_EVENT_COMMIT_SUB) }
else if (event == SUBXACT_EVENT_COMMIT_SUB)
{ {
ereport(DEBUG2, ereport(DEBUG2,
(errmsg("pg_tde_subxact_callback: committing subtransaction"))); (errmsg("pg_tde_subxact_callback: committing subtransaction")));
@ -77,6 +78,7 @@ void
RegisterEntryForDeletion(const RelFileLocator *rlocator, off_t map_entry_offset, bool atCommit) RegisterEntryForDeletion(const RelFileLocator *rlocator, off_t map_entry_offset, bool atCommit)
{ {
PendingMapEntryDelete *pending; PendingMapEntryDelete *pending;
pending = (PendingMapEntryDelete *) MemoryContextAlloc(TopMemoryContext, sizeof(PendingMapEntryDelete)); pending = (PendingMapEntryDelete *) MemoryContextAlloc(TopMemoryContext, sizeof(PendingMapEntryDelete));
pending->map_entry_offset = map_entry_offset; pending->map_entry_offset = map_entry_offset;
memcpy(&pending->rlocator, rlocator, sizeof(RelFileLocator)); memcpy(&pending->rlocator, rlocator, sizeof(RelFileLocator));
@ -124,7 +126,7 @@ do_pending_deletes(bool isCommit)
{ {
ereport(LOG, ereport(LOG,
(errmsg("pg_tde_xact_callback: deleting entry at offset %d", (errmsg("pg_tde_xact_callback: deleting entry at offset %d",
(int)(pending->map_entry_offset)))); (int) (pending->map_entry_offset))));
pg_tde_free_key_map_entry(&pending->rlocator, MAP_ENTRY_VALID, pending->map_entry_offset); pg_tde_free_key_map_entry(&pending->rlocator, MAP_ENTRY_VALID, pending->map_entry_offset);
} }
pfree(pending); pfree(pending);

@ -0,0 +1,113 @@
BulkInsertStateData
BulkInsertStateData
BulkInsertStateData
BulkInsertStateData
CurlString
FileKeyring
GenericKeyring
HeapPageFreeze
HeapPageFreeze
HeapScanDescData
HeapScanDescData
HeapScanDescData
HeapScanDescData
HeapTupleFreeze
HeapTupleFreeze
IndexDeleteCounts
IndexDeleteCounts
IndexFetchHeapData
IndexFetchHeapData
InternalKey
JsonKeringSemState
JsonKeyringField
JsonKeyringState
JsonVaultRespField
JsonVaultRespSemState
JsonVaultRespState
KeyProviders
KeyringProvideRecord
KeyringProviderXLRecord
KeyringReturnCode
LVPagePruneState
LVRelState
LVRelState
LVSavedErrInfo
LVSavedErrInfo
LogicalRewriteMappingData
LogicalRewriteMappingData
PendingMapEntryDelete
ProviderScanType
PruneFreezeResult
RelKeyCache
RelKeyCacheRec
RelKeyData
RewriteMappingDataEntry
RewriteMappingDataEntry
RewriteMappingFile
RewriteMappingFile
RewriteStateData
RewriteStateData
RewriteStateData
RewriteStateData *RewriteState;
TDEBufferHeapTupleTableSlot
TDEFileHeader
TDEKeyringRoutine
TDELocalState
TDELockTypes
TDEMapEntry
TDEMapFilePath
TDEPrincipalKey
TDEPrincipalKeyId
TDEPrincipalKeyInfo
TDEShmemSetupRoutine
TdeCreateEvent
TdeCreateEventType
TdeKeyProviderInfoSharedState
TdePrincipalKeySharedState
TdePrincipalKeylocalState
TdeSharedState
VaultV2Keyring
XLogExtensionInstall
XLogPrincipalKeyRotate
XLogRelKey
itemIdCompactData
itemIdCompactData
keyData
keyInfo
keyName
xl_multi_insert_tuple
xl_multi_insert_tuple
xl_tdeheap_confirm
xl_tdeheap_confirm
xl_tdeheap_delete
xl_tdeheap_delete
xl_tdeheap_freeze_page
xl_tdeheap_freeze_plan
xl_tdeheap_header
xl_tdeheap_header
xl_tdeheap_inplace
xl_tdeheap_inplace
xl_tdeheap_insert
xl_tdeheap_insert
xl_tdeheap_lock
xl_tdeheap_lock
xl_tdeheap_lock_updated
xl_tdeheap_lock_updated
xl_tdeheap_multi_insert
xl_tdeheap_multi_insert
xl_tdeheap_new_cid
xl_tdeheap_new_cid
xl_tdeheap_prune
xl_tdeheap_prune
xl_tdeheap_rewrite_mapping
xl_tdeheap_rewrite_mapping
xl_tdeheap_truncate
xl_tdeheap_truncate
xl_tdeheap_update
xl_tdeheap_update
xl_tdeheap_vacuum
xl_tdeheap_visible
xl_tdeheap_visible
xlhp_freeze_plan
xlhp_freeze_plans
xlhp_prune_items
Loading…
Cancel
Save