diff --git a/src/access/pg_tde_ddl.c b/src/access/pg_tde_ddl.c index ee04af34..f109b649 100644 --- a/src/access/pg_tde_ddl.c +++ b/src/access/pg_tde_ddl.c @@ -20,37 +20,39 @@ static object_access_hook_type prev_object_access_hook = NULL; 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; - object_access_hook = tdeheap_object_access_hook; + prev_object_access_hook = object_access_hook; + object_access_hook = tdeheap_object_access_hook; } static void tdeheap_object_access_hook(ObjectAccessType access, Oid classId, Oid objectId, - int subId, void *arg) - { - Relation rel = NULL; - - if (prev_object_access_hook) - prev_object_access_hook(access, classId, objectId, subId, arg); - - if (access == OAT_DROP && classId == RelationRelationId) - { - ObjectAccessDrop *drop_arg = (ObjectAccessDrop *) arg; - rel = relation_open(objectId, AccessShareLock); - } - if (rel != NULL) - { - if ((rel->rd_rel->relkind == RELKIND_RELATION || - rel->rd_rel->relkind == RELKIND_TOASTVALUE || - rel->rd_rel->relkind == RELKIND_MATVIEW) && - (subId == 0) && is_tdeheap_rel(rel)) - { - pg_tde_delete_key_map_entry(&rel->rd_locator, MAP_ENTRY_VALID); - } - relation_close(rel, AccessShareLock); - } + int subId, void *arg) +{ + Relation rel = NULL; + + if (prev_object_access_hook) + prev_object_access_hook(access, classId, objectId, subId, arg); + + if (access == OAT_DROP && classId == RelationRelationId) + { + ObjectAccessDrop *drop_arg = (ObjectAccessDrop *) arg; + + rel = relation_open(objectId, AccessShareLock); + } + if (rel != NULL) + { + if ((rel->rd_rel->relkind == RELKIND_RELATION || + rel->rd_rel->relkind == RELKIND_TOASTVALUE || + rel->rd_rel->relkind == RELKIND_MATVIEW) && + (subId == 0) && is_tdeheap_rel(rel)) + { + pg_tde_delete_key_map_entry(&rel->rd_locator, MAP_ENTRY_VALID); + } + relation_close(rel, AccessShareLock); + } } diff --git a/src/access/pg_tde_slot.c b/src/access/pg_tde_slot.c index 30565dac..351bb86c 100644 --- a/src/access/pg_tde_slot.c +++ b/src/access/pg_tde_slot.c @@ -40,14 +40,15 @@ const TupleTableSlotOps TTSOpsTDEBufferHeapTuple; static pg_attribute_always_inline void tdeheap_slot_deform_heap_tuple(TupleTableSlot *slot, HeapTuple tuple, uint32 *offp, int natts); static inline void tdeheap_tts_buffer_heap_store_tuple(TupleTableSlot *slot, - HeapTuple tuple, - Buffer buffer, - bool transfer_pin); + HeapTuple tuple, + Buffer buffer, + bool transfer_pin); static inline RelKeyData *get_current_slot_relation_key(TDEBufferHeapTupleTableSlot *bslot, Relation rel); static void tdeheap_tts_buffer_heap_init(TupleTableSlot *slot) { - TDEBufferHeapTupleTableSlot *bslot = (TDEBufferHeapTupleTableSlot *) slot; + TDEBufferHeapTupleTableSlot *bslot = (TDEBufferHeapTupleTableSlot *) slot; + bslot->cached_relation_key = NULL; } @@ -110,34 +111,34 @@ tdeheap_tts_buffer_heap_getsysattr(TupleTableSlot *slot, int attnum, bool *isnul */ if (!bslot->base.tuple) ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("cannot retrieve a system column in this context"))); + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot retrieve a system column in this context"))); return tdeheap_getsysattr(bslot->base.tuple, attnum, - slot->tts_tupleDescriptor, isnull); + slot->tts_tupleDescriptor, isnull); } static bool tdeheap_buffer_is_current_xact_tuple(TupleTableSlot *slot) { - BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot; - TransactionId xmin; + BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot; + TransactionId xmin; - Assert(!TTS_EMPTY(slot)); + Assert(!TTS_EMPTY(slot)); - /* - * In some code paths it's possible to get here with a non-materialized - * slot, in which case we can't check if tuple is created by the current - * transaction. - */ - if (!bslot->base.tuple) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("don't have a storage tuple in this context"))); + /* + * In some code paths it's possible to get here with a non-materialized + * slot, in which case we can't check if tuple is created by the current + * transaction. + */ + if (!bslot->base.tuple) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("don't have a storage tuple in this context"))); - xmin = HeapTupleHeaderGetRawXmin(bslot->base.tuple->t_data); + xmin = HeapTupleHeaderGetRawXmin(bslot->base.tuple->t_data); - return TransactionIdIsCurrentTransactionId(xmin); + return TransactionIdIsCurrentTransactionId(xmin); } static void @@ -171,8 +172,8 @@ tdeheap_tts_buffer_heap_materialize(TupleTableSlot *slot) * materializable. */ bslot->base.tuple = tdeheap_form_tuple(slot->tts_tupleDescriptor, - slot->tts_values, - slot->tts_isnull); + slot->tts_values, + slot->tts_isnull); } else { @@ -228,7 +229,7 @@ tdeheap_tts_buffer_heap_copyslot(TupleTableSlot *dstslot, TupleTableSlot *srcslo Assert(BufferIsValid(bsrcslot->buffer)); tdeheap_tts_buffer_heap_store_tuple(dstslot, bsrcslot->base.tuple, - bsrcslot->buffer, false); + bsrcslot->buffer, false); /* * The HeapTupleData portion of the source tuple might be shorter @@ -245,6 +246,7 @@ static HeapTuple tdeheap_tts_buffer_heap_get_heap_tuple(TupleTableSlot *slot) { BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot; + Assert(!TTS_EMPTY(slot)); if (!bslot->base.tuple) @@ -280,7 +282,7 @@ tdeheap_tts_buffer_heap_copy_minimal_tuple(TupleTableSlot *slot) static inline void tdeheap_tts_buffer_heap_store_tuple(TupleTableSlot *slot, HeapTuple tuple, - Buffer buffer, bool transfer_pin) + Buffer buffer, bool transfer_pin) { BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot; @@ -346,7 +348,7 @@ tdeheap_tts_buffer_heap_store_tuple(TupleTableSlot *slot, HeapTuple tuple, */ static pg_attribute_always_inline void tdeheap_slot_deform_heap_tuple(TupleTableSlot *slot, HeapTuple tuple, uint32 *offp, - int natts) + int natts) { TupleDesc tupleDesc = slot->tts_tupleDescriptor; Datum *values = slot->tts_values; @@ -358,6 +360,7 @@ tdeheap_slot_deform_heap_tuple(TupleTableSlot *slot, HeapTuple tuple, uint32 *of uint32 off; /* offset in tuple data */ bits8 *bp = tup->t_bits; /* ptr to null bitmap in tuple */ bool slow; /* can we use/set attcacheoff? */ + /* We can only fetch as many attributes as the tuple has. */ natts = Min(HeapTupleHeaderGetNatts(tuple->t_data), natts); @@ -444,7 +447,7 @@ tdeheap_slot_deform_heap_tuple(TupleTableSlot *slot, HeapTuple tuple, uint32 *of } static HeapTuple -slot_copytuple(void* buffer, HeapTuple tuple) +slot_copytuple(void *buffer, HeapTuple tuple) { HeapTuple newTuple; @@ -456,7 +459,7 @@ slot_copytuple(void* buffer, HeapTuple tuple) newTuple->t_self = tuple->t_self; newTuple->t_tableOid = tuple->t_tableOid; 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); return newTuple; } @@ -478,7 +481,7 @@ const TupleTableSlotOps TTSOpsTDEBufferHeapTuple = { /* A buffer heap tuple table slot can not "own" a minimal tuple. */ .get_minimal_tuple = NULL, .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 @@ -501,12 +504,13 @@ const TupleTableSlotOps TTSOpsTDEBufferHeapTuple = { */ TupleTableSlot * PGTdeExecStoreBufferHeapTuple(Relation rel, - HeapTuple tuple, - TupleTableSlot *slot, - Buffer buffer) + HeapTuple tuple, + TupleTableSlot *slot, + Buffer buffer) { - TDEBufferHeapTupleTableSlot *bslot = (TDEBufferHeapTupleTableSlot *)slot; + TDEBufferHeapTupleTableSlot *bslot = (TDEBufferHeapTupleTableSlot *) slot; + /* * sanity checks */ @@ -522,9 +526,10 @@ PGTdeExecStoreBufferHeapTuple(Relation rel, if (rel->rd_rel->relkind != RELKIND_TOASTVALUE) { RelKeyData *key = get_current_slot_relation_key(bslot, rel); + slot_copytuple(bslot->decrypted_buffer, tuple); - PG_TDE_DECRYPT_TUPLE_EX(tuple, (HeapTuple)bslot->decrypted_buffer, key, "ExecStoreBuffer"); - tuple->t_data = ((HeapTuple)bslot->decrypted_buffer)->t_data; + PG_TDE_DECRYPT_TUPLE_EX(tuple, (HeapTuple) bslot->decrypted_buffer, key, "ExecStoreBuffer"); + tuple->t_data = ((HeapTuple) bslot->decrypted_buffer)->t_data; } tdeheap_tts_buffer_heap_store_tuple(slot, tuple, buffer, false); @@ -540,11 +545,12 @@ PGTdeExecStoreBufferHeapTuple(Relation rel, */ TupleTableSlot * PGTdeExecStorePinnedBufferHeapTuple(Relation rel, - HeapTuple tuple, - TupleTableSlot *slot, - Buffer buffer) + HeapTuple tuple, + TupleTableSlot *slot, + Buffer buffer) { - TDEBufferHeapTupleTableSlot *bslot = (TDEBufferHeapTupleTableSlot *)slot; + TDEBufferHeapTupleTableSlot *bslot = (TDEBufferHeapTupleTableSlot *) slot; + /* * sanity checks */ @@ -559,12 +565,12 @@ PGTdeExecStorePinnedBufferHeapTuple(Relation rel, 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); - 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 */ - 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); @@ -574,7 +580,7 @@ PGTdeExecStorePinnedBufferHeapTuple(Relation rel, return slot; } -static inline RelKeyData* +static inline RelKeyData * get_current_slot_relation_key(TDEBufferHeapTupleTableSlot *bslot, Relation rel) { Assert(bslot != NULL); diff --git a/src/access/pg_tde_tdemap.c b/src/access/pg_tde_tdemap.c index 1957aa10..5e211f12 100644 --- a/src/access/pg_tde_tdemap.c +++ b/src/access/pg_tde_tdemap.c @@ -58,7 +58,8 @@ #define PG_TDE_MAP_FILENAME "pg_tde.map" #define PG_TDE_KEYDATA_FILENAME "pg_tde.dat" -#define PG_TDE_FILEMAGIC 0x01454454 /* version ID value = TDE 01 */ +#define PG_TDE_FILEMAGIC 0x01454454 /* version ID value = TDE + * 01 */ #define MAP_ENTRY_SIZE sizeof(TDEMapEntry) @@ -66,70 +67,71 @@ typedef struct TDEFileHeader { - int32 file_version; + int32 file_version; TDEPrincipalKeyInfo principal_key_info; } TDEFileHeader; typedef struct TDEMapEntry { RelFileNumber relNumber; - uint32 flags; - int32 key_index; + uint32 flags; + int32 key_index; } TDEMapEntry; typedef struct TDEMapFilePath { - char map_path[MAXPGPATH]; - char keydata_path[MAXPGPATH]; + char map_path[MAXPGPATH]; + char keydata_path[MAXPGPATH]; } TDEMapFilePath; typedef struct RelKeyCacheRec { RelFileNumber rel_number; - uint32 key_type; - RelKeyData key; + uint32 key_type; + RelKeyData key; } RelKeyCacheRec; -/* +/* * Relation keys cache. - * + * * This is a slice backed by memory `*data`. Initially, we allocate one memory * page (usually 4Kb). We reallocate it by adding another page when we run out - * of space. This memory is locked in the RAM so it won't be paged to the swap + * of space. This memory is locked in the RAM so it won't be paged to the swap * (we don't want decrypted keys on disk). We do allocations in mem pages as * these are the units `mlock()` operations are performed in. - * - * Currently, the cache can only grow (no eviction). The data is located in + * + * Currently, the cache can only grow (no eviction). The data is located in * TopMemoryContext hence being wiped when the process exits, as well as memory * is being unlocked by OS. */ typedef struct RelKeyCache { - RelKeyCacheRec *data; /* must be a multiple of a memory page (usually 4Kb) */ - int len; /* num of RelKeyCacheRecs currenty in cache */ - int cap; /* max amount of RelKeyCacheRec data can fit */ + RelKeyCacheRec *data; /* must be a multiple of a memory page + * (usually 4Kb) */ + int len; /* num of RelKeyCacheRecs currenty in cache */ + int cap; /* max amount of RelKeyCacheRec data can fit */ } RelKeyCache; 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 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_file_header_read(char *tde_filename, int fd, TDEFileHeader *fheader, bool *is_new_file, off_t *bytes_read); +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_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 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 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 RelKeyData *pg_tde_get_key_from_cache(RelFileNumber rel_number, uint32 key_type); #ifndef FRONTEND -static int pg_tde_file_header_write(char *tde_filename, int fd, TDEPrincipalKeyInfo *principal_key_info, off_t *bytes_written); +static int pg_tde_file_header_write(char *tde_filename, int fd, TDEPrincipalKeyInfo *principal_key_info, off_t *bytes_written); static int32 pg_tde_write_map_entry(const RelFileLocator *rlocator, uint32 entry_type, char *db_map_path, TDEPrincipalKeyInfo *principal_key_info); static off_t pg_tde_write_one_map_entry(int fd, const RelFileLocator *rlocator, uint32 flags, int32 key_index, TDEMapEntry *map_entry, off_t *offset); static void pg_tde_write_keydata(char *db_keydata_path, TDEPrincipalKeyInfo *principal_key_info, int32 key_index, RelKeyData *enc_rel_key_data); static void pg_tde_write_one_keydata(int keydata_fd, int32 key_index, RelKeyData *enc_rel_key_data); -static int keyrotation_init_file(TDEPrincipalKeyInfo *new_principal_key_info, char *rotated_filename, char *filename, bool *is_new_file, off_t *curr_pos); +static int keyrotation_init_file(TDEPrincipalKeyInfo *new_principal_key_info, char *rotated_filename, char *filename, bool *is_new_file, off_t *curr_pos); static void finalize_key_rotation(char *m_path_old, char *k_path_old, char *m_path_new, char *k_path_new); RelKeyData * @@ -160,8 +162,8 @@ pg_tde_create_key_map_entry(const RelFileLocator *newrlocator, uint32 entry_type RelKeyData *rel_key_data; RelKeyData *enc_rel_key_data; TDEPrincipalKey *principal_key; - XLogRelKey xlrec; - LWLock *lock_pk = tde_lwlock_enc_keys(); + XLogRelKey xlrec; + LWLock *lock_pk = tde_lwlock_enc_keys(); LWLockAcquire(lock_pk, LW_EXCLUSIVE); principal_key = GetPrincipalKey(newrlocator->dbOid, newrlocator->spcOid, LW_EXCLUSIVE); @@ -181,8 +183,8 @@ pg_tde_create_key_map_entry(const RelFileLocator *newrlocator, uint32 entry_type LWLockRelease(lock_pk); ereport(FATAL, (errcode(ERRCODE_INTERNAL_ERROR), - errmsg("could not generate internal key for relation \"%s\": %s", - "TODO", ERR_error_string(ERR_get_error(), NULL)))); + errmsg("could not generate internal key for relation \"%s\": %s", + "TODO", ERR_error_string(ERR_get_error(), NULL)))); return NULL; } @@ -215,10 +217,10 @@ const char * tde_sprint_key(InternalKey *k) { static char buf[256]; - int i; + int 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; } @@ -230,7 +232,8 @@ tde_sprint_key(InternalKey *k) RelKeyData * tde_create_rel_key(RelFileNumber rel_num, uint32 key_type, 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.internal_key, key, sizeof(InternalKey)); rel_key_data.internal_key.ctx = NULL; @@ -238,6 +241,7 @@ tde_create_rel_key(RelFileNumber rel_num, uint32 key_type, InternalKey *key, TDE /* Add to the decrypted key to cache */ return pg_tde_put_key_into_cache(rel_num, key_type, &rel_key_data); } + /* * Encrypts a given key and returns the encrypted one. */ @@ -245,7 +249,7 @@ RelKeyData * tde_encrypt_rel_key(TDEPrincipalKey *principal_key, RelKeyData *rel_key_data, const RelFileLocator *rlocator) { RelKeyData *enc_rel_key_data; - size_t enc_key_bytes; + size_t enc_key_bytes; AesEncryptKey(principal_key, rlocator, rel_key_data, &enc_rel_key_data, &enc_key_bytes); @@ -259,8 +263,8 @@ tde_encrypt_rel_key(TDEPrincipalKey *principal_key, RelKeyData *rel_key_data, co void pg_tde_delete_tde_files(Oid dbOid, Oid spcOid) { - char db_map_path[MAXPGPATH] = {0}; - char db_keydata_path[MAXPGPATH] = {0}; + char db_map_path[MAXPGPATH] = {0}; + char db_keydata_path[MAXPGPATH] = {0}; /* Set the file paths */ pg_tde_set_db_file_paths(dbOid, spcOid, db_map_path, db_keydata_path); @@ -282,18 +286,18 @@ pg_tde_delete_tde_files(Oid dbOid, Oid spcOid) bool pg_tde_save_principal_key(TDEPrincipalKeyInfo *principal_key_info) { - int map_fd = -1; - int keydata_fd = -1; - off_t curr_pos = 0; - bool is_new_map = false; - bool is_new_key_data = false; + int map_fd = -1; + int keydata_fd = -1; + off_t curr_pos = 0; + bool is_new_map = false; + bool is_new_key_data = false; char db_map_path[MAXPGPATH] = {0}; char db_keydata_path[MAXPGPATH] = {0}; /* Set the file paths */ pg_tde_set_db_file_paths(principal_key_info->databaseId, - principal_key_info->tablespaceId, - db_map_path, db_keydata_path); + principal_key_info->tablespaceId, + db_map_path, db_keydata_path); ereport(LOG, (errmsg("pg_tde_save_principal_key"))); @@ -315,7 +319,7 @@ static int pg_tde_file_header_write(char *tde_filename, int fd, TDEPrincipalKeyInfo *principal_key_info, off_t *bytes_written) { TDEFileHeader fheader; - size_t sz = sizeof(TDEPrincipalKeyInfo); + size_t sz = sizeof(TDEPrincipalKeyInfo); Assert(principal_key_info); @@ -333,7 +337,7 @@ pg_tde_file_header_write(char *tde_filename, int fd, TDEPrincipalKeyInfo *princi { ereport(ERROR, (errcode_for_file_access(), - errmsg("could not write tde file \"%s\": %m", + errmsg("could not write tde file \"%s\": %m", tde_filename))); } @@ -359,13 +363,13 @@ pg_tde_file_header_write(char *tde_filename, int fd, TDEPrincipalKeyInfo *princi static int32 pg_tde_write_map_entry(const RelFileLocator *rlocator, uint32 entry_type, char *db_map_path, TDEPrincipalKeyInfo *principal_key_info) { - int map_fd = -1; - int32 key_index = 0; + int map_fd = -1; + int32 key_index = 0; TDEMapEntry map_entry; - bool is_new_file; - off_t curr_pos = 0; - off_t prev_pos = 0; - bool found = false; + bool is_new_file; + off_t curr_pos = 0; + off_t prev_pos = 0; + bool found = false; /* Open and validate file for basic correctness. */ map_fd = pg_tde_open_file(db_map_path, principal_key_info, false, O_RDWR | O_CREAT, &is_new_file, &curr_pos); @@ -373,15 +377,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 - * to be less frequent than vacuum. So let's keep this function here rather - * than overloading the vacuum process. + * to be less frequent than vacuum. So let's keep this function here + * rather than overloading the vacuum process. */ - while(1) + while (1) { prev_pos = 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) break; @@ -389,7 +396,10 @@ pg_tde_write_map_entry(const RelFileLocator *rlocator, uint32 entry_type, char * 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; pg_tde_write_one_map_entry(map_fd, rlocator, entry_type, key_index, &map_entry, &prev_pos); @@ -409,7 +419,7 @@ pg_tde_write_map_entry(const RelFileLocator *rlocator, uint32 entry_type, char * static off_t pg_tde_write_one_map_entry(int fd, const RelFileLocator *rlocator, uint32 flags, int32 key_index, TDEMapEntry *map_entry, off_t *offset) { - int bytes_written = 0; + int bytes_written = 0; Assert(map_entry); @@ -424,16 +434,18 @@ pg_tde_write_one_map_entry(int fd, const RelFileLocator *rlocator, uint32 flags, /* Add the entry to the file */ 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); ereport(FATAL, (errcode_for_file_access(), - errmsg("could not write tde map file \"%s\": %m", + errmsg("could not write tde map file \"%s\": %m", db_map_path))); } 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); ereport(data_sync_elevel(ERROR), (errcode_for_file_access(), @@ -455,9 +467,9 @@ pg_tde_write_one_map_entry(int fd, const RelFileLocator *rlocator, uint32 flags, static void pg_tde_write_keydata(char *db_keydata_path, TDEPrincipalKeyInfo *principal_key_info, int32 key_index, RelKeyData *enc_rel_key_data) { - File fd = -1; - bool is_new_file; - off_t curr_pos = 0; + File fd = -1; + bool is_new_file; + off_t curr_pos = 0; /* Open and validate file for basic correctness. */ fd = pg_tde_open_file(db_keydata_path, principal_key_info, false, O_RDWR | O_CREAT, &is_new_file, &curr_pos); @@ -475,7 +487,7 @@ pg_tde_write_keydata(char *db_keydata_path, TDEPrincipalKeyInfo *principal_key_i static void pg_tde_write_one_keydata(int fd, int32 key_index, RelKeyData *enc_rel_key_data) { - off_t curr_pos; + off_t curr_pos; Assert(fd != -1); @@ -487,7 +499,7 @@ pg_tde_write_one_keydata(int fd, int32 key_index, RelKeyData *enc_rel_key_data) { ereport(FATAL, (errcode_for_file_access(), - errmsg("could not write tde key data file: %m"))); + errmsg("could not write tde key data file: %m"))); } if (pg_fsync(fd) != 0) @@ -508,9 +520,9 @@ pg_tde_write_one_keydata(int fd, int32 key_index, RelKeyData *enc_rel_key_data) void pg_tde_write_key_map_entry(const RelFileLocator *rlocator, uint32 entry_type, RelKeyData *enc_rel_key_data, TDEPrincipalKeyInfo *principal_key_info) { - int32 key_index = 0; - char db_map_path[MAXPGPATH] = {0}; - char db_keydata_path[MAXPGPATH] = {0}; + int32 key_index = 0; + char db_map_path[MAXPGPATH] = {0}; + char db_keydata_path[MAXPGPATH] = {0}; Assert(rlocator); @@ -528,13 +540,14 @@ pg_tde_write_key_map_entry(const RelFileLocator *rlocator, uint32 entry_type, Re * 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. */ -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; - off_t offset = 0; - LWLock *lock_files = tde_lwlock_enc_keys(); - char db_map_path[MAXPGPATH] = {0}; - char db_keydata_path[MAXPGPATH] = {0}; + int32 key_index = 0; + off_t offset = 0; + LWLock *lock_files = tde_lwlock_enc_keys(); + char db_map_path[MAXPGPATH] = {0}; + char db_keydata_path[MAXPGPATH] = {0}; Assert(rlocator); @@ -544,14 +557,14 @@ void pg_tde_delete_key_map_entry(const RelFileLocator *rlocator, uint32 key_type errno = 0; /* Remove the map entry if found */ LWLockAcquire(lock_files, LW_EXCLUSIVE); - key_index = pg_tde_process_map_entry(rlocator, key_type, db_map_path, &offset, false); + key_index = pg_tde_process_map_entry(rlocator, key_type, db_map_path, &offset, false); LWLockRelease(lock_files); if (key_index == -1) { ereport(WARNING, (errcode(ERRCODE_NO_DATA_FOUND), - errmsg("could not find the required map entry for deletion of relation %d in tde map file \"%s\": %m", + errmsg("could not find the required map entry for deletion of relation %d in tde map file \"%s\": %m", rlocator->relNumber, db_map_path))); @@ -573,12 +586,13 @@ void pg_tde_delete_key_map_entry(const RelFileLocator *rlocator, uint32 key_type * The offset allows us to simply seek to the desired location and mark the entry * as MAP_ENTRY_FREE without needing any further processing. */ -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; - LWLock *lock_files = tde_lwlock_enc_keys(); - char db_map_path[MAXPGPATH] = {0}; - char db_keydata_path[MAXPGPATH] = {0}; + int32 key_index = 0; + LWLock *lock_files = tde_lwlock_enc_keys(); + char db_map_path[MAXPGPATH] = {0}; + char db_keydata_path[MAXPGPATH] = {0}; Assert(rlocator); @@ -594,7 +608,7 @@ void pg_tde_free_key_map_entry(const RelFileLocator *rlocator, uint32 key_type, { ereport(WARNING, (errcode(ERRCODE_NO_DATA_FOUND), - errmsg("could not find the required map entry for deletion of relation %d in tde map file \"%s\": %m", + errmsg("could not find the required map entry for deletion of relation %d in tde map file \"%s\": %m", rlocator->relNumber, db_map_path))); @@ -612,7 +626,10 @@ void pg_tde_free_key_map_entry(const RelFileLocator *rlocator, uint32 key_type, static File 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); /* Create file, truncate if the rotate file already exits */ @@ -644,20 +661,20 @@ pg_tde_perform_rotate_key(TDEPrincipalKey *principal_key, TDEPrincipalKey *new_p #define NEW_PRINCIPAL_KEY 1 #define PRINCIPAL_KEY_COUNT 2 - off_t curr_pos[PRINCIPAL_KEY_COUNT] = {0}; - off_t prev_pos[PRINCIPAL_KEY_COUNT] = {0}; - int32 key_index[PRINCIPAL_KEY_COUNT] = {0}; + off_t curr_pos[PRINCIPAL_KEY_COUNT] = {0}; + off_t prev_pos[PRINCIPAL_KEY_COUNT] = {0}; + int32 key_index[PRINCIPAL_KEY_COUNT] = {0}; RelKeyData *rel_key_data[PRINCIPAL_KEY_COUNT]; RelKeyData *enc_rel_key_data[PRINCIPAL_KEY_COUNT]; - int m_fd[PRINCIPAL_KEY_COUNT] = {-1}; - int k_fd[PRINCIPAL_KEY_COUNT] = {-1}; - char m_path[PRINCIPAL_KEY_COUNT][MAXPGPATH]; - char k_path[PRINCIPAL_KEY_COUNT][MAXPGPATH]; - bool found = false; - off_t read_pos_tmp = 0; - bool is_new_file; - off_t map_size; - off_t keydata_size; + int m_fd[PRINCIPAL_KEY_COUNT] = {-1}; + int k_fd[PRINCIPAL_KEY_COUNT] = {-1}; + char m_path[PRINCIPAL_KEY_COUNT][MAXPGPATH]; + char k_path[PRINCIPAL_KEY_COUNT][MAXPGPATH]; + bool found = false; + off_t read_pos_tmp = 0; + bool is_new_file; + off_t map_size; + off_t keydata_size; XLogPrincipalKeyRotate *xlrec; off_t xlrec_size; char db_map_path[MAXPGPATH] = {0}; @@ -665,14 +682,20 @@ pg_tde_perform_rotate_key(TDEPrincipalKey *principal_key, TDEPrincipalKey *new_p /* Set the file paths */ pg_tde_set_db_file_paths(principal_key->keyInfo.databaseId, - principal_key->keyInfo.tablespaceId, - db_map_path, db_keydata_path); + principal_key->keyInfo.tablespaceId, + 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(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]); 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); @@ -680,9 +703,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); /* 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; prev_pos[OLD_PRINCIPAL_KEY] = curr_pos[OLD_PRINCIPAL_KEY]; @@ -696,14 +720,17 @@ pg_tde_perform_rotate_key(TDEPrincipalKey *principal_key, TDEPrincipalKey *new_p if (found == false) 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.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. */ enc_rel_key_data[OLD_PRINCIPAL_KEY] = pg_tde_read_one_keydata(k_fd[OLD_PRINCIPAL_KEY], key_index[OLD_PRINCIPAL_KEY], principal_key); - + /* Decrypt and re-encrypt keys */ rel_key_data[OLD_PRINCIPAL_KEY] = tde_decrypt_rel_key(principal_key, enc_rel_key_data[OLD_PRINCIPAL_KEY], &rloc); enc_rel_key_data[NEW_PRINCIPAL_KEY] = tde_encrypt_rel_key(new_principal_key, rel_key_data[OLD_PRINCIPAL_KEY], &rloc); @@ -768,24 +795,24 @@ bool pg_tde_write_map_keydata_files(off_t map_size, char *m_file_data, off_t keydata_size, char *k_file_data) { TDEFileHeader *fheader; - char m_path_new[MAXPGPATH]; - char k_path_new[MAXPGPATH]; - int m_fd_new; - int k_fd_new; - bool is_new_file; - off_t curr_pos = 0; - off_t read_pos_tmp = 0; - char db_map_path[MAXPGPATH] = {0}; - char db_keydata_path[MAXPGPATH] = {0}; - bool is_err = false; + char m_path_new[MAXPGPATH]; + char k_path_new[MAXPGPATH]; + int m_fd_new; + int k_fd_new; + bool is_new_file; + off_t curr_pos = 0; + off_t read_pos_tmp = 0; + char db_map_path[MAXPGPATH] = {0}; + char db_keydata_path[MAXPGPATH] = {0}; + bool is_err = false; /* Let's get the header. Buff should start with the map file header. */ fheader = (TDEFileHeader *) m_file_data; /* Set the file paths */ pg_tde_set_db_file_paths(fheader->principal_key_info.databaseId, - fheader->principal_key_info.tablespaceId, - db_map_path, db_keydata_path); + fheader->principal_key_info.tablespaceId, + db_map_path, db_keydata_path); /* Initialize the new files and set the names */ m_fd_new = keyrotation_init_file(&fheader->principal_key_info, m_path_new, db_map_path, &is_new_file, &curr_pos); @@ -796,7 +823,7 @@ pg_tde_write_map_keydata_files(off_t map_size, char *m_file_data, off_t keydata_ { ereport(WARNING, (errcode_for_file_access(), - errmsg("could not write tde file \"%s\": %m", + errmsg("could not write tde file \"%s\": %m", m_path_new))); is_err = true; goto FINALIZE; @@ -815,7 +842,7 @@ pg_tde_write_map_keydata_files(off_t map_size, char *m_file_data, off_t keydata_ { ereport(WARNING, (errcode_for_file_access(), - errmsg("could not write tde file \"%s\": %m", + errmsg("could not write tde file \"%s\": %m", k_path_new))); is_err = true; goto FINALIZE; @@ -839,7 +866,7 @@ pg_tde_write_map_keydata_files(off_t map_size, char *m_file_data, off_t keydata_ return !is_err; } -#endif /* !FRONTEND */ +#endif /* !FRONTEND */ /* * Reads the key of the required relation. It identifies its map entry and then simply @@ -849,28 +876,27 @@ RelKeyData * pg_tde_get_key_from_file(const RelFileLocator *rlocator, uint32 key_type) { int32 key_index = 0; - TDEPrincipalKey *principal_key; - RelKeyData *rel_key_data; - RelKeyData *enc_rel_key_data; + TDEPrincipalKey *principal_key; + RelKeyData *rel_key_data; + RelKeyData *enc_rel_key_data; off_t offset = 0; - LWLock *lock_pk = tde_lwlock_enc_keys(); + LWLock *lock_pk = tde_lwlock_enc_keys(); char db_map_path[MAXPGPATH] = {0}; char db_keydata_path[MAXPGPATH] = {0}; Assert(rlocator); - /* + /* * Get/generate a principal key, create the key for relation and get the * encrypted key with bytes to write - * + * * 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, - * the next may happen: - * - GetPrincipalKey returns key "PKey_1". - * - Some other process rotates the Principal key and re-encrypt an - * Internal key with "PKey_2". - * - We read the Internal key and decrypt it with "PKey_1" (that's what - * we've got). As the result we return an invalid Internal key. + * the next may happen: - GetPrincipalKey returns key "PKey_1". - Some + * other process rotates the Principal key and re-encrypt an Internal key + * with "PKey_2". - We read the Internal key and decrypt it with "PKey_1" + * (that's what we've got). As the result we return an invalid Internal + * key. */ LWLockAcquire(lock_pk, LW_SHARED); principal_key = GetPrincipalKey(rlocator->dbOid, rlocator->spcOid, LW_SHARED); @@ -904,7 +930,7 @@ pg_tde_get_key_from_file(const RelFileLocator *rlocator, uint32 key_type) inline void pg_tde_set_db_file_paths(Oid dbOid, Oid spcOid, char *map_path, char *keydata_path) { - char *db_path = pg_tde_get_tde_file_dir(dbOid, spcOid); + char *db_path = pg_tde_get_tde_file_dir(dbOid, spcOid); if (map_path) join_path_components(map_path, db_path, PG_TDE_MAP_FILENAME); @@ -925,19 +951,19 @@ pg_tde_set_db_file_paths(Oid dbOid, Oid spcOid, char *map_path, char *keydata_pa static int32 pg_tde_process_map_entry(const RelFileLocator *rlocator, uint32 key_type, char *db_map_path, off_t *offset, bool should_delete) { - File map_fd = -1; - int32 key_index = 0; + File map_fd = -1; + int32 key_index = 0; TDEMapEntry map_entry; - bool is_new_file; - bool found = false; - off_t prev_pos = 0; - off_t curr_pos = 0; + bool is_new_file; + bool found = false; + off_t prev_pos = 0; + off_t curr_pos = 0; Assert(offset); /* - * Open and validate file for basic correctness. DO NOT create it. - * The file should pre-exist otherwise we should never be here. + * Open and validate file for basic correctness. DO NOT create it. The + * 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); @@ -954,8 +980,8 @@ pg_tde_process_map_entry(const RelFileLocator *rlocator, uint32 key_type, char * { ereport(FATAL, (errcode_for_file_access(), - errmsg("could not seek in tde map file \"%s\": %m", - db_map_path))); + errmsg("could not seek in tde map file \"%s\": %m", + db_map_path))); } } else @@ -966,10 +992,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 - * to be less frequent than vacuum. So let's keep this function here rather - * than overloading the vacuum process. + * to be less frequent than vacuum. So let's keep this function here + * rather than overloading the vacuum process. */ - while(1) + while (1) { prev_pos = curr_pos; found = pg_tde_read_one_map_entry(map_fd, rlocator, key_type, &map_entry, &curr_pos); @@ -1005,15 +1031,15 @@ pg_tde_process_map_entry(const RelFileLocator *rlocator, uint32 key_type, char * /* * Open the file and read the required key data from file and return encrypted key. - * The caller should hold + * The caller should hold */ static RelKeyData * pg_tde_read_keydata(char *db_keydata_path, int32 key_index, TDEPrincipalKey *principal_key) { - int fd = -1; + int fd = -1; RelKeyData *enc_rel_key_data; - off_t read_pos = 0; - bool is_new_file; + off_t read_pos = 0; + bool is_new_file; /* Open and validate file for basic correctness. */ fd = pg_tde_open_file(db_keydata_path, &principal_key->keyInfo, false, O_RDONLY, &is_new_file, &read_pos); @@ -1035,7 +1061,7 @@ RelKeyData * tde_decrypt_rel_key(TDEPrincipalKey *principal_key, RelKeyData *enc_rel_key_data, const RelFileLocator *rlocator) { RelKeyData *rel_key_data = NULL; - size_t key_bytes; + size_t key_bytes; AesDecryptKey(principal_key, rlocator, &rel_key_data, enc_rel_key_data, &key_bytes); @@ -1063,10 +1089,10 @@ tde_decrypt_rel_key(TDEPrincipalKey *principal_key, RelKeyData *enc_rel_key_data 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 *curr_pos) { - int fd = -1; + int fd = -1; TDEFileHeader fheader; - off_t bytes_read = 0; - off_t bytes_written = 0; + off_t bytes_read = 0; + off_t bytes_written = 0; /* * Ensuring that we always open the file in binary mode. The caller must @@ -1080,7 +1106,7 @@ pg_tde_open_file(char *tde_filename, TDEPrincipalKeyInfo *principal_key_info, bo /* In case it's a new file, let's add the header now. */ if (*is_new_file && principal_key_info) pg_tde_file_header_write(tde_filename, fd, principal_key_info, &bytes_written); -#endif /* FRONTEND */ +#endif /* FRONTEND */ *curr_pos = bytes_read + bytes_written; return fd; @@ -1096,7 +1122,7 @@ pg_tde_open_file(char *tde_filename, TDEPrincipalKeyInfo *principal_key_info, bo static int pg_tde_open_file_basic(char *tde_filename, int fileFlags, bool ignore_missing) { - int fd = -1; + int fd = -1; /* * Ensuring that we always open the file in binary mode. The caller must @@ -1132,13 +1158,13 @@ pg_tde_file_header_read(char *tde_filename, int fd, TDEFileHeader *fheader, bool return fd; if (*bytes_read != TDE_FILE_HEADER_SIZE - || fheader->file_version != PG_TDE_FILEMAGIC) + || fheader->file_version != PG_TDE_FILEMAGIC) { /* Corrupt file */ ereport(FATAL, (errcode_for_file_access(), errmsg("TDE map file \"%s\" is corrupted: %m", - tde_filename))); + tde_filename))); } return fd; @@ -1159,8 +1185,8 @@ pg_tde_file_header_read(char *tde_filename, int fd, TDEFileHeader *fheader, bool static bool pg_tde_read_one_map_entry(File map_file, const RelFileLocator *rlocator, int flags, TDEMapEntry *map_entry, off_t *offset) { - bool found; - off_t bytes_read = 0; + bool found; + off_t bytes_read = 0; Assert(map_entry); Assert(offset); @@ -1192,7 +1218,7 @@ static RelKeyData * pg_tde_read_one_keydata(int keydata_fd, int32 key_index, TDEPrincipalKey *principal_key) { RelKeyData *enc_rel_key_data; - off_t read_pos = 0; + off_t read_pos = 0; /* Allocate and fill in the structure */ enc_rel_key_data = (RelKeyData *) palloc(sizeof(RelKeyData)); @@ -1205,11 +1231,12 @@ pg_tde_read_one_keydata(int keydata_fd, int32 key_index, TDEPrincipalKey *princi /* Check if the file has a valid key */ if ((read_pos + INTERNAL_KEY_LEN) > lseek(keydata_fd, 0, SEEK_END)) { - char db_keydata_path[MAXPGPATH] = {0}; - pg_tde_set_db_file_paths(principal_key->keyInfo.databaseId, principal_key->keyInfo.tablespaceId, NULL, db_keydata_path); + char db_keydata_path[MAXPGPATH] = {0}; + + pg_tde_set_db_file_paths(principal_key->keyInfo.databaseId, principal_key->keyInfo.tablespaceId, NULL, db_keydata_path); ereport(FATAL, (errcode(ERRCODE_NO_DATA_FOUND), - errmsg("could not find the required key at index %d in tde data file \"%s\": %m", + errmsg("could not find the required key at index %d in tde data file \"%s\": %m", key_index, db_keydata_path))); } @@ -1218,11 +1245,12 @@ pg_tde_read_one_keydata(int keydata_fd, int32 key_index, TDEPrincipalKey *princi /* TODO: pgstat_report_wait_start / pgstat_report_wait_end */ if (pg_pread(keydata_fd, &(enc_rel_key_data->internal_key), INTERNAL_KEY_LEN, read_pos) != INTERNAL_KEY_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); ereport(FATAL, (errcode_for_file_access(), - errmsg("could not read key at index %d in tde key data file \"%s\": %m", + errmsg("could not read key at index %d in tde key data file \"%s\": %m", key_index, db_keydata_path))); } @@ -1238,11 +1266,11 @@ pg_tde_read_one_keydata(int keydata_fd, int32 key_index, TDEPrincipalKey *princi TDEPrincipalKeyInfo * pg_tde_get_principal_key_info(Oid dbOid, Oid spcOid) { - int fd = -1; + int fd = -1; TDEFileHeader fheader; TDEPrincipalKeyInfo *principal_key_info = NULL; - bool is_new_file = false; - off_t bytes_read = 0; + bool is_new_file = false; + off_t bytes_read = 0; char db_map_path[MAXPGPATH] = {0}; /* Set the file paths */ @@ -1262,10 +1290,13 @@ pg_tde_get_principal_key_info(Oid dbOid, Oid spcOid) 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) { - size_t sz = sizeof(TDEPrincipalKeyInfo); + size_t sz = sizeof(TDEPrincipalKeyInfo); principal_key_info = (TDEPrincipalKeyInfo *) palloc(sz); memcpy(principal_key_info, &fheader.principal_key_info, sz); @@ -1292,7 +1323,8 @@ GetRelationKey(RelFileLocator rel, uint32 key_type) if (key != NULL) { - RelKeyData* cached_key = pg_tde_put_key_into_cache(rel.relNumber, key_type, key); + RelKeyData *cached_key = pg_tde_put_key_into_cache(rel.relNumber, key_type, key); + pfree(key); return cached_key; } @@ -1326,14 +1358,14 @@ GetTdeGlobaleRelationKey(RelFileLocator rel) static RelKeyData * pg_tde_get_key_from_cache(RelFileNumber rel_number, uint32 key_type) { - RelKeyCacheRec *rec; + RelKeyCacheRec *rec; if (tde_rel_key_cache == NULL) return NULL; 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 && (rel_number == InvalidOid || (rec->rel_number == rel_number)) && rec->key_type & key_type) @@ -1346,23 +1378,23 @@ pg_tde_get_key_from_cache(RelFileNumber rel_number, uint32 key_type) } /* Add key to cache. See comments on `RelKeyCache`. - * + * * TODO: add tests. */ RelKeyData * pg_tde_put_key_into_cache(RelFileNumber rel_num, uint32 key_type, RelKeyData *key) { - static long pageSize = 0; - RelKeyCacheRec *rec; - MemoryContext oldCtx; + static long pageSize = 0; + RelKeyCacheRec *rec; + MemoryContext oldCtx; if (pageSize == 0) { #ifndef _SC_PAGESIZE pageSize = getpagesize(); - #else +#else pageSize = sysconf(_SC_PAGESIZE); - #endif +#endif } if (tde_rel_key_cache == NULL) @@ -1385,17 +1417,18 @@ pg_tde_put_key_into_cache(RelFileNumber rel_num, uint32 key_type, RelKeyData *ke 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. */ - if (tde_rel_key_cache->len+1 > + if (tde_rel_key_cache->len + 1 > (tde_rel_key_cache->cap * sizeof(RelKeyCacheRec)) / sizeof(RelKeyCacheRec)) { - size_t size; - size_t old_size; - RelKeyCacheRec *chachePage; + size_t size; + size_t old_size; + 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)); #ifndef FRONTEND diff --git a/src/access/pg_tde_xlog.c b/src/access/pg_tde_xlog.c index 9f84b4c8..32b93a95 100644 --- a/src/access/pg_tde_xlog.c +++ b/src/access/pg_tde_xlog.c @@ -53,14 +53,15 @@ tdeheap_rmgr_redo(XLogReaderState *record) } else if (info == XLOG_TDE_EXTENSION_INSTALL_KEY) { - XLogExtensionInstall *xlrec = (XLogExtensionInstall *)XLogRecGetData(record); + XLogExtensionInstall *xlrec = (XLogExtensionInstall *) XLogRecGetData(record); extension_install_redo(xlrec); } else if (info == XLOG_TDE_ADD_KEY_PROVIDER_KEY) { - KeyringProviderXLRecord *xlrec = (KeyringProviderXLRecord *)XLogRecGetData(record); + KeyringProviderXLRecord *xlrec = (KeyringProviderXLRecord *) XLogRecGetData(record); + redo_key_provider_info(xlrec); } @@ -97,7 +98,7 @@ tdeheap_rmgr_desc(StringInfo buf, XLogReaderState *record) } 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); } @@ -109,7 +110,7 @@ tdeheap_rmgr_desc(StringInfo buf, XLogReaderState *record) } 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); } diff --git a/src/access/pg_tde_xlog_encrypt.c b/src/access/pg_tde_xlog_encrypt.c index c5856619..e109d382 100644 --- a/src/access/pg_tde_xlog_encrypt.c +++ b/src/access/pg_tde_xlog_encrypt.c @@ -34,7 +34,7 @@ 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 /* GUC */ @@ -44,7 +44,7 @@ static XLogPageHeaderData EncryptCurrentPageHrd; static ssize_t TDEXLogWriteEncryptedPages(int fd, const void *buf, size_t count, off_t offset); static char *TDEXLogEncryptBuf = NULL; -static int XLOGChooseNumBuffers(void); +static int XLOGChooseNumBuffers(void); void XLogInitGUC(void) @@ -52,8 +52,8 @@ XLogInitGUC(void) DefineCustomBoolVariable("pg_tde.wal_encrypt", /* name */ "Enable/Disable encryption of WAL.", /* short_desc */ NULL, /* long_desc */ - &EncryptXLog, /* value address */ - false, /* boot value */ + &EncryptXLog, /* value address */ + false, /* boot value */ PGC_POSTMASTER, /* context */ 0, /* flags */ NULL, /* check_hook */ @@ -75,72 +75,72 @@ XLOGChooseNumBuffers(void) return xbuffers; } -/* +/* * Defines the size of the XLog encryption buffer */ Size TDEXLogEncryptBuffSize(void) { - int xbuffers; + int xbuffers; xbuffers = (XLOGbuffers == -1) ? XLOGChooseNumBuffers() : XLOGbuffers; return (Size) XLOG_BLCKSZ * xbuffers; } -/* +/* * Alloc memory for the encryption buffer. - * + * * It should fit XLog buffers (XLOG_BLCKSZ * wal_buffers). We can't * (re)alloc this buf in tdeheap_xlog_seg_write() based on the write size as * it's called in the CRIT section, hence no allocations are allowed. - * + * * Access to this buffer happens during XLogWrite() call which should * be called with WALWriteLock held, hence no need in extra locks. */ void TDEXLogShmemInit(void) { - bool foundBuf; + bool foundBuf; if (EncryptXLog) { TDEXLogEncryptBuf = (char *) TYPEALIGN(PG_IO_ALIGN_SIZE, - ShmemInitStruct("TDE XLog Encryption Buffer", - XLOG_TDE_ENC_BUFF_ALIGNED_SIZE, - &foundBuf)); + ShmemInitStruct("TDE XLog Encryption Buffer", + XLOG_TDE_ENC_BUFF_ALIGNED_SIZE, + &foundBuf)); elog(DEBUG1, "pg_tde: initialized encryption buffer %lu bytes", XLOG_TDE_ENC_BUFF_ALIGNED_SIZE); } } -/* +/* * Encrypt XLog page(s) from the buf and write to the segment file. */ static ssize_t TDEXLogWriteEncryptedPages(int fd, const void *buf, size_t count, off_t offset) { - char iv_prefix[16] = {0,}; - size_t data_size = 0; - XLogPageHeader curr_page_hdr = &EncryptCurrentPageHrd; - XLogPageHeader enc_buf_page; + char iv_prefix[16] = {0,}; + size_t data_size = 0; + XLogPageHeader curr_page_hdr = &EncryptCurrentPageHrd; + XLogPageHeader enc_buf_page; RelKeyData *key = GetTdeGlobaleRelationKey(GLOBAL_SPACE_RLOCATOR(XLOG_TDE_OID)); - off_t enc_off; - size_t page_size = XLOG_BLCKSZ - offset % XLOG_BLCKSZ; - uint32 iv_ctr = 0; + off_t enc_off; + size_t page_size = XLOG_BLCKSZ - offset % XLOG_BLCKSZ; + uint32 iv_ctr = 0; #ifdef TDE_XLOG_DEBUG elog(DEBUG1, "write encrypted WAL, pages amount: %d, size: %lu offset: %ld", count / (Size) XLOG_BLCKSZ, count, offset); #endif /* - * Go through the buf page-by-page and encrypt them. - * We may start or finish writing from/in the middle of the page - * (walsender or `full_page_writes = off`). So preserve a page header - * for the IV init data. - * - * TODO: check if walsender restarts form the beggining of the page - * in case of the crash. + * Go through the buf page-by-page and encrypt them. We may start or + * finish writing from/in the middle of the page (walsender or + * `full_page_writes = off`). So preserve a page header for the IV init + * data. + * + * TODO: check if walsender restarts form the beggining of the page in + * case of the crash. */ for (enc_off = 0; enc_off < count;) { @@ -150,9 +150,10 @@ TDEXLogWriteEncryptedPages(int fd, const void *buf, size_t count, off_t offset) { 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 - * in the XLog buf (XLogInsert has to have access to records' lsn). + /* + * Need to use a separate buf for the encryption so the page + * remains non-crypted in the XLog buf (XLogInsert has to have + * access to records' lsn). */ enc_buf_page = (XLogPageHeader) (TDEXLogEncryptBuf + enc_off); memcpy((char *) enc_buf_page, (char *) buf + enc_off, (Size) XLogPageHeaderSize(curr_page_hdr)); @@ -163,35 +164,35 @@ TDEXLogWriteEncryptedPages(int fd, const void *buf, size_t count, off_t offset) /* it's a beginning of the page */ iv_ctr = 0; } - else + else { /* we're in the middle of the page */ iv_ctr = (offset % XLOG_BLCKSZ) - XLogPageHeaderSize(curr_page_hdr); } - if (data_size + enc_off > count) + if (data_size + enc_off > count) { data_size = count - enc_off; } - /* - * The page is zeroed (no data), no sense to enctypt. - * This may happen when base_backup or other requests XLOG SWITCH and - * some pages in XLog buffer still not used. - */ + /* + * The page is zeroed (no data), no sense to enctypt. This may happen + * when base_backup or other requests XLOG SWITCH and some pages in + * XLog buffer still not used. + */ if (curr_page_hdr->xlp_magic == 0) { /* ensure all the page is {0} */ - Assert((*((char *) buf + enc_off) == 0) && - memcmp((char *) buf + enc_off, (char *) buf + enc_off + 1, data_size - 1) == 0); + Assert((*((char *) buf + enc_off) == 0) && + memcmp((char *) buf + enc_off, (char *) buf + enc_off + 1, data_size - 1) == 0); memcpy((char *) enc_buf_page, (char *) buf + enc_off, data_size); } else { SetXLogPageIVPrefix(curr_page_hdr->xlp_tli, curr_page_hdr->xlp_pageaddr, iv_prefix); - PG_TDE_ENCRYPT_DATA(iv_prefix, iv_ctr, (char *) buf + enc_off, data_size, - TDEXLogEncryptBuf + enc_off, key); + PG_TDE_ENCRYPT_DATA(iv_prefix, iv_ctr, (char *) buf + enc_off, data_size, + TDEXLogEncryptBuf + enc_off, key); } page_size = XLOG_BLCKSZ; @@ -200,7 +201,7 @@ TDEXLogWriteEncryptedPages(int fd, const void *buf, size_t count, off_t offset) return pg_pwrite(fd, TDEXLogEncryptBuf, count, offset); } -#endif /* !FRONTEND */ +#endif /* !FRONTEND */ void TDEXLogSmgrInit(void) @@ -219,20 +220,20 @@ tdeheap_xlog_seg_write(int fd, const void *buf, size_t count, off_t offset) return pg_pwrite(fd, buf, count, offset); } -/* +/* * Read the XLog pages from the segment file and dectypt if need. */ ssize_t tdeheap_xlog_seg_read(int fd, void *buf, size_t count, off_t offset) { - ssize_t readsz; - char iv_prefix[16] = {0,}; - size_t data_size = 0; - XLogPageHeader curr_page_hdr = &DecryptCurrentPageHrd; + ssize_t readsz; + char iv_prefix[16] = {0,}; + size_t data_size = 0; + XLogPageHeader curr_page_hdr = &DecryptCurrentPageHrd; RelKeyData *key = GetTdeGlobaleRelationKey(GLOBAL_SPACE_RLOCATOR(XLOG_TDE_OID)); - size_t page_size = XLOG_BLCKSZ - offset % XLOG_BLCKSZ; - off_t dec_off; - uint32 iv_ctr = 0; + size_t page_size = XLOG_BLCKSZ - offset % XLOG_BLCKSZ; + off_t dec_off; + uint32 iv_ctr = 0; #ifdef TDE_XLOG_DEBUG elog(DEBUG1, "read from a WAL segment, pages amount: %d, size: %lu offset: %ld", count / (Size) XLOG_BLCKSZ, count, offset); @@ -240,14 +241,14 @@ tdeheap_xlog_seg_read(int fd, void *buf, size_t count, off_t offset) readsz = pg_pread(fd, buf, count, offset); - /* - * Read the buf page by page and decypt ecnrypted pages. - * We may start or fihish reading from/in the middle of the page (walreceiver) - * in such a case we should preserve the last read page header for - * the IV data and the encryption state. - * - * TODO: check if walsender/receiver restarts form the beggining of the page - * in case of the crash. + /* + * Read the buf page by page and decypt ecnrypted pages. We may start or + * fihish reading from/in the middle of the page (walreceiver) in such a + * case we should preserve the last read page header for the IV data and + * the encryption state. + * + * TODO: check if walsender/receiver restarts form the beggining of the + * page in case of the crash. */ for (dec_off = 0; dec_off < readsz;) { @@ -266,13 +267,13 @@ tdeheap_xlog_seg_read(int fd, void *buf, size_t count, off_t offset) /* it's a beginning of the page */ iv_ctr = 0; } - else + else { /* we're in the middle of the page */ iv_ctr = (offset % XLOG_BLCKSZ) - XLogPageHeaderSize(curr_page_hdr); } - if ((data_size + dec_off) > readsz) + if ((data_size + dec_off) > readsz) { data_size = readsz - dec_off; } @@ -281,10 +282,10 @@ tdeheap_xlog_seg_read(int fd, void *buf, size_t count, off_t offset) { SetXLogPageIVPrefix(curr_page_hdr->xlp_tli, curr_page_hdr->xlp_pageaddr, iv_prefix); PG_TDE_DECRYPT_DATA( - iv_prefix, iv_ctr, - (char *) buf + dec_off, data_size, (char *) buf + dec_off, key); + iv_prefix, iv_ctr, + (char *) buf + dec_off, data_size, (char *) buf + dec_off, key); } - + page_size = XLOG_BLCKSZ; dec_off += data_size; } @@ -294,7 +295,7 @@ tdeheap_xlog_seg_read(int fd, void *buf, size_t count, off_t offset) /* IV: TLI(uint32) + XLogRecPtr(uint64)*/ 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[1] = ((tli >> 16) & 0xFF); @@ -311,4 +312,4 @@ SetXLogPageIVPrefix(TimeLineID tli, XLogRecPtr lsn, char* iv_prefix) iv_prefix[11] = (lsn & 0xFF); } -#endif /* PERCONA_EXT */ +#endif /* PERCONA_EXT */ diff --git a/src/catalog/tde_global_space.c b/src/catalog/tde_global_space.c index 5ceab027..3e6091a6 100644 --- a/src/catalog/tde_global_space.c +++ b/src/catalog/tde_global_space.c @@ -41,9 +41,9 @@ #ifndef FRONTEND static void init_keys(void); static void init_default_keyring(void); -static TDEPrincipalKey * create_principal_key(const char *key_name, - GenericKeyring * keyring, Oid dbOid, - Oid spcOid); +static TDEPrincipalKey *create_principal_key(const char *key_name, + GenericKeyring *keyring, Oid dbOid, + Oid spcOid); #endif /* !FRONTEND */ @@ -53,7 +53,7 @@ TDEInitGlobalKeys(const char *dir) #ifndef FRONTEND char db_map_path[MAXPGPATH] = {0}; - pg_tde_set_db_file_paths(GLOBAL_DATA_TDE_OID, GLOBALTABLESPACE_OID, db_map_path, NULL); + pg_tde_set_db_file_paths(GLOBAL_DATA_TDE_OID, GLOBALTABLESPACE_OID, db_map_path, NULL); if (access(db_map_path, F_OK) == -1) { init_default_keyring(); @@ -93,19 +93,19 @@ init_default_keyring(void) static KeyringProvideRecord provider = { .provider_name = KEYRING_DEFAULT_NAME, - .provider_type = FILE_KEY_PROVIDER, + .provider_type = FILE_KEY_PROVIDER, }; if (getcwd(path, sizeof(path)) == NULL) elog(WARNING, "unable to get current working dir"); - + /* TODO: not sure about the location. Currently it's in $PGDATA */ join_path_components(path, path, KEYRING_DEFAULT_FILE_NAME); snprintf(provider.options, MAX_KEYRING_OPTION_LEN, "{" "\"type\": \"file\"," - "\"path\": \"%s\"" + "\"path\": \"%s\"" "}", path ); @@ -173,7 +173,7 @@ init_keys(void) * first. */ static TDEPrincipalKey * -create_principal_key(const char *key_name, GenericKeyring * keyring, +create_principal_key(const char *key_name, GenericKeyring *keyring, Oid dbOid, Oid spcOid) { TDEPrincipalKey *principalKey; @@ -198,6 +198,7 @@ create_principal_key(const char *key_name, GenericKeyring * keyring, } principalKey->keyLength = keyInfo->data.len; + memcpy(principalKey->keyData, keyInfo->data.data, keyInfo->data.len); return principalKey; diff --git a/src/catalog/tde_keyring.c b/src/catalog/tde_keyring.c index 379abeec..954a079a 100644 --- a/src/catalog/tde_keyring.c +++ b/src/catalog/tde_keyring.c @@ -37,7 +37,7 @@ #else #include "fe_utils/simple_list.h" #include "pg_tde_fe.h" -#endif /* !FRONTEND */ +#endif /* !FRONTEND */ typedef enum ProviderScanType { @@ -45,7 +45,7 @@ typedef enum ProviderScanType PROVIDER_SCAN_BY_ID, PROVIDER_SCAN_BY_TYPE, PROVIDER_SCAN_ALL -} ProviderScanType; +} ProviderScanType; #define PG_TDE_KEYRING_FILENAME "pg_tde_keyrings" @@ -55,7 +55,7 @@ static VaultV2Keyring *load_vaultV2_keyring_provider_options(char *keyring_optio static void debug_print_kerying(GenericKeyring *keyring); static GenericKeyring *load_keyring_provider_from_record(KeyringProvideRecord *provider); 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 @@ -67,18 +67,18 @@ static void simple_list_free(SimplePtrList *list); static List *scan_key_provider_file(ProviderScanType scanType, void *scanKey, Oid dbOid, Oid spcOid); PG_FUNCTION_INFO_V1(pg_tde_add_key_provider_internal); -Datum pg_tde_add_key_provider_internal(PG_FUNCTION_ARGS); +Datum pg_tde_add_key_provider_internal(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1(pg_tde_list_all_key_providers); -Datum pg_tde_list_all_key_providers(PG_FUNCTION_ARGS); +Datum pg_tde_list_all_key_providers(PG_FUNCTION_ARGS); #define PG_TDE_LIST_PROVIDERS_COLS 4 static void key_provider_startup_cleanup(int tde_tbl_count, XLogExtensionInstall *ext_info, bool redo, void *arg); static const char *get_keyring_provider_typename(ProviderType p_type); -static uint32 write_key_provider_info(KeyringProvideRecord *provider, - Oid database_id, Oid tablespace_id, - off_t position, bool redo, bool recovery); +static uint32 write_key_provider_info(KeyringProvideRecord *provider, + Oid database_id, Oid tablespace_id, + off_t position, bool redo, bool recovery); static Size initialize_shared_state(void *start_address); static Size required_shared_mem_size(void); @@ -88,14 +88,14 @@ typedef struct TdeKeyProviderInfoSharedState LWLockPadded *Locks; } TdeKeyProviderInfoSharedState; -TdeKeyProviderInfoSharedState* sharedPrincipalKeyState = NULL; /* Lives in shared state */ +TdeKeyProviderInfoSharedState *sharedPrincipalKeyState = NULL; /* Lives in shared state */ static const TDEShmemSetupRoutine key_provider_info_shmem_routine = { .init_shared_state = initialize_shared_state, .init_dsa_area_objects = NULL, .required_shared_mem_size = required_shared_mem_size, .shmem_kill = NULL - }; +}; static Size required_shared_mem_size(void) @@ -106,7 +106,7 @@ required_shared_mem_size(void) static Size initialize_shared_state(void *start_address) { - sharedPrincipalKeyState = (TdeKeyProviderInfoSharedState *)start_address; + sharedPrincipalKeyState = (TdeKeyProviderInfoSharedState *) start_address; sharedPrincipalKeyState->Locks = GetNamedLWLockTranche(TDE_TRANCHE_NAME); return sizeof(TdeKeyProviderInfoSharedState); @@ -119,7 +119,8 @@ tde_provider_info_lock(void) return &sharedPrincipalKeyState->Locks[TDE_LWLOCK_PI_FILES].lock; } -void InitializeKeyProviderInfo(void) +void +InitializeKeyProviderInfo(void) { ereport(LOG, (errmsg("initializing TDE key provider info"))); RegisterShmemRequest(&key_provider_info_shmem_routine); @@ -156,12 +157,12 @@ get_keyring_provider_typename(ProviderType p_type) { switch (p_type) { - case FILE_KEY_PROVIDER: - return FILE_KEYRING_TYPE; - case VAULT_V2_KEY_PROVIDER: - return VAULTV2_KEYRING_TYPE; - default: - break; + case FILE_KEY_PROVIDER: + return FILE_KEYRING_TYPE; + case VAULT_V2_KEY_PROVIDER: + return VAULTV2_KEYRING_TYPE; + default: + break; } return NULL; } @@ -176,10 +177,11 @@ GenericKeyring * GetKeyProviderByName(const char *provider_name, Oid dbOid, Oid spcOid) { 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) { - keyring = (GenericKeyring *)linitial(providers); + keyring = (GenericKeyring *) linitial(providers); list_free(providers); } else @@ -194,14 +196,14 @@ GetKeyProviderByName(const char *provider_name, Oid dbOid, Oid spcOid) static uint32 -write_key_provider_info(KeyringProvideRecord *provider, Oid database_id, - Oid tablespace_id, off_t position, bool redo, bool recovery) +write_key_provider_info(KeyringProvideRecord *provider, Oid database_id, + Oid tablespace_id, off_t position, bool redo, bool recovery) { - off_t bytes_written = 0; - off_t curr_pos = 0; - int fd; - int max_provider_id = 0; - char kp_info_path[MAXPGPATH] = {0}; + off_t bytes_written = 0; + off_t curr_pos = 0; + int fd; + int max_provider_id = 0; + char kp_info_path[MAXPGPATH] = {0}; KeyringProvideRecord existing_provider; Assert(provider != NULL); @@ -215,12 +217,15 @@ write_key_provider_info(KeyringProvideRecord *provider, Oid database_id, { LWLockRelease(tde_provider_info_lock()); ereport(ERROR, - (errcode_for_file_access(), - errmsg("could not open tde file \"%s\": %m", kp_info_path))); + (errcode_for_file_access(), + errmsg("could not open tde file \"%s\": %m", kp_info_path))); } if (!redo) { - /* 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)) { if (strcmp(existing_provider.provider_name, provider->provider_name) == 0) @@ -229,7 +234,7 @@ write_key_provider_info(KeyringProvideRecord *provider, Oid database_id, LWLockRelease(tde_provider_info_lock()); ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), - errmsg("key provider \"%s\" already exists", provider->provider_name))); + errmsg("key provider \"%s\" already exists", provider->provider_name))); } if (max_provider_id < existing_provider.provider_id) max_provider_id = existing_provider.provider_id; @@ -237,7 +242,8 @@ write_key_provider_info(KeyringProvideRecord *provider, Oid database_id, provider->provider_id = max_provider_id + 1; 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. */ if (!recovery) @@ -250,18 +256,20 @@ write_key_provider_info(KeyringProvideRecord *provider, Oid database_id, memcpy(&xlrec.provider, provider, sizeof(KeyringProvideRecord)); XLogBeginInsert(); - XLogRegisterData((char *)&xlrec, sizeof(KeyringProviderXLRecord)); + XLogRegisterData((char *) &xlrec, sizeof(KeyringProviderXLRecord)); XLogInsert(RM_TDERMGR_ID, XLOG_TDE_ADD_KEY_PROVIDER_KEY); } } else { - /* we are performing redo, just go to the position received from the - * xlog and write the record there. - * No need to verify the name conflict and generate the provider ID + /* + * we are performing redo, just go to the position received from the + * 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); } + /* * All good, Just add a new provider */ @@ -293,13 +301,13 @@ write_key_provider_info(KeyringProvideRecord *provider, Oid database_id, * Save the key provider info to the file */ uint32 -save_new_key_provider_info(KeyringProvideRecord* provider, Oid databaseId, Oid tablespaceId, bool recovery) +save_new_key_provider_info(KeyringProvideRecord *provider, Oid databaseId, Oid tablespaceId, bool recovery) { return write_key_provider_info(provider, databaseId, tablespaceId, 0, false, recovery); } 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); } @@ -308,7 +316,7 @@ void cleanup_key_provider_info(Oid databaseId, Oid tablespaceId) { /* Remove the key provider info file */ - char kp_info_path[MAXPGPATH] = {0}; + char kp_info_path[MAXPGPATH] = {0}; get_keyring_infofile_path(kp_info_path, databaseId, tablespaceId); PathNameDeleteTemporaryFile(kp_info_path, false); @@ -317,13 +325,13 @@ cleanup_key_provider_info(Oid databaseId, Oid tablespaceId) Datum pg_tde_add_key_provider_internal(PG_FUNCTION_ARGS) { - char *provider_type = text_to_cstring(PG_GETARG_TEXT_PP(0)); - char *provider_name = text_to_cstring(PG_GETARG_TEXT_PP(1)); - char *options = text_to_cstring(PG_GETARG_TEXT_PP(2)); - bool is_global = PG_GETARG_BOOL(3); + char *provider_type = text_to_cstring(PG_GETARG_TEXT_PP(0)); + char *provider_name = text_to_cstring(PG_GETARG_TEXT_PP(1)); + char *options = text_to_cstring(PG_GETARG_TEXT_PP(2)); + bool is_global = PG_GETARG_BOOL(3); KeyringProvideRecord provider; - Oid dbOid = MyDatabaseId; - Oid spcOid = MyDatabaseTableSpace; + Oid dbOid = MyDatabaseId; + Oid spcOid = MyDatabaseTableSpace; if (is_global) { @@ -342,13 +350,14 @@ pg_tde_add_key_provider_internal(PG_FUNCTION_ARGS) Datum pg_tde_list_all_key_providers(PG_FUNCTION_ARGS) { - List* all_providers = GetAllKeyringProviders(MyDatabaseId, MyDatabaseTableSpace); - ListCell *lc; + List *all_providers = GetAllKeyringProviders(MyDatabaseId, MyDatabaseTableSpace); + ListCell *lc; Tuplestorestate *tupstore; - TupleDesc tupdesc; + TupleDesc tupdesc; MemoryContext per_query_ctx; MemoryContext oldcontext; - ReturnSetInfo *rsinfo = (ReturnSetInfo *)fcinfo->resultinfo; + ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; + /* check to see if caller supports us returning a tuplestore */ if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo)) ereport(ERROR, @@ -374,12 +383,12 @@ pg_tde_list_all_key_providers(PG_FUNCTION_ARGS) MemoryContextSwitchTo(oldcontext); - foreach (lc, all_providers) + foreach(lc, all_providers) { - Datum values[PG_TDE_LIST_PROVIDERS_COLS] = {0}; - bool nulls[PG_TDE_LIST_PROVIDERS_COLS] = {0}; - GenericKeyring *keyring = (GenericKeyring *)lfirst(lc); - int i = 0; + Datum values[PG_TDE_LIST_PROVIDERS_COLS] = {0}; + bool nulls[PG_TDE_LIST_PROVIDERS_COLS] = {0}; + GenericKeyring *keyring = (GenericKeyring *) lfirst(lc); + int i = 0; values[i++] = Int32GetDatum(keyring->key_id); values[i++] = CStringGetTextDatum(keyring->provider_name); @@ -390,23 +399,24 @@ pg_tde_list_all_key_providers(PG_FUNCTION_ARGS) debug_print_kerying(keyring); } list_free_deep(all_providers); - return (Datum)0; + return (Datum) 0; } GenericKeyring * GetKeyProviderByID(int provider_id, Oid dbOid, Oid spcOid) { 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) { - keyring = (GenericKeyring *)linitial(providers); + keyring = (GenericKeyring *) linitial(providers); list_free(providers); } return keyring; } -#endif /* !FRONTEND */ +#endif /* !FRONTEND */ #ifdef FRONTEND GenericKeyring * @@ -414,6 +424,7 @@ GetKeyProviderByID(int provider_id, Oid dbOid, Oid spcOid) { GenericKeyring *keyring = NULL; SimplePtrList *providers = scan_key_provider_file(PROVIDER_SCAN_BY_ID, &provider_id, dbOid, spcOid); + if (providers != NULL) { keyring = (GenericKeyring *) providers->head->ptr; @@ -437,7 +448,7 @@ simple_list_free(SimplePtrList *list) cell = next; } } -#endif /* FRONTEND */ +#endif /* FRONTEND */ /* * Scan the key provider info file and can also apply filter based on scanType @@ -449,12 +460,12 @@ static SimplePtrList * #endif scan_key_provider_file(ProviderScanType scanType, void *scanKey, Oid dbOid, Oid spcOid) { - off_t curr_pos = 0; - int fd; - char kp_info_path[MAXPGPATH] = {0}; + off_t curr_pos = 0; + int fd; + char kp_info_path[MAXPGPATH] = {0}; KeyringProvideRecord provider; #ifndef FRONTEND - List *providers_list = NIL; + List *providers_list = NIL; #else SimplePtrList *providers_list = NULL; #endif @@ -471,29 +482,30 @@ scan_key_provider_file(ProviderScanType scanType, void *scanKey, Oid dbOid, Oid { LWLockRelease(tde_provider_info_lock()); ereport(DEBUG2, - (errcode_for_file_access(), - errmsg("could not open tde file \"%s\": %m", kp_info_path))); + (errcode_for_file_access(), + errmsg("could not open tde file \"%s\": %m", kp_info_path))); return providers_list; } while (fetch_next_key_provider(fd, &curr_pos, &provider)) { - bool match = false; + bool match = false; + 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 (strcasecmp(provider.provider_name, (char*)scanKey) == 0) + if (strcasecmp(provider.provider_name, (char *) scanKey) == 0) match = true; } else if (scanType == PROVIDER_SCAN_BY_ID) { - if (provider.provider_id == *(int *)scanKey) + if (provider.provider_id == *(int *) scanKey) match = true; } else if (scanType == PROVIDER_SCAN_BY_TYPE) { - if (provider.provider_type == *(ProviderType*)scanKey) + if (provider.provider_type == *(ProviderType *) scanKey) match = true; } else if (scanType == PROVIDER_SCAN_ALL) @@ -502,6 +514,7 @@ scan_key_provider_file(ProviderScanType scanType, void *scanKey, Oid dbOid, Oid if (match) { GenericKeyring *keyring = load_keyring_provider_from_record(&provider); + if (keyring) { #ifndef FRONTEND @@ -542,14 +555,14 @@ load_keyring_provider_options(ProviderType provider_type, char *keyring_options) { switch (provider_type) { - case FILE_KEY_PROVIDER: - return (GenericKeyring *)load_file_keyring_provider_options(keyring_options); - break; - case VAULT_V2_KEY_PROVIDER: - return (GenericKeyring *)load_vaultV2_keyring_provider_options(keyring_options); - break; - default: - break; + case FILE_KEY_PROVIDER: + return (GenericKeyring *) load_file_keyring_provider_options(keyring_options); + break; + case VAULT_V2_KEY_PROVIDER: + return (GenericKeyring *) load_vaultV2_keyring_provider_options(keyring_options); + break; + default: + break; } return NULL; } @@ -557,17 +570,17 @@ load_keyring_provider_options(ProviderType provider_type, char *keyring_options) static FileKeyring * load_file_keyring_provider_options(char *keyring_options) { - FileKeyring *file_keyring = palloc0(sizeof(FileKeyring)); + FileKeyring *file_keyring = palloc0(sizeof(FileKeyring)); file_keyring->keyring.type = FILE_KEY_PROVIDER; - if (!ParseKeyringJSONOptions(FILE_KEY_PROVIDER, file_keyring, - keyring_options, strlen(keyring_options))) + if (!ParseKeyringJSONOptions(FILE_KEY_PROVIDER, file_keyring, + keyring_options, strlen(keyring_options))) { return NULL; } - if(strlen(file_keyring->file_name) == 0) + if (strlen(file_keyring->file_name) == 0) { ereport(WARNING, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), @@ -581,26 +594,26 @@ load_file_keyring_provider_options(char *keyring_options) static VaultV2Keyring * load_vaultV2_keyring_provider_options(char *keyring_options) { - VaultV2Keyring *vaultV2_keyring = palloc0(sizeof(VaultV2Keyring)); + VaultV2Keyring *vaultV2_keyring = palloc0(sizeof(VaultV2Keyring)); vaultV2_keyring->keyring.type = VAULT_V2_KEY_PROVIDER; - if (!ParseKeyringJSONOptions(VAULT_V2_KEY_PROVIDER, vaultV2_keyring, - keyring_options, strlen(keyring_options))) + if (!ParseKeyringJSONOptions(VAULT_V2_KEY_PROVIDER, vaultV2_keyring, + keyring_options, strlen(keyring_options))) { return NULL; } - - if(strlen(vaultV2_keyring->vault_token) == 0 || - strlen(vaultV2_keyring->vault_url) == 0 || + + if (strlen(vaultV2_keyring->vault_token) == 0 || + strlen(vaultV2_keyring->vault_url) == 0 || strlen(vaultV2_keyring->vault_mount_path) == 0) { ereport(WARNING, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("missing in the keyring options:%s%s%s", - *(vaultV2_keyring->vault_token) ? "" : " token", - *(vaultV2_keyring->vault_url) ? "" : " url", - *(vaultV2_keyring->vault_mount_path) ? "" : " mountPath"))); + *(vaultV2_keyring->vault_token) ? "" : " token", + *(vaultV2_keyring->vault_url) ? "" : " url", + *(vaultV2_keyring->vault_mount_path) ? "" : " mountPath"))); return NULL; } @@ -610,31 +623,33 @@ load_vaultV2_keyring_provider_options(char *keyring_options) static void 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 name: %s", keyring->provider_name); elog(debug_level, "Keyring id: %d", keyring->key_id); switch (keyring->type) { - case FILE_KEY_PROVIDER: - elog(debug_level, "File Keyring Path: %s", ((FileKeyring *)keyring)->file_name); - break; - case VAULT_V2_KEY_PROVIDER: - 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 Mount Path: %s", ((VaultV2Keyring *)keyring)->vault_mount_path); - elog(debug_level, "Vault Keyring CA Path: %s", ((VaultV2Keyring *)keyring)->vault_ca_path); - break; - case UNKNOWN_KEY_PROVIDER: - elog(debug_level, "Unknown Keyring "); - break; + case FILE_KEY_PROVIDER: + elog(debug_level, "File Keyring Path: %s", ((FileKeyring *) keyring)->file_name); + break; + case VAULT_V2_KEY_PROVIDER: + 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 Mount Path: %s", ((VaultV2Keyring *) keyring)->vault_mount_path); + elog(debug_level, "Vault Keyring CA Path: %s", ((VaultV2Keyring *) keyring)->vault_ca_path); + break; + case UNKNOWN_KEY_PROVIDER: + elog(debug_level, "Unknown Keyring "); + break; } } -static char* -get_keyring_infofile_path(char* resPath, Oid dbOid, Oid spcOid) +static char * +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); join_path_components(resPath, db_path, PG_TDE_KEYRING_FILENAME); pfree(db_path); @@ -645,9 +660,9 @@ get_keyring_infofile_path(char* resPath, Oid dbOid, Oid spcOid) * Fetch the next key provider from the file and update the curr_pos */ 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; Assert(provider != NULL); Assert(fd >= 0); @@ -663,8 +678,8 @@ fetch_next_key_provider(int fd, off_t* curr_pos, KeyringProvideRecord *provider) /* Corrupt file */ ereport(ERROR, (errcode_for_file_access(), - errmsg("key provider info file is corrupted: %m"), - errdetail("invalid key provider record size %lld expected %lu", bytes_read, sizeof(KeyringProvideRecord) ))); + errmsg("key provider info file is corrupted: %m"), + errdetail("invalid key provider record size %lld expected %lu", bytes_read, sizeof(KeyringProvideRecord)))); } return true; } diff --git a/src/catalog/tde_keyring_parse_opts.c b/src/catalog/tde_keyring_parse_opts.c index 9c095a87..b9b4238c 100644 --- a/src/catalog/tde_keyring_parse_opts.c +++ b/src/catalog/tde_keyring_parse_opts.c @@ -2,7 +2,7 @@ * * tde_keyring_parse_opts.c * Parser routines for the keyring JSON options - * + * * Each value in the JSON document can be either scalar (string) - a value itself * or a reference to the external object that contains the value. Though the top * level field "type" can be only scalar. @@ -120,14 +120,14 @@ typedef struct JsonKeyringState char *field_type; char *extern_url; char *extern_path; -} JsonKeyringState; +} JsonKeyringState; static JsonParseErrorType json_kring_scalar(void *state, char *token, JsonTokenType tokentype); static JsonParseErrorType json_kring_object_field_start(void *state, char *fname, bool isnull); static JsonParseErrorType json_kring_object_start(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_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 -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; FileKeyring *file = parse->provider_opts; @@ -437,7 +437,7 @@ get_remote_kring_value(const char *url, const char *field_name) /* remove trailing whitespace */ outStr.ptr[strcspn(outStr.ptr, " \t\n\r")] = '\0'; - + return outStr.ptr; } diff --git a/src/catalog/tde_principal_key.c b/src/catalog/tde_principal_key.c index 13e3fc78..f51879f2 100644 --- a/src/catalog/tde_principal_key.c +++ b/src/catalog/tde_principal_key.c @@ -42,28 +42,27 @@ typedef struct TdePrincipalKeySharedState { - LWLockPadded *Locks; - int hashTrancheId; - dshash_table_handle hashHandle; - void *rawDsaArea; /* DSA area pointer */ + LWLockPadded *Locks; + int hashTrancheId; + dshash_table_handle hashHandle; + void *rawDsaArea; /* DSA area pointer */ } TdePrincipalKeySharedState; typedef struct TdePrincipalKeylocalState { - TdePrincipalKeySharedState *sharedPrincipalKeyState; - dsa_area *dsa; /* local dsa area for backend attached to the - * dsa area created by postmaster at startup. - */ - dshash_table *sharedHash; + TdePrincipalKeySharedState *sharedPrincipalKeyState; + dsa_area *dsa; /* local dsa area for backend attached to the + * dsa area created by postmaster at startup. */ + dshash_table *sharedHash; } TdePrincipalKeylocalState; /* parameter for the principal key info shared hash */ static dshash_parameters principal_key_dsh_params = { - sizeof(Oid), - sizeof(TDEPrincipalKey), - dshash_memcmp, /* TODO use int compare instead */ - dshash_memhash}; + sizeof(Oid), + sizeof(TDEPrincipalKey), + dshash_memcmp, /* TODO use int compare instead */ +dshash_memhash}; TdePrincipalKeylocalState principalKeyLocalState; @@ -74,32 +73,33 @@ static Size cache_area_size(void); static Size required_shared_mem_size(void); 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 clear_principal_key_cache(Oid databaseId) ; +static void clear_principal_key_cache(Oid databaseId); 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_cache(Oid dbOid); static void push_principal_key_to_cache(TDEPrincipalKey *principalKey); static Datum pg_tde_get_key_info(PG_FUNCTION_ARGS, Oid dbOid, Oid spcOid); -static keyInfo *load_latest_versioned_key_name(TDEPrincipalKeyInfo *principal_key_info, - GenericKeyring *keyring, - bool ensure_new_key); -static TDEPrincipalKey *set_principal_key_with_keyring(const char *key_name, - GenericKeyring *keyring, - Oid dbOid, Oid spcOid, - bool ensure_new_key); +static keyInfo *load_latest_versioned_key_name(TDEPrincipalKeyInfo *principal_key_info, + GenericKeyring *keyring, + bool ensure_new_key); +static TDEPrincipalKey *set_principal_key_with_keyring(const char *key_name, + GenericKeyring *keyring, + Oid dbOid, Oid spcOid, + bool ensure_new_key); static const TDEShmemSetupRoutine principal_key_info_shmem_routine = { - .init_shared_state = initialize_shared_state, - .init_dsa_area_objects = initialize_objects_in_dsa_area, - .required_shared_mem_size = required_shared_mem_size, - .shmem_kill = shared_memory_shutdown - }; + .init_shared_state = initialize_shared_state, + .init_dsa_area_objects = initialize_objects_in_dsa_area, + .required_shared_mem_size = required_shared_mem_size, + .shmem_kill = shared_memory_shutdown +}; -void InitializePrincipalKeyInfo(void) +void +InitializePrincipalKeyInfo(void) { - ereport(LOG, (errmsg("Initializing TDE principal key info"))); - RegisterShmemRequest(&principal_key_info_shmem_routine); - on_ext_install(principal_key_startup_cleanup, NULL); + ereport(LOG, (errmsg("Initializing TDE principal key info"))); + RegisterShmemRequest(&principal_key_info_shmem_routine); + on_ext_install(principal_key_startup_cleanup, NULL); } /* @@ -109,23 +109,24 @@ void InitializePrincipalKeyInfo(void) LWLock * tde_lwlock_enc_keys(void) { - Assert(principalKeyLocalState.sharedPrincipalKeyState); + Assert(principalKeyLocalState.sharedPrincipalKeyState); - return &principalKeyLocalState.sharedPrincipalKeyState->Locks[TDE_LWLOCK_ENC_KEY].lock; + return &principalKeyLocalState.sharedPrincipalKeyState->Locks[TDE_LWLOCK_ENC_KEY].lock; } static Size cache_area_size(void) { - return MAXALIGN(8192 * 100); /* TODO: Probably get it from guc */ + return MAXALIGN(8192 * 100); /* TODO: Probably get it from guc */ } static Size required_shared_mem_size(void) { - Size sz = cache_area_size(); - sz = add_size(sz, sizeof(TdePrincipalKeySharedState)); - return MAXALIGN(sz); + Size sz = cache_area_size(); + + sz = add_size(sz, sizeof(TdePrincipalKeySharedState)); + return MAXALIGN(sz); } /* @@ -136,35 +137,37 @@ required_shared_mem_size(void) static Size initialize_shared_state(void *start_address) { - TdePrincipalKeySharedState *sharedState = (TdePrincipalKeySharedState *)start_address; - ereport(LOG, (errmsg("initializing shared state for principal key"))); - principalKeyLocalState.dsa = NULL; - principalKeyLocalState.sharedHash = NULL; + TdePrincipalKeySharedState *sharedState = (TdePrincipalKeySharedState *) start_address; + + ereport(LOG, (errmsg("initializing shared state for principal key"))); + principalKeyLocalState.dsa = NULL; + principalKeyLocalState.sharedHash = NULL; - sharedState->Locks = GetNamedLWLockTranche(TDE_TRANCHE_NAME); + sharedState->Locks = GetNamedLWLockTranche(TDE_TRANCHE_NAME); - principalKeyLocalState.sharedPrincipalKeyState = sharedState; - return sizeof(TdePrincipalKeySharedState); + principalKeyLocalState.sharedPrincipalKeyState = sharedState; + 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; - TdePrincipalKeySharedState *sharedState = principalKeyLocalState.sharedPrincipalKeyState; + dshash_table *dsh; + TdePrincipalKeySharedState *sharedState = principalKeyLocalState.sharedPrincipalKeyState; - ereport(LOG, (errmsg("initializing dsa area objects for principal key"))); + ereport(LOG, (errmsg("initializing dsa area objects for principal key"))); - Assert(sharedState != NULL); + Assert(sharedState != NULL); - sharedState->rawDsaArea = raw_dsa_area; - sharedState->hashTrancheId = LWLockNewTrancheId(); - principal_key_dsh_params.tranche_id = sharedState->hashTrancheId; + sharedState->rawDsaArea = raw_dsa_area; + sharedState->hashTrancheId = LWLockNewTrancheId(); + principal_key_dsh_params.tranche_id = sharedState->hashTrancheId; #if PG_VERSION_NUM >= 170000 - principal_key_dsh_params.copy_function = dshash_memcpy; + principal_key_dsh_params.copy_function = dshash_memcpy; #endif - dsh = dshash_create(dsa, &principal_key_dsh_params, 0); - sharedState->hashHandle = dshash_get_hash_table_handle(dsh); - dshash_detach(dsh); + dsh = dshash_create(dsa, &principal_key_dsh_params, 0); + sharedState->hashHandle = dshash_get_hash_table_handle(dsh); + dshash_detach(dsh); } /* @@ -173,44 +176,44 @@ void initialize_objects_in_dsa_area(dsa_area *dsa, void *raw_dsa_area) static void principal_key_info_attach_shmem(void) { - MemoryContext oldcontext; - - if (principalKeyLocalState.dsa) - return; - - /* - * We want the dsa to remain valid throughout the lifecycle of this - * process. so switch to TopMemoryContext before attaching - */ - oldcontext = MemoryContextSwitchTo(TopMemoryContext); - - principalKeyLocalState.dsa = dsa_attach_in_place(principalKeyLocalState.sharedPrincipalKeyState->rawDsaArea, - NULL); - - /* - * pin the attached area to keep the area attached until end of session or - * explicit detach. - */ - dsa_pin_mapping(principalKeyLocalState.dsa); - - principal_key_dsh_params.tranche_id = principalKeyLocalState.sharedPrincipalKeyState->hashTrancheId; - principalKeyLocalState.sharedHash = dshash_attach(principalKeyLocalState.dsa, &principal_key_dsh_params, - principalKeyLocalState.sharedPrincipalKeyState->hashHandle, 0); - MemoryContextSwitchTo(oldcontext); + MemoryContext oldcontext; + + if (principalKeyLocalState.dsa) + return; + + /* + * We want the dsa to remain valid throughout the lifecycle of this + * process. so switch to TopMemoryContext before attaching + */ + oldcontext = MemoryContextSwitchTo(TopMemoryContext); + + principalKeyLocalState.dsa = dsa_attach_in_place(principalKeyLocalState.sharedPrincipalKeyState->rawDsaArea, + NULL); + + /* + * pin the attached area to keep the area attached until end of session or + * explicit detach. + */ + dsa_pin_mapping(principalKeyLocalState.dsa); + + principal_key_dsh_params.tranche_id = principalKeyLocalState.sharedPrincipalKeyState->hashTrancheId; + principalKeyLocalState.sharedHash = dshash_attach(principalKeyLocalState.dsa, &principal_key_dsh_params, + principalKeyLocalState.sharedPrincipalKeyState->hashHandle, 0); + MemoryContextSwitchTo(oldcontext); } static void shared_memory_shutdown(int code, Datum arg) { - principalKeyLocalState.sharedPrincipalKeyState = NULL; + principalKeyLocalState.sharedPrincipalKeyState = NULL; } bool save_principal_key_info(TDEPrincipalKeyInfo *principal_key_info) { - Assert(principal_key_info != NULL); + Assert(principal_key_info != NULL); - return pg_tde_save_principal_key(principal_key_info); + return pg_tde_save_principal_key(principal_key_info); } /* @@ -219,159 +222,162 @@ save_principal_key_info(TDEPrincipalKeyInfo *principal_key_info) */ TDEPrincipalKey * set_principal_key_with_keyring(const char *key_name, GenericKeyring *keyring, - Oid dbOid, Oid spcOid, bool ensure_new_key) + Oid dbOid, Oid spcOid, bool ensure_new_key) { - TDEPrincipalKey *principalKey = NULL; - LWLock *lock_files = tde_lwlock_enc_keys(); - bool is_dup_key = false; + TDEPrincipalKey *principalKey = NULL; + LWLock *lock_files = tde_lwlock_enc_keys(); + bool is_dup_key = false; - /* - * Try to get principal key from cache. - */ - LWLockAcquire(lock_files, LW_EXCLUSIVE); + /* + * Try to get principal key from cache. + */ + LWLockAcquire(lock_files, LW_EXCLUSIVE); - principalKey = get_principal_key_from_cache(dbOid); - is_dup_key = (principalKey != NULL); + principalKey = get_principal_key_from_cache(dbOid); + is_dup_key = (principalKey != NULL); - /* TODO: Add the key in the cache? */ - if (!is_dup_key) - is_dup_key = (pg_tde_get_principal_key_info(dbOid, spcOid) != NULL); + /* TODO: Add the key in the cache? */ + if (!is_dup_key) + is_dup_key = (pg_tde_get_principal_key_info(dbOid, spcOid) != NULL); - if (!is_dup_key) - { - const keyInfo *keyInfo = NULL; + if (!is_dup_key) + { + const keyInfo *keyInfo = NULL; - principalKey = palloc(sizeof(TDEPrincipalKey)); - principalKey->keyInfo.databaseId = dbOid; - principalKey->keyInfo.tablespaceId = spcOid; - principalKey->keyInfo.keyId.version = DEFAULT_PRINCIPAL_KEY_VERSION; - principalKey->keyInfo.keyringId = keyring->key_id; - strncpy(principalKey->keyInfo.keyId.name, key_name, TDE_KEY_NAME_LEN); - gettimeofday(&principalKey->keyInfo.creationTime, NULL); + principalKey = palloc(sizeof(TDEPrincipalKey)); + principalKey->keyInfo.databaseId = dbOid; + principalKey->keyInfo.tablespaceId = spcOid; + principalKey->keyInfo.keyId.version = DEFAULT_PRINCIPAL_KEY_VERSION; + principalKey->keyInfo.keyringId = keyring->key_id; + strncpy(principalKey->keyInfo.keyId.name, key_name, TDE_KEY_NAME_LEN); + gettimeofday(&principalKey->keyInfo.creationTime, NULL); - keyInfo = load_latest_versioned_key_name(&principalKey->keyInfo, keyring, ensure_new_key); + keyInfo = load_latest_versioned_key_name(&principalKey->keyInfo, keyring, ensure_new_key); - if (keyInfo == NULL) - keyInfo = KeyringGenerateNewKeyAndStore(keyring, principalKey->keyInfo.keyId.versioned_name, INTERNAL_KEY_LEN, false); + if (keyInfo == NULL) + keyInfo = KeyringGenerateNewKeyAndStore(keyring, principalKey->keyInfo.keyId.versioned_name, INTERNAL_KEY_LEN, false); - if (keyInfo == NULL) - { - LWLockRelease(lock_files); + if (keyInfo == NULL) + { + LWLockRelease(lock_files); - ereport(ERROR, - (errmsg("failed to retrieve principal key. Create one using pg_tde_set_principal_key before using encrypted tables."))); - } + ereport(ERROR, + (errmsg("failed to retrieve principal key. Create one using pg_tde_set_principal_key before using encrypted tables."))); + } - principalKey->keyLength = keyInfo->data.len; - memcpy(principalKey->keyData, keyInfo->data.data, keyInfo->data.len); + principalKey->keyLength = keyInfo->data.len; - save_principal_key_info(&principalKey->keyInfo); + memcpy(principalKey->keyData, keyInfo->data.data, keyInfo->data.len); - /* XLog the new key*/ - XLogBeginInsert(); - XLogRegisterData((char *) &principalKey->keyInfo, sizeof(TDEPrincipalKeyInfo)); - XLogInsert(RM_TDERMGR_ID, XLOG_TDE_ADD_PRINCIPAL_KEY); + save_principal_key_info(&principalKey->keyInfo); - push_principal_key_to_cache(principalKey); - } + /* XLog the new key */ + XLogBeginInsert(); + XLogRegisterData((char *) &principalKey->keyInfo, sizeof(TDEPrincipalKeyInfo)); + XLogInsert(RM_TDERMGR_ID, XLOG_TDE_ADD_PRINCIPAL_KEY); - LWLockRelease(lock_files); + push_principal_key_to_cache(principalKey); + } - if (is_dup_key) - { - /* - * Seems like just before we got the lock, the key was installed by some other caller - * Throw an error and mover no - */ + LWLockRelease(lock_files); - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_OBJECT), - errmsg("Principal key already exists for the database"), - errhint("Use rotate_key interface to change the principal key"))); - } + if (is_dup_key) + { + /* + * Seems like just before we got the lock, the key was installed by + * some other caller Throw an error and mover no + */ - return principalKey; + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("Principal key already exists for the database"), + errhint("Use rotate_key interface to change the principal key"))); + } + + return principalKey; } bool SetPrincipalKey(const char *key_name, const char *provider_name, bool ensure_new_key) { - TDEPrincipalKey *principal_key = set_principal_key_with_keyring(key_name, - GetKeyProviderByName(provider_name, MyDatabaseId, MyDatabaseTableSpace), - MyDatabaseId, MyDatabaseTableSpace, - ensure_new_key); + TDEPrincipalKey *principal_key = set_principal_key_with_keyring(key_name, + GetKeyProviderByName(provider_name, MyDatabaseId, MyDatabaseTableSpace), + MyDatabaseId, MyDatabaseTableSpace, + ensure_new_key); - return (principal_key != NULL); + return (principal_key != NULL); } bool RotatePrincipalKey(TDEPrincipalKey *current_key, const char *new_key_name, const char *new_provider_name, bool ensure_new_key) { - TDEPrincipalKey new_principal_key; - const keyInfo *keyInfo = NULL; - GenericKeyring *keyring; - bool is_rotated; - MemoryContext keyRotateCtx; - MemoryContext oldCtx; - - Assert(current_key != NULL); - - keyRotateCtx = AllocSetContextCreate(CurrentMemoryContext, - "TDE key rotation temporary context", - ALLOCSET_DEFAULT_SIZES); - oldCtx = MemoryContextSwitchTo(keyRotateCtx); - - /* - * Let's set everything the same as the older principal key and - * update only the required attributes. - * */ - memcpy(&new_principal_key, current_key, sizeof(TDEPrincipalKey)); - - if (new_key_name == NULL) - { - new_principal_key.keyInfo.keyId.version++; - } - else - { - strncpy(new_principal_key.keyInfo.keyId.name, new_key_name, sizeof(new_principal_key.keyInfo.keyId.name)); - new_principal_key.keyInfo.keyId.version = DEFAULT_PRINCIPAL_KEY_VERSION; - - if (new_provider_name != NULL) - { - new_principal_key.keyInfo.keyringId = GetKeyProviderByName(new_provider_name, - new_principal_key.keyInfo.databaseId, - new_principal_key.keyInfo.tablespaceId)->key_id; - } - } - - /* We need a valid keyring structure */ - keyring = GetKeyProviderByID(new_principal_key.keyInfo.keyringId, - new_principal_key.keyInfo.databaseId, - new_principal_key.keyInfo.tablespaceId); - - keyInfo = load_latest_versioned_key_name(&new_principal_key.keyInfo, keyring, ensure_new_key); - - if (keyInfo == NULL) - keyInfo = KeyringGenerateNewKeyAndStore(keyring, new_principal_key.keyInfo.keyId.versioned_name, INTERNAL_KEY_LEN, false); - - if (keyInfo == NULL) - { - ereport(ERROR, - (errmsg("Failed to generate new key name"))); - } - - new_principal_key.keyLength = 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); - if (is_rotated && current_key->keyInfo.tablespaceId != GLOBALTABLESPACE_OID) { - clear_principal_key_cache(current_key->keyInfo.databaseId); - push_principal_key_to_cache(&new_principal_key); - } - - MemoryContextSwitchTo(oldCtx); - MemoryContextDelete(keyRotateCtx); - - return is_rotated; + TDEPrincipalKey new_principal_key; + const keyInfo *keyInfo = NULL; + GenericKeyring *keyring; + bool is_rotated; + MemoryContext keyRotateCtx; + MemoryContext oldCtx; + + Assert(current_key != NULL); + + keyRotateCtx = AllocSetContextCreate(CurrentMemoryContext, + "TDE key rotation temporary context", + ALLOCSET_DEFAULT_SIZES); + oldCtx = MemoryContextSwitchTo(keyRotateCtx); + + /* + * Let's set everything the same as the older principal key and update + * only the required attributes. + */ + memcpy(&new_principal_key, current_key, sizeof(TDEPrincipalKey)); + + if (new_key_name == NULL) + { + new_principal_key.keyInfo.keyId.version++; + } + else + { + strncpy(new_principal_key.keyInfo.keyId.name, new_key_name, sizeof(new_principal_key.keyInfo.keyId.name)); + new_principal_key.keyInfo.keyId.version = DEFAULT_PRINCIPAL_KEY_VERSION; + + if (new_provider_name != NULL) + { + new_principal_key.keyInfo.keyringId = GetKeyProviderByName(new_provider_name, + new_principal_key.keyInfo.databaseId, + new_principal_key.keyInfo.tablespaceId)->key_id; + } + } + + /* We need a valid keyring structure */ + keyring = GetKeyProviderByID(new_principal_key.keyInfo.keyringId, + new_principal_key.keyInfo.databaseId, + new_principal_key.keyInfo.tablespaceId); + + keyInfo = load_latest_versioned_key_name(&new_principal_key.keyInfo, keyring, ensure_new_key); + + if (keyInfo == NULL) + keyInfo = KeyringGenerateNewKeyAndStore(keyring, new_principal_key.keyInfo.keyId.versioned_name, INTERNAL_KEY_LEN, false); + + if (keyInfo == NULL) + { + ereport(ERROR, + (errmsg("Failed to generate new key name"))); + } + + new_principal_key.keyLength = 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); + if (is_rotated && current_key->keyInfo.tablespaceId != GLOBALTABLESPACE_OID) + { + clear_principal_key_cache(current_key->keyInfo.databaseId); + push_principal_key_to_cache(&new_principal_key); + } + + MemoryContextSwitchTo(oldCtx); + MemoryContextDelete(keyRotateCtx); + + return is_rotated; } /* @@ -380,10 +386,10 @@ RotatePrincipalKey(TDEPrincipalKey *current_key, const char *new_key_name, const bool xl_tde_perform_rotate_key(XLogPrincipalKeyRotate *xlrec) { - bool ret; + bool ret; - ret = pg_tde_write_map_keydata_files(xlrec->map_size, xlrec->buff, xlrec->keydata_size, &xlrec->buff[xlrec->map_size]); - clear_principal_key_cache(xlrec->databaseId); + ret = pg_tde_write_map_keydata_files(xlrec->map_size, xlrec->buff, xlrec->keydata_size, &xlrec->buff[xlrec->map_size]); + clear_principal_key_cache(xlrec->databaseId); return ret; } @@ -396,63 +402,72 @@ xl_tde_perform_rotate_key(XLogPrincipalKeyRotate *xlrec) keyInfo * load_latest_versioned_key_name(TDEPrincipalKeyInfo *principal_key_info, GenericKeyring *keyring, bool ensure_new_key) { - KeyringReturnCodes kr_ret; - keyInfo *keyInfo = NULL; - int base_version = principal_key_info->keyId.version; - Assert(principal_key_info != NULL); - Assert(keyring != NULL); - 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 - */ - snprintf(principal_key_info->keyId.versioned_name, TDE_KEY_NAME_LEN, - "%s_%d", principal_key_info->keyId.name, principal_key_info->keyId.version); - - while (true) - { - 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 */ - if (kr_ret != KEYRING_CODE_SUCCESS && kr_ret != KEYRING_CODE_RESOURCE_NOT_AVAILABLE) - { - ereport(FATAL, - (errmsg("failed to retrieve principal key from keyring provider :\"%s\"", keyring->provider_name), - errdetail("Error code: %d", kr_ret))); - } - if (keyInfo == NULL) - { - if (ensure_new_key == false) - { - /* - * If ensure_key is false and we are not at the base version, - * We should return the last existent version. - */ - if (base_version < principal_key_info->keyId.version) - { - /* Not optimal but keep the things simple */ - principal_key_info->keyId.version -= 1; - snprintf(principal_key_info->keyId.versioned_name, TDE_KEY_NAME_LEN, - "%s_%d", principal_key_info->keyId.name, principal_key_info->keyId.version); - keyInfo = KeyringGetKey(keyring, principal_key_info->keyId.versioned_name, false, &kr_ret); - } - } - return keyInfo; - } - - 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. - */ - if (principal_key_info->keyId.version > MAX_PRINCIPAL_KEY_VERSION_NUM) - { - ereport(ERROR, - (errmsg("failed to retrieve principal key. %d versions already exist", MAX_PRINCIPAL_KEY_VERSION_NUM))); - } - } - return NULL; /* Just to keep compiler quite */ + KeyringReturnCodes kr_ret; + keyInfo *keyInfo = NULL; + int base_version = principal_key_info->keyId.version; + + Assert(principal_key_info != NULL); + Assert(keyring != NULL); + 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 + */ + snprintf(principal_key_info->keyId.versioned_name, TDE_KEY_NAME_LEN, + "%s_%d", principal_key_info->keyId.name, principal_key_info->keyId.version); + + while (true) + { + 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 + */ + if (kr_ret != KEYRING_CODE_SUCCESS && kr_ret != KEYRING_CODE_RESOURCE_NOT_AVAILABLE) + { + ereport(FATAL, + (errmsg("failed to retrieve principal key from keyring provider :\"%s\"", keyring->provider_name), + errdetail("Error code: %d", kr_ret))); + } + if (keyInfo == NULL) + { + if (ensure_new_key == false) + { + /* + * If ensure_key is false and we are not at the base version, + * We should return the last existent version. + */ + if (base_version < principal_key_info->keyId.version) + { + /* Not optimal but keep the things simple */ + principal_key_info->keyId.version -= 1; + snprintf(principal_key_info->keyId.versioned_name, TDE_KEY_NAME_LEN, + "%s_%d", principal_key_info->keyId.name, principal_key_info->keyId.version); + keyInfo = KeyringGetKey(keyring, principal_key_info->keyId.versioned_name, false, &kr_ret); + } + } + return keyInfo; + } + + 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. + */ + if (principal_key_info->keyId.version > MAX_PRINCIPAL_KEY_VERSION_NUM) + { + ereport(ERROR, + (errmsg("failed to retrieve principal key. %d versions already exist", MAX_PRINCIPAL_KEY_VERSION_NUM))); + } + } + return NULL; /* Just to keep compiler quite */ } + /* * Returns the provider ID of the keyring that holds the principal key * Return InvalidOid if the principal key is not set for the database @@ -460,32 +475,35 @@ load_latest_versioned_key_name(TDEPrincipalKeyInfo *principal_key_info, GenericK Oid GetPrincipalKeyProviderId(void) { - TDEPrincipalKey *principalKey = NULL; - TDEPrincipalKeyInfo *principalKeyInfo = NULL; - Oid keyringId = InvalidOid; - Oid dbOid = MyDatabaseId; - LWLock *lock_files = tde_lwlock_enc_keys(); - - LWLockAcquire(lock_files, LW_SHARED); - - principalKey = get_principal_key_from_cache(dbOid); - if (principalKey) - { - keyringId = principalKey->keyInfo.keyringId; - } - { - /* Principal key not present in cache. Try Loading it from the info file */ - principalKeyInfo = pg_tde_get_principal_key_info(dbOid, MyDatabaseTableSpace); - if (principalKeyInfo) - { - keyringId = principalKeyInfo->keyringId; - pfree(principalKeyInfo); - } - } - - LWLockRelease(lock_files); - - return keyringId; + TDEPrincipalKey *principalKey = NULL; + TDEPrincipalKeyInfo *principalKeyInfo = NULL; + Oid keyringId = InvalidOid; + Oid dbOid = MyDatabaseId; + LWLock *lock_files = tde_lwlock_enc_keys(); + + LWLockAcquire(lock_files, LW_SHARED); + + principalKey = get_principal_key_from_cache(dbOid); + if (principalKey) + { + keyringId = principalKey->keyInfo.keyringId; + } + { + /* + * Principal key not present in cache. Try Loading it from the info + * file + */ + principalKeyInfo = pg_tde_get_principal_key_info(dbOid, MyDatabaseTableSpace); + if (principalKeyInfo) + { + keyringId = principalKeyInfo->keyringId; + pfree(principalKeyInfo); + } + } + + LWLockRelease(lock_files); + + return keyringId; } /* @@ -496,8 +514,8 @@ GetPrincipalKeyProviderId(void) static inline dshash_table * get_principal_key_Hash(void) { - principal_key_info_attach_shmem(); - return principalKeyLocalState.sharedHash; + principal_key_info_attach_shmem(); + return principalKeyLocalState.sharedHash; } /* @@ -506,14 +524,14 @@ get_principal_key_Hash(void) static TDEPrincipalKey * get_principal_key_from_cache(Oid dbOid) { - TDEPrincipalKey *cacheEntry = NULL; + TDEPrincipalKey *cacheEntry = NULL; - cacheEntry = (TDEPrincipalKey *)dshash_find(get_principal_key_Hash(), - &dbOid, false); - if (cacheEntry) - dshash_release_lock(get_principal_key_Hash(), cacheEntry); + cacheEntry = (TDEPrincipalKey *) dshash_find(get_principal_key_Hash(), + &dbOid, false); + if (cacheEntry) + dshash_release_lock(get_principal_key_Hash(), cacheEntry); - return cacheEntry; + return cacheEntry; } /* @@ -529,18 +547,19 @@ get_principal_key_from_cache(Oid dbOid) static void push_principal_key_to_cache(TDEPrincipalKey *principalKey) { - TDEPrincipalKey *cacheEntry = NULL; - Oid databaseId = principalKey->keyInfo.databaseId; - bool found = false; - cacheEntry = dshash_find_or_insert(get_principal_key_Hash(), - &databaseId, &found); - if (!found) - memcpy(cacheEntry, principalKey, sizeof(TDEPrincipalKey)); - dshash_release_lock(get_principal_key_Hash(), cacheEntry); - - /* we don't want principal keys to end up paged to the swap */ - if (mlock(cacheEntry, sizeof(TDEPrincipalKey)) == -1) - elog(ERROR, "could not mlock principal key cache entry: %m"); + TDEPrincipalKey *cacheEntry = NULL; + Oid databaseId = principalKey->keyInfo.databaseId; + bool found = false; + + cacheEntry = dshash_find_or_insert(get_principal_key_Hash(), + &databaseId, &found); + if (!found) + memcpy(cacheEntry, principalKey, sizeof(TDEPrincipalKey)); + dshash_release_lock(get_principal_key_Hash(), cacheEntry); + + /* we don't want principal keys to end up paged to the swap */ + if (mlock(cacheEntry, sizeof(TDEPrincipalKey)) == -1) + elog(ERROR, "could not mlock principal key cache entry: %m"); } /* @@ -556,59 +575,61 @@ push_principal_key_to_cache(TDEPrincipalKey *principalKey) static void principal_key_startup_cleanup(int tde_tbl_count, XLogExtensionInstall *ext_info, bool redo, void *arg) { - if (tde_tbl_count > 0) - { - ereport(WARNING, - (errmsg("Failed to perform initialization. database already has %d TDE tables", tde_tbl_count))); - return; - } - - cleanup_principal_key_info(ext_info->database_id, ext_info->tablespace_id); + if (tde_tbl_count > 0) + { + ereport(WARNING, + (errmsg("Failed to perform initialization. database already has %d TDE tables", tde_tbl_count))); + return; + } + + cleanup_principal_key_info(ext_info->database_id, ext_info->tablespace_id); } void cleanup_principal_key_info(Oid databaseId, Oid tablespaceId) { - clear_principal_key_cache(databaseId); - /* - * TODO: Although should never happen. Still verify if any table in the - * database is using tde - */ - - /* Remove the tde files */ - pg_tde_delete_tde_files(databaseId, tablespaceId); + clear_principal_key_cache(databaseId); + + /* + * TODO: Although should never happen. Still verify if any table in the + * database is using tde + */ + + /* Remove the tde files */ + pg_tde_delete_tde_files(databaseId, tablespaceId); } static void clear_principal_key_cache(Oid databaseId) { - TDEPrincipalKey *cache_entry; - - /* Start with deleting the cache entry for the database */ - cache_entry = (TDEPrincipalKey *)dshash_find(get_principal_key_Hash(), - &databaseId, true); - if (cache_entry) - { - dshash_delete_entry(get_principal_key_Hash(), cache_entry); - } + TDEPrincipalKey *cache_entry; + + /* Start with deleting the cache entry for the database */ + cache_entry = (TDEPrincipalKey *) dshash_find(get_principal_key_Hash(), + &databaseId, true); + if (cache_entry) + { + dshash_delete_entry(get_principal_key_Hash(), cache_entry); + } } /* * SQL interface to 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 *provider_name = text_to_cstring(PG_GETARG_TEXT_PP(1)); - bool ensure_new_key = PG_GETARG_BOOL(2); - bool ret; - - ereport(LOG, (errmsg("Setting principal key [%s : %s] for the database", principal_key_name, provider_name))); - ret = SetPrincipalKey(principal_key_name, provider_name, ensure_new_key); - PG_RETURN_BOOL(ret); + char *principal_key_name = text_to_cstring(PG_GETARG_TEXT_PP(0)); + char *provider_name = text_to_cstring(PG_GETARG_TEXT_PP(1)); + bool ensure_new_key = PG_GETARG_BOOL(2); + bool ret; + + ereport(LOG, (errmsg("Setting principal key [%s : %s] for the database", principal_key_name, provider_name))); + ret = SetPrincipalKey(principal_key_name, provider_name, ensure_new_key); + PG_RETURN_BOOL(ret); } /* @@ -618,21 +639,21 @@ PG_FUNCTION_INFO_V1(pg_tde_rotate_principal_key_internal); Datum pg_tde_rotate_principal_key_internal(PG_FUNCTION_ARGS) { - char *new_principal_key_name = NULL; - char *new_provider_name = NULL; - bool ensure_new_key; - bool is_global; - bool ret; - TDEPrincipalKey *current_key; - Oid dbOid = MyDatabaseId; - Oid spcOid = MyDatabaseTableSpace; - - if (!PG_ARGISNULL(0)) - new_principal_key_name = text_to_cstring(PG_GETARG_TEXT_PP(0)); - if (!PG_ARGISNULL(1)) - new_provider_name = text_to_cstring(PG_GETARG_TEXT_PP(1)); - ensure_new_key = PG_GETARG_BOOL(2); - is_global = PG_GETARG_BOOL(3); + char *new_principal_key_name = NULL; + char *new_provider_name = NULL; + bool ensure_new_key; + bool is_global; + bool ret; + TDEPrincipalKey *current_key; + Oid dbOid = MyDatabaseId; + Oid spcOid = MyDatabaseTableSpace; + + if (!PG_ARGISNULL(0)) + new_principal_key_name = text_to_cstring(PG_GETARG_TEXT_PP(0)); + if (!PG_ARGISNULL(1)) + new_provider_name = text_to_cstring(PG_GETARG_TEXT_PP(1)); + ensure_new_key = PG_GETARG_BOOL(2); + is_global = PG_GETARG_BOOL(3); #ifdef PERCONA_EXT if (is_global) @@ -642,25 +663,26 @@ pg_tde_rotate_principal_key_internal(PG_FUNCTION_ARGS) } #endif - ereport(LOG, (errmsg("rotating principal key to [%s : %s] the for the %s", - new_principal_key_name, - new_provider_name, - is_global ? "cluster" : "database"))); + ereport(LOG, (errmsg("rotating principal key to [%s : %s] the for the %s", + new_principal_key_name, + new_provider_name, + is_global ? "cluster" : "database"))); LWLockAcquire(tde_lwlock_enc_keys(), LW_EXCLUSIVE); - current_key = GetPrincipalKey(dbOid, spcOid, LW_EXCLUSIVE); - ret = RotatePrincipalKey(current_key, new_principal_key_name, new_provider_name, ensure_new_key); + current_key = GetPrincipalKey(dbOid, spcOid, LW_EXCLUSIVE); + ret = RotatePrincipalKey(current_key, new_principal_key_name, new_provider_name, ensure_new_key); LWLockRelease(tde_lwlock_enc_keys()); - PG_RETURN_BOOL(ret); + PG_RETURN_BOOL(ret); } 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 spcOid = MyDatabaseTableSpace; - bool is_global = PG_GETARG_BOOL(0); + Oid dbOid = MyDatabaseId; + Oid spcOid = MyDatabaseTableSpace; + bool is_global = PG_GETARG_BOOL(0); if (is_global) { @@ -668,133 +690,134 @@ Datum pg_tde_principal_key_info_internal(PG_FUNCTION_ARGS) spcOid = GLOBALTABLESPACE_OID; } - return pg_tde_get_key_info(fcinfo, dbOid, spcOid); + return pg_tde_get_key_info(fcinfo, dbOid, spcOid); } -static Datum +static Datum pg_tde_get_key_info(PG_FUNCTION_ARGS, Oid dbOid, Oid spcOid) { - TupleDesc tupdesc; - Datum values[6]; - bool isnull[6]; - HeapTuple tuple; - Datum result; - TDEPrincipalKey *principal_key; - TimestampTz ts; - GenericKeyring *keyring; - - /* Build a tuple descriptor for our result type */ - if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("function returning record called in context that cannot accept type record"))); + TupleDesc tupdesc; + Datum values[6]; + bool isnull[6]; + HeapTuple tuple; + Datum result; + TDEPrincipalKey *principal_key; + TimestampTz ts; + GenericKeyring *keyring; + + /* Build a tuple descriptor for our result type */ + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("function returning record called in context that cannot accept type record"))); LWLockAcquire(tde_lwlock_enc_keys(), LW_SHARED); - principal_key = GetPrincipalKey(dbOid, spcOid, LW_SHARED); + principal_key = GetPrincipalKey(dbOid, spcOid, LW_SHARED); LWLockRelease(tde_lwlock_enc_keys()); - if (principal_key == NULL) + if (principal_key == NULL) { ereport(ERROR, - (errmsg("Principal key does not exists for the database"), - errhint("Use set_principal_key interface to set the principal key"))); + (errmsg("Principal key does not exists for the database"), + errhint("Use set_principal_key interface to set the principal key"))); PG_RETURN_NULL(); } - keyring = GetKeyProviderByID(principal_key->keyInfo.keyringId, dbOid, spcOid); - - /* Initialize the values and null flags */ - - /* TEXT: Principal key name */ - values[0] = CStringGetTextDatum(principal_key->keyInfo.keyId.name); - isnull[0] = false; - /* TEXT: Keyring provider name */ - if (keyring) - { - values[1] = CStringGetTextDatum(keyring->provider_name); - isnull[1] = false; - } - else - isnull[1] = true; - - /* INTEGERT: key provider id */ - values[2] = Int32GetDatum(principal_key->keyInfo.keyringId); - isnull[2] = false; - - /* TEXT: Principal key versioned name */ - values[3] = CStringGetTextDatum(principal_key->keyInfo.keyId.versioned_name); - isnull[3] = false; - /* INTEGERT: Principal key version */ - values[4] = Int32GetDatum(principal_key->keyInfo.keyId.version); - isnull[4] = false; - /* TIMESTAMP TZ: Principal key creation time */ - 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; - values[5] = TimestampTzGetDatum(ts); - isnull[5] = false; - - /* Form the tuple */ - tuple = heap_form_tuple(tupdesc, values, isnull); - - /* Make the tuple into a datum */ - result = HeapTupleGetDatum(tuple); - - PG_RETURN_DATUM(result); + keyring = GetKeyProviderByID(principal_key->keyInfo.keyringId, dbOid, spcOid); + + /* Initialize the values and null flags */ + + /* TEXT: Principal key name */ + values[0] = CStringGetTextDatum(principal_key->keyInfo.keyId.name); + isnull[0] = false; + /* TEXT: Keyring provider name */ + if (keyring) + { + values[1] = CStringGetTextDatum(keyring->provider_name); + isnull[1] = false; + } + else + isnull[1] = true; + + /* INTEGERT: key provider id */ + values[2] = Int32GetDatum(principal_key->keyInfo.keyringId); + isnull[2] = false; + + /* TEXT: Principal key versioned name */ + values[3] = CStringGetTextDatum(principal_key->keyInfo.keyId.versioned_name); + isnull[3] = false; + /* INTEGERT: Principal key version */ + values[4] = Int32GetDatum(principal_key->keyInfo.keyId.version); + isnull[4] = false; + /* TIMESTAMP TZ: Principal key creation time */ + 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; + values[5] = TimestampTzGetDatum(ts); + isnull[5] = false; + + /* Form the tuple */ + tuple = heap_form_tuple(tupdesc, values, isnull); + + /* Make the tuple into a datum */ + result = HeapTupleGetDatum(tuple); + + PG_RETURN_DATUM(result); } -#endif /* FRONTEND */ +#endif /* FRONTEND */ -/* +/* * Gets principal key form the keyring and pops it into cache if key exists * Caller should hold an exclusive tde_lwlock_enc_keys lock */ TDEPrincipalKey * get_principal_key_from_keyring(Oid dbOid, Oid spcOid) { - GenericKeyring *keyring; - TDEPrincipalKey *principalKey = NULL; - TDEPrincipalKeyInfo *principalKeyInfo = NULL; - const keyInfo *keyInfo = NULL; - KeyringReturnCodes keyring_ret; + GenericKeyring *keyring; + TDEPrincipalKey *principalKey = NULL; + TDEPrincipalKeyInfo *principalKeyInfo = NULL; + const keyInfo *keyInfo = NULL; + KeyringReturnCodes keyring_ret; - Assert(LWLockHeldByMeInMode(tde_lwlock_enc_keys(), LW_EXCLUSIVE)); + Assert(LWLockHeldByMeInMode(tde_lwlock_enc_keys(), LW_EXCLUSIVE)); - principalKeyInfo = pg_tde_get_principal_key_info(dbOid, spcOid); - if (principalKeyInfo == NULL) - { - return NULL; - } + principalKeyInfo = pg_tde_get_principal_key_info(dbOid, spcOid); + if (principalKeyInfo == NULL) + { + return NULL; + } - keyring = GetKeyProviderByID(principalKeyInfo->keyringId, dbOid, spcOid); - if (keyring == NULL) - { - return NULL; - } + keyring = GetKeyProviderByID(principalKeyInfo->keyringId, dbOid, spcOid); + if (keyring == NULL) + { + return NULL; + } - keyInfo = KeyringGetKey(keyring, principalKeyInfo->keyId.versioned_name, false, &keyring_ret); - if (keyInfo == NULL) - { - return NULL; - } + keyInfo = KeyringGetKey(keyring, principalKeyInfo->keyId.versioned_name, false, &keyring_ret); - principalKey = palloc(sizeof(TDEPrincipalKey)); + if (keyInfo == NULL) + { + return NULL; + } - memcpy(&principalKey->keyInfo, principalKeyInfo, sizeof(principalKey->keyInfo)); - memcpy(principalKey->keyData, keyInfo->data.data, keyInfo->data.len); - principalKey->keyLength = keyInfo->data.len; + principalKey = palloc(sizeof(TDEPrincipalKey)); - Assert(dbOid == principalKey->keyInfo.databaseId); + memcpy(&principalKey->keyInfo, principalKeyInfo, sizeof(principalKey->keyInfo)); + memcpy(principalKey->keyData, keyInfo->data.data, keyInfo->data.len); + principalKey->keyLength = keyInfo->data.len; + + Assert(dbOid == principalKey->keyInfo.databaseId); #ifndef FRONTEND - /* We don't store global space key in cache */ - if (spcOid != GLOBALTABLESPACE_OID) - { - push_principal_key_to_cache(principalKey); - } + /* We don't store global space key in cache */ + if (spcOid != GLOBALTABLESPACE_OID) + { + push_principal_key_to_cache(principalKey); + } #endif - if (principalKeyInfo) - pfree(principalKeyInfo); + if (principalKeyInfo) + pfree(principalKeyInfo); - return principalKey; + return principalKey; } /* @@ -803,12 +826,12 @@ get_principal_key_from_keyring(Oid dbOid, Oid spcOid) * the keyring and stored in the cache. * When the principal key is not set for the database. The function returns * throws an error. - * + * * The caller must hold a `tde_lwlock_enc_keys` lock and pass its obtained mode * via the `lockMode` param (LW_SHARED or LW_EXCLUSIVE). We expect the key to be * most likely in the cache. So the caller should use LW_SHARED if there are no * principal key changes planned as this is faster and creates less contention. - * But if there is no key in the cache, we have to switch the lock + * But if there is no key in the cache, we have to switch the lock * (LWLockRelease + LWLockAcquire) to LW_EXCLUSIVE mode to write the key to the * cache. */ @@ -816,26 +839,26 @@ TDEPrincipalKey * GetPrincipalKey(Oid dbOid, Oid spcOid, LWLockMode lockMode) { #ifndef FRONTEND - TDEPrincipalKey *principalKey = NULL; + TDEPrincipalKey *principalKey = NULL; - Assert(LWLockHeldByMeInMode(tde_lwlock_enc_keys(), lockMode)); - /* We don't store global space key in cache */ - if (spcOid != GLOBALTABLESPACE_OID) - { - principalKey = get_principal_key_from_cache(dbOid); - } + Assert(LWLockHeldByMeInMode(tde_lwlock_enc_keys(), lockMode)); + /* We don't store global space key in cache */ + if (spcOid != GLOBALTABLESPACE_OID) + { + principalKey = get_principal_key_from_cache(dbOid); + } - if (likely(principalKey)) + if (likely(principalKey)) { - return principalKey; + return principalKey; } - if (lockMode != LW_EXCLUSIVE) - { - LWLockRelease(tde_lwlock_enc_keys()); - LWLockAcquire(tde_lwlock_enc_keys(), LW_EXCLUSIVE); - } + if (lockMode != LW_EXCLUSIVE) + { + LWLockRelease(tde_lwlock_enc_keys()); + LWLockAcquire(tde_lwlock_enc_keys(), LW_EXCLUSIVE); + } #endif - return get_principal_key_from_keyring(dbOid, spcOid); + return get_principal_key_from_keyring(dbOid, spcOid); } diff --git a/src/common/pg_tde_shmem.c b/src/common/pg_tde_shmem.c index 3f42ff15..be1262a1 100644 --- a/src/common/pg_tde_shmem.c +++ b/src/common/pg_tde_shmem.c @@ -17,39 +17,42 @@ typedef struct TdeSharedState { - LWLock *principalKeyLock; - int principalKeyHashTrancheId; - void *rawDsaArea; /* DSA area pointer to store cache hashes */ + LWLock *principalKeyLock; + int principalKeyHashTrancheId; + void *rawDsaArea; /* DSA area pointer to store cache hashes */ dshash_table_handle principalKeyHashHandle; } TdeSharedState; typedef struct TDELocalState { TdeSharedState *sharedTdeState; - dsa_area **dsa; /* local dsa area for backend attached to the - * dsa area created by postmaster at startup. - */ + dsa_area **dsa; /* local dsa area for backend attached to the + * dsa area created by postmaster at startup. */ dshash_table *principalKeySharedHash; } TDELocalState; static void tde_shmem_shutdown(int code, Datum arg); -List *registeredShmemRequests = NIL; -bool shmemInited = false; +List *registeredShmemRequests = NIL; +bool shmemInited = false; -void RegisterShmemRequest(const TDEShmemSetupRoutine *routine) +void +RegisterShmemRequest(const TDEShmemSetupRoutine *routine) { Assert(shmemInited == false); - registeredShmemRequests = lappend(registeredShmemRequests, (void *)routine); + registeredShmemRequests = lappend(registeredShmemRequests, (void *) routine); } -Size TdeRequiredSharedMemorySize(void) +Size +TdeRequiredSharedMemorySize(void) { - Size sz = 0; - ListCell *lc; - foreach (lc, registeredShmemRequests) + Size sz = 0; + ListCell *lc; + + foreach(lc, registeredShmemRequests) { - TDEShmemSetupRoutine *routine = (TDEShmemSetupRoutine *)lfirst(lc); + TDEShmemSetupRoutine *routine = (TDEShmemSetupRoutine *) lfirst(lc); + if (routine->required_shared_mem_size) sz = add_size(sz, routine->required_shared_mem_size()); } @@ -57,16 +60,18 @@ Size TdeRequiredSharedMemorySize(void) return MAXALIGN(sz); } -int TdeRequiredLocksCount(void) +int +TdeRequiredLocksCount(void) { return TDE_LWLOCK_COUNT; } -void TdeShmemInit(void) +void +TdeShmemInit(void) { - bool found; + bool found; TdeSharedState *tdeState; - Size required_shmem_size = TdeRequiredSharedMemorySize(); + Size required_shmem_size = TdeRequiredSharedMemorySize(); LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE); /* Create or attach to the shared memory state */ @@ -76,19 +81,20 @@ void TdeShmemInit(void) if (!found) { /* First time through ... */ - char *p = (char *)tdeState; - dsa_area *dsa; - ListCell *lc; - Size used_size = 0; - Size dsa_area_size; + char *p = (char *) tdeState; + dsa_area *dsa; + ListCell *lc; + Size used_size = 0; + Size dsa_area_size; p += MAXALIGN(sizeof(TdeSharedState)); used_size += MAXALIGN(sizeof(TdeSharedState)); /* Now place all shared state structures */ - foreach (lc, registeredShmemRequests) + foreach(lc, registeredShmemRequests) { - Size sz = 0; - TDEShmemSetupRoutine *routine = (TDEShmemSetupRoutine *)lfirst(lc); + Size sz = 0; + TDEShmemSetupRoutine *routine = (TDEShmemSetupRoutine *) lfirst(lc); + if (routine->init_shared_state) { sz = routine->init_shared_state(p); @@ -110,29 +116,33 @@ void TdeShmemInit(void) dsa_set_size_limit(dsa, dsa_area_size); /* 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) routine->init_dsa_area_objects(dsa, tdeState->rawDsaArea); } 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; } LWLockRelease(AddinShmemInitLock); - on_shmem_exit(tde_shmem_shutdown, (Datum)0); + on_shmem_exit(tde_shmem_shutdown, (Datum) 0); } static void tde_shmem_shutdown(int code, Datum arg) { - ListCell *lc; - foreach (lc, registeredShmemRequests) + ListCell *lc; + + foreach(lc, registeredShmemRequests) { - TDEShmemSetupRoutine *routine = (TDEShmemSetupRoutine *)lfirst(lc); + TDEShmemSetupRoutine *routine = (TDEShmemSetupRoutine *) lfirst(lc); + if (routine->shmem_kill) routine->shmem_kill(code, arg); } diff --git a/src/common/pg_tde_utils.c b/src/common/pg_tde_utils.c index c7768ff8..3a9ada07 100644 --- a/src/common/pg_tde_utils.c +++ b/src/common/pg_tde_utils.c @@ -23,89 +23,92 @@ Oid get_tde_basic_table_am_oid(void) { - return get_table_am_oid("tde_heap_basic", false); + return get_table_am_oid("tde_heap_basic", false); } Oid get_tde_table_am_oid(void) { - return get_table_am_oid("tde_heap", false); + return get_table_am_oid("tde_heap", false); } /* * Returns the list of OIDs for all TDE tables in a database */ -List* +List * get_all_tde_tables(void) { - Relation pg_class; - SysScanDesc scan; - HeapTuple tuple; - List* tde_tables = NIL; - Oid am_oid = get_tde_basic_table_am_oid(); - - /* Open the pg_class table */ - pg_class = table_open(RelationRelationId, AccessShareLock); - - /* Start a scan */ - scan = systable_beginscan(pg_class, ClassOidIndexId, true, - SnapshotSelf, 0, NULL); - - /* Iterate over all tuples in the table */ - while ((tuple = systable_getnext(scan)) != NULL) - { - Form_pg_class classForm = (Form_pg_class)GETSTRUCT(tuple); - - /* Check if the table uses the specified access method */ - if (classForm->relam == am_oid) - { - /* Print the name of the table */ - tde_tables = lappend_oid(tde_tables, classForm->oid); - elog(DEBUG2, "Table %s uses the TDE access method.", NameStr(classForm->relname)); - } - } - - /* End the scan */ - systable_endscan(scan); - - /* Close the pg_class table */ - table_close(pg_class, AccessShareLock); - return tde_tables; + Relation pg_class; + SysScanDesc scan; + HeapTuple tuple; + List *tde_tables = NIL; + Oid am_oid = get_tde_basic_table_am_oid(); + + /* Open the pg_class table */ + pg_class = table_open(RelationRelationId, AccessShareLock); + + /* Start a scan */ + scan = systable_beginscan(pg_class, ClassOidIndexId, true, + SnapshotSelf, 0, NULL); + + /* Iterate over all tuples in the table */ + while ((tuple = systable_getnext(scan)) != NULL) + { + Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple); + + /* Check if the table uses the specified access method */ + if (classForm->relam == am_oid) + { + /* Print the name of the table */ + tde_tables = lappend_oid(tde_tables, classForm->oid); + elog(DEBUG2, "Table %s uses the TDE access method.", NameStr(classForm->relname)); + } + } + + /* End the scan */ + systable_endscan(scan); + + /* Close the pg_class table */ + table_close(pg_class, AccessShareLock); + return tde_tables; } int get_tde_tables_count(void) { - List* tde_tables = get_all_tde_tables(); - int count = list_length(tde_tables); - list_free(tde_tables); - return count; + List *tde_tables = get_all_tde_tables(); + int count = list_length(tde_tables); + + list_free(tde_tables); + return count; } -#endif /* !FRONTEND */ +#endif /* !FRONTEND */ static char globalspace_dir[MAXPGPATH] = {0}; void pg_tde_set_globalspace_dir(const char *dir) { - Assert(dir != NULL); - strncpy(globalspace_dir, dir, sizeof(globalspace_dir)); + Assert(dir != NULL); + strncpy(globalspace_dir, dir, sizeof(globalspace_dir)); } /* returns the palloc'd string */ char * 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 (strlen(globalspace_dir) > 0) - return pstrdup(globalspace_dir); + { + if (strlen(globalspace_dir) > 0) + return pstrdup(globalspace_dir); return pstrdup("global"); - } + } return GetDatabasePath(dbOid, spcOid); } diff --git a/src/encryption/enc_aes.c b/src/encryption/enc_aes.c index adc2e01f..e72acad0 100644 --- a/src/encryption/enc_aes.c +++ b/src/encryption/enc_aes.c @@ -39,48 +39,51 @@ * * When a new block is requested, we use this stored context to encrypt the position information * * And then XOR it with the data * - * This is still not as fast as using 8k blocks, but already 2 orders of magnitude better than direct CTR with + * This is still not as fast as using 8k blocks, but already 2 orders of magnitude better than direct CTR with * 16 byte blocks. */ -const EVP_CIPHER* cipher = NULL; -const EVP_CIPHER* cipher2 = NULL; -int cipher_block_size = 0; +const EVP_CIPHER *cipher = NULL; +const EVP_CIPHER *cipher2 = NULL; +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(); ERR_load_crypto_strings(); - + cipher = EVP_aes_128_cbc(); - cipher_block_size = EVP_CIPHER_block_size(cipher); // == buffer size - cipher2 = EVP_aes_128_ecb(); + cipher_block_size = EVP_CIPHER_block_size(cipher); + //== buffer size + cipher2 = EVP_aes_128_ecb(); 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 -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) { *ctxPtr = EVP_CIPHER_CTX_new(); 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 - fprintf(stderr, "ERROR: EVP_CipherInit_ex failed. OpenSSL error: %s\n", ERR_error_string(ERR_get_error(), NULL)); - #else - ereport(ERROR, +#ifdef FRONTEND + fprintf(stderr, "ERROR: EVP_CipherInit_ex failed. OpenSSL error: %s\n", ERR_error_string(ERR_get_error(), NULL)); +#else + ereport(ERROR, (errmsg("EVP_CipherInit_ex failed. OpenSSL error: %s", ERR_error_string(ERR_get_error(), NULL)))); - #endif +#endif return; } @@ -88,103 +91,109 @@ AesRunCtr(EVP_CIPHER_CTX** ctxPtr, int enc, const unsigned char* key, const unsi 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 - fprintf(stderr, "ERROR: EVP_CipherUpdate failed. OpenSSL error: %s\n", ERR_error_string(ERR_get_error(), NULL)); - #else - ereport(ERROR, +#ifdef FRONTEND + fprintf(stderr, "ERROR: EVP_CipherUpdate failed. OpenSSL error: %s\n", ERR_error_string(ERR_get_error(), NULL)); +#else + ereport(ERROR, (errmsg("EVP_CipherUpdate failed. OpenSSL error: %s", ERR_error_string(ERR_get_error(), NULL)))); - #endif +#endif 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; - EVP_CIPHER_CTX* ctx = NULL; + int out_len_final = 0; + EVP_CIPHER_CTX *ctx = NULL; + ctx = EVP_CIPHER_CTX_new(); 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 - fprintf(stderr, "ERROR: EVP_CipherInit_ex failed. OpenSSL error: %s\n", ERR_error_string(ERR_get_error(), NULL)); - #else - ereport(ERROR, +#ifdef FRONTEND + fprintf(stderr, "ERROR: EVP_CipherInit_ex failed. OpenSSL error: %s\n", ERR_error_string(ERR_get_error(), NULL)); +#else + ereport(ERROR, (errmsg("EVP_CipherInit_ex failed. OpenSSL error: %s", ERR_error_string(ERR_get_error(), NULL)))); - #endif +#endif goto cleanup; } EVP_CIPHER_CTX_set_padding(ctx, 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 - fprintf(stderr, "ERROR: EVP_CipherUpdate failed. OpenSSL error: %s\n", ERR_error_string(ERR_get_error(), NULL)); - #else - ereport(ERROR, +#ifdef FRONTEND + fprintf(stderr, "ERROR: EVP_CipherUpdate failed. OpenSSL error: %s\n", ERR_error_string(ERR_get_error(), NULL)); +#else + ereport(ERROR, (errmsg("EVP_CipherUpdate failed. OpenSSL error: %s", ERR_error_string(ERR_get_error(), NULL)))); - #endif +#endif 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 - fprintf(stderr, "ERROR: EVP_CipherFinal_ex failed. OpenSSL error: %s\n", ERR_error_string(ERR_get_error(), NULL)); - #else - ereport(ERROR, +#ifdef FRONTEND + fprintf(stderr, "ERROR: EVP_CipherFinal_ex failed. OpenSSL error: %s\n", ERR_error_string(ERR_get_error(), NULL)); +#else + ereport(ERROR, (errmsg("EVP_CipherFinal_ex failed. OpenSSL error: %s", ERR_error_string(ERR_get_error(), NULL)))); - #endif +#endif 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; Assert(in_len == *out_len); cleanup: - EVP_CIPHER_CTX_cleanup(ctx); - EVP_CIPHER_CTX_free(ctx); + EVP_CIPHER_CTX_cleanup(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); } -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); } /* 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; - int outLen; + int outLen; Assert(blockNumber2 >= blockNumber1); - for(int j=blockNumber1;jip_blkid.bi_hi / 256; iv_prefix[1] = ip->ip_blkid.bi_hi % 256; @@ -37,20 +40,20 @@ SetIVPrefix(ItemPointerData* ip, char* iv_prefix) iv_prefix[5] = ip->ip_posid % 256; } -/* +/* * ================================================================ * ACTUAL ENCRYPTION/DECRYPTION FUNCTIONS * ================================================================ */ -/* +/* * pg_tde_crypt_simple: * Encrypts/decrypts `data` with a given `key`. The result is written to `out`. * start_offset: is the absolute location of start of data in the file. * This function assumes that everything is in a single block, and has an assertion ensuring this */ 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_end_block = (start_offset + data_len + (AES_BLOCK_SIZE - 1)) / AES_BLOCK_SIZE; @@ -63,38 +66,39 @@ 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); #ifdef ENCRYPTION_DEBUG -{ - char ivp_debug[33]; - iv_prefix_debug(iv_prefix, ivp_debug); - ereport(LOG, - (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))); -} + { + char ivp_debug[33]; + + iv_prefix_debug(iv_prefix, ivp_debug); + ereport(LOG, + (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))); + } #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]; } } -/* +/* * pg_tde_crypt_complex: * Encrypts/decrypts `data` with a given `key`. The result is written to `out`. * start_offset: is the absolute location of start of data in the file. * This is a generic function intended for large data, that do not fit into a single block */ 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_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; - uint32 batch_no = 0; - uint32 data_index = 0; - uint64 batch_end_block; - uint32 current_batch_bytes; + uint32 batch_no = 0; + uint32 data_index = 0; + uint64 batch_end_block; + uint32 current_batch_bytes; unsigned char enc_key[DATA_BYTES_PER_AES_BATCH]; /* do max NUM_AES_BLOCKS_IN_BATCH blocks at a time */ @@ -104,60 +108,64 @@ 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); #ifdef ENCRYPTION_DEBUG -{ - char ivp_debug[33]; - iv_prefix_debug(iv_prefix, ivp_debug); - ereport(LOG, - (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))); -} + { + char ivp_debug[33]; + + iv_prefix_debug(iv_prefix, ivp_debug); + ereport(LOG, + (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))); + } #endif 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) 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 - * start from `aes_block_no`-th index of the enc_key[] - * so N-th will be crypted with the same enc_key byte despite - * what start_offset the function was called with. - * For example start_offset = 10; MAX_AES_ENC_BATCH_KEY_SIZE = 6: - * data: [10 11 12 13 14 15 16] - * encKey: [...][0 1 2 3 4 5][0 1 2 3 4 5] - * so the 10th data byte is encoded with the 4th byte of the 2nd enc_key etc. - * We need this shift so each byte will be coded the same despite - * the initial offset. - * Let's see the same data but sent to the func starting from the offset 0: - * data: [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16] - * encKey: [0 1 2 3 4 5][0 1 2 3 4 5][ 0 1 2 3 4 5] - * again, the 10th data byte is encoded with the 4th byte of the 2nd enc_key etc. + /* + * As the size of enc_key always is a multiple of 16 we start from + * `aes_block_no`-th index of the enc_key[] so N-th will be + * crypted with the same enc_key byte despite what start_offset + * the function was called with. For example start_offset = 10; + * MAX_AES_ENC_BATCH_KEY_SIZE = 6: data: [10 11 12 + * 13 14 15 16] encKey: [...][0 1 2 3 4 5][0 1 2 3 4 5] so + * the 10th data byte is encoded with the 4th byte of the 2nd + * enc_key etc. We need this shift so each byte will be coded the + * same despite the initial offset. Let's see the same data but + * sent to the func starting from the offset 0: data: [0 1 2 3 + * 4 5 6 7 8 9 10 11 12 13 14 15 16] encKey: [0 1 2 3 4 5][0 1 2 3 + * 4 5][ 0 1 2 3 4 5] 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]; data_index++; } batch_no++; - } + } } -/* +/* * pg_tde_crypt: * Encrypts/decrypts `data` with a given `key`. The result is written to `out`. * start_offset: is the absolute location of start of data in the file. * This function simply selects between the two above variations based on the data length */ 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); - } else + } + else { pg_tde_crypt_simple(iv_prefix, start_offset, data, data_len, out, key, context); } @@ -172,51 +180,52 @@ pg_tde_crypt(const char* iv_prefix, uint32 start_offset, const char* data, uint3 * context: Optional context message to be used in debug log * */ 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}; - uint32 data_len = tuple->t_len - 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 iv_prefix[16] = {0}; + uint32 data_len = tuple->t_len - 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; SetIVPrefix(&tuple->t_self, iv_prefix); #ifdef ENCRYPTION_DEBUG - ereport(LOG, - (errmsg("%s: table Oid: %u data size: %u", - context?context:"", tuple->t_tableOid, - data_len))); + ereport(LOG, + (errmsg("%s: table Oid: %u data size: %u", + context ? context : "", tuple->t_tableOid, + data_len))); #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 PGTdePageAddItemExtended(RelFileLocator rel, - Oid oid, - BlockNumber bn, - Page page, - Item item, - Size size, - OffsetNumber offsetNumber, - int flags) + Oid oid, + BlockNumber bn, + Page page, + Item item, + Size size, + OffsetNumber offsetNumber, + int flags) { - OffsetNumber off = PageAddItemExtended(page,item,size,offsetNumber,flags); + OffsetNumber off = PageAddItemExtended(page, item, size, offsetNumber, flags); PageHeader phdr = (PageHeader) page; - unsigned long header_size = ((HeapTupleHeader)item)->t_hoff; - char iv_prefix[16] = {0,}; - char* toAddr = ((char*)phdr) + phdr->pd_upper + header_size; - char* data = item + header_size; - uint32 data_len = size - header_size; + unsigned long header_size = ((HeapTupleHeader) item)->t_hoff; + char iv_prefix[16] = {0,}; + char *toAddr = ((char *) phdr) + phdr->pd_upper + header_size; + char *data = item + header_size; + uint32 data_len = size - header_size; + /* ctid stored in item is incorrect (not set) at this point */ ItemPointerData ip; RelKeyData *key = GetHeapBaiscRelationKey(rel); - ItemPointerSet(&ip, bn, off); + ItemPointerSet(&ip, bn, off); SetIVPrefix(&ip, iv_prefix); @@ -234,21 +243,21 @@ PGTdePageAddItemExtended(RelFileLocator rel, void 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 */ Assert(principal_key); memcpy(iv, &rlocator->spcOid, sizeof(Oid)); memcpy(iv + sizeof(Oid), &rlocator->dbOid, sizeof(Oid)); - + *p_enc_rel_key_data = (RelKeyData *) palloc(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 */ /* * Provide a simple interface to decrypt a given key. @@ -257,31 +266,32 @@ 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 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 */ Assert(principal_key); - + memcpy(iv, &rlocator->spcOid, sizeof(Oid)); memcpy(iv + sizeof(Oid), &rlocator->dbOid, sizeof(Oid)); - + #ifndef FRONTEND - MemoryContext oldcontext; + MemoryContext oldcontext; - oldcontext = MemoryContextSwitchTo(TopMemoryContext); + oldcontext = MemoryContextSwitchTo(TopMemoryContext); #endif *p_rel_key_data = (RelKeyData *) palloc(sizeof(RelKeyData)); #ifndef FRONTEND - MemoryContextSwitchTo(oldcontext); + MemoryContextSwitchTo(oldcontext); #endif /* Fill in the structure */ memcpy(*p_rel_key_data, enc_rel_key_data, sizeof(RelKeyData)); (*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); } diff --git a/src/include/access/pg_tde_slot.h b/src/include/access/pg_tde_slot.h index 619c0e8c..efbddf46 100644 --- a/src/include/access/pg_tde_slot.h +++ b/src/include/access/pg_tde_slot.h @@ -39,12 +39,12 @@ extern PGDLLIMPORT const TupleTableSlotOps TTSOpsTDEBufferHeapTuple; #define TTS_IS_TDE_BUFFERTUPLE(slot) ((slot)->tts_ops == &TTSOpsTDEBufferHeapTuple) extern TupleTableSlot *PGTdeExecStorePinnedBufferHeapTuple(Relation rel, - HeapTuple tuple, - TupleTableSlot *slot, - Buffer buffer); + HeapTuple tuple, + TupleTableSlot *slot, + Buffer buffer); extern TupleTableSlot *PGTdeExecStoreBufferHeapTuple(Relation rel, - HeapTuple tuple, - TupleTableSlot *slot, - Buffer buffer); + HeapTuple tuple, + TupleTableSlot *slot, + Buffer buffer); -#endif /* PG_TDE_SLOT_H */ +#endif /* PG_TDE_SLOT_H */ diff --git a/src/include/access/pg_tde_tdemap.h b/src/include/access/pg_tde_tdemap.h index 72c152e3..74094d41 100644 --- a/src/include/access/pg_tde_tdemap.h +++ b/src/include/access/pg_tde_tdemap.h @@ -23,22 +23,23 @@ typedef struct InternalKey { - uint8 key[INTERNAL_KEY_LEN]; - void* ctx; /* TODO: shouldn't be here / written to the disk */ + uint8 key[INTERNAL_KEY_LEN]; + void *ctx; /* TODO: shouldn't be here / written to the + * disk */ } InternalKey; typedef struct RelKeyData { - TDEPrincipalKeyId principal_key_id; - InternalKey internal_key; + TDEPrincipalKeyId principal_key_id; + InternalKey internal_key; } RelKeyData; typedef struct XLogRelKey { - RelFileLocator rlocator; - uint32 entry_type; - RelKeyData relKey; + RelFileLocator rlocator; + uint32 entry_type; + RelKeyData relKey; } XLogRelKey; extern RelKeyData *pg_tde_create_smgr_key(const RelFileLocator *newrlocator); @@ -67,8 +68,8 @@ extern RelKeyData *pg_tde_get_key_from_file(const RelFileLocator *rlocator, uint 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, uint32 key_type, RelKeyData *key); -#endif /*PG_TDE_MAP_H*/ +#endif /* PG_TDE_MAP_H */ diff --git a/src/include/catalog/tde_keyring.h b/src/include/catalog/tde_keyring.h index 2d3a1675..c394aafd 100644 --- a/src/include/catalog/tde_keyring.h +++ b/src/include/catalog/tde_keyring.h @@ -22,53 +22,55 @@ #define FILE_KEYRING_TYPE "file" #define VAULTV2_KEYRING_TYPE "vault-v2" -#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_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_KEYRING_OPTION_LEN 1024 typedef enum ProviderType { UNKNOWN_KEY_PROVIDER, FILE_KEY_PROVIDER, VAULT_V2_KEY_PROVIDER, -} ProviderType; +} ProviderType; /* Base type for all keyring */ typedef struct GenericKeyring { - ProviderType type; /* Must be the first field */ - Oid key_id; - char provider_name[MAX_PROVIDER_NAME_LEN]; - char options[MAX_KEYRING_OPTION_LEN]; /* User provided options string*/ + ProviderType type; /* Must be the first field */ + Oid key_id; + char provider_name[MAX_PROVIDER_NAME_LEN]; + char options[MAX_KEYRING_OPTION_LEN]; /* User provided options + * string */ } GenericKeyring; typedef struct FileKeyring { - GenericKeyring keyring; /* Must be the first field */ - char file_name[MAXPGPATH]; + GenericKeyring keyring; /* Must be the first field */ + char file_name[MAXPGPATH]; } FileKeyring; typedef struct VaultV2Keyring { - GenericKeyring keyring; /* Must be the first field */ - char vault_token[MAX_VAULT_V2_KEY_LEN]; - char vault_url[MAXPGPATH]; - char vault_ca_path[MAXPGPATH]; - char vault_mount_path[MAXPGPATH]; + GenericKeyring keyring; /* Must be the first field */ + char vault_token[MAX_VAULT_V2_KEY_LEN]; + char vault_url[MAXPGPATH]; + char vault_ca_path[MAXPGPATH]; + char vault_mount_path[MAXPGPATH]; } VaultV2Keyring; /* This record goes into key provider info file */ typedef struct KeyringProvideRecord { - int provider_id; - char provider_name[MAX_PROVIDER_NAME_LEN]; - char options[MAX_KEYRING_OPTION_LEN]; + int provider_id; + char provider_name[MAX_PROVIDER_NAME_LEN]; + char options[MAX_KEYRING_OPTION_LEN]; ProviderType provider_type; } KeyringProvideRecord; typedef struct KeyringProviderXLRecord { - Oid database_id; - Oid tablespace_id; - off_t offset_in_file; + Oid database_id; + Oid tablespace_id; + off_t offset_in_file; KeyringProvideRecord provider; } KeyringProviderXLRecord; @@ -82,5 +84,5 @@ extern uint32 save_new_key_provider_info(KeyringProvideRecord *provider, Oid dat extern uint32 redo_key_provider_info(KeyringProviderXLRecord *xlrec); extern bool ParseKeyringJSONOptions(ProviderType provider_type, void *out_opts, - char *in_buf, int buf_len); -#endif /*TDE_KEYRING_H*/ + char *in_buf, int buf_len); +#endif /* TDE_KEYRING_H */ diff --git a/src/include/catalog/tde_principal_key.h b/src/include/catalog/tde_principal_key.h index 3904fb66..ca297ce0 100644 --- a/src/include/catalog/tde_principal_key.h +++ b/src/include/catalog/tde_principal_key.h @@ -25,17 +25,17 @@ typedef struct TDEPrincipalKeyId { - uint32 version; - char name[PRINCIPAL_KEY_NAME_LEN]; - char versioned_name[PRINCIPAL_KEY_NAME_LEN + 4]; + uint32 version; + char name[PRINCIPAL_KEY_NAME_LEN]; + char versioned_name[PRINCIPAL_KEY_NAME_LEN + 4]; } TDEPrincipalKeyId; typedef struct TDEPrincipalKeyInfo { - Oid databaseId; - Oid tablespaceId; - Oid userId; - Oid keyringId; + Oid databaseId; + Oid tablespaceId; + Oid userId; + Oid keyringId; struct timeval creationTime; TDEPrincipalKeyId keyId; } TDEPrincipalKeyInfo; @@ -44,15 +44,15 @@ typedef struct TDEPrincipalKey { TDEPrincipalKeyInfo keyInfo; unsigned char keyData[MAX_KEY_DATA_SIZE]; - uint32 keyLength; + uint32 keyLength; } TDEPrincipalKey; typedef struct XLogPrincipalKeyRotate { - Oid databaseId; - off_t map_size; - off_t keydata_size; - char buff[FLEXIBLE_ARRAY_MEMBER]; + Oid databaseId; + off_t map_size; + off_t keydata_size; + char buff[FLEXIBLE_ARRAY_MEMBER]; } XLogPrincipalKeyRotate; #define SizeoOfXLogPrincipalKeyRotate offsetof(XLogPrincipalKeyRotate, buff) @@ -62,16 +62,16 @@ extern void cleanup_principal_key_info(Oid databaseId, Oid tablespaceId); #ifndef FRONTEND 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 -extern TDEPrincipalKey* GetPrincipalKey(Oid dbOid, Oid spcOid, void *lockMode); +extern TDEPrincipalKey *GetPrincipalKey(Oid dbOid, Oid spcOid, void *lockMode); #endif extern bool save_principal_key_info(TDEPrincipalKeyInfo *principalKeyInfo); -extern Oid GetPrincipalKeyProviderId(void); +extern Oid GetPrincipalKeyProviderId(void); extern bool SetPrincipalKey(const char *key_name, const char *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); - -#endif /*PG_TDE_PRINCIPAL_KEY_H*/ + +#endif /* PG_TDE_PRINCIPAL_KEY_H */ diff --git a/src/include/common/pg_tde_shmem.h b/src/include/common/pg_tde_shmem.h index e92a0968..680e03f2 100644 --- a/src/include/common/pg_tde_shmem.h +++ b/src/include/common/pg_tde_shmem.h @@ -18,43 +18,46 @@ typedef enum { - TDE_LWLOCK_ENC_KEY, - TDE_LWLOCK_PI_FILES, + TDE_LWLOCK_ENC_KEY, + TDE_LWLOCK_PI_FILES, - /* Must be the last entry in the enum */ - TDE_LWLOCK_COUNT -} TDELockTypes; + /* Must be the last entry in the enum */ + TDE_LWLOCK_COUNT +} TDELockTypes; 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 - * shared memory in this callback - * The callback must return the size of the shared memory area acquired. - * The argument to the function is the start of the shared memory address - * that can be used to store the shared data structures. - */ - Size (*init_shared_state)(void *raw_dsa_area); - /* - * shmem_startup gets called at the time of postmaster shutdown - */ - void (*shmem_kill)(int code, Datum arg); - /* - * The callback must return the size of the shared memory acquired. - */ - Size (*required_shared_mem_size)(void); - /* - * Gets called after all shared memory structures are initialized and - * here you can create shared memory hash tables or any other shared - * objects that needs to live in DSA area. - */ - void (*init_dsa_area_objects)(dsa_area *dsa, void *raw_dsa_area); + /* + * init_shared_state gets called at the time of extension load you can + * initialize the data structures required to be placed in shared memory + * in this callback The callback must return the size of the shared memory + * area acquired. The argument to the function is the start of the shared + * memory address that can be used to store the shared data structures. + */ + Size (*init_shared_state) (void *raw_dsa_area); + + /* + * shmem_startup gets called at the time of postmaster shutdown + */ + void (*shmem_kill) (int code, Datum arg); + + /* + * The callback must return the size of the shared memory acquired. + */ + Size (*required_shared_mem_size) (void); + + /* + * Gets called after all shared memory structures are initialized and here + * you can create shared memory hash tables or any other shared objects + * that needs to live in DSA area. + */ + void (*init_dsa_area_objects) (dsa_area *dsa, void *raw_dsa_area); } TDEShmemSetupRoutine; /* Interface to register the shared memory requests */ extern void RegisterShmemRequest(const TDEShmemSetupRoutine *routine); extern void TdeShmemInit(void); extern Size TdeRequiredSharedMemorySize(void); -extern int TdeRequiredLocksCount(void); +extern int TdeRequiredLocksCount(void); -#endif /*PG_TDE_SHMEM_H*/ +#endif /* PG_TDE_SHMEM_H */ diff --git a/src/include/common/pg_tde_utils.h b/src/include/common/pg_tde_utils.h index bb0b3841..c41bf408 100644 --- a/src/include/common/pg_tde_utils.h +++ b/src/include/common/pg_tde_utils.h @@ -13,12 +13,12 @@ #ifndef FRONTEND #include "nodes/pg_list.h" -extern Oid get_tde_basic_table_am_oid(void); -extern Oid get_tde_table_am_oid(void); +extern Oid get_tde_basic_table_am_oid(void); +extern Oid get_tde_table_am_oid(void); extern List *get_all_tde_tables(void); -extern int get_tde_tables_count(void); -#endif /* !FRONTEND */ +extern int get_tde_tables_count(void); +#endif /* !FRONTEND */ extern char *pg_tde_get_tde_file_dir(Oid dbOid, Oid spcOid); extern void pg_tde_set_globalspace_dir(const char *dir); -#endif /*PG_TDE_UTILS_H*/ +#endif /* PG_TDE_UTILS_H */ diff --git a/src/include/encryption/enc_aes.h b/src/include/encryption/enc_aes.h index 3eab81b8..882e3dba 100644 --- a/src/include/encryption/enc_aes.h +++ b/src/include/encryption/enc_aes.h @@ -16,11 +16,11 @@ #define NUM_AES_BLOCKS_IN_BATCH 200 #define DATA_BYTES_PER_AES_BATCH (NUM_AES_BLOCKS_IN_BATCH * AES_BLOCK_SIZE) -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); +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); /* 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 AesDecrypt(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); -#endif /*ENC_AES_H*/ +#endif /* ENC_AES_H */ diff --git a/src/include/encryption/enc_tde.h b/src/include/encryption/enc_tde.h index 78444832..e25c9ae1 100644 --- a/src/include/encryption/enc_tde.h +++ b/src/include/encryption/enc_tde.h @@ -18,17 +18,17 @@ #include "keyring/keyring_api.h" 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 -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 */ extern OffsetNumber -PGTdePageAddItemExtended(RelFileLocator rel, Oid oid, BlockNumber bn, Page page, - Item item, - Size size, - OffsetNumber offsetNumber, - int flags); + PGTdePageAddItemExtended(RelFileLocator rel, Oid oid, BlockNumber bn, Page page, + Item item, + Size size, + OffsetNumber offsetNumber, + int flags); /* Function Macros over crypt */ @@ -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 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 */ diff --git a/src/include/keyring/keyring_api.h b/src/include/keyring/keyring_api.h index 0207ced9..5c67a579 100644 --- a/src/include/keyring/keyring_api.h +++ b/src/include/keyring/keyring_api.h @@ -12,24 +12,24 @@ #include "catalog/tde_keyring.h" #define TDE_KEY_NAME_LEN 256 -#define MAX_KEY_DATA_SIZE 32 /* maximum 256 bit encryption */ +#define MAX_KEY_DATA_SIZE 32 /* maximum 256 bit encryption */ #define INTERNAL_KEY_LEN 16 typedef struct keyName { - char name[TDE_KEY_NAME_LEN]; + char name[TDE_KEY_NAME_LEN]; } keyName; typedef struct keyData { unsigned char data[MAX_KEY_DATA_SIZE]; - unsigned len; + unsigned len; } keyData; typedef struct keyInfo { - keyName name; - keyData data; + keyName name; + keyData data; } keyInfo; typedef enum KeyringReturnCodes @@ -42,19 +42,19 @@ typedef enum KeyringReturnCodes KEYRING_CODE_INVALID_RESPONSE, KEYRING_CODE_INVALID_KEY_SIZE, KEYRING_CODE_DATA_CORRUPTED -} KeyringReturnCodes; +} KeyringReturnCodes; typedef struct TDEKeyringRoutine { - 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); + 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); } TDEKeyringRoutine; extern bool RegisterKeyProvider(const TDEKeyringRoutine *routine, ProviderType type); 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 *KeyringGenerateNewKey(const char *key_name, unsigned key_len); -#endif /* KEYRING_API_H */ +#endif /* KEYRING_API_H */ diff --git a/src/include/keyring/keyring_curl.h b/src/include/keyring/keyring_curl.h index 6904831b..8f1a282d 100644 --- a/src/include/keyring/keyring_curl.h +++ b/src/include/keyring/keyring_curl.h @@ -19,13 +19,14 @@ #include #include -typedef struct CurlString { - char *ptr; - size_t len; +typedef struct CurlString +{ + char *ptr; + size_t len; } 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 */ diff --git a/src/include/keyring/keyring_file.h b/src/include/keyring/keyring_file.h index 034789b9..804f71d5 100644 --- a/src/include/keyring/keyring_file.h +++ b/src/include/keyring/keyring_file.h @@ -14,4 +14,4 @@ extern bool InstallFileKeyring(void); -#endif /*KEYRING_FILE_H*/ +#endif /* KEYRING_FILE_H */ diff --git a/src/include/keyring/keyring_vault.h b/src/include/keyring/keyring_vault.h index 86b3a4ac..16d4eeac 100644 --- a/src/include/keyring/keyring_vault.h +++ b/src/include/keyring/keyring_vault.h @@ -14,4 +14,4 @@ extern bool InstallVaultV2Keyring(void); -#endif // KEYRING_FILE_H +#endif /* // KEYRING_FILE_H */ diff --git a/src/include/pg_tde.h b/src/include/pg_tde.h index 3178edd1..069f14ab 100644 --- a/src/include/pg_tde.h +++ b/src/include/pg_tde.h @@ -10,13 +10,13 @@ typedef struct XLogExtensionInstall { - Oid database_id; - Oid tablespace_id; + Oid database_id; + Oid tablespace_id; } 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); -#endif /*PG_TDE_H*/ +#endif /* PG_TDE_H */ diff --git a/src/include/pg_tde_defines.h b/src/include/pg_tde_defines.h index d8693655..ba4925bc 100644 --- a/src/include/pg_tde_defines.h +++ b/src/include/pg_tde_defines.h @@ -19,10 +19,10 @@ * ---------- */ -//#define ENCRYPTION_DEBUG 1 -//#define KEYRING_DEBUG 1 -//#define TDE_FORK_DEBUG 1 -// #define TDE_XLOG_DEBUG 1 +/* #define ENCRYPTION_DEBUG 1 */ +/* #define KEYRING_DEBUG 1 */ +/* #define TDE_FORK_DEBUG 1 */ +/* #define TDE_XLOG_DEBUG 1 */ #define tdeheap_fill_tuple heap_fill_tuple #define tdeheap_form_tuple heap_form_tuple @@ -47,4 +47,4 @@ /* ---------- */ -#endif /* PG_TDE_DEFINES_H */ +#endif /* PG_TDE_DEFINES_H */ diff --git a/src/include/pg_tde_defs.h b/src/include/pg_tde_defs.h index ae5ffb96..1402c6a8 100644 --- a/src/include/pg_tde_defs.h +++ b/src/include/pg_tde_defs.h @@ -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_version(void); -#endif /*PG_TDE_DEFS_H*/ +#endif /* PG_TDE_DEFS_H */ diff --git a/src/include/pg_tde_event_capture.h b/src/include/pg_tde_event_capture.h index d93226ff..a0ff3e0c 100644 --- a/src/include/pg_tde_event_capture.h +++ b/src/include/pg_tde_event_capture.h @@ -26,8 +26,8 @@ typedef struct TdeCreateEvent * contains InvalidOid */ RangeVar *relation; /* Reference to the parsed relation from * create statement */ -} TdeCreateEvent; +} TdeCreateEvent; -extern TdeCreateEvent * GetCurrentTdeCreateEvent(void); +extern TdeCreateEvent *GetCurrentTdeCreateEvent(void); #endif diff --git a/src/include/smgr/pg_tde_smgr.h b/src/include/smgr/pg_tde_smgr.h index 72070adf..d56c9ac0 100644 --- a/src/include/smgr/pg_tde_smgr.h +++ b/src/include/smgr/pg_tde_smgr.h @@ -12,4 +12,4 @@ extern void RegisterStorageMgr(void); -#endif /* PG_TDE_SMGR_H */ +#endif /* PG_TDE_SMGR_H */ diff --git a/src/include/transam/pg_tde_xact_handler.h b/src/include/transam/pg_tde_xact_handler.h index a2d2cf0a..4cde60f7 100644 --- a/src/include/transam/pg_tde_xact_handler.h +++ b/src/include/transam/pg_tde_xact_handler.h @@ -13,9 +13,9 @@ extern void pg_tde_xact_callback(XactEvent event, void *arg); extern void pg_tde_subxact_callback(SubXactEvent event, SubTransactionId mySubid, - SubTransactionId parentSubid, void *arg); + SubTransactionId parentSubid, void *arg); extern void RegisterEntryForDeletion(const RelFileLocator *rlocator, off_t map_entry_offset, bool atCommit); -#endif /* PG_TDE_XACT_HANDLER_H */ +#endif /* PG_TDE_XACT_HANDLER_H */ diff --git a/src/keyring/keyring_api.c b/src/keyring/keyring_api.c index 24c9a060..05465eba 100644 --- a/src/keyring/keyring_api.c +++ b/src/keyring/keyring_api.c @@ -23,7 +23,7 @@ typedef struct KeyProviders } KeyProviders; #ifndef FRONTEND -List *registeredKeyProviders = NIL; +List *registeredKeyProviders = NIL; #else SimplePtrList registeredKeyProviders = {NULL, NULL}; #endif @@ -33,10 +33,12 @@ static KeyProviders *find_key_provider(ProviderType type); static KeyProviders * find_key_provider(ProviderType type) { - ListCell *lc; - foreach (lc, registeredKeyProviders) + ListCell *lc; + + foreach(lc, registeredKeyProviders) { - KeyProviders *kp = (KeyProviders *)lfirst(lc); + KeyProviders *kp = (KeyProviders *) lfirst(lc); + if (kp->type == type) { return kp; @@ -49,9 +51,11 @@ static KeyProviders * find_key_provider(ProviderType type) { SimplePtrListCell *lc; + for (lc = registeredKeyProviders.head; lc; lc = lc->next) { KeyProviders *kp = (KeyProviders *) lc->ptr; + if (kp->type == type) { return kp; @@ -59,9 +63,10 @@ find_key_provider(ProviderType type) } return NULL; } -#endif /* !FRONTEND */ +#endif /* !FRONTEND */ -bool RegisterKeyProvider(const TDEKeyringRoutine *routine, ProviderType type) +bool +RegisterKeyProvider(const TDEKeyringRoutine *routine, ProviderType type) { KeyProviders *kp; @@ -79,10 +84,11 @@ bool RegisterKeyProvider(const TDEKeyringRoutine *routine, ProviderType type) #ifndef FRONTEND MemoryContext oldcontext; + oldcontext = MemoryContextSwitchTo(TopMemoryContext); #endif kp = palloc(sizeof(KeyProviders)); - kp->routine = (TDEKeyringRoutine *)routine; + kp->routine = (TDEKeyringRoutine *) routine; kp->type = type; #ifndef FRONTEND registeredKeyProviders = lappend(registeredKeyProviders, kp); @@ -95,9 +101,10 @@ bool RegisterKeyProvider(const TDEKeyringRoutine *routine, ProviderType type) } 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); + if (kp == NULL) { ereport(throw_error ? ERROR : WARNING, @@ -112,6 +119,7 @@ KeyringReturnCodes KeyringStoreKey(GenericKeyring *keyring, keyInfo *key, bool throw_error) { KeyProviders *kp = find_key_provider(keyring->type); + if (kp == NULL) { ereport(throw_error ? ERROR : WARNING, @@ -124,14 +132,15 @@ KeyringStoreKey(GenericKeyring *keyring, keyInfo *key, bool throw_error) keyInfo * KeyringGenerateNewKey(const char *key_name, unsigned key_len) { - keyInfo *key; + keyInfo *key; + Assert(key_len <= 32); key = palloc(sizeof(keyInfo)); key->data.len = key_len; if (!RAND_bytes(key->data.data, key_len)) { pfree(key); - return NULL; /*openssl error*/ + return NULL; /* openssl error */ } strncpy(key->name.name, key_name, sizeof(key->name.name)); return key; @@ -140,7 +149,8 @@ KeyringGenerateNewKey(const char *key_name, unsigned key_len) keyInfo * 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) { ereport(throw_error ? ERROR : WARNING, diff --git a/src/keyring/keyring_curl.c b/src/keyring/keyring_curl.c index 46721f7f..5c2a58e7 100644 --- a/src/keyring/keyring_curl.c +++ b/src/keyring/keyring_curl.c @@ -14,50 +14,69 @@ #include "keyring/keyring_curl.h" #include "pg_tde_defines.h" -CURL* keyringCurl = NULL; +CURL *keyringCurl = NULL; 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; - s->ptr = repalloc(s->ptr, new_len+1); - if (s->ptr == NULL) { + size_t new_len = s->len + size * nmemb; + + s->ptr = repalloc(s->ptr, new_len + 1); + if (s->ptr == NULL) + { 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->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(); - if(keyringCurl == NULL) return 0; - } else { - curl_easy_reset(keyringCurl); - } + if (keyringCurl == NULL) + return 0; + } + else + { + curl_easy_reset(keyringCurl); + } - if(curl_easy_setopt(keyringCurl, CURLOPT_SSL_VERIFYPEER, 1) != CURLE_OK) return 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_SSL_VERIFYPEER, 1) != CURLE_OK) + return 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_CONNECTTIMEOUT, 3) != CURLE_OK) return 0; - if(curl_easy_setopt(keyringCurl, CURLOPT_TIMEOUT, 10) != 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_WRITEFUNCTION,write_func) != CURLE_OK) 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; + if (curl_easy_setopt(keyringCurl, CURLOPT_FOLLOWLOCATION, 1L) != CURLE_OK) + return 0; + if (curl_easy_setopt(keyringCurl, CURLOPT_CONNECTTIMEOUT, 3) != CURLE_OK) + return 0; + if (curl_easy_setopt(keyringCurl, CURLOPT_TIMEOUT, 10) != 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_WRITEFUNCTION, write_func) != CURLE_OK) + 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; } diff --git a/src/keyring/keyring_file.c b/src/keyring/keyring_file.c index f4326096..0163a4c4 100644 --- a/src/keyring/keyring_file.c +++ b/src/keyring/keyring_file.c @@ -26,8 +26,8 @@ #include #include -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 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); const TDEKeyringRoutine keyringFileRoutine = { .keyring_get_key = get_key_by_name, @@ -41,14 +41,14 @@ InstallFileKeyring(void) } -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) { - keyInfo* key = NULL; - int fd = -1; - FileKeyring* file_keyring = (FileKeyring*)keyring; - off_t bytes_read = 0; - off_t curr_pos = 0; + keyInfo *key = NULL; + int fd = -1; + FileKeyring *file_keyring = (FileKeyring *) keyring; + off_t bytes_read = 0; + off_t curr_pos = 0; *return_code = KEYRING_CODE_SUCCESS; @@ -57,15 +57,16 @@ get_key_by_name(GenericKeyring* keyring, const char* key_name, bool throw_error, return NULL; key = palloc(sizeof(keyInfo)); - while(true) + while (true) { bytes_read = pg_pread(fd, key, sizeof(keyInfo), curr_pos); 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); pfree(key); @@ -77,11 +78,11 @@ get_key_by_name(GenericKeyring* keyring, const char* key_name, bool throw_error, pfree(key); /* Corrupt file */ *return_code = KEYRING_CODE_DATA_CORRUPTED; - ereport(throw_error?ERROR:WARNING, - (errcode_for_file_access(), - errmsg("keyring file \"%s\" is corrupted: %m", - file_keyring->file_name), - errdetail("invalid key size %llu expected %lu", bytes_read, sizeof(keyInfo)))); + ereport(throw_error ? ERROR : WARNING, + (errcode_for_file_access(), + errmsg("keyring file \"%s\" is corrupted: %m", + file_keyring->file_name), + errdetail("invalid key size %llu expected %lu", bytes_read, sizeof(keyInfo)))); return NULL; } if (strncasecmp(key->name.name, key_name, sizeof(key->name.name)) == 0) @@ -96,13 +97,13 @@ get_key_by_name(GenericKeyring* keyring, const char* key_name, bool throw_error, } 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 curr_pos = 0; - int fd; - FileKeyring* file_keyring = (FileKeyring*)keyring; - keyInfo *existing_key; + off_t bytes_written = 0; + off_t curr_pos = 0; + int fd; + FileKeyring *file_keyring = (FileKeyring *) keyring; + keyInfo *existing_key; KeyringReturnCodes return_code = KEYRING_CODE_SUCCESS; Assert(key != NULL); @@ -119,9 +120,9 @@ set_key_by_name(GenericKeyring* keyring, keyInfo *key, bool throw_error) fd = BasicOpenFile(file_keyring->file_name, O_CREAT | O_RDWR | PG_BINARY); if (fd < 0) { - ereport(throw_error?ERROR:WARNING, - (errcode_for_file_access(), - errmsg("Failed to open keyring file %s :%m", file_keyring->file_name))); + ereport(throw_error ? ERROR : WARNING, + (errcode_for_file_access(), + errmsg("Failed to open keyring file %s :%m", file_keyring->file_name))); return KEYRING_CODE_RESOURCE_NOT_ACCESSABLE; } /* Write key to the end of file */ @@ -130,20 +131,20 @@ set_key_by_name(GenericKeyring* keyring, keyInfo *key, bool throw_error) if (bytes_written != sizeof(keyInfo)) { close(fd); - ereport(throw_error?ERROR:WARNING, - (errcode_for_file_access(), - errmsg("keyring file \"%s\" can't be written: %m", - file_keyring->file_name))); + ereport(throw_error ? ERROR : WARNING, + (errcode_for_file_access(), + errmsg("keyring file \"%s\" can't be written: %m", + file_keyring->file_name))); return KEYRING_CODE_RESOURCE_NOT_ACCESSABLE; } if (pg_fsync(fd) != 0) { close(fd); - ereport(throw_error?ERROR:WARNING, + ereport(throw_error ? ERROR : WARNING, (errcode_for_file_access(), errmsg("could not fsync file \"%s\": %m", - file_keyring->file_name))); + file_keyring->file_name))); return KEYRING_CODE_RESOURCE_NOT_ACCESSABLE; } close(fd); diff --git a/src/keyring/keyring_vault.c b/src/keyring/keyring_vault.c index 49a03c45..792f296f 100644 --- a/src/keyring/keyring_vault.c +++ b/src/keyring/keyring_vault.c @@ -18,7 +18,7 @@ #include "common/jsonapi.h" #include "mb/pg_wchar.h" #include "utils/builtins.h" - + #include #include @@ -38,29 +38,29 @@ typedef enum JRESP_EXPECT_TOP_DATA, JRESP_EXPECT_DATA, JRESP_EXPECT_KEY -} JsonVaultRespSemState; +} JsonVaultRespSemState; typedef enum { JRESP_F_UNUSED, JRESP_F_KEY -} JsonVaultRespField; +} JsonVaultRespField; typedef struct JsonVaultRespState { - JsonVaultRespSemState state; - JsonVaultRespField field; - int level; - - char *key; + JsonVaultRespSemState state; + JsonVaultRespField field; + int level; + + char *key; } JsonVaultRespState; static JsonParseErrorType json_resp_object_start(void *state); static JsonParseErrorType json_resp_object_end(void *state); static JsonParseErrorType json_resp_scalar(void *state, char *token, JsonTokenType tokentype); static JsonParseErrorType json_resp_object_field_start(void *state, char *fname, bool isnull); -static JsonParseErrorType parse_json_response(JsonVaultRespState *parse, JsonLexContext *lex); +static JsonParseErrorType parse_json_response(JsonVaultRespState *parse, JsonLexContext *lex); struct curl_slist *curlList = NULL; @@ -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 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 = { .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); } @@ -85,20 +86,24 @@ bool InstallVaultV2Keyring(void) static bool curl_setup_token(VaultV2Keyring *keyring) { - if(curlList == NULL) + if (curlList == NULL) { - char tokenHeader[256]; + char tokenHeader[256]; + strcpy(tokenHeader, "X-Vault-Token:"); strcat(tokenHeader, keyring->vault_token); 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"); - 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; } @@ -106,10 +111,10 @@ curl_setup_token(VaultV2Keyring *keyring) static bool curl_perform(VaultV2Keyring *keyring, const char *url, CurlString *outStr, long *httpCode, const char *postData) { - CURLcode ret; + CURLcode ret; #if KEYRING_DEBUG 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); } @@ -123,9 +128,10 @@ curl_perform(VaultV2Keyring *keyring, const char *url, CurlString *outStr, long if (!curl_setup_token(keyring)) 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); @@ -135,7 +141,8 @@ curl_perform(VaultV2Keyring *keyring, const char *url, CurlString *outStr, long 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 elog(DEBUG2, "Vault response [%li] '%s'", *httpCode, outStr->ptr != NULL ? outStr->ptr : ""); @@ -160,23 +167,26 @@ get_keyring_vault_url(VaultV2Keyring *keyring, const char *key_name, char *out, } 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; - char url[VAULT_URL_MAX_LEN]; - CurlString str; - long httpCode = 0; - char jsonText[512]; + VaultV2Keyring *vault_keyring = (VaultV2Keyring *) keyring; + char url[VAULT_URL_MAX_LEN]; + CurlString str; + long httpCode = 0; + char jsonText[512]; char keyData[64]; - int keyLen = 0; + int keyLen = 0; 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 - keyLen = pg_b64_encode((char *)key->data.data, key->data.len, keyData, 64); - keyData[keyLen] = 0; - + /* + * 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 */ + keyLen = pg_b64_encode((char *) key->data.data, key->data.len, keyData, 64); + keyData[ keyLen] = 0; + snprintf(jsonText, 512, "{\"data\":{\"key\":\"%s\"}}", keyData); #if KEYRING_DEBUG @@ -207,18 +217,18 @@ 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) +get_key_by_name(GenericKeyring *keyring, const char *key_name, bool throw_error, KeyringReturnCodes * return_code) { - VaultV2Keyring *vault_keyring = (VaultV2Keyring *)keyring; - keyInfo* key = NULL; - char url[VAULT_URL_MAX_LEN]; - CurlString str; - long httpCode = 0; - JsonParseErrorType json_error; - JsonLexContext *jlex = NULL; - JsonVaultRespState parse; + VaultV2Keyring *vault_keyring = (VaultV2Keyring *) keyring; + keyInfo *key = NULL; + char url[VAULT_URL_MAX_LEN]; + CurlString str; + long httpCode = 0; + JsonParseErrorType json_error; + JsonLexContext *jlex = NULL; + JsonVaultRespState parse; - const char* responseKey; + const char *responseKey; *return_code = KEYRING_CODE_SUCCESS; @@ -271,7 +281,7 @@ get_key_by_name(GenericKeyring *keyring, const char *key_name, bool throw_error, #endif 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) { @@ -285,7 +295,7 @@ get_key_by_name(GenericKeyring *keyring, const char *key_name, bool throw_error, } cleanup: - if(str.ptr != NULL) + if (str.ptr != NULL) pfree(str.ptr); #if PG_VERSION_NUM >= 170000 if (jlex != NULL) @@ -296,7 +306,7 @@ get_key_by_name(GenericKeyring *keyring, const char *key_name, bool throw_error, /* * JSON parser routines - * + * * We expect the response in the form of: * { * ... @@ -307,14 +317,14 @@ get_key_by_name(GenericKeyring *keyring, const char *key_name, bool throw_error, * } * ... * } - * + * * the rest fields are ignored */ static JsonParseErrorType -parse_json_response(JsonVaultRespState *parse, JsonLexContext *lex) +parse_json_response(JsonVaultRespState *parse, JsonLexContext *lex) { - JsonSemAction sem; + JsonSemAction sem; parse->state = JRESP_EXPECT_TOP_DATA; parse->level = -1; @@ -408,6 +418,6 @@ json_resp_object_field_start(void *state, char *fname, bool isnull) parse->field = JRESP_F_KEY; break; } - + return JSON_SUCCESS; } diff --git a/src/pg_tde.c b/src/pg_tde.c index b8baf829..14c89f37 100644 --- a/src/pg_tde.c +++ b/src/pg_tde.c @@ -45,15 +45,15 @@ PG_MODULE_MAGIC; struct OnExtInstall { pg_tde_on_ext_install_callback function; - void* arg; + void *arg; }; static struct OnExtInstall on_ext_install_list[MAX_ON_INSTALLS]; -static int on_ext_install_index = 0; +static int on_ext_install_index = 0; static void run_extension_install_callbacks(XLogExtensionInstall *xlrec, bool redo); -void _PG_init(void); -Datum pg_tde_extension_initialize(PG_FUNCTION_ARGS); -Datum pg_tde_version(PG_FUNCTION_ARGS); +void _PG_init(void); +Datum pg_tde_extension_initialize(PG_FUNCTION_ARGS); +Datum pg_tde_version(PG_FUNCTION_ARGS); static shmem_startup_hook_type prev_shmem_startup_hook = NULL; static shmem_request_hook_type prev_shmem_request_hook = NULL; @@ -63,8 +63,8 @@ PG_FUNCTION_INFO_V1(pg_tde_version); static void tde_shmem_request(void) { - Size sz = TdeRequiredSharedMemorySize(); - int required_locks = TdeRequiredLocksCount(); + Size sz = TdeRequiredSharedMemorySize(); + int required_locks = TdeRequiredLocksCount(); #ifdef PERCONA_EXT sz = add_size(sz, XLOG_TDE_ENC_BUFF_ALIGNED_SIZE); @@ -122,16 +122,22 @@ _PG_init(void) RegisterStorageMgr(); } -Datum pg_tde_extension_initialize(PG_FUNCTION_ARGS) +Datum +pg_tde_extension_initialize(PG_FUNCTION_ARGS) { /* Initialize the TDE map */ XLogExtensionInstall xlrec; + xlrec.database_id = MyDatabaseId; xlrec.tablespace_id = MyDatabaseTableSpace; 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(); - XLogRegisterData((char *)&xlrec, sizeof(XLogExtensionInstall)); + XLogRegisterData((char *) &xlrec, sizeof(XLogExtensionInstall)); XLogInsert(RM_TDERMGR_ID, XLOG_TDE_EXTENSION_INSTALL_KEY); PG_RETURN_NULL(); @@ -149,12 +155,13 @@ extension_install_redo(XLogExtensionInstall *xlrec) * 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) ereport(FATAL, - (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), - errmsg_internal("out of on extension install slots"))); + (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg_internal("out of on extension install slots"))); on_ext_install_list[on_ext_install_index].function = function; on_ext_install_list[on_ext_install_index].arg = arg; @@ -167,14 +174,14 @@ void on_ext_install(pg_tde_on_ext_install_callback function, void *arg) * ------------------ */ static void -run_extension_install_callbacks(XLogExtensionInstall* xlrec , bool redo) +run_extension_install_callbacks(XLogExtensionInstall *xlrec, bool redo) { - int i; - int tde_table_count =0; + int i; + int tde_table_count = 0; + /* - * Get the number of tde tables in this database - * should always be zero. But still, it prevents - * the cleanup if someone explicitly calls this + * Get the number of tde tables in this database should always be zero. + * But still, it prevents the cleanup if someone explicitly calls this * function. */ if (!redo) diff --git a/src/pg_tde_defs.c b/src/pg_tde_defs.c index 4414dc52..22d2602c 100644 --- a/src/pg_tde_defs.c +++ b/src/pg_tde_defs.c @@ -18,7 +18,7 @@ /* Returns package version */ -const char* +const char * pg_tde_package_string(void) { return PACKAGE_STRING; @@ -29,7 +29,7 @@ pg_tde_package_name(void) { return PACKAGE_NAME; } -const char* +const char * pg_tde_package_version(void) { return PACKAGE_VERSION; diff --git a/src/pg_tde_event_capture.c b/src/pg_tde_event_capture.c index 180eb49c..1e68924c 100644 --- a/src/pg_tde_event_capture.c +++ b/src/pg_tde_event_capture.c @@ -101,8 +101,8 @@ pg_tde_ddl_command_start_capture(PG_FUNCTION_ARGS) else if (IsA(parsetree, CreateStmt)) { CreateStmt *stmt = (CreateStmt *) parsetree; - TDEPrincipalKey * principal_key; - Oid tablespace_oid; + TDEPrincipalKey *principal_key; + Oid tablespace_oid; tdeCurrentCreateEvent.eventType = TDE_TABLE_CREATE_EVENT; tdeCurrentCreateEvent.relation = stmt->relation; @@ -110,15 +110,16 @@ pg_tde_ddl_command_start_capture(PG_FUNCTION_ARGS) if (stmt->accessMethod && strcmp(stmt->accessMethod, "tde_heap") == 0) { 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; } - if(tdeCurrentCreateEvent.encryptMode) + if (tdeCurrentCreateEvent.encryptMode) { - tablespace_oid = stmt->tablespacename != NULL ? get_tablespace_oid(stmt->tablespacename, false) - : MyDatabaseTableSpace; + tablespace_oid = stmt->tablespacename != NULL ? get_tablespace_oid(stmt->tablespacename, false) + : MyDatabaseTableSpace; LWLockAcquire(tde_lwlock_enc_keys(), LW_SHARED); principal_key = GetPrincipalKey(MyDatabaseId, tablespace_oid, LW_SHARED); LWLockRelease(tde_lwlock_enc_keys()); @@ -135,24 +136,30 @@ pg_tde_ddl_command_start_capture(PG_FUNCTION_ARGS) { LOCKMODE lockmode = AccessShareLock; /* TODO. Verify lock mode? */ AlterTableStmt *stmt = (AlterTableStmt *) parsetree; - TDEPrincipalKey * principal_key; - Oid relationId = RangeVarGetRelid(stmt->relation, NoLock, true); + TDEPrincipalKey *principal_key; + Oid relationId = RangeVarGetRelid(stmt->relation, NoLock, true); Relation rel = table_open(relationId, lockmode); - Oid tablespace_oid = rel->rd_locator.spcOid; + Oid tablespace_oid = rel->rd_locator.spcOid; ListCell *lcmd; + table_close(rel, lockmode); foreach(lcmd, stmt->cmds) - { + { AlterTableCmd *cmd = (AlterTableCmd *) lfirst(lcmd); - if(cmd->subtype == AT_SetAccessMethod && strcmp(cmd->name, "tde_heap")==0) { + + if (cmd->subtype == AT_SetAccessMethod && strcmp(cmd->name, "tde_heap") == 0) + { tdeCurrentCreateEvent.encryptMode = true; tdeCurrentCreateEvent.eventType = TDE_TABLE_CREATE_EVENT; tdeCurrentCreateEvent.relation = stmt->relation; } } - // 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) { diff --git a/src/smgr/pg_tde_smgr.c b/src/smgr/pg_tde_smgr.c index 36f0dce0..b840d03e 100644 --- a/src/smgr/pg_tde_smgr.c +++ b/src/smgr/pg_tde_smgr.c @@ -14,18 +14,19 @@ typedef struct TDESMgrRelationData { /* parent data */ SMgrRelationData reln; + /* * for md.c; per-fork arrays of the number of open segments * (md_num_open_segs) and the segments themselves (md_seg_fds). */ - int md_num_open_segs[MAX_FORKNUM + 1]; + int md_num_open_segs[MAX_FORKNUM + 1]; struct _MdfdVec *md_seg_fds[MAX_FORKNUM + 1]; - bool encrypted_relation; - RelKeyData relKey; -} TDESMgrRelationData; + bool encrypted_relation; + RelKeyData relKey; +} TDESMgrRelationData; -typedef TDESMgrRelationData *TDESMgrRelation; +typedef TDESMgrRelationData * TDESMgrRelation; /* * 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)); } -static RelKeyData* +static RelKeyData * tde_smgr_get_key(SMgrRelation reln) { TdeCreateEvent *event; RelKeyData *rkd; 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; } LWLockAcquire(tde_lwlock_enc_keys(), LW_SHARED); pk = GetPrincipalKey(reln->smgr_rlocator.locator.dbOid, reln->smgr_rlocator.locator.spcOid, LW_SHARED); LWLockRelease(tde_lwlock_enc_keys()); - if(pk == NULL) + if (pk == NULL) { return NULL; } 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); - if(rkd != NULL) + if (rkd != NULL) { return rkd; } - // if this is a CREATE TABLE, we have to generate the key - if(event->encryptMode == true && event->eventType == TDE_TABLE_CREATE_EVENT) + /* if this is a CREATE TABLE, we have to generate the key */ + if (event->encryptMode == true && event->eventType == TDE_TABLE_CREATE_EVENT) { 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(event->encryptMode == true && event->eventType == TDE_INDEX_CREATE_EVENT) + + /* 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) { - // For now keep it simple and create separate key for indexes - // Later we might modify the map infrastructure to support the same keys + /* For now keep it simple and create separate key for indexes */ + /* + * Later we might modify the map infrastructure to support the same + * keys + */ return pg_tde_create_smgr_key(&reln->smgr_rlocator.locator); } @@ -86,9 +90,9 @@ tde_smgr_get_key(SMgrRelation reln) static void 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; if (!tde_is_encryption_required(tdereln, forknum)) @@ -97,26 +101,28 @@ tde_mdwritev(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, } else { - char *local_blocks = palloc(BLCKSZ * (nblocks + 1)); - char *local_blocks_aligned = (char *)TYPEALIGN(PG_IO_ALIGN_SIZE, local_blocks); + char *local_blocks = palloc(BLCKSZ * (nblocks + 1)); + char *local_blocks_aligned = (char *) TYPEALIGN(PG_IO_ALIGN_SIZE, local_blocks); const void **local_buffers = palloc(sizeof(void *) * nblocks); 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]; BlockNumber bn = blocknum + i; 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, - local_buffers, nblocks, skipFsync); + local_buffers, nblocks, skipFsync); pfree(local_blocks); pfree(local_buffers); @@ -125,9 +131,9 @@ tde_mdwritev(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, static void 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; if (!tde_is_encryption_required(tdereln, forknum)) @@ -136,9 +142,9 @@ tde_mdextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, } else { - char *local_blocks = palloc(BLCKSZ * (1 + 1)); - char *local_blocks_aligned = (char *)TYPEALIGN(PG_IO_ALIGN_SIZE, local_blocks); - int out_len = BLCKSZ; + char *local_blocks = palloc(BLCKSZ * (1 + 1)); + char *local_blocks_aligned = (char *) TYPEALIGN(PG_IO_ALIGN_SIZE, local_blocks); + int out_len = BLCKSZ; unsigned char iv[16] = { 0, }; @@ -146,7 +152,7 @@ tde_mdextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, AesInit(); 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); @@ -156,10 +162,10 @@ tde_mdextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, static void tde_mdreadv(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, - void **buffers, BlockNumber nblocks) + void **buffers, BlockNumber nblocks) { - int out_len = BLCKSZ; - TDESMgrRelation tdereln = (TDESMgrRelation)reln; + int out_len = BLCKSZ; + TDESMgrRelation tdereln = (TDESMgrRelation) reln; RelKeyData *rkd = &tdereln->relKey; mdreadv(reln, forknum, blocknum, buffers, nblocks); @@ -169,42 +175,60 @@ tde_mdreadv(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, 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; 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. - // 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 + /* + * Postgres creates all zero blocks in an optimized route, + * which we do not try + */ + /* 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; break; } } - if(allZero) + if (allZero) 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 tde_mdcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo) { - 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 - RelKeyData* key = tde_smgr_get_key(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 + */ + RelKeyData *key = tde_smgr_get_key(reln); + if (key) { tdereln->encrypted_relation = true; @@ -224,8 +248,9 @@ tde_mdcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo) static void tde_mdopen(SMgrRelation reln) { - TDESMgrRelation tdereln = (TDESMgrRelation)reln; + TDESMgrRelation tdereln = (TDESMgrRelation) reln; RelKeyData *key = tde_smgr_get_key(reln); + if (key) { tdereln->encrypted_relation = true; @@ -260,16 +285,18 @@ static const struct f_smgr tde_smgr = { .smgr_registersync = mdregistersync, }; -void RegisterStorageMgr(void) +void +RegisterStorageMgr(void) { tde_smgr_id = smgr_register(&tde_smgr, sizeof(TDESMgrRelationData)); - // TODO: figure out how this part should work in a real extension - storage_manager_id = tde_smgr_id; + /* TODO: figure out how this part should work in a real extension */ + storage_manager_id = tde_smgr_id; } #else -void RegisterStorageMgr(void) +void +RegisterStorageMgr(void) { } -#endif /* PERCONA_EXT */ +#endif /* PERCONA_EXT */ diff --git a/src/transam/pg_tde_xact_handler.c b/src/transam/pg_tde_xact_handler.c index 6fb02cd0..e8b5e1d5 100644 --- a/src/transam/pg_tde_xact_handler.c +++ b/src/transam/pg_tde_xact_handler.c @@ -20,14 +20,14 @@ typedef struct PendingMapEntryDelete { - off_t map_entry_offset; /* map entry offset */ - RelFileLocator rlocator; /* main for use as relation OID */ - bool atCommit; /* T=delete at commit; F=delete at abort */ - int nestLevel; /* xact nesting level of request */ - struct PendingMapEntryDelete *next; /* linked-list link */ + off_t map_entry_offset; /* map entry offset */ + RelFileLocator rlocator; /* main for use as relation OID */ + bool atCommit; /* T=delete at commit; F=delete at abort */ + int nestLevel; /* xact nesting level of request */ + struct PendingMapEntryDelete *next; /* linked-list link */ } PendingMapEntryDelete; -static PendingMapEntryDelete *pendingDeletes = NULL; /* head of linked list */ +static PendingMapEntryDelete *pendingDeletes = NULL; /* head of linked list */ static void do_pending_deletes(bool isCommit); static void reassign_pending_deletes_to_parent_xact(void); @@ -37,53 +37,55 @@ static void pending_delete_cleanup(void); void pg_tde_xact_callback(XactEvent event, void *arg) { - if (event == XACT_EVENT_PARALLEL_ABORT || - event == XACT_EVENT_ABORT) - { - ereport(DEBUG2, - (errmsg("pg_tde_xact_callback: aborting transaction"))); - do_pending_deletes(false); - } - else if (event == XACT_EVENT_COMMIT) - { - do_pending_deletes(true); - pending_delete_cleanup(); - } - else if (event == XACT_EVENT_PREPARE) - { - pending_delete_cleanup(); - } + if (event == XACT_EVENT_PARALLEL_ABORT || + event == XACT_EVENT_ABORT) + { + ereport(DEBUG2, + (errmsg("pg_tde_xact_callback: aborting transaction"))); + do_pending_deletes(false); + } + else if (event == XACT_EVENT_COMMIT) + { + do_pending_deletes(true); + pending_delete_cleanup(); + } + else if (event == XACT_EVENT_PREPARE) + { + pending_delete_cleanup(); + } } void pg_tde_subxact_callback(SubXactEvent event, SubTransactionId mySubid, - SubTransactionId parentSubid, void *arg) + SubTransactionId parentSubid, void *arg) { - /* TODO: takle all possible transaction states */ - if (event == SUBXACT_EVENT_ABORT_SUB) - { - ereport(DEBUG2, - (errmsg("pg_tde_subxact_callback: aborting subtransaction"))); - do_pending_deletes(false); - } else if (event == SUBXACT_EVENT_COMMIT_SUB) - { - ereport(DEBUG2, - (errmsg("pg_tde_subxact_callback: committing subtransaction"))); - reassign_pending_deletes_to_parent_xact(); - } + /* TODO: takle all possible transaction states */ + if (event == SUBXACT_EVENT_ABORT_SUB) + { + ereport(DEBUG2, + (errmsg("pg_tde_subxact_callback: aborting subtransaction"))); + do_pending_deletes(false); + } + else if (event == SUBXACT_EVENT_COMMIT_SUB) + { + ereport(DEBUG2, + (errmsg("pg_tde_subxact_callback: committing subtransaction"))); + reassign_pending_deletes_to_parent_xact(); + } } void RegisterEntryForDeletion(const RelFileLocator *rlocator, off_t map_entry_offset, bool atCommit) { - PendingMapEntryDelete *pending; - pending = (PendingMapEntryDelete *) MemoryContextAlloc(TopMemoryContext, sizeof(PendingMapEntryDelete)); - pending->map_entry_offset = map_entry_offset; - memcpy(&pending->rlocator, rlocator, sizeof(RelFileLocator)); - pending->atCommit = atCommit; /* delete if abort */ - pending->nestLevel = GetCurrentTransactionNestLevel(); - pending->next = pendingDeletes; - pendingDeletes = pending; + PendingMapEntryDelete *pending; + + pending = (PendingMapEntryDelete *) MemoryContextAlloc(TopMemoryContext, sizeof(PendingMapEntryDelete)); + pending->map_entry_offset = map_entry_offset; + memcpy(&pending->rlocator, rlocator, sizeof(RelFileLocator)); + pending->atCommit = atCommit; /* delete if abort */ + pending->nestLevel = GetCurrentTransactionNestLevel(); + pending->next = pendingDeletes; + pendingDeletes = pending; } /* @@ -91,44 +93,44 @@ RegisterEntryForDeletion(const RelFileLocator *rlocator, off_t map_entry_offset, * * This also runs when aborting a subxact; we want to clean up a failed * subxact immediately. - * + * */ static void do_pending_deletes(bool isCommit) { - int nestLevel = GetCurrentTransactionNestLevel(); - PendingMapEntryDelete *pending; - PendingMapEntryDelete *prev; - PendingMapEntryDelete *next; - - prev = NULL; - for (pending = pendingDeletes; pending != NULL; pending = next) - { - next = pending->next; - if (pending->nestLevel != nestLevel) - { - /* outer-level entries should not be processed yet */ - prev = pending; - continue; - } - - /* unlink list entry first, so we don't retry on failure */ - if (prev) - prev->next = next; - else - pendingDeletes = next; - /* do deletion if called for */ - if (pending->atCommit == isCommit) - { - ereport(LOG, - (errmsg("pg_tde_xact_callback: deleting entry at offset %d", - (int)(pending->map_entry_offset)))); - pg_tde_free_key_map_entry(&pending->rlocator, MAP_ENTRY_VALID, pending->map_entry_offset); - } - pfree(pending); - /* prev does not change */ - - } + int nestLevel = GetCurrentTransactionNestLevel(); + PendingMapEntryDelete *pending; + PendingMapEntryDelete *prev; + PendingMapEntryDelete *next; + + prev = NULL; + for (pending = pendingDeletes; pending != NULL; pending = next) + { + next = pending->next; + if (pending->nestLevel != nestLevel) + { + /* outer-level entries should not be processed yet */ + prev = pending; + continue; + } + + /* unlink list entry first, so we don't retry on failure */ + if (prev) + prev->next = next; + else + pendingDeletes = next; + /* do deletion if called for */ + if (pending->atCommit == isCommit) + { + ereport(LOG, + (errmsg("pg_tde_xact_callback: deleting entry at offset %d", + (int) (pending->map_entry_offset)))); + pg_tde_free_key_map_entry(&pending->rlocator, MAP_ENTRY_VALID, pending->map_entry_offset); + } + pfree(pending); + /* prev does not change */ + + } } @@ -139,20 +141,20 @@ do_pending_deletes(bool isCommit) * 1. Only top level transaction can perform on-commit deletes. * 2. Subtransaction and top level transaction can perform on-abort deletes. * So we have to decrement the nesting level of pending deletes to reassing them to the parent transaction - * if subtransaction was not self aborted. In other words if subtransaction state is commited all its pending + * if subtransaction was not self aborted. In other words if subtransaction state is commited all its pending * deletes are reassigned to the parent transaction. */ -static void +static void reassign_pending_deletes_to_parent_xact(void) { - PendingMapEntryDelete *pending; - int nestLevel = GetCurrentTransactionNestLevel(); - - for (pending = pendingDeletes; pending != NULL; pending = pending->next) - { - if (pending->nestLevel == nestLevel) - pending->nestLevel--; - } + PendingMapEntryDelete *pending; + int nestLevel = GetCurrentTransactionNestLevel(); + + for (pending = pendingDeletes; pending != NULL; pending = pending->next) + { + if (pending->nestLevel == nestLevel) + pending->nestLevel--; + } } /* @@ -165,13 +167,13 @@ reassign_pending_deletes_to_parent_xact(void) static void pending_delete_cleanup(void) { - PendingMapEntryDelete *pending; - PendingMapEntryDelete *next; - - for (pending = pendingDeletes; pending != NULL; pending = next) - { - next = pending->next; - pendingDeletes = next; - pfree(pending); - } + PendingMapEntryDelete *pending; + PendingMapEntryDelete *next; + + for (pending = pendingDeletes; pending != NULL; pending = next) + { + next = pending->next; + pendingDeletes = next; + pfree(pending); + } }