From fba051add0f0ec73770db415bba5a1c486d41c27 Mon Sep 17 00:00:00 2001 From: Masahiko Sawada Date: Mon, 11 Jan 2021 19:37:12 +0900 Subject: [PATCH 3/3] Poc: buffer encryption. --- contrib/bloom/blinsert.c | 1 + src/backend/access/hash/hashpage.c | 1 + src/backend/access/heap/rewriteheap.c | 1 + src/backend/access/nbtree/nbtree.c | 1 + src/backend/access/nbtree/nbtsort.c | 1 + src/backend/access/spgist/spginsert.c | 3 + src/backend/access/transam/xloginsert.c | 13 +++ src/backend/bootstrap/bootstrap.c | 3 + src/backend/catalog/storage.c | 2 +- src/backend/crypto/Makefile | 1 + src/backend/crypto/bufenc.c | 138 ++++++++++++++++++++++++ src/backend/postmaster/postmaster.c | 2 + src/backend/storage/buffer/bufmgr.c | 25 ++++- src/backend/storage/page/bufpage.c | 49 ++++++++- src/backend/tcop/postgres.c | 2 + src/common/cipher_openssl.c | 26 +++++ src/include/access/xloginsert.h | 1 + src/include/common/cipher.h | 3 +- src/include/crypto/bufenc.h | 27 +++++ src/include/crypto/kmgr.h | 2 + src/include/storage/bufpage.h | 11 +- 21 files changed, 306 insertions(+), 7 deletions(-) create mode 100644 src/backend/crypto/bufenc.c create mode 100644 src/include/crypto/bufenc.h diff --git a/contrib/bloom/blinsert.c b/contrib/bloom/blinsert.c index 32b5d62e1f..d474af753c 100644 --- a/contrib/bloom/blinsert.c +++ b/contrib/bloom/blinsert.c @@ -177,6 +177,7 @@ blbuildempty(Relation index) * XLOG_DBASE_CREATE or XLOG_TBLSPC_CREATE record. Therefore, we need * this even when wal_level=minimal. */ + PageEncryptInplace(metapage, INIT_FORKNUM, BLOOM_METAPAGE_BLKNO); PageSetChecksumInplace(metapage, BLOOM_METAPAGE_BLKNO); smgrwrite(index->rd_smgr, INIT_FORKNUM, BLOOM_METAPAGE_BLKNO, (char *) metapage, true); diff --git a/src/backend/access/hash/hashpage.c b/src/backend/access/hash/hashpage.c index 49a9867787..7ee505c6ba 100644 --- a/src/backend/access/hash/hashpage.c +++ b/src/backend/access/hash/hashpage.c @@ -1025,6 +1025,7 @@ _hash_alloc_buckets(Relation rel, BlockNumber firstblock, uint32 nblocks) true); RelationOpenSmgr(rel); + PageEncryptInplace(page, MAIN_FORKNUM, lastblock); PageSetChecksumInplace(page, lastblock); smgrextend(rel->rd_smgr, MAIN_FORKNUM, lastblock, zerobuf.data, false); diff --git a/src/backend/access/heap/rewriteheap.c b/src/backend/access/heap/rewriteheap.c index 29ffe40670..d752331706 100644 --- a/src/backend/access/heap/rewriteheap.c +++ b/src/backend/access/heap/rewriteheap.c @@ -325,6 +325,7 @@ end_heap_rewrite(RewriteState state) true); RelationOpenSmgr(state->rs_new_rel); + PageEncryptInplace(state->rs_buffer, MAIN_FORKNUM, state->rs_blockno); PageSetChecksumInplace(state->rs_buffer, state->rs_blockno); smgrextend(state->rs_new_rel->rd_smgr, MAIN_FORKNUM, state->rs_blockno, diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c index ba79a7f3e9..b2969dd07e 100644 --- a/src/backend/access/nbtree/nbtree.c +++ b/src/backend/access/nbtree/nbtree.c @@ -175,6 +175,7 @@ btbuildempty(Relation index) * XLOG_DBASE_CREATE or XLOG_TBLSPC_CREATE record. Therefore, we need * this even when wal_level=minimal. */ + PageEncryptInplace(metapage, INIT_FORKNUM, BTREE_METAPAGE); PageSetChecksumInplace(metapage, BTREE_METAPAGE); smgrwrite(index->rd_smgr, INIT_FORKNUM, BTREE_METAPAGE, (char *) metapage, true); diff --git a/src/backend/access/nbtree/nbtsort.c b/src/backend/access/nbtree/nbtsort.c index c904fc8ef7..04da2d865b 100644 --- a/src/backend/access/nbtree/nbtsort.c +++ b/src/backend/access/nbtree/nbtsort.c @@ -665,6 +665,7 @@ _bt_blwritepage(BTWriteState *wstate, Page page, BlockNumber blkno) true); } + PageEncryptInplace(page, MAIN_FORKNUM, blkno); PageSetChecksumInplace(page, blkno); /* diff --git a/src/backend/access/spgist/spginsert.c b/src/backend/access/spgist/spginsert.c index 2e1d8a33d1..84187583d2 100644 --- a/src/backend/access/spgist/spginsert.c +++ b/src/backend/access/spgist/spginsert.c @@ -168,6 +168,7 @@ spgbuildempty(Relation index) * of their existing content when the corresponding create records are * replayed. */ + PageEncryptInplace(page, INIT_FORKNUM, SPGIST_METAPAGE_BLKNO); PageSetChecksumInplace(page, SPGIST_METAPAGE_BLKNO); smgrwrite(index->rd_smgr, INIT_FORKNUM, SPGIST_METAPAGE_BLKNO, (char *) page, true); @@ -177,6 +178,7 @@ spgbuildempty(Relation index) /* Likewise for the root page. */ SpGistInitPage(page, SPGIST_LEAF); + PageEncryptInplace(page, INIT_FORKNUM, SPGIST_ROOT_BLKNO); PageSetChecksumInplace(page, SPGIST_ROOT_BLKNO); smgrwrite(index->rd_smgr, INIT_FORKNUM, SPGIST_ROOT_BLKNO, (char *) page, true); @@ -186,6 +188,7 @@ spgbuildempty(Relation index) /* Likewise for the null-tuples root page. */ SpGistInitPage(page, SPGIST_LEAF | SPGIST_NULLS); + PageEncryptInplace(page, INIT_FORKNUM, SPGIST_NULL_BLKNO); PageSetChecksumInplace(page, SPGIST_NULL_BLKNO); smgrwrite(index->rd_smgr, INIT_FORKNUM, SPGIST_NULL_BLKNO, (char *) page, true); diff --git a/src/backend/access/transam/xloginsert.c b/src/backend/access/transam/xloginsert.c index 7052dc245e..d7738c8834 100644 --- a/src/backend/access/transam/xloginsert.c +++ b/src/backend/access/transam/xloginsert.c @@ -1190,6 +1190,19 @@ log_newpage_range(Relation rel, ForkNumber forkNum, } } +/* Write a no-op dummy xlog */ +XLogRecPtr +log_noop(void) +{ + bool dummy; + + XLogBeginInsert(); + + /* register dummy data as the record have to contain data */ + XLogRegisterData((char *) &dummy, sizeof(bool)); + return XLogInsert(RM_XLOG_ID, XLOG_NOOP); +} + /* * Allocate working buffers needed for WAL record construction. */ diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index e2231f1430..9eba3735a5 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -28,6 +28,7 @@ #include "catalog/pg_collation.h" #include "catalog/pg_type.h" #include "common/link-canary.h" +#include "crypto/bufenc.h" #include "crypto/kmgr.h" #include "libpq/pqsignal.h" #include "miscadmin.h" @@ -528,6 +529,8 @@ BootstrapModeMain(void) InitPostgres(NULL, InvalidOid, NULL, InvalidOid, NULL, false); + InitializeBufferEncryption(); + /* Initialize stuff for bootstrap-file processing */ for (i = 0; i < MAXATTR; i++) { diff --git a/src/backend/catalog/storage.c b/src/backend/catalog/storage.c index cba7a9ada0..c876c536a5 100644 --- a/src/backend/catalog/storage.c +++ b/src/backend/catalog/storage.c @@ -443,7 +443,7 @@ RelationCopyStorage(SMgrRelation src, SMgrRelation dst, smgrread(src, forkNum, blkno, buf.data); - if (!PageIsVerifiedExtended(page, blkno, + if (!PageIsVerifiedExtended(page, forkNum, blkno, PIV_LOG_WARNING | PIV_REPORT_STAT)) ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), diff --git a/src/backend/crypto/Makefile b/src/backend/crypto/Makefile index c27362029d..8985a66875 100644 --- a/src/backend/crypto/Makefile +++ b/src/backend/crypto/Makefile @@ -13,6 +13,7 @@ top_builddir = ../../.. include $(top_builddir)/src/Makefile.global OBJS = \ + bufenc.o \ kmgr.o include $(top_srcdir)/src/backend/common.mk diff --git a/src/backend/crypto/bufenc.c b/src/backend/crypto/bufenc.c new file mode 100644 index 0000000000..4401303fe9 --- /dev/null +++ b/src/backend/crypto/bufenc.c @@ -0,0 +1,138 @@ +/*------------------------------------------------------------------------- + * + * bufenc.c + * + * Copyright (c) 2020, PostgreSQL Global Development Group + * + * + * IDENTIFICATION + * src/backend/crypto/bufenc.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "miscadmin.h" +#include "lib/stringinfo.h" + +#include "storage/bufpage.h" +#include "storage/fd.h" +#include "crypto/kmgr.h" +#include "crypto/bufenc.h" + +/*------------------------------------------------------------------------- + * We use both page LSN and page number to create a nonce for each page. Page + * LSN is 8 byte, page number is 4 byte, and the maximum required counter for + * AES-CTR is 2048, which fits in 3 byte. Since the length of IV is 16 byte + * it's fine. Using the LSN and page number as part of the nonce has + * three benefits: + * + * 1. We don't need to decrypt/re-encrypt during CREATE DATABASE since the page + * contents are the same in both places, and once one database changes its pages, + * it gets a new LSN, and hence a new nonce. + * 2. For each change of an 8k page, we get a new nonce, so we are not encrypting + * different data with the same nonce/IV. + * 3. We avoid requiring pg_upgrade to preserve database oids, tablespace oids, + * relfilenodes. + * + * Different two pages could have the same page LSN when heap update expires the + * old tuple and add the new tuple to the another page. By using the page number + * as a part of nonce we can get an unique nonce even in this case. We assume that + * we don't use the same LSN in different relations. + *------------------------------------------------------------------------- + */ +#define BUFENC_IV_SIZE 16 + +static unsigned char buf_encryption_iv[BUFENC_IV_SIZE]; + +PgCipherCtx *BufencCtx = NULL; +PgCipherCtx *BufdecCtx = NULL; + +static void set_buffer_encryption_iv(Page page, BlockNumber blkno); + +void +InitializeBufferEncryption(void) +{ + const CryptoKey *key; + + if (!DataEncryptionEnabled()) + return; + + key = KmgrGetKey(KMGR_KEY_ID_REL); + + BufencCtx = pg_cipher_ctx_create(PG_CIPHER_AES_CTR, + (unsigned char *) key->key, + (file_encryption_keylen / 8), true); + if (!BufencCtx) + elog(ERROR, "could not intialize encryption context"); + + BufdecCtx = pg_cipher_ctx_create(PG_CIPHER_AES_CTR, + (unsigned char *) key->key, + (file_encryption_keylen / 8), false); + if (!BufdecCtx) + elog(ERROR, "could not intialize decryption context"); +} + +/* Encrypt the given page with the relation key */ +void +EncryptPage(Page page, BlockNumber blkno) +{ + unsigned char *ptr = (unsigned char *) page + PageEncryptOffset; + int enclen; + + Assert(BufencCtx != NULL); + + set_buffer_encryption_iv(page, blkno); + if (unlikely(!pg_cipher_encrypt(BufencCtx, + (const unsigned char *) ptr, /* input */ + SizeOfPageEncryption, + ptr, /* length */ + &enclen, /* resulting length */ + buf_encryption_iv, /* iv */ + BUFENC_IV_SIZE, + NULL, 0))) + elog(ERROR, "could not encrypt page %u", blkno); + Assert(enclen == SizeOfPageEncryption); +} + +/* Decrypt the given page with the relation key */ +void +DecryptPage(Page page, BlockNumber blkno) +{ + unsigned char *ptr = (unsigned char *) page + PageEncryptOffset; + int enclen; + + Assert(BufdecCtx != NULL); + + set_buffer_encryption_iv(page, blkno); + if (unlikely(!pg_cipher_decrypt(BufdecCtx, + (const unsigned char *) ptr, /* input */ + SizeOfPageEncryption, + ptr, /* output */ + &enclen, /* resulting length */ + buf_encryption_iv, /* iv */ + BUFENC_IV_SIZE, + NULL, 0))) + elog(ERROR, "could not decrypt page %u", blkno); + Assert(enclen == SizeOfPageEncryption); +} + +/* Construct iv for the given page */ +static void +set_buffer_encryption_iv(Page page, BlockNumber blkno) +{ + unsigned char *p = buf_encryption_iv; + + MemSet(buf_encryption_iv, 0, BUFENC_IV_SIZE); + + /* page lsn (8 byte) */ + memcpy(p, &((PageHeader) page)->pd_lsn, sizeof(PageXLogRecPtr)); + p += sizeof(PageXLogRecPtr); + + /* block number (4 byte) */ + memcpy(p, &blkno, sizeof(BlockNumber)); + p += sizeof(BlockNumber); + + /* remainig 4 bytes are the space for the counter, already set to 0 */ +} diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index e2f8e07c88..c0424f3f36 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -100,6 +100,7 @@ #include "common/file_perm.h" #include "common/ip.h" #include "common/string.h" +#include "crypto/bufenc.h" #include "crypto/kmgr.h" #include "lib/ilist.h" #include "libpq/auth.h" @@ -1333,6 +1334,7 @@ PostmasterMain(int argc, char *argv[]) RemovePgTempFiles(); InitializeKmgr(); + InitializeBufferEncryption(); if (terminal_fd != -1) close(terminal_fd); diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index 71b5852224..c86b6ea068 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -37,6 +37,7 @@ #include "access/xlog.h" #include "catalog/catalog.h" #include "catalog/storage.h" +#include "crypto/bufenc.h" #include "executor/instrument.h" #include "lib/binaryheap.h" #include "miscadmin.h" @@ -918,7 +919,7 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum, } /* check for garbage data */ - if (!PageIsVerifiedExtended((Page) bufBlock, blockNum, + if (!PageIsVerifiedExtended((Page) bufBlock, forkNum, blockNum, PIV_LOG_WARNING | PIV_REPORT_STAT)) { if (mode == RBM_ZERO_ON_ERROR || zero_damaged_pages) @@ -2792,12 +2793,15 @@ FlushBuffer(BufferDesc *buf, SMgrRelation reln) */ bufBlock = BufHdrGetBlock(buf); + bufToWrite = PageEncryptCopy((Page) bufBlock, buf->tag.forkNum, + buf->tag.blockNum); + /* * Update page checksum if desired. Since we have only shared lock on the * buffer, other processes might be updating hint bits in it, so we must * copy the page to private storage if we do checksumming. */ - bufToWrite = PageSetChecksumCopy((Page) bufBlock, buf->tag.blockNum); + bufToWrite = PageSetChecksumCopy((Page) bufToWrite, buf->tag.blockNum); if (track_io_timing) INSTR_TIME_SET_CURRENT(io_start); @@ -3280,6 +3284,8 @@ FlushRelationBuffers(Relation rel) errcallback.previous = error_context_stack; error_context_stack = &errcallback; + PageEncryptInplace(localpage, bufHdr->tag.forkNum, + bufHdr->tag.blockNum); PageSetChecksumInplace(localpage, bufHdr->tag.blockNum); smgrwrite(rel->rd_smgr, @@ -3677,6 +3683,21 @@ MarkBufferDirtyHint(Buffer buffer, bool buffer_std) { dirtied = true; /* Means "will be dirtied by this action" */ + /* + * We will dirty the page but the page lsn is not changed if we + * doesn't write a backup block. We don't want to encrypt the + * different bits stream with the same combination of nonce and key + * since in buffer encryption the page lsn is a part of nonce. + * Therefore we WAL-log no-op record just to move page lsn forward if + * we doesn't write a backup block, even when this is not the first + * modification in this checkpoint round. + */ + if (XLogRecPtrIsInvalid(lsn) && DataEncryptionEnabled()) + { + lsn = log_noop(); + Assert(!XLogRecPtrIsInvalid(lsn)); + } + /* * Set the page LSN if we wrote a backup block. We aren't supposed * to set this when only holding a share lock but as long as we diff --git a/src/backend/storage/page/bufpage.c b/src/backend/storage/page/bufpage.c index 9ac556b4ae..3a480e7b82 100644 --- a/src/backend/storage/page/bufpage.c +++ b/src/backend/storage/page/bufpage.c @@ -17,6 +17,7 @@ #include "access/htup_details.h" #include "access/itup.h" #include "access/xlog.h" +#include "crypto/bufenc.h" #include "pgstat.h" #include "storage/checksum.h" #include "utils/memdebug.h" @@ -85,7 +86,8 @@ PageInit(Page page, Size pageSize, Size specialSize) * to pgstat. */ bool -PageIsVerifiedExtended(Page page, BlockNumber blkno, int flags) +PageIsVerifiedExtended(Page page, ForkNumber forknum, BlockNumber blkno, + int flags) { PageHeader p = (PageHeader) page; size_t *pagebytes; @@ -108,6 +110,9 @@ PageIsVerifiedExtended(Page page, BlockNumber blkno, int flags) checksum_failure = true; } + if (DataEncryptionEnabled()) + PageDecryptInplace(page, forknum, blkno); + /* * The following checks don't prove the header is correct, only that * it looks sane enough to allow into the buffer pool. Later usage of @@ -1427,3 +1432,45 @@ PageSetChecksumInplace(Page page, BlockNumber blkno) ((PageHeader) page)->pd_checksum = pg_checksum_page((char *) page, blkno); } + +char * +PageEncryptCopy(Page page, ForkNumber forknum, BlockNumber blkno) +{ + static char *pageCopy = NULL; + + /* If we don't need a checksum, just return the passed-in data */ + if (PageIsNew(page) || !PageNeedsToBeEncrypted(forknum)) + return (char *) page; + + /* + * We allocate the copy space once and use it over on each subsequent + * call. The point of palloc'ing here, rather than having a static char + * array, is first to ensure adequate alignment for the checksumming code + * and second to avoid wasting space in processes that never call this. + */ + if (pageCopy == NULL) + pageCopy = MemoryContextAlloc(TopMemoryContext, BLCKSZ); + + memcpy(pageCopy, (char *) page, BLCKSZ); + EncryptPage(pageCopy, blkno); + return pageCopy; +} + +void +PageEncryptInplace(Page page, ForkNumber forknum, BlockNumber blkno) +{ + if (PageIsNew(page) || !PageNeedsToBeEncrypted(forknum)) + return; + + EncryptPage(page, blkno); +} + + +void +PageDecryptInplace(Page page, ForkNumber forknum, BlockNumber blkno) +{ + if (PageIsNew(page) || PageNeedsToBeEncrypted(forknum)) + return; + + DecryptPage(page, blkno); +} diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 0463da6d46..36759c0190 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -43,6 +43,7 @@ #include "commands/async.h" #include "commands/prepare.h" #include "crypto/kmgr.h" +#include "crypto/bufenc.h" #include "executor/spi.h" #include "jit/jit.h" #include "libpq/libpq.h" @@ -3978,6 +3979,7 @@ PostgresMain(int argc, char *argv[], if (!IsUnderPostmaster) { InitializeKmgr(); + InitializeBufferEncryption(); if (terminal_fd != -1) close(terminal_fd); diff --git a/src/common/cipher_openssl.c b/src/common/cipher_openssl.c index 28f613cecc..9a6b4ddbc1 100644 --- a/src/common/cipher_openssl.c +++ b/src/common/cipher_openssl.c @@ -34,6 +34,7 @@ static ossl_EVP_cipher_func get_evp_aes_gcm(int klen); static ossl_EVP_cipher_func get_evp_aes_kw(int klen); static EVP_CIPHER_CTX *ossl_cipher_ctx_create(int cipher, unsigned char *key, int klen, bool enc); +static ossl_EVP_cipher_func get_evp_aes_ctr(int klen); /* * Return a newly created cipher context. 'cipher' specifies cipher algorithm @@ -343,6 +344,26 @@ get_evp_aes_kwp(int klen) } } +/* + * Returns the correct cipher functions for OpenSSL based + * on the key length requested. + */ +static ossl_EVP_cipher_func +get_evp_aes_ctr(int klen) +{ + switch (klen) + { + case PG_AES128_KEY_LEN: + return EVP_aes_128_ctr; + case PG_AES192_KEY_LEN: + return EVP_aes_192_ctr; + case PG_AES256_KEY_LEN: + return EVP_aes_256_ctr; + default: + return NULL; + } +} + /* * Initialize and return an EVP_CIPHER_CTX. Returns NULL if the given * cipher algorithm is not supported or on failure. @@ -389,6 +410,11 @@ ossl_cipher_ctx_create(int cipher, unsigned char *key, int klen, bool enc) if (!func) goto failed; break; + case PG_CIPHER_AES_CTR: + func = get_evp_aes_ctr(klen); + if (!func) + goto failed; + break; default: goto failed; } diff --git a/src/include/access/xloginsert.h b/src/include/access/xloginsert.h index f1d8c39edf..43c4f1f611 100644 --- a/src/include/access/xloginsert.h +++ b/src/include/access/xloginsert.h @@ -59,6 +59,7 @@ extern void log_newpages(RelFileNode *rnode, ForkNumber forkNum, int num_pages, extern XLogRecPtr log_newpage_buffer(Buffer buffer, bool page_std); extern void log_newpage_range(Relation rel, ForkNumber forkNum, BlockNumber startblk, BlockNumber endblk, bool page_std); +extern XLogRecPtr log_noop(void); extern XLogRecPtr XLogSaveBufferForHint(Buffer buffer, bool buffer_std); extern void InitXLogInsert(void); diff --git a/src/include/common/cipher.h b/src/include/common/cipher.h index 7d446e86b6..9c4a630cd6 100644 --- a/src/include/common/cipher.h +++ b/src/include/common/cipher.h @@ -27,7 +27,8 @@ #define PG_CIPHER_AES_GCM 0 #define PG_CIPHER_AES_KW 1 #define PG_CIPHER_AES_KWP 2 -#define PG_MAX_CIPHER_ID 3 +#define PG_CIPHER_AES_CTR 3 +#define PG_MAX_CIPHER_ID 4 /* AES128/192/256 various length definitions */ #define PG_AES128_KEY_LEN (128 / 8) diff --git a/src/include/crypto/bufenc.h b/src/include/crypto/bufenc.h new file mode 100644 index 0000000000..97302a4f3f --- /dev/null +++ b/src/include/crypto/bufenc.h @@ -0,0 +1,27 @@ +/*------------------------------------------------------------------------- + * + * bufenc.h + * + * Portions Copyright (c) 2021, PostgreSQL Global Development Group + * + * src/include/crypto/bufenc.h + * + *------------------------------------------------------------------------- + */ +#ifndef BUFENC_H +#define BUFENC_H + +#include "storage/bufmgr.h" +#include "crypto/kmgr.h" + +#define DataEncryptionEnabled() (file_encryption_keylen > 0) + +/* Cluster encryption encrypts only main fork */ +#define PageNeedsToBeEncrypted(forknum) \ + (DataEncryptionEnabled() && ((forknum) == MAIN_FORKNUM)) + +extern void InitializeBufferEncryption(void); +extern void EncryptPage(Page page, BlockNumber blkno); +extern void DecryptPage(Page page, BlockNumber blkno); + +#endif /* BUFENC_H */ diff --git a/src/include/crypto/kmgr.h b/src/include/crypto/kmgr.h index 386ac1cb4a..6a728ebefc 100644 --- a/src/include/crypto/kmgr.h +++ b/src/include/crypto/kmgr.h @@ -16,6 +16,8 @@ #include "storage/relfilenode.h" #include "storage/bufpage.h" +#define DataEncryptionEnabled() (file_encryption_keylen > 0) + /* GUC parameters */ extern int file_encryption_keylen; extern char *cluster_key_command; diff --git a/src/include/storage/bufpage.h b/src/include/storage/bufpage.h index 359b749f7f..fc855cc3b5 100644 --- a/src/include/storage/bufpage.h +++ b/src/include/storage/bufpage.h @@ -15,6 +15,7 @@ #define BUFPAGE_H #include "access/xlogdefs.h" +#include "common/relpath.h" #include "storage/block.h" #include "storage/item.h" #include "storage/off.h" @@ -164,6 +165,8 @@ typedef struct PageHeaderData } PageHeaderData; typedef PageHeaderData *PageHeader; +#define PageEncryptOffset offsetof(PageHeaderData, pd_special) +#define SizeOfPageEncryption (BLCKSZ - PageEncryptOffset) /* * pd_flags contains the following flag bits. Undefined bits are initialized @@ -419,7 +422,7 @@ do { \ ((is_heap) ? PAI_IS_HEAP : 0)) #define PageIsVerified(page, blkno) \ - PageIsVerifiedExtended(page, blkno, \ + PageIsVerifiedExtended(page, MAIN_FORKNUM, blkno, \ PIV_LOG_WARNING | PIV_REPORT_STAT) /* @@ -433,7 +436,8 @@ StaticAssertDecl(BLCKSZ == ((BLCKSZ / sizeof(size_t)) * sizeof(size_t)), "BLCKSZ has to be a multiple of sizeof(size_t)"); extern void PageInit(Page page, Size pageSize, Size specialSize); -extern bool PageIsVerifiedExtended(Page page, BlockNumber blkno, int flags); +extern bool PageIsVerifiedExtended(Page page, ForkNumber forknum, BlockNumber blkno, + int flags); extern OffsetNumber PageAddItemExtended(Page page, Item item, Size size, OffsetNumber offsetNumber, int flags); extern Page PageGetTempPage(Page page); @@ -452,5 +456,8 @@ extern bool PageIndexTupleOverwrite(Page page, OffsetNumber offnum, Item newtup, Size newsize); extern char *PageSetChecksumCopy(Page page, BlockNumber blkno); extern void PageSetChecksumInplace(Page page, BlockNumber blkno); +extern char *PageEncryptCopy(Page page, ForkNumber forknum, BlockNumber blkno); +extern void PageEncryptInplace(Page page, ForkNumber forknum, BlockNumber blkno); +extern void PageDecryptInplace(Page page, ForkNumber forknum, BlockNumber blkno); #endif /* BUFPAGE_H */ -- 2.27.0