From 6f142dc888ea98cdb5d20833114ad754115be83b Mon Sep 17 00:00:00 2001 From: Masahiko Sawada Date: Thu, 15 Aug 2019 13:12:03 +0900 Subject: [PATCH 2/5] Add key management module for cluster encryption. --- src/backend/access/transam/xlog.c | 2 + src/backend/postmaster/pgstat.c | 9 + src/backend/postmaster/postmaster.c | 6 + src/backend/storage/encryption/kmgr.c | 517 ++++++++++++++++++++++++++++++++++ src/backend/storage/ipc/ipci.c | 3 + src/backend/tcop/postgres.c | 8 + src/bin/pg_checksums/pg_checksums.c | 1 + src/include/pgstat.h | 3 + src/include/storage/kmgr.h | 68 +++++ 9 files changed, 617 insertions(+) create mode 100644 src/backend/storage/encryption/kmgr.c create mode 100644 src/include/storage/kmgr.h diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index f553523..5cc2a40 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -57,6 +57,7 @@ #include "storage/bufmgr.h" #include "storage/fd.h" #include "storage/ipc.h" +#include "storage/kmgr.h" #include "storage/large_object.h" #include "storage/latch.h" #include "storage/pmsignal.h" @@ -5264,6 +5265,7 @@ BootStrapXLOG(void) BootStrapCommitTs(); BootStrapSUBTRANS(); BootStrapMultiXact(); + BootStrapKmgr(bootstrap_data_encryption_cipher); pfree(buffer); diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index 2bb14cd..daf19e4 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -3956,6 +3956,15 @@ pgstat_get_wait_io(WaitEventIO w) case WAIT_EVENT_DSM_FILL_ZERO_WRITE: event_name = "DSMFillZeroWrite"; break; + case WAIT_EVENT_KMGR_FILE_READ: + event_name = "KmgrFileRead"; + break; + case WAIT_EVENT_KMGR_FILE_SYNC: + event_name = "KmgrFileSync"; + break; + case WAIT_EVENT_KMGR_FILE_WRITE: + event_name = "KmgrFileWrite"; + break; case WAIT_EVENT_LOCK_FILE_ADDTODATADIR_READ: event_name = "LockFileAddToDataDirRead"; break; diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 3339804..1aeda3c 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -119,6 +119,7 @@ #include "replication/walsender.h" #include "storage/fd.h" #include "storage/ipc.h" +#include "storage/kmgr.h" #include "storage/pg_shmem.h" #include "storage/pmsignal.h" #include "storage/proc.h" @@ -1313,6 +1314,11 @@ PostmasterMain(int argc, char *argv[]) autovac_init(); /* + * Initialize cluster encryption key manager. + */ + InitializeKmgr(); + + /* * Load configuration files for client authentication. */ if (!load_hba()) diff --git a/src/backend/storage/encryption/kmgr.c b/src/backend/storage/encryption/kmgr.c new file mode 100644 index 0000000..c44af9e --- /dev/null +++ b/src/backend/storage/encryption/kmgr.c @@ -0,0 +1,517 @@ +/*------------------------------------------------------------------------- + * + * kmgr.c + * Encryption key management module. + * + * Copyright (c) 2019, PostgreSQL Global Development Group + * + * IDENTIFICATION + * src/backend/storage/encryption/kmgr.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include + +#include "funcapi.h" +#include "miscadmin.h" +#include "pgstat.h" + +#include "access/xlog.h" +#include "storage/encryption.h" +#include "storage/fd.h" +#include "storage/kmgr.h" +#include "storage/lwlock.h" +#include "storage/shmem.h" +#include "utils/builtins.h" +#include "utils/guc.h" +#include "utils/hsearch.h" +#include "utils/memutils.h" +#include "utils/inval.h" +#include "utils/syscache.h" + +/* Kmgr file name */ +#define KMGR_FILENAME "global/pg_kmgr" + +/* Info for key derivation of TDEK and WDEK */ +#define TDE_TDEK_INFO "TDEK" +#define TDE_WDEK_INFO "WDEK" + +typedef unsigned char keydata_t; + +/* + * Struct for key manager meta data written in KMGR_FILENAME. Kmgr file stores + * information that is used for KEK derivation, verification and wrapped MDEK. + * The file is written once when bootstrapping and is read when postmaster + * startup. + */ +typedef struct KmgrFileData +{ + /* salt used for KEK derivation */ + keydata_t kek_salt[TDE_KEK_DEVIRATION_SALT_SIZE]; + + /* HMAC for KEK */ + keydata_t kek_hmac[TDE_KEK_HMAC_SIZE]; + + /* MDEK in encrypted state, NULL-terminated */ + keydata_t mdek[TDE_MDEK_WRAPPED_SIZE]; + + /* CRC of all above ... MUST BE LAST! */ + pg_crc32c crc; +} KmgrFileData; + +/* + * Shared memory struct for encryption key information. All keys are stored + * in non-encrypted state and never be modified during running. Therefore + * processes can use them without locking. + */ +typedef struct KmgrCtlData +{ + /* Master data encryption key */ + keydata_t mdek[TDE_MDEK_SIZE]; + + /* Table data encryption key */ + keydata_t tdek[ENC_MAX_ENCRYPTION_KEY_SIZE]; + + /* WAL data encryption key */ + keydata_t wdek[ENC_MAX_ENCRYPTION_KEY_SIZE]; +} KmgrCtlData; +static KmgrCtlData *KmgrCtl = NULL; + +/* GUC variable */ +char *cluster_passphrase_command = NULL; + +static int run_cluster_passphrase_command(const char *prompt, + char *buf, int size); +static KmgrFileData *read_kmgr_file(void); +static void write_kmgr_file(KmgrFileData *filedata); +static void get_kek_and_hmackey_from_passphrase(char *passphrase, char passlen, + keydata_t salt[TDE_KEK_DEVIRATION_SALT_SIZE], + keydata_t kek[TDE_KEK_SIZE], + keydata_t hmackey[TDE_KEK_HMAC_KEY_SIZE]); +static bool verify_passphrase(KmgrFileData *kmgfile, + char passphrase[TDE_MAX_PASSPHRASE_LEN], + int passlen, keydata_t kek[TDE_KEK_SIZE]); +static void derive_encryption_key(char *id, keydata_t key[ENC_MAX_ENCRYPTION_KEY_SIZE]); + +/* + * This func must be called ONCE on system install. we derive KEK, + * generate MDEK and salt, compute hmac, write kmgr file etc. + */ +void +BootStrapKmgr(int bootstrap_data_encryption_cipher) +{ + const char *prompt = "Enter database encryption pass phrase:"; + KmgrFileData kmgrfile; + char passphrase[TDE_MAX_PASSPHRASE_LEN]; + keydata_t kek_salt[TDE_KEK_DEVIRATION_SALT_SIZE]; + keydata_t kek_hmac[TDE_KEK_HMAC_SIZE]; + keydata_t mdek[TDE_MDEK_SIZE]; + keydata_t encmdek[TDE_MDEK_WRAPPED_SIZE]; + keydata_t kek[TDE_KEK_SIZE]; + keydata_t hmackey[TDE_KEK_HMAC_KEY_SIZE]; + int encmdek_size; + int len; + int ret; + +#ifndef USE_OPENSSL + ereport(ERROR, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + (errmsg("cluster encryption is not supported because OpenSSL is not supported by this build"), + errhint("Compile with --with-openssl to use cluster encryption.")))); +#endif + + if (bootstrap_data_encryption_cipher == 0) + return; + + /* + * Set data encryption cipher so that subsequent bootstrapping process + * can proceed. + */ + SetConfigOption("data_encryption_cipher", + EncryptionCipherString(bootstrap_data_encryption_cipher), + PGC_INTERNAL, PGC_S_OVERRIDE); + + /* Get encryption key passphrase */ + len = run_cluster_passphrase_command(prompt, + passphrase, + TDE_MAX_PASSPHRASE_LEN); + + /* Generate salt for KEK derivation */ + ret = pg_strong_random(kek_salt, TDE_KEK_DEVIRATION_SALT_SIZE); + if (!ret) + ereport(ERROR, + (errmsg("failed to generate random salt for key encryption key"))); + + /* Get KEK and HMAC key */ + get_kek_and_hmackey_from_passphrase(passphrase, len, kek_salt, kek, hmackey); + + /* Generate salt for KEK */ + ret = pg_strong_random(mdek, TDE_MDEK_SIZE); + if (!ret) + ereport(ERROR, + (errmsg("failed to generate the master encryption key"))); + + /* Encrypt MDEK with KEK */ + pg_wrap_key(kek, TDE_KEK_SIZE, mdek, TDE_MDEK_SIZE, encmdek, &encmdek_size); + + if (encmdek_size != TDE_MDEK_WRAPPED_SIZE) + elog(ERROR, "wrapped MDEK key size is invalid, got %d expected %d", + encmdek_size, TDE_MDEK_WRAPPED_SIZE); + + /* Compute HMAC */ + pg_compute_hmac(hmackey, TDE_KEK_HMAC_SIZE, encmdek, TDE_MDEK_WRAPPED_SIZE, + kek_hmac); + + /* Fill out the kmgr file contents */ + memcpy(kmgrfile.kek_salt, kek_salt, TDE_KEK_DEVIRATION_SALT_SIZE); + memcpy(kmgrfile.kek_hmac, kek_hmac, TDE_KEK_HMAC_SIZE); + memcpy(kmgrfile.mdek, encmdek, TDE_MDEK_WRAPPED_SIZE); + + /* write kmgr file to the disk */ + write_kmgr_file(&kmgrfile); + + /* Set keys */ + memcpy(KmgrCtl->mdek, mdek, TDE_MDEK_SIZE); + derive_encryption_key(TDE_TDEK_INFO, KmgrCtl->tdek); + derive_encryption_key(TDE_WDEK_INFO, KmgrCtl->wdek); +} + +Size +KmgrShmemSize(void) +{ + return sizeof(KmgrCtlData); +} + +void +KmgrShmemInit(void) +{ + bool found; + + KmgrCtl = (KmgrCtlData *) ShmemInitStruct("KeyManagementData", + KmgrShmemSize(), &found); + + if (!found) + MemSet(KmgrCtl, 0, KmgrShmemSize()); +} + +/* + * Run cluster_passphrase_command + * + * prompt will be substituted for %p. + * + * The result will be put in buffer buf, which is of size size. The return + * value is the length of the actual result. + */ +static int +run_cluster_passphrase_command(const char *prompt, char *buf, int size) +{ + StringInfoData command; + char *p; + FILE *fh; + int pclose_rc; + size_t len = 0; + + Assert(prompt); + Assert(size > 0); + buf[0] = '\0'; + + initStringInfo(&command); + + for (p = cluster_passphrase_command; *p; p++) + { + if (p[0] == '%') + { + switch (p[1]) + { + case 'p': + appendStringInfoString(&command, prompt); + p++; + break; + case '%': + appendStringInfoChar(&command, '%'); + p++; + break; + default: + appendStringInfoChar(&command, p[0]); + } + } + else + appendStringInfoChar(&command, p[0]); + } + + fh = OpenPipeStream(command.data, "r"); + if (fh == NULL) + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not execute command \"%s\": %m", + command.data))); + + if (!fgets(buf, size, fh)) + { + if (ferror(fh)) + { + pfree(command.data); + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not read from command \"%s\": %m", + command.data))); + } + } + + pclose_rc = ClosePipeStream(fh); + if (pclose_rc == -1) + { + pfree(command.data); + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not close pipe to external command: %m"))); + } + else if (pclose_rc != 0) + { + pfree(command.data); + ereport(ERROR, + (errcode_for_file_access(), + errmsg("command \"%s\" failed", + command.data), + errdetail_internal("%s", wait_result_to_str(pclose_rc)))); + } + + /* strip trailing newline */ + len = strlen(buf); + if (len > 0 && buf[len - 1] == '\n') + buf[--len] = '\0'; + + pfree(command.data); + + return len; +} + +/* + * Get encryption key passphrase and verify it, then get the un-encrypted + * MDEK. This function is called by postmaster at startup time. + */ +void +InitializeKmgr(void) +{ + const char *prompt = "Enter database encryption pass phrase:"; + char passphrase[TDE_MAX_PASSPHRASE_LEN]; + keydata_t kek[TDE_KEK_SIZE]; + keydata_t mdek[TDE_MDEK_SIZE]; + KmgrFileData *kmgrfile; + int len; + int mdek_size; + + if (!DataEncryptionEnabled()) + return; + + /* Get contents of kmgr file */ + kmgrfile = read_kmgr_file(); + + /* Get encryption key passphrase */ + len = run_cluster_passphrase_command(prompt, + passphrase, + TDE_MAX_PASSPHRASE_LEN); + + /* Verify the given passphrase */ + if (!verify_passphrase(kmgrfile, passphrase, len, kek)) + ereport(ERROR, + (errmsg("cluster passphrase does not match expected passphrase"))); + + /* Unwrap MDEK with KEK */ + pg_unwrap_key(kek, TDE_KEK_SIZE, kmgrfile->mdek, TDE_MDEK_WRAPPED_SIZE, + mdek, &mdek_size); + + if (mdek_size != TDE_MDEK_SIZE) + elog(ERROR, "unwrapped MDEK key size is invalid, got %d expected %d", + mdek_size, TDE_MDEK_SIZE); + + /* Set MDEK, TDEK and WDEK to the shared memory struct */ + memcpy(KmgrCtl->mdek, mdek, TDE_MDEK_SIZE); + derive_encryption_key(TDE_TDEK_INFO, KmgrCtl->tdek); + derive_encryption_key(TDE_WDEK_INFO, KmgrCtl->wdek); +} + +/* + * Read kmgr file, and return palloc'd file data. + */ +static KmgrFileData * +read_kmgr_file(void) +{ + KmgrFileData *kmgrfile; + pg_crc32c crc; + int read_len; + int fd; + + fd = BasicOpenFile(KMGR_FILENAME, O_RDONLY | PG_BINARY); + + if (fd < 0) + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not open file \"%s\": %m", KMGR_FILENAME))); + + /* Read data */ + kmgrfile = (KmgrFileData *) palloc(sizeof(KmgrFileData)); + + pgstat_report_wait_start(WAIT_EVENT_KMGR_FILE_READ); + if ((read_len = read(fd, kmgrfile, sizeof(KmgrFileData))) < 0) + ereport(ERROR, + (errcode_for_file_access(), + (errmsg("could not read from file \"%s\": %m", KMGR_FILENAME)))); + pgstat_report_wait_end(); + + if (close(fd)) + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not close file \"%s\": %m", KMGR_FILENAME))); + + /* Verify CRC */ + INIT_CRC32C(crc); + COMP_CRC32C(crc, (char *) kmgrfile, offsetof(KmgrFileData, crc)); + FIN_CRC32C(crc); + + if (!EQ_CRC32C(crc, kmgrfile->crc)) + ereport(ERROR, + (errcode(ERRCODE_DATA_CORRUPTED), + errmsg("calculated CRC checksum does not match value stored in file \"%s\"", + KMGR_FILENAME))); + + return kmgrfile; +} + +/* + * Write kmgr file. This function is used only when bootstrapping. + */ +static void +write_kmgr_file(KmgrFileData *filedata) +{ + int fd; + + INIT_CRC32C(filedata->crc); + COMP_CRC32C(filedata->crc, filedata, offsetof(KmgrFileData, crc)); + FIN_CRC32C(filedata->crc); + + fd = BasicOpenFile(KMGR_FILENAME, PG_BINARY | O_CREAT | O_RDWR); + + if (fd < 0) + { + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not open file \"%s\": %m", + KMGR_FILENAME))); + return; + } + + pgstat_report_wait_start(WAIT_EVENT_KMGR_FILE_WRITE); + if (write(fd, filedata, sizeof(KmgrFileData)) != sizeof(KmgrFileData)) + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not write kmgr file \"%s\": %m", + KMGR_FILENAME))); + pgstat_report_wait_end(); + + pgstat_report_wait_start(WAIT_EVENT_KMGR_FILE_SYNC); + if (pg_fsync(fd) != 0) + ereport(ERROR, + (errcode_for_file_access(), + (errmsg("could not sync file \"%s\": %m", + KMGR_FILENAME)))); + pgstat_report_wait_end(); + + if (close(fd)) + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not close file \"%s\": %m", KMGR_FILENAME))); + +} + +/* + * Derive key from passphrase and extract KEK and HMAC key from the derived key. + */ +static void +get_kek_and_hmackey_from_passphrase(char *passphrase, char passlen, + keydata_t salt[TDE_KEK_DEVIRATION_SALT_SIZE], + keydata_t kek[TDE_KEK_SIZE], + keydata_t hmackey[TDE_KEK_HMAC_KEY_SIZE]) +{ + keydata_t enckey_and_hmackey[TDE_KEK_DERIVED_KEY_SIZE]; + + /* Derive key from passphrase, or error */ + pg_derive_key_passphrase(passphrase, passlen, + salt, TDE_KEK_DEVIRATION_SALT_SIZE, + TDE_KEK_DEVIRATION_ITER_COUNT, + TDE_KEK_SIZE + TDE_KEK_HMAC_KEY_SIZE, + enckey_and_hmackey); + + /* Extract KEK and HMAC key from the derived key */ + memcpy(kek, enckey_and_hmackey, TDE_KEK_SIZE); + memcpy(hmackey, enckey_and_hmackey + TDE_KEK_SIZE, TDE_KEK_HMAC_KEY_SIZE); +} + +/* + * Verify correctness of the given passphrase. We compute HMAC of encrypted + * MDEK written in the kmgr file, and compare it to the HMAC written in the kmgr + * file. Return true and set KEK if the passphrase is verified, otherwise return + * false. + */ +static bool +verify_passphrase(KmgrFileData *kmgrfile, char passphrase[TDE_MAX_PASSPHRASE_LEN], + int passlen, keydata_t kek[TDE_KEK_SIZE]) +{ + keydata_t hmac[TDE_KEK_HMAC_SIZE]; + keydata_t kek_tmp[TDE_KEK_SIZE]; + keydata_t hmackey_tmp[TDE_KEK_HMAC_KEY_SIZE]; + + get_kek_and_hmackey_from_passphrase(passphrase, passlen, + kmgrfile->kek_salt, kek_tmp, + hmackey_tmp); + + /* + * Compute HMAC of encrypted MDEK in kmgr file with the HMAC key derived + * from passphrase. + */ + pg_compute_hmac(hmackey_tmp, TDE_KEK_HMAC_KEY_SIZE, kmgrfile->mdek, + TDE_MDEK_WRAPPED_SIZE, hmac); + + /* Compare two HMACs */ + if (memcmp(kmgrfile->kek_hmac, hmac, TDE_KEK_HMAC_SIZE) != 0) + return false; + + /* user-provided passphrase is correct, set KEK */ + memcpy(kek, kek_tmp, TDE_KEK_SIZE); + + return true; +} + +/* Return table data encryption key (TDEK) */ +const char * +GetTableEncryptionKey(void) +{ + Assert(KmgrCtl != NULL); + + return (char *) KmgrCtl->tdek; +} + +/* Return WAL data encryption key (WDEK) */ +const char * +GetWALEncryptionKey(void) +{ + Assert(KmgrCtl != NULL); + + return (const char *) KmgrCtl->wdek; +} + +/* + * Derive new encryption key with info from MDEK. + */ +static void +derive_encryption_key(char *info, keydata_t key[ENC_MAX_ENCRYPTION_KEY_SIZE]) +{ + char key_len = EncryptionKeySize; + + /* derive new TDEK that length is EncryptionKeySize from MDEK */ + pg_derive_key(KmgrCtl->mdek, TDE_MDEK_SIZE, (keydata_t *) info, + key, key_len); +} diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c index d7d7335..f8b3e76 100644 --- a/src/backend/storage/ipc/ipci.c +++ b/src/backend/storage/ipc/ipci.c @@ -36,6 +36,7 @@ #include "storage/bufmgr.h" #include "storage/dsm.h" #include "storage/ipc.h" +#include "storage/kmgr.h" #include "storage/pg_shmem.h" #include "storage/pmsignal.h" #include "storage/predicate.h" @@ -147,6 +148,7 @@ CreateSharedMemoryAndSemaphores(int port) size = add_size(size, BTreeShmemSize()); size = add_size(size, SyncScanShmemSize()); size = add_size(size, AsyncShmemSize()); + size = add_size(size, KmgrShmemSize()); #ifdef EXEC_BACKEND size = add_size(size, ShmemBackendArraySize()); #endif @@ -263,6 +265,7 @@ CreateSharedMemoryAndSemaphores(int port) BTreeShmemInit(); SyncScanShmemInit(); AsyncShmemInit(); + KmgrShmemInit(); #ifdef EXEC_BACKEND diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index e8d8e6f..b225918 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -63,6 +63,7 @@ #include "replication/walsender.h" #include "rewrite/rewriteHandler.h" #include "storage/bufmgr.h" +#include "storage/kmgr.h" #include "storage/ipc.h" #include "storage/proc.h" #include "storage/procsignal.h" @@ -3859,6 +3860,13 @@ PostgresMain(int argc, char *argv[], BaseInit(); /* + * Initialize kmgr for cluster encryption. Since kmgr needs to attach to + * shared memory the initialization must be called after BaseInit(). + */ + if (!IsUnderPostmaster) + InitializeKmgr(); + + /* * Create a per-backend PGPROC struct in shared memory, except in the * EXEC_BACKEND case where this was done in SubPostmasterMain. We must do * this before we can use LWLocks (and in the EXEC_BACKEND case we already diff --git a/src/bin/pg_checksums/pg_checksums.c b/src/bin/pg_checksums/pg_checksums.c index 8c00ec9..4d311ed 100644 --- a/src/bin/pg_checksums/pg_checksums.c +++ b/src/bin/pg_checksums/pg_checksums.c @@ -100,6 +100,7 @@ static const char *const skip[] = { "pg_control", "pg_filenode.map", "pg_internal.init", + "pg_kmgr", "PG_VERSION", #ifdef EXEC_BACKEND "config_exec_params", diff --git a/src/include/pgstat.h b/src/include/pgstat.h index 0a3ad3a..8ec5ecf 100644 --- a/src/include/pgstat.h +++ b/src/include/pgstat.h @@ -896,6 +896,9 @@ typedef enum WAIT_EVENT_DATA_FILE_TRUNCATE, WAIT_EVENT_DATA_FILE_WRITE, WAIT_EVENT_DSM_FILL_ZERO_WRITE, + WAIT_EVENT_KMGR_FILE_READ, + WAIT_EVENT_KMGR_FILE_SYNC, + WAIT_EVENT_KMGR_FILE_WRITE, WAIT_EVENT_LOCK_FILE_ADDTODATADIR_READ, WAIT_EVENT_LOCK_FILE_ADDTODATADIR_SYNC, WAIT_EVENT_LOCK_FILE_ADDTODATADIR_WRITE, diff --git a/src/include/storage/kmgr.h b/src/include/storage/kmgr.h new file mode 100644 index 0000000..b62a0ae --- /dev/null +++ b/src/include/storage/kmgr.h @@ -0,0 +1,68 @@ +/*------------------------------------------------------------------------- + * + * kmgr.h + * Key management module for transparent data encryption + * + * Portions Copyright (c) 2019, PostgreSQL Global Development Group + * + * src/include/storage/kmgr.h + * + *------------------------------------------------------------------------- + */ +#ifndef KMGR_H +#define KMGR_H + +#include "storage/relfilenode.h" +#include "storage/bufpage.h" + +/* Size of key encryption key (KEK), which is always AES-256 key */ +#define TDE_KEK_SIZE 32 + +/* + * Size of HMAC key for KEK is the same as the length of hash, we use + * SHA-256. + */ +#define TDE_KEK_HMAC_KEY_SIZE 32 + +/* SHA-256 results 256 bits HMAC */ +#define TDE_KEK_HMAC_SIZE 32 + +/* + * Size of the derived key from passphrase. It consists of KEK and HMAC key. + */ +#define TDE_KEK_DERIVED_KEY_SIZE (TDE_KEK_SIZE + TDE_KEK_HMAC_KEY_SIZE) + +/* + * Iteration count of password based key derivation. NIST recommends that + * minimum iteration count is 1000. + */ +#define TDE_KEK_DEVIRATION_ITER_COUNT 100000 + +/* + * Size of salt for password based key derivation. NIST recommended that + * salt size is at least 16 + */ +#define TDE_KEK_DEVIRATION_SALT_SIZE 64 + +/* Key wrapping appends the initial 64 bit value */ +#define TDE_KEY_WRAP_VALUE_SIZE 8 + +/* Size of master data encryption key (MDEK), which is always AES-256 key */ +#define TDE_MDEK_SIZE 32 + +/* Wrapped key size is n+1 value */ +#define TDE_MDEK_WRAPPED_SIZE (TDE_MDEK_SIZE + TDE_KEY_WRAP_VALUE_SIZE) + +#define TDE_MAX_PASSPHRASE_LEN MAXPGPATH + +/* GUC variable */ +extern char *cluster_passphrase_command; + +extern void BootStrapKmgr(int bootstrap_data_encryption_cipher); +extern Size KmgrShmemSize(void); +extern void KmgrShmemInit(void); +extern void InitializeKmgr(void); +extern const char *GetTableEncryptionKey(void); +extern const char *GetWALEncryptionKey(void); + +#endif /* KMGR_H */ -- 2.10.5