From b3251edebfac62c095d973189a652c3925db4a24 Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Mon, 25 Jan 2021 14:15:57 -0500
Subject: [PATCH] key squash commit

---
 doc/src/sgml/database-encryption.sgml (new) | 124 ++++++++++++++++++++
 doc/src/sgml/filelist.sgml                  |   1 +
 doc/src/sgml/installation.sgml              |   5 +-
 doc/src/sgml/postgres.sgml                  |   1 +
 4 files changed, 129 insertions(+), 2 deletions(-)

diff --git a/doc/src/sgml/database-encryption.sgml b/doc/src/sgml/database-encryption.sgml
new file mode 100644
index 0000000000..e8e1e69ec7
--- /dev/null
+++ b/doc/src/sgml/database-encryption.sgml
@@ -0,0 +1,124 @@
+<!-- doc/src/sgml/database-encryption.sgml -->
+
+<chapter id="database-file-encryption">
+ <title>Cluster File Encryption</title>
+
+ <indexterm zone="database-file-encryption">
+  <primary>Cluster File Encryption</primary>
+ </indexterm>
+
+ <para>
+  The purpose of cluster file encryption is to prevent users with read
+  access to the directories used to store database files and write-ahead
+  log files from being able to access the data stored in those files.
+  For example, when using cluster file encryption, users who have read
+  access to the cluster directories for backup purposes will not be able
+  to decrypt the data stored in these files.  It also protects against
+  decrypted data access after media theft.
+ </para>
+
+ <para>
+  File system write access can allow for unauthorized file system data
+  decryption if the writes can be used to weaken the system's security
+  and this weakened system is later supplied with externally-stored keys.
+  This also does not protect from users who have read access to system
+  memory.
+ </para>
+
+ <para>
+  Cluster file encryption uses two levels of encryption.  The first level
+  is data encryption keys, specifically keys zero and one.  Key zero is
+  the key used to encrypt database heap and index files which are stored in
+  the file system, plus temporary files created during database operation.
+  Key one is used to encrypt write-ahead log (WAL) files.  Two different
+  keys are used so that primary and standby servers can use different zero
+  (heap/index/temp) keys, but the same one (WAL) key, so that these keys
+  can (in a future release) be rotated by switching the primary to the
+  standby and then changing the WAL key.
+ </para>
+
+ <para>
+  The second level of encryption is a key used to encrypt first-level
+  keys.  This type of key is often referred to as a Key Encryption Key
+  (<acronym>KEK</acronym>).  This key is <emphasis>not</emphasis> stored
+  in the file system, but provided at <command>initdb</command> time and
+  each time the server is started.  This key prevents anyone with access
+  to the database directories from decrypting the data because they do
+  not know the second-level key which encrypted the first-level keys
+  which encrypted the database cluster files.  This key can be easily
+  changed via <command>pg_alterckey</command> without requiring any
+  changes to the the data files or <command>WAL</command> files, which
+  are encrypted with the data keys.
+ </para>
+
+ <sect1 id="encryption-file-encryption">
+  <title>Initialization</title>
+
+  <para>
+   Cluster file encryption is enabled when
+   <productname>PostgreSQL</productname> is built
+   with <literal>--with-openssl</literal> and <xref
+   linkend="app-initdb-cluster-key-command"/> is specified
+   during <command>initdb</command>.  The cluster key
+   provided by the <option>--cluster-key-command</option>
+   option during <command>initdb</command> and the one generated
+   by <xref linkend="guc-cluster-key-command"/> in the
+   <filename>postgresql.conf</filename> must match for the database
+   cluster to start. Note that the cluster key command
+   passed to <command>initdb</command> must return a key of
+   64 hexadecimal characters. For example:
+<programlisting>
+initdb -D dbname --cluster-key-command='ckey_passphrase.sh'
+</programlisting>
+  </para>
+ </sect1>
+
+ <sect1 id="key-encryption-key">
+  <title>Internals</title>
+
+  <para>
+   During the <command>initdb</command> process, if
+   <option>--cluster-key-command</option> is specified, two data-level
+   encryption keys are created.   These two keys are then encrypted with
+   the key encryption key (KEK) supplied by the cluster key command before
+   being stored in the database directory.  The key or passphrase that
+   derives the key must be supplied from the terminal or stored in a
+   trusted key store, such as key vault software or a hardware security
+   module.
+  </para>
+
+  <para>
+   If the <productname>PostgreSQL</productname> server has
+   been initialized to require a cluster key, each time the
+   server starts the <filename>postgresql.conf</filename>
+   <varname>cluster_key_command</varname> command will be executed
+   and the cluster key retrieved.  The data encryption keys in the
+   <filename>pg_cryptokeys</filename> directory will then be decrypted
+   using the supplied key and integrity-checked to ensure it matches the
+   initdb-supplied key.  (If this check fails, the server will refuse
+   to start.)  The cluster encryption key will then be removed from
+   system memory.  The decrypted data encryption keys will remain in
+   shared memory until the server is stopped.
+  </para>
+
+  <para>
+   The data encryption keys are randomly generated and can be 128, 192,
+   or 256-bits in length, depending on whether <literal>AES128</literal>,
+   <literal>AES192</literal>, or <literal>AES256</literal> is specified.
+   They are encrypted by the key encryption key (KEK) using Advanced
+   Encryption Standard (<acronym>AES256</acronym>) encryption in Key
+   Wrap Padded Mode, which also provides KEK authentication;  see <ulink
+   url="https://tools.ietf.org/html/rfc5649">RFC 5649</ulink>. While
+   128-bit encryption is sufficient for most sites, 256-bit encryption
+   is thought to be more immune to future quantum cryptographic attacks
+  </para>
+
+  <para>.
+   If you prefer to create the random keys on your own, you can create
+   a empty directory with a <filename>pg_cryptokeys/live</filename>
+   subdirectory, generate the keys there using your tools. and use the
+   <command>initdb</command> <option>--copy-encryption-keys</option>
+   to copy those keys into the newly-created  cluster.
+  </para>
+ </sect1>
+</chapter>
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 38e8aa0bbf..b96f4ace6c 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -49,6 +49,7 @@
 <!ENTITY wal           SYSTEM "wal.sgml">
 <!ENTITY logical-replication    SYSTEM "logical-replication.sgml">
 <!ENTITY jit    SYSTEM "jit.sgml">
+<!ENTITY database-encryption SYSTEM "database-encryption.sgml">
 
 <!-- programmer's guide -->
 <!ENTITY bgworker   SYSTEM "bgworker.sgml">
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index a53389b728..a1473bbf8d 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -976,8 +976,9 @@ build-postgresql:
        <listitem>
         <para>
          Build with support for <acronym>SSL</acronym> (encrypted)
-         connections. This requires the <productname>OpenSSL</productname>
-         package to be installed.  <filename>configure</filename> will check
+         connections and cluster file encryption. This requires the
+         <productname>OpenSSL</productname> package to be installed.
+         <filename>configure</filename> will check
          for the required header files and libraries to make sure that
          your <productname>OpenSSL</productname> installation is sufficient
          before proceeding.
diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml
index 730d5fdc34..0ea7da604b 100644
--- a/doc/src/sgml/postgres.sgml
+++ b/doc/src/sgml/postgres.sgml
@@ -171,6 +171,7 @@ break is not needed in a wider output rendering.
   &wal;
   &logical-replication;
   &jit;
+  &database-encryption;
   &regress;
 
  </part>
-- 
2.20.1

