From 1902246af4fefa6e9a6754b229c2f90d8026966f Mon Sep 17 00:00:00 2001 From: Masahiko Sawada Date: Thu, 15 Aug 2019 13:08:56 +0900 Subject: [PATCH v2 1/5] Introduce cryptographic functions for cluster encryption. --- configure | 15 +- configure.in | 9 +- src/backend/storage/Makefile | 3 +- src/backend/storage/encryption/Makefile | 21 + src/backend/storage/encryption/enc_cipher.c | 129 ++++++ src/backend/storage/encryption/enc_openssl.c | 397 +++++++++++++++++++ src/include/pg_config.h.in | 6 + src/include/storage/enc_cipher.h | 33 ++ src/include/storage/enc_common.h | 34 ++ src/include/storage/enc_internal.h | 34 ++ src/include/storage/encryption.h | 39 ++ 11 files changed, 717 insertions(+), 3 deletions(-) create mode 100644 src/backend/storage/encryption/Makefile create mode 100644 src/backend/storage/encryption/enc_cipher.c create mode 100644 src/backend/storage/encryption/enc_openssl.c create mode 100644 src/include/storage/enc_cipher.h create mode 100644 src/include/storage/enc_common.h create mode 100644 src/include/storage/enc_internal.h create mode 100644 src/include/storage/encryption.h diff --git a/configure b/configure index 6b1c779ee3..b41fc519c7 100755 --- a/configure +++ b/configure @@ -12058,7 +12058,7 @@ done # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it # doesn't have these OpenSSL 1.1.0 functions. So check for individual # functions. - for ac_func in OPENSSL_init_ssl BIO_get_data BIO_meth_new ASN1_STRING_get0_data + for ac_func in OPENSSL_init_ssl OPENSSL_init_crypto BIO_get_data BIO_meth_new ASN1_STRING_get0_data EVP_PKEY_derive do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" @@ -12772,6 +12772,19 @@ fi done +# check for +for ac_header in netinet/tcp.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "openssl/kdf.h" "ac_cv_header_openssl_kdf_h" "$ac_includes_default" +if test "x$ac_cv_header_openssl_kdf_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OPENSSL_KDF 1 +_ACEOF + +fi + +done + if expr x"$pgac_cv_check_readline" : 'x-lreadline' >/dev/null ; then for ac_header in readline/readline.h diff --git a/configure.in b/configure.in index 2b9025cac3..3e0b3f937d 100644 --- a/configure.in +++ b/configure.in @@ -1190,7 +1190,7 @@ if test "$with_openssl" = yes ; then # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it # doesn't have these OpenSSL 1.1.0 functions. So check for individual # functions. - AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_get_data BIO_meth_new ASN1_STRING_get0_data]) + AC_CHECK_FUNCS([OPENSSL_init_ssl OPENSSL_init_crypto BIO_get_data BIO_meth_new ASN1_STRING_get0_data]) # OpenSSL versions before 1.1.0 required setting callback functions, for # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock() # function was removed. @@ -1322,6 +1322,13 @@ AC_CHECK_HEADERS(netinet/tcp.h, [], [], #include ]) +if test "$with_openssl" = yes ; then + AC_CHECK_HEADERS(openssl/kdf.h, [], [], +[AC_INCLUDES_DEFAULT +#include +]) +fi + if expr x"$pgac_cv_check_readline" : 'x-lreadline' >/dev/null ; then AC_CHECK_HEADERS(readline/readline.h, [], [AC_CHECK_HEADERS(readline.h, [], diff --git a/src/backend/storage/Makefile b/src/backend/storage/Makefile index 8376cdfca2..2a6d2aba8c 100644 --- a/src/backend/storage/Makefile +++ b/src/backend/storage/Makefile @@ -8,6 +8,7 @@ subdir = src/backend/storage top_builddir = ../../.. include $(top_builddir)/src/Makefile.global -SUBDIRS = buffer file freespace ipc large_object lmgr page smgr sync +SUBDIRS = buffer file freespace ipc large_object lmgr page smgr sync \ + encryption include $(top_srcdir)/src/backend/common.mk diff --git a/src/backend/storage/encryption/Makefile b/src/backend/storage/encryption/Makefile new file mode 100644 index 0000000000..50244c30e7 --- /dev/null +++ b/src/backend/storage/encryption/Makefile @@ -0,0 +1,21 @@ +#------------------------------------------------------------------------- +# +# Makefile-- +# Makefile for storage/encryption +# +# IDENTIFICATION +# src/backend/storage/encryption/Makefile +# +#------------------------------------------------------------------------- + +subdir = src/backend/storage/encryption/ +top_builddir = ../../../.. +include $(top_builddir)/src/Makefile.global + +OBJS = kmgr.o bufenc.o walenc.o enc_cipher.o + +ifeq ($(with_openssl),yes) +OBJS += enc_openssl.o +endif + +include $(top_srcdir)/src/backend/common.mk diff --git a/src/backend/storage/encryption/enc_cipher.c b/src/backend/storage/encryption/enc_cipher.c new file mode 100644 index 0000000000..046e531556 --- /dev/null +++ b/src/backend/storage/encryption/enc_cipher.c @@ -0,0 +1,129 @@ +/*------------------------------------------------------------------------- + * + * enc_openssl.c + * This code handles encryption and decryption using OpenSSL + * + * Copyright (c) 2019, PostgreSQL Global Development Group + * + * + * IDENTIFICATION + * src/backend/storage/encryption/enc_openssl.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "storage/enc_cipher.h" +#include "storage/enc_common.h" +#include "storage/enc_internal.h" + +/* GUC parameter */ +int data_encryption_cipher; +int EncryptionKeySize; + +/* Data encryption */ +void +pg_encrypt(const char *input, char *output, int size, + const char *key, const char *iv) +{ +#ifdef USE_OPENSSL + ossl_encrypt_data(input, output, size, key, iv); +#endif +} + +/* Data decryption */ +void +pg_decrypt(const char *input, char *output, int size, + const char *key, const char *iv) +{ +#ifdef USE_OPENSSL + ossl_decrypt_data(input, output, size, key, iv); +#endif +} + +/* Key derivation */ +void +pg_derive_key(const unsigned char *base_key, int base_size, unsigned char *info, + unsigned char *derived_key, Size derived_size) +{ +#ifdef USE_OPENSSL + ossl_derive_key(base_key, base_size, info, derived_key, derived_size); +#endif +} + +/* HMAC computation */ +void +pg_compute_hmac(const unsigned char *hmac_key, int key_size, unsigned char *data, + int data_size, unsigned char *hmac) +{ +#ifdef USE_OPENSSL + ossl_compute_hmac(hmac_key, key_size, data, data_size, hmac); +#endif +} + +/* Key wrap */ +void +pg_wrap_key(const unsigned char *key, int key_size, unsigned char *in, + int in_size, unsigned char *out, int *out_size) +{ +#ifdef USE_OPENSSL + ossl_wrap_key(key, key_size, in, in_size, out, out_size); +#endif +} + +/* Key unwrap */ +void +pg_unwrap_key(const unsigned char *key, int key_size, unsigned char *in, + int in_size, unsigned char *out, int *out_size) +{ +#ifdef USE_OPENSSL + ossl_unwrap_key(key, key_size, in, in_size, out, out_size); +#endif +} + +/* Convert cipher name string to integer value */ +int +EncryptionCipherValue(const char *name) +{ + if (strcmp(name, "aes-128") == 0) + return TDE_ENCRYPTION_AES_128; + else if (strcmp(name, "aes-256") == 0) + return TDE_ENCRYPTION_AES_256; + else + return TDE_ENCRYPTION_OFF; +} + +/* Convert integer value to cipher name string */ +char * +EncryptionCipherString(int value) +{ + switch (value) + { + case TDE_ENCRYPTION_OFF : + return "off"; + case TDE_ENCRYPTION_AES_128: + return "aes-128"; + case TDE_ENCRYPTION_AES_256: + return "aes-256"; + } + + return "unknown"; +} + +void +assign_data_encryption_cipher(int new_encryption_cipher, void *extra) +{ + switch (new_encryption_cipher) + { + case TDE_ENCRYPTION_OFF: + EncryptionKeySize = 0; + break; + case TDE_ENCRYPTION_AES_128: + EncryptionKeySize = 16; + break; + case TDE_ENCRYPTION_AES_256: + EncryptionKeySize = 32; + break; + } +} diff --git a/src/backend/storage/encryption/enc_openssl.c b/src/backend/storage/encryption/enc_openssl.c new file mode 100644 index 0000000000..95f165f695 --- /dev/null +++ b/src/backend/storage/encryption/enc_openssl.c @@ -0,0 +1,397 @@ +/*------------------------------------------------------------------------- + * + * enc_openssl.c + * This code handles encryption and decryption using OpenSSL + * + * Copyright (c) 2019, PostgreSQL Global Development Group + * + * + * IDENTIFICATION + * src/backend/storage/encryption/enc_openssl.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include + +#include "storage/enc_internal.h" +#include "storage/enc_common.h" +#include "utils/memutils.h" + +#include +#include +#include +#include +#ifdef HAVE_OPENSSL_KDF +#include +#endif + +/* + * prototype for the EVP functions that return an algorithm, e.g. + * EVP_aes_128_cbc(). + */ +typedef const EVP_CIPHER *(*ossl_EVP_cipher_func) (void); + +/* + * Supported cipher function and its key size. The index of each cipher + * is (data_encryption_cipher - 1). + */ +ossl_EVP_cipher_func cipher_func_table[] = +{ + EVP_aes_128_ctr, /* TDE_ENCRYPTION_AES_128 */ + EVP_aes_256_ctr /* TDE_ENCRYPTION_AES_256 */ +}; + +typedef struct CipherCtx +{ + /* Encryption context */ + EVP_CIPHER_CTX *enc_ctx; + + /* Decryption context */ + EVP_CIPHER_CTX *dec_ctx; + + /* Key wrap context */ + EVP_CIPHER_CTX *wrap_ctx; + + /* Key unwrap context */ + EVP_CIPHER_CTX *unwrap_ctx; + + /* Key derivation context */ + EVP_PKEY_CTX *derive_ctx; +} CipherCtx; + +CipherCtx *MyCipherCtx = NULL; +MemoryContext EncMemoryCtx; + +static void createCipherContext(void); +static EVP_CIPHER_CTX *create_ossl_encryption_ctx(ossl_EVP_cipher_func func, + int klen, bool isenc, + bool iswrap); +static EVP_PKEY_CTX *create_ossl_derive_ctx(void); +static void setup_encryption_ossl(void); +static void setup_encryption(void) ; + +static void +createCipherContext(void) +{ + ossl_EVP_cipher_func cipherfunc = cipher_func_table[data_encryption_cipher - 1]; + MemoryContext old_ctx; + CipherCtx *cctx; + + if (MyCipherCtx != NULL) + return; + + if (EncMemoryCtx == NULL) + EncMemoryCtx = AllocSetContextCreate(TopMemoryContext, + "db encryption context", + ALLOCSET_DEFAULT_SIZES); + + old_ctx = MemoryContextSwitchTo(EncMemoryCtx); + + cctx = (CipherCtx *) palloc(sizeof(CipherCtx)); + + /* Create encryption/decryption contexts */ + cctx->enc_ctx = create_ossl_encryption_ctx(cipherfunc, + EncryptionKeySize, + true, false); + cctx->dec_ctx = create_ossl_encryption_ctx(cipherfunc, + EncryptionKeySize, + false, false); + + /* Create key wrap/unwrap contexts */ + cctx->wrap_ctx = create_ossl_encryption_ctx(EVP_aes_256_wrap, + 32, true, true); + cctx->unwrap_ctx = create_ossl_encryption_ctx(EVP_aes_256_wrap, + 32, false, true); + + /* Create key derivation context */ + cctx->derive_ctx = create_ossl_derive_ctx(); + + /* Set my cipher context and key size */ + MyCipherCtx = cctx; + + MemoryContextSwitchTo(old_ctx); +} + +/* Create openssl's key derivation context */ +static EVP_PKEY_CTX * +create_ossl_derive_ctx(void) +{ + EVP_PKEY_CTX *pctx = NULL; + +#ifdef HAVE_OPENSSL_KDF + pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL); + + if (EVP_PKEY_derive_init(pctx) <= 0) + ereport(ERROR, + (errmsg("openssl encountered error during initializing derive context"), + (errdetail("openssl error string: %s", + ERR_error_string(ERR_get_error(), NULL))))); + + if (EVP_PKEY_CTX_set_hkdf_md(pctx, EVP_sha256()) <= 0) + ereport(ERROR, + (errmsg("openssl encountered error during setting HKDF context"), + (errdetail("openssl error string: %s", + ERR_error_string(ERR_get_error(), NULL))))); +#endif + + return pctx; +} + +/* Create openssl's encryption context */ +static EVP_CIPHER_CTX * +create_ossl_encryption_ctx(ossl_EVP_cipher_func func, int klen, bool isenc, + bool iswrap) +{ + EVP_CIPHER_CTX *ctx; + int ret; + + /* Create new openssl cipher context */ + ctx = EVP_CIPHER_CTX_new(); + + /* Enable key wrap algorithm */ + if (iswrap) + EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW); + + if (ctx == NULL) + ereport(ERROR, + (errmsg("openssl encountered error during creating context"), + (errdetail("openssl error string: %s", + ERR_error_string(ERR_get_error(), NULL))))); + + if (isenc) + ret = EVP_EncryptInit_ex(ctx, (const EVP_CIPHER *) func(), NULL, + NULL, NULL); + else + ret = EVP_DecryptInit_ex(ctx, (const EVP_CIPHER *) func(), NULL, + NULL, NULL); + + if (ret != 1) + ereport(ERROR, + (errmsg("openssl encountered error during initializing context"), + (errdetail("openssl error string: %s", + ERR_error_string(ERR_get_error(), NULL))))); + + if (!EVP_CIPHER_CTX_set_key_length(ctx, klen)) + ereport(ERROR, + (errmsg("openssl encountered error during setting key length"), + (errdetail("openssl error string: %s", + ERR_error_string(ERR_get_error(), NULL))))); + + return ctx; +} + +/* + * Initialize encryption subsystem for use. Must be called before any + * encryptable data is read from or written to data directory. + */ +static void +setup_encryption(void) +{ + setup_encryption_ossl(); + createCipherContext(); +} + +static void +setup_encryption_ossl(void) +{ +#ifndef HAVE_OPENSSL_KDF + /* + * We can initialize openssl even with openssl is 1.0.0 or older, but + * since AES key wrap algorithms have introduced in openssl 1.1.0 + * we require 1.1.0 or higher version for cluster encryption. + */ + ereport(ERROR, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + (errmsg("openssl 1.1.0 or higher is required for cluster encryption")))); +#endif + +#ifdef HAVE_OPENSSL_INIT_CRYPTO + /* Setup OpenSSL */ + OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL); +#endif +} + +void +ossl_encrypt_data(const char *input, char *output, int size, + const char *key, const char *iv) +{ + int out_size; + EVP_CIPHER_CTX *ctx; + + /* Ensure encryption has setup */ + if (MyCipherCtx == NULL) + setup_encryption(); + + ctx = MyCipherCtx->enc_ctx; + + if (EVP_EncryptInit_ex(ctx, NULL, NULL, (unsigned char *) key, + (unsigned char *) iv) != 1) + ereport(ERROR, + (errmsg("openssl encountered initialization error during encryption"), + (errdetail("openssl error string: %s", + ERR_error_string(ERR_get_error(), NULL))))); + + if (EVP_EncryptUpdate(ctx, (unsigned char *) output, + &out_size, (unsigned char *) input, size) != 1) + ereport(ERROR, + (errmsg("openssl encountered error during encryption"), + (errdetail("openssl error string: %s", + ERR_error_string(ERR_get_error(), NULL))))); + + Assert(out_size == size); +} + +void +ossl_decrypt_data(const char *input, char *output, int size, + const char *key, const char *iv) +{ + int out_size; + EVP_CIPHER_CTX *ctx; + + /* Ensure encryption has setup */ + if (MyCipherCtx == NULL) + setup_encryption(); + + ctx = MyCipherCtx->dec_ctx; + + if (EVP_DecryptInit_ex(ctx, NULL, NULL, (unsigned char *) key, + (unsigned char *) iv) != 1) + ereport(ERROR, + (errmsg("openssl encountered initialization error during decryption"), + (errdetail("openssl error string: %s", + ERR_error_string(ERR_get_error(), NULL))))); + + if (EVP_DecryptUpdate(ctx, (unsigned char *) output, + &out_size, (unsigned char *) input, size) != 1) + ereport(ERROR, + (errmsg("openssl encountered error during decryption"), + (errdetail("openssl error string: %s", + ERR_error_string(ERR_get_error(), NULL))))); + + Assert(out_size == size); +} + +void +ossl_derive_key(const unsigned char *base_key, int base_size, unsigned char *info, + unsigned char *derived_key, Size derived_size) +{ +#ifdef HAVE_OPENSSL_KDF + EVP_PKEY_CTX *pctx; + + pctx = MyCipherCtx->derive_ctx; + + if (EVP_PKEY_CTX_set1_hkdf_key(pctx, base_key, base_size) != 1) + ereport(ERROR, + (errmsg("openssl encountered setting key error during key derivation"), + (errdetail("openssl error string: %s", + ERR_error_string(ERR_get_error(), NULL))))); + + /* + * we don't need to set salt since the input key is already present + * as cryptographically strong. + */ + + if (EVP_PKEY_CTX_add1_hkdf_info(pctx, (unsigned char *) info, + strlen((char *) info)) != 1) + ereport(ERROR, + (errmsg("openssl encountered setting info error during key derivation"), + (errdetail("openssl error string: %s", + ERR_error_string(ERR_get_error(), NULL))))); + + /* + * The 'derivedkey_size' should contain the length of the 'derivedkey' + * buffer, if the call got successful the derived key is written to + * 'derivedkey' and the amount of data written to 'derivedkey_size' + */ + if (EVP_PKEY_derive(pctx, derived_key, &derived_size) != 1) + ereport(ERROR, + (errmsg("openssl encountered error during key derivation"), + (errdetail("openssl error string: %s", + ERR_error_string(ERR_get_error(), NULL))))); +#endif +} + +void +ossl_compute_hmac(const unsigned char *hmac_key, int key_size, + unsigned char *data, int data_size, unsigned char *hmac) +{ + unsigned char *h; + uint32 hmac_size; + + Assert(hmac != NULL); + + h = HMAC(EVP_sha256(), hmac_key, key_size, data, data_size, hmac, &hmac_size); + + if (h == NULL) + ereport(ERROR, + (errmsg("could not compute HMAC"), + (errdetail("openssl error string: %s", + ERR_error_string(ERR_get_error(), NULL))))); + + memcpy(hmac, h, hmac_size); +} + +void +ossl_wrap_key(const unsigned char *key, int key_size, unsigned char *in, + int in_size, unsigned char *out, int *out_size) +{ + EVP_CIPHER_CTX *ctx; + + /* Ensure encryption has setup */ + if (MyCipherCtx == NULL) + setup_encryption(); + + ctx = MyCipherCtx->wrap_ctx; + + if (EVP_EncryptInit_ex(ctx, NULL, NULL, key, NULL) != 1) + ereport(ERROR, + (errmsg("openssl encountered initialization error during unwrapping key"), + (errdetail("openssl error string: %s", + ERR_error_string(ERR_get_error(), NULL))))); + + if (!EVP_CIPHER_CTX_set_key_length(ctx, key_size)) + ereport(ERROR, + (errmsg("openssl encountered setting key length error during wrapping key"), + (errdetail("openssl error string: %s", + ERR_error_string(ERR_get_error(), NULL))))); + + if (!EVP_EncryptUpdate(ctx, out, out_size, in, in_size)) + ereport(ERROR, + (errmsg("openssl encountered error during wrapping key"), + (errdetail("openssl error string: %s", + ERR_error_string(ERR_get_error(), NULL))))); +} + +void +ossl_unwrap_key(const unsigned char *key, int key_size, unsigned char *in, + int in_size, unsigned char *out, int *out_size) +{ + EVP_CIPHER_CTX *ctx; + + /* Ensure encryption has setup */ + if (MyCipherCtx == NULL) + setup_encryption(); + + ctx = MyCipherCtx->unwrap_ctx; + + if (EVP_DecryptInit_ex(ctx, NULL, NULL, key, NULL) != 1) + ereport(ERROR, + (errmsg("openssl encountered initialization error during unwrapping key"), + (errdetail("openssl error string: %s", + ERR_error_string(ERR_get_error(), NULL))))); + + if (!EVP_CIPHER_CTX_set_key_length(ctx, key_size)) + ereport(ERROR, + (errmsg("openssl encountered setting key length error during unwrapping key"), + (errdetail("openssl error string: %s", + ERR_error_string(ERR_get_error(), NULL))))); + + if (EVP_DecryptUpdate(ctx, out, out_size, in, in_size) != 1) + ereport(ERROR, + (errmsg("openssl encountered error during unwrapping key"), + (errdetail("openssl error string: %s", + ERR_error_string(ERR_get_error(), NULL))))); +} diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index 939245db39..f2e248d9ca 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -419,6 +419,12 @@ /* Define to 1 if you have the `OPENSSL_init_ssl' function. */ #undef HAVE_OPENSSL_INIT_SSL +/* Define to 1 if you have the `OPENSSL_init_crypto' function. */ +#undef HAVE_OPENSSL_INIT_CRYPTO + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_KDF + /* Define to 1 if you have the header file. */ #undef HAVE_OSSP_UUID_H diff --git a/src/include/storage/enc_cipher.h b/src/include/storage/enc_cipher.h new file mode 100644 index 0000000000..b78862fb57 --- /dev/null +++ b/src/include/storage/enc_cipher.h @@ -0,0 +1,33 @@ +/*------------------------------------------------------------------------- + * + * enc_cipher.h + * This file contains definitions for structures and externs for + * functions used by data encryption. + * + * Portions Copyright (c) 2019, PostgreSQL Global Development Group + * + * src/include/storage/enc_cipher.h + * + *------------------------------------------------------------------------- + */ +#ifndef ENC_CIPHER_H +#define ENC_CIPHER_H + +extern void pg_encrypt(const char *input, char *output, int size, + const char *key, const char *iv); +extern void pg_decrypt(const char *input, char *output, int size, + const char *key, const char *iv); +extern void pg_derive_key(const unsigned char *base_key, int base_size, + unsigned char *info, unsigned char *derived_key, + Size derived_size); +extern void pg_compute_hmac(const unsigned char *hmac_key, int key_size, + unsigned char *data, int data_size, + unsigned char *hmac); +extern void pg_wrap_key(const unsigned char *key, int key_size, + unsigned char *in, int in_size, unsigned char *out, + int *out_size); +extern void pg_unwrap_key(const unsigned char *key, int key_size, + unsigned char *in, int in_size, unsigned char *out, + int *out_size); + +#endif /* ENC_CIPHER_H */ diff --git a/src/include/storage/enc_common.h b/src/include/storage/enc_common.h new file mode 100644 index 0000000000..09adc4d540 --- /dev/null +++ b/src/include/storage/enc_common.h @@ -0,0 +1,34 @@ +/*------------------------------------------------------------------------- + * + * enc_common.h + * This file contains common definitions for cluster encryption. + * + * Portions Copyright (c) 2019, PostgreSQL Global Development Group + * + * src/include/storage/enc_common.h + * + *------------------------------------------------------------------------- + */ +#ifndef ENC_COMMON_H +#define ENC_COMMON_H + +/* Value of data_encryption_cipher */ +enum +{ + TDE_ENCRYPTION_OFF = 0, + TDE_ENCRYPTION_AES_128, + TDE_ENCRYPTION_AES_256 +}; + +/* GUC parameter */ +extern PGDLLIMPORT int data_encryption_cipher; + +/* Encryption keys (TDEK and WDEK) size */ +extern int EncryptionKeySize; + +extern char *EncryptionCipherString(int value); +extern int EncryptionCipherValue(const char *name); +extern void assign_data_encryption_cipher(int new_encryption_cipher, + void *extra); + +#endif /* ENC_COMMON_H */ diff --git a/src/include/storage/enc_internal.h b/src/include/storage/enc_internal.h new file mode 100644 index 0000000000..bcc60fe2b1 --- /dev/null +++ b/src/include/storage/enc_internal.h @@ -0,0 +1,34 @@ +/*------------------------------------------------------------------------- + * + * enc_internal.h + * This file contains internal definitions of encryption cipher + * functions. + * + * Portions Copyright (c) 2019, PostgreSQL Global Development Group + * + * src/include/storage/enc_internal.h + * + *------------------------------------------------------------------------- + */ +#ifndef ENC_INTERNAL_H +#define ENC_INTERNAL_H + +/* enc_openssl.h */ +extern void ossl_encrypt_data(const char *input, char *output, int size, + const char *key, const char *iv); +extern void ossl_decrypt_data(const char *input, char *output, int size, + const char *key, const char *iv); +extern void ossl_derive_key(const unsigned char *base_key, int base_size, + unsigned char *info, unsigned char *derived_keyen, + Size derived_size); +extern void ossl_compute_hmac(const unsigned char *hmac_key, int key_size, + unsigned char *data, int data_size, + unsigned char *hmac); +extern void ossl_wrap_key(const unsigned char *kek, int key_size, + unsigned char *in, int in_size, unsigned char *out, + int *out_size); +extern void ossl_unwrap_key(const unsigned char *key, int key_size, + unsigned char *in, int in_size, unsigned char *out, + int *out_size); + +#endif /* ENC_INTERNAL_H */ diff --git a/src/include/storage/encryption.h b/src/include/storage/encryption.h new file mode 100644 index 0000000000..a7dcd9282f --- /dev/null +++ b/src/include/storage/encryption.h @@ -0,0 +1,39 @@ +/*------------------------------------------------------------------------- + * + * encryption.h + * Cluster encryption functions. + * + * Portions Copyright (c) 2019, PostgreSQL Global Development Group + * + * src/include/storage/encryption.h + * + *------------------------------------------------------------------------- + */ +#ifndef ENCRYPTION_H +#define ENCRYPTION_H + +#include "access/xlogdefs.h" +#include "storage/bufpage.h" +#include "storage/enc_cipher.h" +#include "storage/enc_common.h" + +#define DataEncryptionEnabled() \ + (data_encryption_cipher > TDE_ENCRYPTION_OFF) + +/* + * The encrypted data is a series of blocks of size ENCRYPTION_BLOCK. + * Initialization vector(IV) is the same size of cipher block. + */ +#define ENC_BLOCK_SIZE 16 +#define ENC_IV_SIZE (ENC_BLOCK_SIZE) + +/* + * Maximum encryption key size is used by AES-256. + */ +#define ENC_MAX_ENCRYPTION_KEY_SIZE 32 + +/* bufenc.c */ +extern void DecryptBufferBlock(BlockNumber blocknum, Page page); +extern void EncryptBufferBlock(BlockNumber blocknum, Page page); + +#endif /* ENCRYPTION_H */ -- 2.23.0