@ -55,9 +55,6 @@
}
}
# endif
# endif
# 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 */
@ -163,7 +160,7 @@ pg_tde_create_key_map_entry(const RelFileLocator *newrlocator, uint32 entry_type
LWLock * lock_pk = tde_lwlock_enc_keys ( ) ;
LWLock * lock_pk = tde_lwlock_enc_keys ( ) ;
LWLockAcquire ( lock_pk , LW_EXCLUSIVE ) ;
LWLockAcquire ( lock_pk , LW_EXCLUSIVE ) ;
principal_key = GetPrincipalKey ( newrlocator - > dbOid , newrlocator - > spcOid , LW_EXCLUSIVE ) ;
principal_key = GetPrincipalKey ( newrlocator - > dbOid , LW_EXCLUSIVE ) ;
if ( principal_key = = NULL )
if ( principal_key = = NULL )
{
{
LWLockRelease ( lock_pk ) ;
LWLockRelease ( lock_pk ) ;
@ -190,7 +187,7 @@ pg_tde_create_key_map_entry(const RelFileLocator *newrlocator, uint32 entry_type
/* Encrypt the key */
/* Encrypt the key */
rel_key_data = tde_create_rel_key ( newrlocator - > relNumber , & int_key , & principal_key - > keyInfo ) ;
rel_key_data = tde_create_rel_key ( newrlocator - > relNumber , & int_key , & principal_key - > keyInfo ) ;
enc_rel_key_data = tde_encrypt_rel_key ( principal_key , rel_key_data , newrlocator ) ;
enc_rel_key_data = tde_encrypt_rel_key ( principal_key , rel_key_data , newrlocator - > dbOid ) ;
/*
/*
* XLOG internal key
* XLOG internal key
@ -244,12 +241,12 @@ tde_create_rel_key(RelFileNumber rel_num, InternalKey *key, TDEPrincipalKeyInfo
* Encrypts a given key and returns the encrypted one .
* Encrypts a given key and returns the encrypted one .
*/
*/
RelKeyData *
RelKeyData *
tde_encrypt_rel_key ( TDEPrincipalKey * principal_key , RelKeyData * rel_key_data , const RelFileLocator * rlocator )
tde_encrypt_rel_key ( TDEPrincipalKey * principal_key , RelKeyData * rel_key_data , Oid dbOid )
{
{
RelKeyData * enc_rel_key_data ;
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 ) ;
AesEncryptKey ( principal_key , dbOid , rel_key_data , & enc_rel_key_data , & enc_key_bytes ) ;
return enc_rel_key_data ;
return enc_rel_key_data ;
}
}
@ -259,13 +256,13 @@ tde_encrypt_rel_key(TDEPrincipalKey *principal_key, RelKeyData *rel_key_data, co
* Returns true if both map and key data files are created .
* Returns true if both map and key data files are created .
*/
*/
void
void
pg_tde_delete_tde_files ( Oid dbOid , Oid spcOid )
pg_tde_delete_tde_files ( Oid dbOid )
{
{
char db_map_path [ MAXPGPATH ] = { 0 } ;
char db_map_path [ MAXPGPATH ] = { 0 } ;
char db_keydata_path [ MAXPGPATH ] = { 0 } ;
char db_keydata_path [ MAXPGPATH ] = { 0 } ;
/* Set the file paths */
/* Set the file paths */
pg_tde_set_db_file_paths ( dbOid , spcOid , db_map_path , db_keydata_path ) ;
pg_tde_set_db_file_paths ( dbOid , db_map_path , db_keydata_path ) ;
/* Remove these files without emitting any error */
/* Remove these files without emitting any error */
PathNameDeleteTemporaryFile ( db_map_path , false ) ;
PathNameDeleteTemporaryFile ( db_map_path , false ) ;
@ -294,7 +291,6 @@ pg_tde_save_principal_key(TDEPrincipalKeyInfo *principal_key_info)
/* Set the file paths */
/* Set the file paths */
pg_tde_set_db_file_paths ( principal_key_info - > databaseId ,
pg_tde_set_db_file_paths ( principal_key_info - > databaseId ,
principal_key_info - > tablespaceId ,
db_map_path , db_keydata_path ) ;
db_map_path , db_keydata_path ) ;
ereport ( LOG , ( errmsg ( " pg_tde_save_principal_key " ) ) ) ;
ereport ( LOG , ( errmsg ( " pg_tde_save_principal_key " ) ) ) ;
@ -434,7 +430,7 @@ pg_tde_write_one_map_entry(int fd, const RelFileLocator *rlocator, uint32 flags,
{
{
char db_map_path [ MAXPGPATH ] = { 0 } ;
char db_map_path [ MAXPGPATH ] = { 0 } ;
pg_tde_set_db_file_paths ( rlocator - > dbOid , rlocator - > spcOid , db_map_path , NULL ) ;
pg_tde_set_db_file_paths ( rlocator - > dbOid , db_map_path , NULL ) ;
ereport ( FATAL ,
ereport ( FATAL ,
( errcode_for_file_access ( ) ,
( errcode_for_file_access ( ) ,
errmsg ( " could not write tde map file \" %s \" : %m " ,
errmsg ( " could not write tde map file \" %s \" : %m " ,
@ -444,7 +440,7 @@ pg_tde_write_one_map_entry(int fd, const RelFileLocator *rlocator, uint32 flags,
{
{
char db_map_path [ MAXPGPATH ] = { 0 } ;
char db_map_path [ MAXPGPATH ] = { 0 } ;
pg_tde_set_db_file_paths ( rlocator - > dbOid , rlocator - > spcOid , db_map_path , NULL ) ;
pg_tde_set_db_file_paths ( rlocator - > dbOid , db_map_path , NULL ) ;
ereport ( data_sync_elevel ( ERROR ) ,
ereport ( data_sync_elevel ( ERROR ) ,
( errcode_for_file_access ( ) ,
( errcode_for_file_access ( ) ,
errmsg ( " could not fsync file \" %s \" : %m " , db_map_path ) ) ) ;
errmsg ( " could not fsync file \" %s \" : %m " , db_map_path ) ) ) ;
@ -525,7 +521,7 @@ pg_tde_write_key_map_entry(const RelFileLocator *rlocator, RelKeyData *enc_rel_k
Assert ( rlocator ) ;
Assert ( rlocator ) ;
/* Set the file paths */
/* Set the file paths */
pg_tde_set_db_file_paths ( rlocator - > dbOid , rlocator - > spcOid , db_map_path , db_keydata_path ) ;
pg_tde_set_db_file_paths ( rlocator - > dbOid , db_map_path , db_keydata_path ) ;
/* Create the map entry and then add the encrypted key to the data file */
/* Create the map entry and then add the encrypted key to the data file */
key_index = pg_tde_write_map_entry ( rlocator , enc_rel_key_data - > internal_key . rel_type , db_map_path , principal_key_info ) ;
key_index = pg_tde_write_map_entry ( rlocator , enc_rel_key_data - > internal_key . rel_type , db_map_path , principal_key_info ) ;
@ -550,7 +546,7 @@ pg_tde_delete_key_map_entry(const RelFileLocator *rlocator, uint32 key_type)
Assert ( rlocator ) ;
Assert ( rlocator ) ;
/* Get the file paths */
/* Get the file paths */
pg_tde_set_db_file_paths ( rlocator - > dbOid , rlocator - > spcOid , db_map_path , db_keydata_path ) ;
pg_tde_set_db_file_paths ( rlocator - > dbOid , db_map_path , db_keydata_path ) ;
errno = 0 ;
errno = 0 ;
/* Remove the map entry if found */
/* Remove the map entry if found */
@ -596,7 +592,7 @@ pg_tde_free_key_map_entry(const RelFileLocator *rlocator, uint32 key_type, off_t
Assert ( rlocator ) ;
Assert ( rlocator ) ;
/* Get the file paths */
/* Get the file paths */
pg_tde_set_db_file_paths ( rlocator - > dbOid , rlocator - > spcOid , db_map_path , NULL ) ;
pg_tde_set_db_file_paths ( rlocator - > dbOid , db_map_path , NULL ) ;
/* Remove the map entry if found */
/* Remove the map entry if found */
key_index = pg_tde_process_map_entry ( rlocator , key_type , db_map_path , & offset , true ) ;
key_index = pg_tde_process_map_entry ( rlocator , key_type , db_map_path , & offset , true ) ;
@ -610,17 +606,6 @@ pg_tde_free_key_map_entry(const RelFileLocator *rlocator, uint32 key_type, off_t
db_map_path ) ) ) ;
db_map_path ) ) ) ;
}
}
/*
* Remove TDE files it was the last TDE relation in a custom tablespace .
* DROP TABLESPACE needs an empty dir .
*/
if ( rlocator - > spcOid ! = GLOBALTABLESPACE_OID & &
rlocator - > spcOid ! = DEFAULTTABLESPACE_OID & &
pg_tde_process_map_entry ( NULL , key_type , db_map_path , & start , false ) = = - 1 )
{
pg_tde_delete_tde_files ( rlocator - > dbOid , rlocator - > spcOid ) ;
cleanup_key_provider_info ( rlocator - > dbOid , rlocator - > spcOid ) ;
}
}
}
/*
/*
@ -689,7 +674,6 @@ pg_tde_perform_rotate_key(TDEPrincipalKey *principal_key, TDEPrincipalKey *new_p
/* Set the file paths */
/* Set the file paths */
pg_tde_set_db_file_paths ( principal_key - > keyInfo . databaseId ,
pg_tde_set_db_file_paths ( principal_key - > keyInfo . databaseId ,
principal_key - > keyInfo . tablespaceId ,
db_map_path , db_keydata_path ) ;
db_map_path , db_keydata_path ) ;
/*
/*
@ -729,14 +713,13 @@ pg_tde_perform_rotate_key(TDEPrincipalKey *principal_key, TDEPrincipalKey *new_p
rloc . relNumber = read_map_entry . relNumber ;
rloc . relNumber = read_map_entry . relNumber ;
rloc . dbOid = principal_key - > keyInfo . databaseId ;
rloc . dbOid = principal_key - > keyInfo . databaseId ;
rloc . spcOid = principal_key - > keyInfo . tablespaceId ;
/* Let's get the decrypted key and re-encrypt it with the new key. */
/* Let's get the decrypted key and re-encrypt it with the new key. */
enc_rel_key_data [ OLD_PRINCIPAL_KEY ] = pg_tde_read_one_keydata ( k_fd [ OLD_PRINCIPAL_KEY ] , key_index [ OLD_PRINCIPAL_KEY ] , principal_key ) ;
enc_rel_key_data [ OLD_PRINCIPAL_KEY ] = pg_tde_read_one_keydata ( k_fd [ OLD_PRINCIPAL_KEY ] , key_index [ OLD_PRINCIPAL_KEY ] , principal_key ) ;
/* Decrypt and re-encrypt keys */
/* 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 ) ;
rel_key_data [ OLD_PRINCIPAL_KEY ] = tde_decrypt_rel_key ( principal_key , enc_rel_key_data [ OLD_PRINCIPAL_KEY ] , principal_key - > keyInfo . databaseId ) ;
enc_rel_key_data [ NEW_PRINCIPAL_KEY ] = tde_encrypt_rel_key ( new_principal_key , 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 ] , principal_key - > keyInfo . databaseId ) ;
/* Write the given entry at the location pointed by prev_pos */
/* Write the given entry at the location pointed by prev_pos */
prev_pos [ NEW_PRINCIPAL_KEY ] = curr_pos [ NEW_PRINCIPAL_KEY ] ;
prev_pos [ NEW_PRINCIPAL_KEY ] = curr_pos [ NEW_PRINCIPAL_KEY ] ;
@ -814,7 +797,6 @@ pg_tde_write_map_keydata_files(off_t map_size, char *m_file_data, off_t keydata_
/* Set the file paths */
/* Set the file paths */
pg_tde_set_db_file_paths ( fheader - > principal_key_info . databaseId ,
pg_tde_set_db_file_paths ( fheader - > principal_key_info . databaseId ,
fheader - > principal_key_info . tablespaceId ,
db_map_path , db_keydata_path ) ;
db_map_path , db_keydata_path ) ;
/* Initialize the new files and set the names */
/* Initialize the new files and set the names */
@ -870,10 +852,7 @@ FINALIZE:
}
}
/*
/*
* Move relation ' s key to the new physical location and cache it with the new
* Saves the relation key with the new relfilenode .
* relfilenode . It recreates * . map and * . dat files with the old principal key
* and re - encrypted with the new relfilenode internal key . And copies the
* old keyring to the new location .
* Needed by ALTER TABLE SET TABLESPACE for example .
* Needed by ALTER TABLE SET TABLESPACE for example .
*/
*/
bool
bool
@ -890,40 +869,21 @@ pg_tde_move_rel_key(const RelFileLocator *newrlocator, const RelFileLocator *old
off_t offset = 0 ;
off_t offset = 0 ;
int32 key_index = 0 ;
int32 key_index = 0 ;
pg_tde_set_db_file_paths ( oldrlocator - > dbOid , oldrlocator - > spcOid , db_map_path , db_keydata_path ) ;
pg_tde_set_db_file_paths ( oldrlocator - > dbOid , db_map_path , db_keydata_path ) ;
LWLockAcquire ( tde_lwlock_enc_keys ( ) , LW_EXCLUSIVE ) ;
LWLockAcquire ( tde_lwlock_enc_keys ( ) , LW_EXCLUSIVE ) ;
principal_key = GetPrincipalKey ( oldrlocator - > dbOid , oldrlocator - > spcOid , LW_EXCLUSIVE ) ;
principal_key = GetPrincipalKey ( oldrlocator - > dbOid , LW_EXCLUSIVE ) ;
Assert ( principal_key ) ;
Assert ( principal_key ) ;
/*
/*
* Copy kering provider info .
* We don ' t use internal_key cache to avoid locking complications .
*
* TODO : we can potentially avoid moving keyring and key tde files keeping
* these files always in dbOid + MyDatabaseTableSpace path . But the
* background writer isn ' t aware of MyDatabaseTableSpace hence it won ' t
* work with SMGR - > tde_heap . Revisit this after chages in SMGR ( mdcreate )
* interface .
*/
*/
keyring = GetKeyProviderByID ( principal_key - > keyInfo . keyringId , oldrlocator - > dbOid , oldrlocator - > spcOid ) ;
Assert ( keyring ) ;
memcpy ( provider_rec . provider_name , keyring - > provider_name , sizeof ( keyring - > provider_name ) ) ;
provider_rec . provider_type = keyring - > type ;
memcpy ( provider_rec . options , keyring - > options , sizeof ( keyring - > options ) ) ;
copy_key_provider_info ( & provider_rec , newrlocator - > dbOid , newrlocator - > spcOid , true ) ;
principal_key - > keyInfo . keyringId = provider_rec . provider_id ;
key_index = pg_tde_process_map_entry ( oldrlocator , MAP_ENTRY_VALID , db_map_path , & offset , false ) ;
key_index = pg_tde_process_map_entry ( oldrlocator , MAP_ENTRY_VALID , db_map_path , & offset , false ) ;
Assert ( key_index ! = - 1 ) ;
Assert ( key_index ! = - 1 ) ;
/*
* Re - encrypt relation key . We don ' t use internal_key cache to avoid locking
* complications .
*/
enc_key = pg_tde_read_keydata ( db_keydata_path , key_index , principal_key ) ;
enc_key = pg_tde_read_keydata ( db_keydata_path , key_index , principal_key ) ;
rel_key = tde_decrypt_rel_key ( principal_key , enc_key , oldrlocator ) ;
rel_key = tde_decrypt_rel_key ( principal_key , enc_key , oldrlocator - > dbOid ) ;
enc_key = tde_encrypt_rel_key ( principal_key , rel_key , newrlocator ) ;
xlrec . rlocator = * newrlocator ;
xlrec . rlocator = * newrlocator ;
xlrec . relKey = * enc_key ;
xlrec . relKey = * enc_key ;
@ -983,7 +943,7 @@ pg_tde_get_key_from_file(const RelFileLocator *rlocator, uint32 key_type, bool n
* key .
* key .
*/
*/
LWLockAcquire ( lock_pk , LW_SHARED ) ;
LWLockAcquire ( lock_pk , LW_SHARED ) ;
principal_key = GetPrincipalKey ( rlocator - > dbOid , rlocator - > spcOid , LW_SHARED ) ;
principal_key = GetPrincipalKey ( rlocator - > dbOid , LW_SHARED ) ;
if ( principal_key = = NULL )
if ( principal_key = = NULL )
{
{
LWLockRelease ( lock_pk ) ;
LWLockRelease ( lock_pk ) ;
@ -992,7 +952,7 @@ pg_tde_get_key_from_file(const RelFileLocator *rlocator, uint32 key_type, bool n
}
}
/* Get the file paths */
/* Get the file paths */
pg_tde_set_db_file_paths ( rlocator - > dbOid , rlocator - > spcOid , db_map_path , db_keydata_path ) ;
pg_tde_set_db_file_paths ( rlocator - > dbOid , db_map_path , db_keydata_path ) ;
if ( no_map_ok & & access ( db_map_path , F_OK ) = = - 1 )
if ( no_map_ok & & access ( db_map_path , F_OK ) = = - 1 )
{
{
@ -1011,23 +971,11 @@ pg_tde_get_key_from_file(const RelFileLocator *rlocator, uint32 key_type, bool n
enc_rel_key_data = pg_tde_read_keydata ( db_keydata_path , key_index , principal_key ) ;
enc_rel_key_data = pg_tde_read_keydata ( db_keydata_path , key_index , principal_key ) ;
LWLockRelease ( lock_pk ) ;
LWLockRelease ( lock_pk ) ;
rel_key_data = tde_decrypt_rel_key ( principal_key , enc_rel_key_data , rlocator ) ;
rel_key_data = tde_decrypt_rel_key ( principal_key , enc_rel_key_data , rlocator - > dbOid ) ;
return rel_key_data ;
return rel_key_data ;
}
}
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 ) ;
if ( map_path )
join_path_components ( map_path , db_path , PG_TDE_MAP_FILENAME ) ;
if ( keydata_path )
join_path_components ( keydata_path , db_path , PG_TDE_KEYDATA_FILENAME ) ;
pfree ( db_path ) ;
}
/*
/*
* Returns the index of the read map if we find a valid match ; i . e .
* Returns the index of the read map if we find a valid match ; i . e .
* - flags is set to MAP_ENTRY_VALID and the relNumber matches the one
* - flags is set to MAP_ENTRY_VALID and the relNumber matches the one
@ -1147,12 +1095,12 @@ pg_tde_read_keydata(char *db_keydata_path, int32 key_index, TDEPrincipalKey *pri
* Decrypts a given key and returns the decrypted one .
* Decrypts a given key and returns the decrypted one .
*/
*/
RelKeyData *
RelKeyData *
tde_decrypt_rel_key ( TDEPrincipalKey * principal_key , RelKeyData * enc_rel_key_data , const RelFileLocator * rlocator )
tde_decrypt_rel_key ( TDEPrincipalKey * principal_key , RelKeyData * enc_rel_key_data , Oid dbOid )
{
{
RelKeyData * rel_key_data = NULL ;
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 ) ;
AesDecryptKey ( principal_key , dbOid , & rel_key_data , enc_rel_key_data , & key_bytes ) ;
return rel_key_data ;
return rel_key_data ;
}
}
@ -1321,7 +1269,7 @@ pg_tde_read_one_keydata(int keydata_fd, int32 key_index, TDEPrincipalKey *princi
{
{
char db_keydata_path [ MAXPGPATH ] = { 0 } ;
char db_keydata_path [ MAXPGPATH ] = { 0 } ;
pg_tde_set_db_file_paths ( principal_key - > keyInfo . databaseId , principal_key - > keyInfo . tablespaceId , NULL , db_keydata_path ) ;
pg_tde_set_db_file_paths ( principal_key - > keyInfo . databaseId , NULL , db_keydata_path ) ;
ereport ( FATAL ,
ereport ( FATAL ,
( errcode ( ERRCODE_NO_DATA_FOUND ) ,
( 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 " ,
@ -1335,7 +1283,7 @@ pg_tde_read_one_keydata(int keydata_fd, int32 key_index, TDEPrincipalKey *princi
{
{
char db_keydata_path [ MAXPGPATH ] = { 0 } ;
char db_keydata_path [ MAXPGPATH ] = { 0 } ;
pg_tde_set_db_file_paths ( principal_key - > keyInfo . databaseId , principal_key - > keyInfo . tablespaceId , NULL , db_keydata_path ) ;
pg_tde_set_db_file_paths ( principal_key - > keyInfo . databaseId , NULL , db_keydata_path ) ;
ereport ( FATAL ,
ereport ( FATAL ,
( errcode_for_file_access ( ) ,
( 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 " ,
@ -1352,7 +1300,7 @@ pg_tde_read_one_keydata(int keydata_fd, int32 key_index, TDEPrincipalKey *princi
* a LW_SHARED or higher lock on files before calling this function .
* a LW_SHARED or higher lock on files before calling this function .
*/
*/
TDEPrincipalKeyInfo *
TDEPrincipalKeyInfo *
pg_tde_get_principal_key_info ( Oid dbOid , Oid spcOid )
pg_tde_get_principal_key_info ( Oid dbOid )
{
{
int fd = - 1 ;
int fd = - 1 ;
TDEFileHeader fheader ;
TDEFileHeader fheader ;
@ -1362,7 +1310,7 @@ pg_tde_get_principal_key_info(Oid dbOid, Oid spcOid)
char db_map_path [ MAXPGPATH ] = { 0 } ;
char db_map_path [ MAXPGPATH ] = { 0 } ;
/* Set the file paths */
/* Set the file paths */
pg_tde_set_db_file_paths ( dbOid , spcOid , db_map_path , NULL ) ;
pg_tde_set_db_file_paths ( dbOid , db_map_path , NULL ) ;
/*
/*
* Ensuring that we always open the file in binary mode . The caller must
* Ensuring that we always open the file in binary mode . The caller must