diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 4d6a0edd91..4b60382778 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -1452,18 +1452,18 @@ include_dir 'conf.d' mechanism is used. - The command must print the passphrase to the standard output - and exit with code 0. It can prompt from the terminal if - is used. In the parameter value, - %R represents the file descriptor number opened - to the terminal that started the server. A file descriptor is only - available if enabled at server start. If %R - is used and no file descriptor is available, the server will not - start. Value %p is replaced by a pre-defined - prompt string. (Write %% for a literal - %.) Note that the prompt string will probably - contain whitespace, so be sure to quote its use adequately. - Newlines are stripped from the end of the output if present. + The command must print the passphrase to the standard output and exit + with code 0. In the parameter value, %p is + replaced by a prompt string. (Write %% for a + literal %.) Note that the prompt string will + probably contain whitespace, so be sure to quote adequately. A single + newline is stripped from the end of the output if present. + + + The command does not actually have to prompt the user for a + passphrase. It can read it from a file, obtain it from a keychain + facility, or similar. It is up to the user to make sure the chosen + mechanism is adequately secure. This parameter can only be set in the postgresql.conf @@ -1486,12 +1486,10 @@ include_dir 'conf.d' parameter is off (the default), then ssl_passphrase_command will be ignored during a reload and the SSL configuration will not be reloaded if a passphrase - is needed. This setting is appropriate for a command that requires a - terminal for prompting, which will likely not be available when the server is - running. ( closes the terminal file - descriptor soon after server start.) Setting this parameter on - might be appropriate, for example, if the passphrase is obtained - from a file. + is needed. That setting is appropriate for a command that requires a + TTY for prompting, which might not be available when the server is + running. Setting this parameter to on might be appropriate if the + passphrase is obtained from a file, for example. This parameter can only be set in the postgresql.conf @@ -7818,52 +7816,6 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv; - - Cluster File Encryption - - - - cluster_key_command (string) - - cluster_key_command configuration parameter - - - - - This option specifies an external command to obtain the cluster-level - key for cluster file encryption during server initialization and - server start. - - - The command must print the cluster key to the standard output as - 64 hexadecimal characters, and exit with code 0. The command - can prompt for the passphrase or PIN from the terminal if - is used. In the parameter value, - %R represents the file descriptor number opened - to the terminal that started the server. A file descriptor is only - available if enabled at server start. If %R - is used and no file descriptor is available, the server will not - start. Value %p is replaced by a pre-defined - prompt string. Value %d is replaced by the - directory containing the keys; this is useful if the command - must create files with the keys, e.g., to store a cluster-level - key encryped by a key stored in a hardware security module. - (Write %% for a literal %.) - Note that the prompt string will probably contain whitespace, - so be sure to quote its use adequately. Newlines are stripped - from the end of the output if present. - - - This parameter can only be set by - initdb, in the - postgresql.conf file, or on the server - command line. - - - - - - Client Connection Defaults @@ -9685,22 +9637,6 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir' - - file_encryption_keylen (boolean) - - Cluster file encryption key length - - - - - Reports the bit length of the cluster file - encryption key, or zero if disabled. See for more - information. - - - - data_directory_mode (integer) diff --git a/doc/src/sgml/database-encryption.sgml b/doc/src/sgml/database-encryption.sgml deleted file mode 100644 index 82bc137a61..0000000000 --- a/doc/src/sgml/database-encryption.sgml +++ /dev/null @@ -1,97 +0,0 @@ - - - - Cluster File Encryption - - - Cluster File Encryption - - - - 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 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. - - - - 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 eventually be rotated by switching the primary to the standby - and then changing the WAL key. - - - - 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 - (KEK). This key is not stored - in the file system, but provided at initdb 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. - - - - Initialization - - - Cluster file encryption is enabled when - PostgreSQL is built - with --with-openssl and is specified - during initdb. The cluster key - provided by the - option during initdb and the one generated - by in the - postgresql.conf must match for the database - cluster to start. Note that the cluster key command - passed to initdb must return a key of - 64 hexadecimal characters. For example. - -initdb -D dbname --cluster-key-command='ckey_passphrase.sh' - - - - - - Internals - - - During the initdb process, if - 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, hardware security module. - - - - If the PostgreSQL server has - been initialized to require a cluster key, each time the - server starts the postgresql.conf - cluster_key_command command will be executed - and the cluster key retrieved. The data encryption keys in the - pg_cryptokeys 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 data encryption keys are randomly generated and are 128, 192, - or 256-bits in length. They are encrypted by the key encryption key - (KEK) using Advanced Encryption Standard (AES256) - encryption in Galois/Counter Mode (GCM), which also - provides KEK authentication. - - - diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml index b96f4ace6c..38e8aa0bbf 100644 --- a/doc/src/sgml/filelist.sgml +++ b/doc/src/sgml/filelist.sgml @@ -49,7 +49,6 @@ - diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml index bcc8024049..0ac1cb9999 100644 --- a/doc/src/sgml/installation.sgml +++ b/doc/src/sgml/installation.sgml @@ -976,9 +976,8 @@ build-postgresql: Build with support for SSL (encrypted) - connections and cluster file encryption. This requires the - OpenSSL package to be installed. - configure will check + connections. This requires the OpenSSL + package to be installed. configure will check for the required header files and libraries to make sure that your OpenSSL installation is sufficient before proceeding. diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml index 0ea7da604b..730d5fdc34 100644 --- a/doc/src/sgml/postgres.sgml +++ b/doc/src/sgml/postgres.sgml @@ -171,7 +171,6 @@ break is not needed in a wider output rendering. &wal; &logical-replication; &jit; - &database-encryption; ®ress; diff --git a/doc/src/sgml/ref/allfiles.sgml b/doc/src/sgml/ref/allfiles.sgml index 4e9504e11b..0f0064150c 100644 --- a/doc/src/sgml/ref/allfiles.sgml +++ b/doc/src/sgml/ref/allfiles.sgml @@ -189,7 +189,6 @@ Complete list of usable sgml source files in this directory. - @@ -216,7 +215,7 @@ Complete list of usable sgml source files in this directory. - + diff --git a/doc/src/sgml/ref/initdb.sgml b/doc/src/sgml/ref/initdb.sgml index d994f407fa..385ac25150 100644 --- a/doc/src/sgml/ref/initdb.sgml +++ b/doc/src/sgml/ref/initdb.sgml @@ -163,17 +163,6 @@ PostgreSQL documentation - - - - - This option specifies an external command to obtain the cluster-level - key for cluster file encryption during server initialization and - server start; see for details. - - - - @@ -234,18 +223,6 @@ PostgreSQL documentation - - - - - - Specifies the number of bits for the file encryption keys. The - default is 128 bits. - - - - @@ -308,17 +285,6 @@ PostgreSQL documentation - - - - - - Allows the command - to prompt for a passphrase or PIN. - - - - @@ -341,18 +307,6 @@ PostgreSQL documentation - - - - - - Copies cluster file encryption keys from another cluster; required - when using pg_upgrade on a cluster - with cluster file encryption enabled. - - - - diff --git a/doc/src/sgml/ref/pg_alterckey.sgml b/doc/src/sgml/ref/pg_alterckey.sgml deleted file mode 100644 index f80946dcc6..0000000000 --- a/doc/src/sgml/ref/pg_alterckey.sgml +++ /dev/null @@ -1,197 +0,0 @@ - - - - - pg_alterckey - - - - pg_alterckey - 1 - Application - - - - pg_alterckey - alter the PostgreSQL cluster key - - - - - pg_alterckey - - - - - - - - old_cluster_key_command - new_cluster_key_command - - - - - - - - datadir - - - - - - pg_alterckey - - - - - - - - - - - - - - - - - datadir - - - - - - - Description - - pg_alterckey alters the cluster key used - for cluster file encryption. The cluster key is initially set - during . The command can be run while the - server is running or stopped. The new password must be used the next - time the server is started. - - - - Technically, pg_alterckey changes the key - encryption key (KEK) which encrypts the data - encryption keys; it does not change the data encryption keys. It does - this by decrypting each data encryption key using the old_cluster_key_command, - re-encrypting it using the new_cluster_key_command, and - then writes the result back to the cluster directory. - - - - See the documentation for how to define - the old and new passphrase commands. You can use different executables - for these commands, or you can use the same executable with different - arguments to specify retrieval of the old or new key. - - - - When started, pg_alterckey repairs any files that - remain from previous pg_alterckey failures before - altering the cluster key. To perform only the repair task, - use the option. The server will not start - if repair is needed, though a running server is unaffected by an - unrepaired cluster key configuration. - - - - You can specify the data directory on the command line, or use - the environment variable PGDATA. - - - - - Options - - - - - - - - - Allows the and - commands - to prompt for a passphrase or PIN. - - - - - - - - Other options: - - - - - - - - Print the pg_alterckey version and exit. - - - - - - - - - - Show help about pg_alterckey command line - arguments, and exit. - - - - - - - - - - - Environment - - - - PGDATA - - - - Default data directory location - - - - - - PG_COLOR - - - Specifies whether to use color in diagnostic messages. Possible values - are always, auto and - never. - - - - - - - - See Also - - - - - - - diff --git a/doc/src/sgml/ref/pg_ctl-ref.sgml b/doc/src/sgml/ref/pg_ctl-ref.sgml index 0662ae051a..3946fa52ea 100644 --- a/doc/src/sgml/ref/pg_ctl-ref.sgml +++ b/doc/src/sgml/ref/pg_ctl-ref.sgml @@ -38,7 +38,6 @@ PostgreSQL documentation options path - @@ -73,7 +72,6 @@ PostgreSQL documentation seconds options - @@ -375,18 +373,6 @@ PostgreSQL documentation - - - - - - Allows or - to prompt for a passphrase - or PIN. - - - - diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index b1bcdb77a3..92e1d09a55 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -167,15 +167,6 @@ PostgreSQL documentation - - - - allows or - to prompt for a passphrase - or PIN. - - - dir dir @@ -318,9 +309,7 @@ make prefix=/usr/local/pgsql.new install Again, use compatible initdb flags that match the old cluster. Many prebuilt installers do this step automatically. There is no need to - start the new cluster. If upgrading a cluster that uses - cluster file encryption, the initdb option - must be specified. + start the new cluster. @@ -849,13 +838,6 @@ psql --username=postgres --file=script.sql postgres is down. - - If the old cluster uses file encryption, the new cluster must use - the same keys, so pg_upgrade copies them to the - new cluster. It is necessary to initialize the new cluster with - the same cluster_key_command and the same - file encryption key length. - diff --git a/doc/src/sgml/ref/postgres-ref.sgml b/doc/src/sgml/ref/postgres-ref.sgml index 805da81e07..4aaa7abe1a 100644 --- a/doc/src/sgml/ref/postgres-ref.sgml +++ b/doc/src/sgml/ref/postgres-ref.sgml @@ -297,19 +297,6 @@ PostgreSQL documentation - - - - - Makes postgres prompt for a passphrase or PIN - from the specified open numeric file descriptor. The descriptor - is closed after the key is read. The file descriptor number - -1 duplicates standard error for the terminal; - this is useful for single-user mode. - - - - diff --git a/doc/src/sgml/reference.sgml b/doc/src/sgml/reference.sgml index fdb4e65144..dd2bddab8c 100644 --- a/doc/src/sgml/reference.sgml +++ b/doc/src/sgml/reference.sgml @@ -240,7 +240,6 @@ - &pgalterckey; &clusterdb; &createdb; &createuser; diff --git a/doc/src/sgml/storage.sgml b/doc/src/sgml/storage.sgml index cdbc214a51..3234adb639 100644 --- a/doc/src/sgml/storage.sgml +++ b/doc/src/sgml/storage.sgml @@ -77,11 +77,6 @@ Item Subdirectory containing transaction commit timestamp data - - pg_cryptokeys - Subdirectory containing file encryption keys - - pg_dynshmem Subdirectory containing files used by the dynamic shared memory diff --git a/src/backend/Makefile b/src/backend/Makefile index 3a64affd50..9706a95848 100644 --- a/src/backend/Makefile +++ b/src/backend/Makefile @@ -21,7 +21,7 @@ SUBDIRS = access bootstrap catalog parser commands executor foreign lib libpq \ main nodes optimizer partitioning port postmaster \ regex replication rewrite \ statistics storage tcop tsearch utils $(top_builddir)/src/timezone \ - jit crypto + jit include $(srcdir)/common.mk @@ -212,12 +212,6 @@ endif $(INSTALL_DATA) $(srcdir)/libpq/pg_hba.conf.sample '$(DESTDIR)$(datadir)/pg_hba.conf.sample' $(INSTALL_DATA) $(srcdir)/libpq/pg_ident.conf.sample '$(DESTDIR)$(datadir)/pg_ident.conf.sample' $(INSTALL_DATA) $(srcdir)/utils/misc/postgresql.conf.sample '$(DESTDIR)$(datadir)/postgresql.conf.sample' - $(INSTALL_DATA) $(srcdir)/crypto/ckey_aws.sh.sample '$(DESTDIR)$(datadir)/auth_commands/ckey_aws.sh.sample' - $(INSTALL_DATA) $(srcdir)/crypto/ckey_direct.sh.sample '$(DESTDIR)$(datadir)/auth_commands/ckey_direct.sh.sample' - $(INSTALL_DATA) $(srcdir)/crypto/ckey_passphrase.sh.sample '$(DESTDIR)$(datadir)/auth_commands/ckey_passphrase.sh.sample' - $(INSTALL_DATA) $(srcdir)/crypto/ckey_piv_nopin.sh.sample '$(DESTDIR)$(datadir)/auth_commands/ckey_piv_nopin.sh.sample' - $(INSTALL_DATA) $(srcdir)/crypto/ckey_piv_pin.sh.sample '$(DESTDIR)$(datadir)/auth_commands/ckey_piv_pin.sh.sample' - $(INSTALL_DATA) $(srcdir)/crypto/ssl_passphrase.sh.sample '$(DESTDIR)$(datadir)/auth_commands/ssl_passphrase.sh.sample' ifeq ($(with_llvm), yes) install-bin: install-postgres-bitcode @@ -243,7 +237,6 @@ endif installdirs: $(MKDIR_P) '$(DESTDIR)$(bindir)' '$(DESTDIR)$(datadir)' - $(MKDIR_P) '$(DESTDIR)$(datadir)' '$(DESTDIR)$(datadir)/auth_commands' ifeq ($(PORTNAME), cygwin) ifeq ($(MAKE_DLL), true) $(MKDIR_P) '$(DESTDIR)$(libdir)' @@ -283,13 +276,7 @@ endif $(MAKE) -C utils uninstall-data rm -f '$(DESTDIR)$(datadir)/pg_hba.conf.sample' \ '$(DESTDIR)$(datadir)/pg_ident.conf.sample' \ - '$(DESTDIR)$(datadir)/postgresql.conf.sample' \ - '$(DESTDIR)$(datadir)/auth_commands/ckey_aws.sh.sample' \ - '$(DESTDIR)$(datadir)/auth_commands/ckey_direct.sh.sample' \ - '$(DESTDIR)$(datadir)/auth_commands/ckey_passphrase.sh.sample' \ - '$(DESTDIR)$(datadir)/auth_commands/ckey_piv_nopin.sh.sample' \ - '$(DESTDIR)$(datadir)/auth_commands/ckey_piv_pin.sh.sample' \ - '$(DESTDIR)$(datadir)/auth_commands/ssl_passphrase.sh.sample' + '$(DESTDIR)$(datadir)/postgresql.conf.sample' ifeq ($(with_llvm), yes) $(call uninstall_llvm_module,postgres) endif diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 48ca46a941..9867e1b403 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -44,13 +44,11 @@ #include "commands/tablespace.h" #include "common/controldata_utils.h" #include "executor/instrument.h" -#include "crypto/kmgr.h" #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" #include "port/atomics.h" #include "postmaster/bgwriter.h" -#include "postmaster/postmaster.h" #include "postmaster/startup.h" #include "postmaster/walwriter.h" #include "replication/basebackup.h" @@ -83,7 +81,6 @@ #include "utils/timestamp.h" extern uint32 bootstrap_data_checksum_version; -extern int bootstrap_file_encryption_keylen; /* Unsupported old recovery command file names (relative to $PGDATA) */ #define RECOVERY_COMMAND_FILE "recovery.conf" @@ -4621,7 +4618,6 @@ InitControlFile(uint64 sysidentifier) ControlFile->wal_log_hints = wal_log_hints; ControlFile->track_commit_timestamp = track_commit_timestamp; ControlFile->data_checksum_version = bootstrap_data_checksum_version; - ControlFile->file_encryption_keylen = bootstrap_file_encryption_keylen; } static void @@ -4721,7 +4717,6 @@ ReadControlFile(void) pg_crc32c crc; int fd; static char wal_segsz_str[20]; - static char file_encryption_keylen_str[20]; int r; /* @@ -4910,12 +4905,6 @@ ReadControlFile(void) /* Make the initdb settings visible as GUC variables, too */ SetConfigOption("data_checksums", DataChecksumsEnabled() ? "yes" : "no", PGC_INTERNAL, PGC_S_OVERRIDE); - - Assert(ControlFile != NULL); - snprintf(file_encryption_keylen_str, sizeof(file_encryption_keylen_str), "%d", - ControlFile->file_encryption_keylen); - SetConfigOption("file_encryption_keylen", file_encryption_keylen_str, PGC_INTERNAL, - PGC_S_OVERRIDE); } /* @@ -5365,16 +5354,6 @@ BootStrapXLOG(void) /* some additional ControlFile fields are set in WriteControlFile() */ WriteControlFile(); - /* Enable file encryption if required */ - if (ControlFile->file_encryption_keylen > 0) - BootStrapKmgr(); - - if (terminal_fd != -1) - { - close(terminal_fd); - terminal_fd = -1; - } - /* Bootstrap the commit log, too */ BootStrapCLOG(); BootStrapCommitTs(); diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index bf93135a48..a7ed93fdc1 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -28,14 +28,12 @@ #include "catalog/pg_collation.h" #include "catalog/pg_type.h" #include "common/link-canary.h" -#include "crypto/kmgr.h" #include "libpq/pqsignal.h" #include "miscadmin.h" #include "nodes/makefuncs.h" #include "pg_getopt.h" #include "pgstat.h" #include "postmaster/bgwriter.h" -#include "postmaster/postmaster.h" #include "postmaster/startup.h" #include "postmaster/walwriter.h" #include "replication/walreceiver.h" @@ -53,8 +51,6 @@ #include "utils/relmapper.h" uint32 bootstrap_data_checksum_version = 0; /* No checksum */ -int bootstrap_file_encryption_keylen = 0; /* disabled */ -char *bootstrap_old_key_datadir = NULL; /* disabled */ static void CheckerModeMain(void); @@ -228,7 +224,7 @@ AuxiliaryProcessMain(int argc, char *argv[]) /* If no -x argument, we are a CheckerProcess */ MyAuxProcType = CheckerProcess; - while ((flag = getopt(argc, argv, "B:c:d:D:FkK:r:R:u:x:X:-:")) != -1) + while ((flag = getopt(argc, argv, "B:c:d:D:Fkr:x:X:-:")) != -1) { switch (flag) { @@ -257,18 +253,9 @@ AuxiliaryProcessMain(int argc, char *argv[]) case 'k': bootstrap_data_checksum_version = PG_DATA_CHECKSUM_VERSION; break; - case 'K': - bootstrap_file_encryption_keylen = atoi(optarg); - break; - case 'u': - bootstrap_old_key_datadir = pstrdup(optarg); - break; case 'r': strlcpy(OutputFileName, optarg, MAXPGPATH); break; - case 'R': - terminal_fd = atoi(optarg); - break; case 'x': MyAuxProcType = atoi(optarg); break; @@ -325,12 +312,6 @@ AuxiliaryProcessMain(int argc, char *argv[]) proc_exit(1); } - if (bootstrap_file_encryption_keylen != 0 && - bootstrap_file_encryption_keylen != 128 && - bootstrap_file_encryption_keylen != 192 && - bootstrap_file_encryption_keylen != 256) - elog(PANIC, "unrecognized file encryption length: %d", bootstrap_file_encryption_keylen); - switch (MyAuxProcType) { case StartupProcess: diff --git a/src/backend/crypto/Makefile b/src/backend/crypto/Makefile deleted file mode 100644 index c27362029d..0000000000 --- a/src/backend/crypto/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -#------------------------------------------------------------------------- -# -# Makefile -# Makefile for src/backend/crypto -# -# IDENTIFICATION -# src/backend/crypto/Makefile -# -#------------------------------------------------------------------------- - -subdir = src/backend/crypto -top_builddir = ../../.. -include $(top_builddir)/src/Makefile.global - -OBJS = \ - kmgr.o - -include $(top_srcdir)/src/backend/common.mk diff --git a/src/backend/crypto/ckey_aws.sh.sample b/src/backend/crypto/ckey_aws.sh.sample deleted file mode 100755 index 0341621c2e..0000000000 --- a/src/backend/crypto/ckey_aws.sh.sample +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/sh - -# This uses the AWS Secrets Manager using the AWS CLI and OpenSSL. - -[ "$#" -ne 1 ] && echo "cluster_key_command usage: $0 \"%d\"" 1>&2 && exit 1 -# No need for %R or -R since we are not prompting - -DIR="$1" -[ ! -e "$DIR" ] && echo "$DIR does not exist" 1>&2 && exit 1 -[ ! -d "$DIR" ] && echo "$DIR is not a directory" 1>&2 && exit 1 - -# File containing the id of the AWS secret -AWS_ID_FILE="$DIR/aws-secret.id" - - -# ---------------------------------------------------------------------- - - -# Create an AWS Secrets Manager secret? -if [ ! -e "$AWS_ID_FILE" ] -then # The 'postgres' operating system user must have permission to - # access the AWS CLI - - # The epoch-time/directory/hostname combination is unique - HASH=$(echo -n "$(date '+%s')$DIR$(hostname)" | sha1sum | cut -d' ' -f1) - AWS_SECRET_ID="Postgres-cluster-key-$HASH" - - # Use stdin to avoid passing the secret on the command line - openssl rand -hex 32 | - aws secretsmanager create-secret \ - --name "$AWS_SECRET_ID" \ - --description 'Used for Postgres cluster file encryption' \ - --secret-string 'file:///dev/stdin' \ - --output text > /dev/null - if [ "$?" -ne 0 ] - then echo 'cluster key generation failed' 1>&2 - exit 1 - fi - - echo "$AWS_SECRET_ID" > "$AWS_ID_FILE" -fi - -if ! aws secretsmanager get-secret-value \ - --secret-id "$(cat "$AWS_ID_FILE")" \ - --output text -then echo 'cluster key retrieval failed' 1>&2 - exit 1 -fi | awk -F'\t' 'NR == 1 {print $4}' - -exit 0 diff --git a/src/backend/crypto/ckey_direct.sh.sample b/src/backend/crypto/ckey_direct.sh.sample deleted file mode 100755 index 1c41d53acc..0000000000 --- a/src/backend/crypto/ckey_direct.sh.sample +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh - -# This uses a key supplied by the user -# If OpenSSL is installed, you can generate a pseudo-random key by running: -# openssl rand -hex 32 -# To get a true random key, run: -# wget -q -O - 'https://www.random.org/cgi-bin/randbyte?nbytes=32&format=h' | tr -d ' \n'; echo - -[ "$#" -lt 1 ] && echo "cluster_key_command usage: $0 %R [%p]" 1>&2 && exit 1 -# Supports environment variable PROMPT - -FD="$1" -[ ! -t "$FD" ] && echo "file descriptor $FD does not refer to a terminal" 1>&2 && exit 1 - -[ "$2" ] && PROMPT="$2" - - -# ---------------------------------------------------------------------- - -[ ! "$PROMPT" ] && PROMPT='Enter cluster key as 64 hexadecimal characters: ' - -stty -echo <&"$FD" - -echo 1>&"$FD" -echo -n "$PROMPT" 1>&"$FD" -read KEY <&"$FD" - -stty echo <&"$FD" - -if [ "$(expr "$KEY" : '[0-9a-fA-F]*$')" -ne 64 ] -then echo 'invalid; must be 64 hexadecimal characters' 1>&2 - exit 1 -fi - -echo "$KEY" - -exit 0 diff --git a/src/backend/crypto/ckey_passphrase.sh.sample b/src/backend/crypto/ckey_passphrase.sh.sample deleted file mode 100755 index 1098e99e54..0000000000 --- a/src/backend/crypto/ckey_passphrase.sh.sample +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/sh - -# This uses a passphrase supplied by the user. - -[ "$#" -lt 1 ] && echo "cluster_key_command usage: $0 %R [\"%p\"]" 1>&2 && exit 1 - -FD="$1" -[ ! -t "$FD" ] && echo "file descriptor $FD does not refer to a terminal" 1>&2 && exit 1 -# Supports environment variable PROMPT - -[ "$2" ] && PROMPT="$2" - - -# ---------------------------------------------------------------------- - -[ ! "$PROMPT" ] && PROMPT='Enter cluster passphrase: ' - -stty -echo <&"$FD" - -echo 1>&"$FD" -echo -n "$PROMPT" 1>&"$FD" -read PASS <&"$FD" - -stty echo <&"$FD" - -if [ ! "$PASS" ] -then echo 'invalid: empty passphrase' 1>&2 - exit 1 -fi - -echo "$PASS" | sha256sum | cut -d' ' -f1 - -exit 0 diff --git a/src/backend/crypto/ckey_piv_nopin.sh.sample b/src/backend/crypto/ckey_piv_nopin.sh.sample deleted file mode 100755 index ac7dc941ee..0000000000 --- a/src/backend/crypto/ckey_piv_nopin.sh.sample +++ /dev/null @@ -1,63 +0,0 @@ -#!/bin/sh - -# This uses the public/private keys on a PIV device, like a CAC or Yubikey. -# It uses a PIN stored in a file. -# It uses OpenSSL with PKCS11 enabled via OpenSC. - -[ "$#" -ne 1 ] && echo "cluster_key_command usage: $0 \"%d\"" 1>&2 && exit 1 -# Supports environment variable PIV_PIN_FILE -# No need for %R or -R since we are not prompting for a PIN - -DIR="$1" -[ ! -e "$DIR" ] && echo "$DIR does not exist" 1>&2 && exit 1 -[ ! -d "$DIR" ] && echo "$DIR is not a directory" 1>&2 && exit 1 - -# Set these here or pass in as environment variables. -# File that stores the PIN to unlock the PIV -#PIV_PIN_FILE='' -# PIV slot 3 is the "Key Management" slot, so we use '0:3' -PIV_SLOT='0:3' - -# File containing the cluster key encrypted with the PIV_SLOT's public key -KEY_FILE="$DIR/pivpass.key" - - -# ---------------------------------------------------------------------- - -[ ! "$PIV_PIN_FILE" ] && echo 'PIV_PIN_FILE undefined' 1>&2 && exit 1 -[ ! -e "$PIV_PIN_FILE" ] && echo "$PIV_PIN_FILE does not exist" 1>&2 && exit 1 -[ -d "$PIV_PIN_FILE" ] && echo "$PIV_PIN_FILE is a directory" 1>&2 && exit 1 - -[ ! "$KEY_FILE" ] && echo 'KEY_FILE undefined' 1>&2 && exit 1 -[ -d "$KEY_FILE" ] && echo "$KEY_FILE is a directory" 1>&2 && exit 1 - -# Create a cluster key encrypted with the PIV_SLOT's public key? -if [ ! -e "$KEY_FILE" ] -then # The 'postgres' operating system user must have permission to - # access the PIV device. - - openssl rand -hex 32 | - if ! openssl rsautl -engine pkcs11 -keyform engine -encrypt \ - -inkey "$PIV_SLOT" -passin file:"$PIV_PIN_FILE" -out "$KEY_FILE" - then echo 'cluster key generation failed' 1>&2 - exit 1 - fi - - # Warn the user to save the cluster key in a safe place - cat 1>&2 <&2 - exit 1 -fi - -exit 0 diff --git a/src/backend/crypto/ckey_piv_pin.sh.sample b/src/backend/crypto/ckey_piv_pin.sh.sample deleted file mode 100755 index e6310087ff..0000000000 --- a/src/backend/crypto/ckey_piv_pin.sh.sample +++ /dev/null @@ -1,76 +0,0 @@ -#!/bin/sh - -# This uses the public/private keys on a PIV device, like a CAC or Yubikey. -# It requires a user-entered PIN. -# It uses OpenSSL with PKCS11 enabled via OpenSC. - -[ "$#" -lt 2 ] && echo "cluster_key_command usage: $0 \"%d\" %R [\"%p\"]" 1>&2 && exit 1 -# Supports environment variable PROMPT - -DIR="$1" -[ ! -e "$DIR" ] && echo "$DIR does not exist" 1>&2 && exit 1 -[ ! -d "$DIR" ] && echo "$DIR is not a directory" 1>&2 && exit 1 - -FD="$2" -[ ! -t "$FD" ] && echo "file descriptor $FD does not refer to a terminal" 1>&2 && exit 1 - -[ "$3" ] && PROMPT="$3" - -# PIV slot 3 is the "Key Management" slot, so we use '0:3' -PIV_SLOT='0:3' - -# File containing the cluster key encrypted with the PIV_SLOT's public key -KEY_FILE="$DIR/pivpass.key" - - -# ---------------------------------------------------------------------- - -[ ! "$PROMPT" ] && PROMPT='Enter PIV PIN: ' - -stty -echo <&"$FD" - -# Create a cluster key encrypted with the PIV_SLOT's public key? -if [ ! -e "$KEY_FILE" ] -then echo 1>&"$FD" - echo -n "$PROMPT" 1>&"$FD" - - # The 'postgres' operating system user must have permission to - # access the PIV device. - - openssl rand -hex 32 | - # 'engine "pkcs11" set.' message confuses prompting - if ! openssl rsautl -engine pkcs11 -keyform engine -encrypt \ - -inkey "$PIV_SLOT" -passin fd:"$FD" -out "$KEY_FILE" 2>&1 - then stty echo <&"$FD" - echo 'cluster key generation failed' 1>&2 - exit 1 - fi | grep -v 'engine "pkcs11" set\.' - - echo 1>&"$FD" - - # Warn the user to save the cluster key in a safe place - cat 1>&"$FD" <&"$FD" -echo -n "$PROMPT" 1>&"$FD" - -# Decrypt the cluster key encrypted with the PIV_SLOT's public key -if ! openssl rsautl -engine pkcs11 -keyform engine -decrypt \ - -inkey "$PIV_SLOT" -passin fd:"$FD" -in "$KEY_FILE" 2>&1 -then stty echo <&"$FD" - echo 'cluster key retrieval failed' 1>&2 - exit 1 -fi | grep -v 'engine "pkcs11" set\.' - -echo 1>&"$FD" - -stty echo <&"$FD" - -exit 0 diff --git a/src/backend/crypto/kmgr.c b/src/backend/crypto/kmgr.c deleted file mode 100644 index 4e701e0275..0000000000 --- a/src/backend/crypto/kmgr.c +++ /dev/null @@ -1,372 +0,0 @@ -/*------------------------------------------------------------------------- - * - * kmgr.c - * Cluster file encryption routines - * - * Cluster file encryption is enabled if user requests it during initdb. - * During bootstrap, we generate data encryption keys, wrap them with the - * cluster-level key, and store them into each file located at KMGR_DIR. - * Once generated, these are not changed. During startup, we decrypt all - * internal keys and load them to the shared memory space. Internal keys - * on the shared memory are read-only. All wrapping and unwrapping key - * routines require the OpenSSL library. - * - * Copyright (c) 2020, PostgreSQL Global Development Group - * - * IDENTIFICATION - * src/backend/crypto/kmgr.c - *------------------------------------------------------------------------- - */ - -#include "postgres.h" - -#include -#include - -#include "funcapi.h" -#include "miscadmin.h" -#include "pgstat.h" - -#include "common/file_perm.h" -#include "common/hex_decode.h" -#include "common/kmgr_utils.h" -#include "common/sha2.h" -#include "access/xlog.h" -#include "crypto/kmgr.h" -#include "storage/copydir.h" -#include "storage/fd.h" -#include "storage/ipc.h" -#include "storage/shmem.h" -#include "utils/builtins.h" -#include "utils/memutils.h" -/* Struct stores file encryption keys in plaintext format */ -typedef struct KmgrShmemData -{ - CryptoKey intlKeys[KMGR_MAX_INTERNAL_KEYS]; -} KmgrShmemData; -static KmgrShmemData *KmgrShmem; - -/* GUC variables */ -char *cluster_key_command = NULL; -int file_encryption_keylen = 0; - -CryptoKey bootstrap_keys[KMGR_MAX_INTERNAL_KEYS]; - -extern char *bootstrap_old_key_datadir; -extern int bootstrap_file_encryption_keylen; - -static void bzeroKmgrKeys(int status, Datum arg); -static void KmgrSaveCryptoKeys(const char *dir, CryptoKey *keys); -static CryptoKey *generate_crypto_key(int len); - -/* - * This function must be called ONCE during initdb. - */ -void -BootStrapKmgr(void) -{ - char live_path[MAXPGPATH]; - CryptoKey *keys_wrap; - int nkeys; - char cluster_key_hex[ALLOC_KMGR_CLUSTER_KEY_LEN]; - int cluster_key_hex_len; - unsigned char cluster_key[KMGR_CLUSTER_KEY_LEN]; - -#ifndef USE_OPENSSL - ereport(ERROR, - (errcode(ERRCODE_CONFIG_FILE_ERROR), - (errmsg("cluster file encryption is not supported because OpenSSL is not supported by this build"), - errhint("Compile with --with-openssl to use this feature.")))); -#endif - - snprintf(live_path, sizeof(live_path), "%s/%s", DataDir, LIVE_KMGR_DIR); - - /* copy cluster file encryption keys from an old cluster? */ - if (bootstrap_old_key_datadir != NULL) - { - char old_key_dir[MAXPGPATH]; - - snprintf(old_key_dir, sizeof(old_key_dir), "%s/%s", - bootstrap_old_key_datadir, LIVE_KMGR_DIR); - copydir(old_key_dir, LIVE_KMGR_DIR, true); - } - /* create empty directory */ - else - { - if (mkdir(LIVE_KMGR_DIR, pg_dir_create_mode) < 0) - ereport(ERROR, - (errcode_for_file_access(), - errmsg("could not create cluster file encryption directory \"%s\": %m", - LIVE_KMGR_DIR))); - } - - /* - * Get key encryption key from the cluster_key command. The cluster_key - * command might want to check for the existance of files in the - * live directory, so run this _after_ copying the directory in place. - */ - cluster_key_hex_len = kmgr_run_cluster_key_command(cluster_key_command, - cluster_key_hex, - ALLOC_KMGR_CLUSTER_KEY_LEN, - live_path); - - if (hex_decode(cluster_key_hex, cluster_key_hex_len, (char*) cluster_key) != - KMGR_CLUSTER_KEY_LEN) - ereport(ERROR, - (errmsg("cluster key must be %d hexadecimal characters", - KMGR_CLUSTER_KEY_LEN * 2))); - - /* generate new cluster file encryption keys */ - if (bootstrap_old_key_datadir == NULL) - { - CryptoKey bootstrap_keys_wrap[KMGR_MAX_INTERNAL_KEYS]; - PgCipherCtx *cluster_key_ctx; - - /* Create KEK encryption context */ - cluster_key_ctx = pg_cipher_ctx_create(PG_CIPHER_AES_GCM, cluster_key, - KMGR_CLUSTER_KEY_LEN, true); - if (!cluster_key_ctx) - elog(ERROR, "could not initialize encryption context"); - - /* Wrap all data encryption keys by key encryption key */ - for (int id = 0; id < KMGR_MAX_INTERNAL_KEYS; id++) - { - CryptoKey *key; - - /* generate a data encryption key */ - key = generate_crypto_key(bootstrap_file_encryption_keylen); - - /* Set this key's ID */ - key->pgkey_id = id; - - if (!kmgr_wrap_key(cluster_key_ctx, key, &(bootstrap_keys_wrap[id]))) - { - pg_cipher_ctx_free(cluster_key_ctx); - elog(ERROR, "failed to wrap data encryption key"); - } - - explicit_bzero(key, sizeof(CryptoKey)); - } - - /* Save data encryption keys to the disk */ - KmgrSaveCryptoKeys(LIVE_KMGR_DIR, bootstrap_keys_wrap); - - explicit_bzero(bootstrap_keys_wrap, sizeof(bootstrap_keys_wrap)); - pg_cipher_ctx_free(cluster_key_ctx); - } - - /* - * We are either decrypting keys we copied from an old cluster, or - * decrypting keys we just wrote above --- either way, we decrypt - * them here and store them in a file-scoped variable for use in - * later encrypting during bootstrap mode. - */ - - /* Get the crypto keys from the file */ - keys_wrap = kmgr_get_cryptokeys(LIVE_KMGR_DIR, &nkeys); - Assert(nkeys == KMGR_MAX_INTERNAL_KEYS); - - if (!kmgr_verify_cluster_key(cluster_key, keys_wrap, bootstrap_keys, - KMGR_MAX_INTERNAL_KEYS)) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("supplied cluster key does not match expected cluster_key"))); - - /* bzero keys on exit */ - on_proc_exit(bzeroKmgrKeys, 0); - - explicit_bzero(cluster_key_hex, cluster_key_hex_len); - explicit_bzero(cluster_key, KMGR_CLUSTER_KEY_LEN); -} - -/* Report shared-memory space needed by KmgrShmem */ -Size -KmgrShmemSize(void) -{ - if (!file_encryption_keylen) - return 0; - - return MAXALIGN(sizeof(KmgrShmemData)); -} - -/* Allocate and initialize key manager memory */ -void -KmgrShmemInit(void) -{ - bool found; - - if (!file_encryption_keylen) - return; - - KmgrShmem = (KmgrShmemData *) ShmemInitStruct("File encryption key manager", - KmgrShmemSize(), &found); - - on_shmem_exit(bzeroKmgrKeys, 0); -} - -/* - * Get cluster key and verify it, then get the data encryption keys. - * This function is called by postmaster at startup time. - */ -void -InitializeKmgr(void) -{ - CryptoKey *keys_wrap; - int nkeys; - char cluster_key_hex[ALLOC_KMGR_CLUSTER_KEY_LEN]; - int cluster_key_hex_len; - struct stat buffer; - char live_path[MAXPGPATH]; - unsigned char cluster_key[KMGR_CLUSTER_KEY_LEN]; - - if (!file_encryption_keylen) - return; - - elog(DEBUG1, "starting up cluster file encryption manager"); - - if (stat(KMGR_DIR, &buffer) != 0 || !S_ISDIR(buffer.st_mode)) - ereport(ERROR, - (errcode(ERRCODE_INTERNAL_ERROR), - (errmsg("cluster file encryption directory %s is missing", KMGR_DIR)))); - - if (stat(KMGR_DIR_PID, &buffer) == 0) - ereport(ERROR, - (errcode(ERRCODE_INTERNAL_ERROR), - (errmsg("cluster had a pg_alterckey failure that needs repair or pg_alterckey is running"), - errhint("Run pg_alterckey --repair or wait for it to complete.")))); - - /* - * We want OLD deleted since it allows access to the data encryption - * keys using the old cluster key. If NEW exists, it means either - * NEW is partly written, or NEW wasn't renamed to LIVE --- in either - * case, it needs to be repaired. - */ - if (stat(OLD_KMGR_DIR, &buffer) == 0 || stat(NEW_KMGR_DIR, &buffer) == 0) - ereport(ERROR, - (errcode(ERRCODE_INTERNAL_ERROR), - (errmsg("cluster had a pg_alterckey failure that needs repair"), - errhint("Run pg_alterckey --repair.")))); - - /* If OLD, NEW, and LIVE do not exist, there is a serious problem. */ - if (stat(LIVE_KMGR_DIR, &buffer) != 0 || !S_ISDIR(buffer.st_mode)) - ereport(ERROR, - (errcode(ERRCODE_INTERNAL_ERROR), - (errmsg("cluster has no data encryption keys")))); - - /* Get cluster key */ - snprintf(live_path, sizeof(live_path), "%s/%s", DataDir, LIVE_KMGR_DIR); - cluster_key_hex_len = kmgr_run_cluster_key_command(cluster_key_command, - cluster_key_hex, - ALLOC_KMGR_CLUSTER_KEY_LEN, - live_path); - - if (hex_decode(cluster_key_hex, cluster_key_hex_len, (char*) cluster_key) != - KMGR_CLUSTER_KEY_LEN) - ereport(ERROR, - (errmsg("cluster key must be %d hexadecimal characters", - KMGR_CLUSTER_KEY_LEN * 2))); - - /* Get the crypto keys from the file */ - keys_wrap = kmgr_get_cryptokeys(LIVE_KMGR_DIR, &nkeys); - Assert(nkeys == KMGR_MAX_INTERNAL_KEYS); - - /* - * Verify cluster key and prepare a data encryption key in plaintext in shared memory. - */ - if (!kmgr_verify_cluster_key(cluster_key, keys_wrap, KmgrShmem->intlKeys, - KMGR_MAX_INTERNAL_KEYS)) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("supplied cluster key does not match expected cluster key"))); - - explicit_bzero(cluster_key_hex, cluster_key_hex_len); - explicit_bzero(cluster_key, KMGR_CLUSTER_KEY_LEN); -} - -static void -bzeroKmgrKeys(int status, Datum arg) -{ - if (IsBootstrapProcessingMode()) - explicit_bzero(bootstrap_keys, sizeof(bootstrap_keys)); - else - explicit_bzero(KmgrShmem->intlKeys, sizeof(KmgrShmem->intlKeys)); -} - -const CryptoKey * -KmgrGetKey(int id) -{ - Assert(id < KMGR_MAX_INTERNAL_KEYS); - - return (const CryptoKey *) (IsBootstrapProcessingMode() ? - &(bootstrap_keys[id]) : &(KmgrShmem->intlKeys[id])); -} - -/* Generate an empty CryptoKey */ -static CryptoKey * -generate_crypto_key(int len) -{ - CryptoKey *newkey; - - Assert(len <= KMGR_MAX_KEY_LEN); - newkey = (CryptoKey *) palloc0(sizeof(CryptoKey)); - - /* We store the key as length + key into 'encrypted_key' */ - memcpy(newkey->encrypted_key, &len, sizeof(len)); - - if (!pg_strong_random(newkey->encrypted_key + sizeof(len), len)) - elog(ERROR, "failed to generate new file encryption key"); - - return newkey; -} - -/* - * Save the given file encryption keys to the disk. - */ -static void -KmgrSaveCryptoKeys(const char *dir, CryptoKey *keys) -{ - elog(DEBUG2, "saving all cryptographic keys"); - - for (int i = 0; i < KMGR_MAX_INTERNAL_KEYS; i++) - { - int fd; - char path[MAXPGPATH]; - - CryptoKeyFilePath(path, dir, i); - - if ((fd = BasicOpenFile(path, O_RDWR | O_CREAT | O_EXCL | PG_BINARY)) < 0) - ereport(ERROR, - (errcode_for_file_access(), - errmsg("could not open file \"%s\": %m", - path))); - - errno = 0; - pgstat_report_wait_start(WAIT_EVENT_KEY_FILE_WRITE); - if (write(fd, &(keys[i]), sizeof(CryptoKey)) != sizeof(CryptoKey)) - { - /* if write didn't set errno, assume problem is no disk space */ - if (errno == 0) - errno = ENOSPC; - - ereport(ERROR, - (errcode_for_file_access(), - errmsg("could not write file \"%s\": %m", - path))); - } - pgstat_report_wait_end(); - - pgstat_report_wait_start(WAIT_EVENT_KEY_FILE_SYNC); - if (pg_fsync(fd) != 0) - ereport(PANIC, - (errcode_for_file_access(), - errmsg("could not fsync file \"%s\": %m", - path))); - pgstat_report_wait_end(); - - if (close(fd) != 0) - ereport(ERROR, - (errcode_for_file_access(), - errmsg("could not close file \"%s\": %m", - path))); - } -} diff --git a/src/backend/crypto/ssl_passphrase.sh.sample b/src/backend/crypto/ssl_passphrase.sh.sample deleted file mode 100755 index 6859f1bbb5..0000000000 --- a/src/backend/crypto/ssl_passphrase.sh.sample +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/sh - -# This uses a passphrase supplied by the user. - -[ "$#" -lt 1 ] && echo "ssl_passphrase_command usage: $0 %R [\"%p\"]" 1>&2 && exit 1 - -FD="$1" -[ ! -t "$FD" ] && echo "file descriptor $FD does not refer to a terminal" 1>&2 && exit 1 -# Supports environment variable PROMPT - -[ "$2" ] && PROMPT="$2" - - -# ---------------------------------------------------------------------- - -[ ! "$PROMPT" ] && PROMPT='Enter cluster passphrase: ' - -stty -echo <&"$FD" - -echo 1>&"$FD" -echo -n "$PROMPT" 1>&"$FD" -read PASS <&"$FD" - -stty echo <&"$FD" - -if [ ! "$PASS" ] -then echo 'invalid: empty passphrase' 1>&2 - exit 1 -fi - -echo "$PASS" - -exit 0 diff --git a/src/backend/libpq/be-secure-common.c b/src/backend/libpq/be-secure-common.c index 1b712cfbba..94cdf4c887 100644 --- a/src/backend/libpq/be-secure-common.c +++ b/src/backend/libpq/be-secure-common.c @@ -22,7 +22,6 @@ #include #include -#include "postmaster/postmaster.h" #include "common/string.h" #include "libpq/libpq.h" #include "storage/fd.h" @@ -62,19 +61,6 @@ run_ssl_passphrase_command(const char *prompt, bool is_server_start, char *buf, appendStringInfoString(&command, prompt); p++; break; - case 'R': - { - char fd_str[20]; - - if (terminal_fd == -1) - ereport(ERROR, - (errcode(ERRCODE_INTERNAL_ERROR), - errmsg("ssl_passphrase_command referenced %%R, but -R not specified"))); - p++; - snprintf(fd_str, sizeof(fd_str), "%d", terminal_fd); - appendStringInfoString(&command, fd_str); - break; - } case '%': appendStringInfoChar(&command, '%'); p++; diff --git a/src/backend/main/main.c b/src/backend/main/main.c index 19aa502614..b6e5128832 100644 --- a/src/backend/main/main.c +++ b/src/backend/main/main.c @@ -324,7 +324,6 @@ help(const char *progname) #endif printf(_(" -N MAX-CONNECT maximum number of allowed connections\n")); printf(_(" -p PORT port number to listen on\n")); - printf(_(" -R fd prompt for the cluster key\n")); printf(_(" -s show statistics after each query\n")); printf(_(" -S WORK-MEM set amount of memory for sorts (in kB)\n")); printf(_(" -V, --version output version information, then exit\n")); @@ -352,9 +351,7 @@ help(const char *progname) printf(_("\nOptions for bootstrapping mode:\n")); printf(_(" --boot selects bootstrapping mode (must be first argument)\n")); printf(_(" DBNAME database name (mandatory argument in bootstrapping mode)\n")); - printf(_(" -K LEN enable cluster file encryption with specified key length\n")); printf(_(" -r FILENAME send stdout and stderr to given file\n")); - printf(_(" -u DATADIR copy encryption keys from datadir\n")); printf(_(" -x NUM internal use\n")); printf(_("\nPlease read the documentation for the complete list of run-time\n" diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index 71f2b90ca8..d87d9d06ee 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -4152,15 +4152,6 @@ pgstat_get_wait_io(WaitEventIO w) case WAIT_EVENT_DSM_FILL_ZERO_WRITE: event_name = "DSMFillZeroWrite"; break; - case WAIT_EVENT_KEY_FILE_READ: - event_name = "KeyFileRead"; - break; - case WAIT_EVENT_KEY_FILE_WRITE: - event_name = "KeyFileWrite"; - break; - case WAIT_EVENT_KEY_FILE_SYNC: - event_name = "KeyFileSync"; - 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 bf883184b1..fff4227e0b 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -100,7 +100,6 @@ #include "common/file_perm.h" #include "common/ip.h" #include "common/string.h" -#include "crypto/kmgr.h" #include "lib/ilist.h" #include "libpq/auth.h" #include "libpq/libpq.h" @@ -232,7 +231,6 @@ static int SendStop = false; /* still more option variables */ bool EnableSSL = false; -int terminal_fd = -1; int PreAuthDelay = 0; int AuthenticationTimeout = 60; @@ -689,7 +687,7 @@ PostmasterMain(int argc, char *argv[]) * tcop/postgres.c (the option sets should not conflict) and with the * common help() function in main/main.c. */ - while ((opt = getopt(argc, argv, "B:bc:C:D:d:EeFf:h:ijk:lN:nOPp:r:R:S:sTt:W:-:")) != -1) + while ((opt = getopt(argc, argv, "B:bc:C:D:d:EeFf:h:ijk:lN:nOPp:r:S:sTt:W:-:")) != -1) { switch (opt) { @@ -780,10 +778,6 @@ PostmasterMain(int argc, char *argv[]) /* only used by single-user backend */ break; - case 'R': - terminal_fd = atoi(optarg); - break; - case 'S': SetConfigOption("work_mem", optarg, PGC_POSTMASTER, PGC_S_ARGV); break; @@ -1332,11 +1326,6 @@ PostmasterMain(int argc, char *argv[]) */ RemovePgTempFiles(); - InitializeKmgr(); - - if (terminal_fd != -1) - close(terminal_fd); - /* * Initialize stats collection subsystem (this does NOT start the * collector process!) diff --git a/src/backend/replication/basebackup.c b/src/backend/replication/basebackup.c index c9fc2f4b4e..1d8d1742a7 100644 --- a/src/backend/replication/basebackup.c +++ b/src/backend/replication/basebackup.c @@ -18,7 +18,6 @@ #include "access/xlog_internal.h" /* for pg_start/stop_backup */ #include "catalog/pg_type.h" -#include "common/kmgr_utils.h" #include "common/file_perm.h" #include "commands/progress.h" #include "lib/stringinfo.h" @@ -153,10 +152,6 @@ struct exclude_list_item */ static const char *const excludeDirContents[] = { - /* Skip temporary crypto key directories */ - NEW_KMGR_DIR, - OLD_KMGR_DIR, - /* * Skip temporary statistics files. PG_STAT_TMP_DIR must be skipped even * when stats_temp_directory is set because PGSS_TEXT_FILE is always diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c index 64fe10ca2a..96c2aaabbd 100644 --- a/src/backend/storage/ipc/ipci.c +++ b/src/backend/storage/ipc/ipci.c @@ -23,7 +23,6 @@ #include "access/syncscan.h" #include "access/twophase.h" #include "commands/async.h" -#include "crypto/kmgr.h" #include "miscadmin.h" #include "pgstat.h" #include "postmaster/autovacuum.h" @@ -150,7 +149,6 @@ CreateSharedMemoryAndSemaphores(void) 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 @@ -269,7 +267,6 @@ CreateSharedMemoryAndSemaphores(void) BTreeShmemInit(); SyncScanShmemInit(); AsyncShmemInit(); - KmgrShmemInit(); #ifdef EXEC_BACKEND diff --git a/src/backend/storage/lmgr/lwlocknames.txt b/src/backend/storage/lmgr/lwlocknames.txt index a44805d5c3..774292fd94 100644 --- a/src/backend/storage/lmgr/lwlocknames.txt +++ b/src/backend/storage/lmgr/lwlocknames.txt @@ -53,4 +53,3 @@ XactTruncationLock 44 # 45 was XactTruncationLock until removal of BackendRandomLock WrapLimitsVacuumLock 46 NotifyQueueTailLock 47 -KmgrFileLock 48 diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 81e64616d4..d35c5020ea 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -42,7 +42,6 @@ #include "catalog/pg_type.h" #include "commands/async.h" #include "commands/prepare.h" -#include "crypto/kmgr.h" #include "executor/spi.h" #include "jit/jit.h" #include "libpq/libpq.h" @@ -3579,7 +3578,7 @@ process_postgres_switches(int argc, char *argv[], GucContext ctx, * postmaster/postmaster.c (the option sets should not conflict) and with * the common help() function in main/main.c. */ - while ((flag = getopt(argc, argv, "B:bc:C:D:d:EeFf:h:ijk:lN:nOPp:r:R:S:sTt:v:W:-:")) != -1) + while ((flag = getopt(argc, argv, "B:bc:C:D:d:EeFf:h:ijk:lN:nOPp:r:S:sTt:v:W:-:")) != -1) { switch (flag) { @@ -3671,16 +3670,6 @@ process_postgres_switches(int argc, char *argv[], GucContext ctx, strlcpy(OutputFileName, optarg, MAXPGPATH); break; - case 'R': - terminal_fd = atoi(optarg); - if (terminal_fd == -1) - /* - * Allow file descriptor closing to be bypassed via -1. - * We just dup sterr. This is useful for single-user mode. - */ - terminal_fd = dup(2); - break; - case 'S': SetConfigOption("work_mem", optarg, ctx, gucsource); break; @@ -3932,18 +3921,6 @@ PostgresMain(int argc, char *argv[], /* Early initialization */ BaseInit(); - /* - * Initialize kmgr for cluster encryption. Since kmgr needs to attach to - * shared memory the initialization must be called after BaseInit(). - */ - if (!IsUnderPostmaster) - { - InitializeKmgr(); - - if (terminal_fd != -1) - close(terminal_fd); - } - /* * Create a per-backend PGPROC struct in shared memory, except in the * EXEC_BACKEND case where this was done in SubPostmasterMain. We must do diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index bbaf037bc6..878fcc2236 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -47,7 +47,6 @@ #include "commands/vacuum.h" #include "commands/variable.h" #include "common/string.h" -#include "crypto/kmgr.h" #include "funcapi.h" #include "jit/jit.h" #include "libpq/auth.h" @@ -746,8 +745,6 @@ const char *const config_group_names[] = gettext_noop("Statistics / Monitoring"), /* STATS_COLLECTOR */ gettext_noop("Statistics / Query and Index Statistics Collector"), - /* ENCRYPTION */ - gettext_noop("Encryption"), /* AUTOVACUUM */ gettext_noop("Autovacuum"), /* CLIENT_CONN */ @@ -3392,17 +3389,6 @@ static struct config_int ConfigureNamesInt[] = check_huge_page_size, NULL, NULL }, - { - {"file_encryption_keylen", PGC_INTERNAL, PRESET_OPTIONS, - gettext_noop("Shows the bit length of the file encryption key."), - NULL, - GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE - }, - &file_encryption_keylen, - 0, 0, 256, - NULL, NULL, NULL - }, - /* End-of-list marker */ { {NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL, NULL @@ -4397,16 +4383,6 @@ static struct config_string ConfigureNamesString[] = NULL, NULL, NULL }, - { - {"cluster_key_command", PGC_SIGHUP, ENCRYPTION, - gettext_noop("Command to obtain cluster key for cluster file encryption."), - NULL - }, - &cluster_key_command, - "", - NULL, NULL, NULL - }, - { {"application_name", PGC_USERSET, LOGGING_WHAT, gettext_noop("Sets the application name to be reported in statistics and logs."), diff --git a/src/backend/utils/misc/pg_controldata.c b/src/backend/utils/misc/pg_controldata.c index 6fcab31172..d50d87a602 100644 --- a/src/backend/utils/misc/pg_controldata.c +++ b/src/backend/utils/misc/pg_controldata.c @@ -263,8 +263,8 @@ pg_control_recovery(PG_FUNCTION_ARGS) Datum pg_control_init(PG_FUNCTION_ARGS) { - Datum values[12]; - bool nulls[12]; + Datum values[11]; + bool nulls[11]; TupleDesc tupdesc; HeapTuple htup; ControlFileData *ControlFile; @@ -274,7 +274,7 @@ pg_control_init(PG_FUNCTION_ARGS) * Construct a tuple descriptor for the result row. This must match this * function's pg_proc entry! */ - tupdesc = CreateTemplateTupleDesc(12); + tupdesc = CreateTemplateTupleDesc(11); TupleDescInitEntry(tupdesc, (AttrNumber) 1, "max_data_alignment", INT4OID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 2, "database_block_size", @@ -297,8 +297,6 @@ pg_control_init(PG_FUNCTION_ARGS) BOOLOID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 11, "data_page_checksum_version", INT4OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 12, "file_encryption_keylen", - INT4OID, -1, 0); tupdesc = BlessTupleDesc(tupdesc); /* read the control file */ @@ -340,9 +338,6 @@ pg_control_init(PG_FUNCTION_ARGS) values[10] = Int32GetDatum(ControlFile->data_checksum_version); nulls[10] = false; - values[11] = Int32GetDatum(ControlFile->file_encryption_keylen); - nulls[11] = false; - htup = heap_form_tuple(tupdesc, values, nulls); PG_RETURN_DATUM(HeapTupleGetDatum(htup)); diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index f19cfe5f6a..b7fb2ec1fe 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -632,11 +632,6 @@ # autovacuum, -1 means use # vacuum_cost_limit -#------------------------------------------------------------------------------ -# ENCRYPTION -#------------------------------------------------------------------------------ - -#cluster_key_command = '' #------------------------------------------------------------------------------ # CLIENT CONNECTION DEFAULTS diff --git a/src/bin/Makefile b/src/bin/Makefile index d3c9e07536..8b870357a1 100644 --- a/src/bin/Makefile +++ b/src/bin/Makefile @@ -16,7 +16,6 @@ include $(top_builddir)/src/Makefile.global SUBDIRS = \ initdb \ pg_archivecleanup \ - pg_alterckey \ pg_basebackup \ pg_checksums \ pg_config \ diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c index 33a11e0d2b..f994c4216b 100644 --- a/src/bin/initdb/initdb.c +++ b/src/bin/initdb/initdb.c @@ -141,16 +141,11 @@ static bool debug = false; static bool noclean = false; static bool do_sync = true; static bool sync_only = false; -static bool pass_terminal_fd = false; -static char *term_fd_opt = NULL; -static int file_encryption_keylen = 0; static bool show_setting = false; static bool data_checksums = false; static char *xlog_dir = NULL; static char *str_wal_segment_size_mb = NULL; static int wal_segment_size_mb; -static char *cluster_key_cmd = NULL; -static char *old_key_datadir = NULL; /* internal vars */ @@ -208,7 +203,6 @@ static const char *const subdirs[] = { "global", "pg_wal/archive_status", "pg_commit_ts", - "pg_cryptokeys", "pg_dynshmem", "pg_notify", "pg_serial", @@ -960,13 +954,12 @@ test_config_settings(void) test_buffs = MIN_BUFS_FOR_CONNS(test_conns); snprintf(cmd, sizeof(cmd), - "\"%s\" --boot -x0 %s %s " + "\"%s\" --boot -x0 %s " "-c max_connections=%d " "-c shared_buffers=%d " "-c dynamic_shared_memory_type=%s " "< \"%s\" > \"%s\" 2>&1", backend_exec, boot_options, - term_fd_opt ? term_fd_opt : "", test_conns, test_buffs, dynamic_shared_memory_type, DEVNULL, DEVNULL); @@ -997,13 +990,12 @@ test_config_settings(void) } snprintf(cmd, sizeof(cmd), - "\"%s\" --boot -x0 %s %s " + "\"%s\" --boot -x0 %s " "-c max_connections=%d " "-c shared_buffers=%d " "-c dynamic_shared_memory_type=%s " "< \"%s\" > \"%s\" 2>&1", backend_exec, boot_options, - term_fd_opt ? term_fd_opt : "", n_connections, test_buffs, dynamic_shared_memory_type, DEVNULL, DEVNULL); @@ -1193,13 +1185,6 @@ setup_config(void) "password_encryption = md5"); } - if (cluster_key_cmd) - { - snprintf(repltok, sizeof(repltok), "cluster_key_command = '%s'", - escape_quotes(cluster_key_cmd)); - conflines = replace_token(conflines, "#cluster_key_command = ''", repltok); - } - /* * If group access has been enabled for the cluster then it makes sense to * ensure that the log files also allow group access. Otherwise a backup @@ -1409,22 +1394,13 @@ bootstrap_template1(void) /* Also ensure backend isn't confused by this environment var: */ unsetenv("PGCLIENTENCODING"); - if (file_encryption_keylen != 0) - sprintf(buf, "%d", file_encryption_keylen); - else - buf[0] = '\0'; - snprintf(cmd, sizeof(cmd), - "\"%s\" --boot -x1 -X %u %s %s %s %s %s %s %s %s", + "\"%s\" --boot -x1 -X %u %s %s %s", backend_exec, wal_segment_size_mb * (1024 * 1024), data_checksums ? "-k" : "", - cluster_key_cmd ? "-K" : "", buf, - old_key_datadir ? "-u" : "", - old_key_datadir ? old_key_datadir : "", boot_options, - debug ? "-d 5" : "", - term_fd_opt ? term_fd_opt : ""); + debug ? "-d 5" : ""); PG_CMD_OPEN; @@ -2305,29 +2281,21 @@ usage(const char *progname) " set default locale in the respective category for\n" " new databases (default taken from environment)\n")); printf(_(" --no-locale equivalent to --locale=C\n")); - printf(_(" --pwfile=FILE read the new superuser password from file\n")); + printf(_(" --pwfile=FILE read password for the new superuser from file\n")); printf(_(" -T, --text-search-config=CFG\n" " default text search configuration\n")); printf(_(" -U, --username=NAME database superuser name\n")); - printf(_(" -W, --pwprompt prompt for the new superuser password\n")); + printf(_(" -W, --pwprompt prompt for a password for the new superuser\n")); printf(_(" -X, --waldir=WALDIR location for the write-ahead log directory\n")); printf(_(" --wal-segsize=SIZE size of WAL segments, in megabytes\n")); printf(_("\nLess commonly used options:\n")); - printf(_(" -c --cluster-key-command=COMMAND\n" - " enable cluster file encryption and set command\n" - " to obtain the cluster key\n")); printf(_(" -d, --debug generate lots of debugging output\n")); printf(_(" -k, --data-checksums use data page checksums\n")); - printf(_(" -K, --file-encryption-keylen=LENGTH\n" - " bit length of the file encryption key\n")); printf(_(" -L DIRECTORY where to find the input files\n")); printf(_(" -n, --no-clean do not clean up after errors\n")); printf(_(" -N, --no-sync do not wait for changes to be written safely to disk\n")); - printf(_(" -R, --authprompt prompt for a passphrase or PIN\n")); printf(_(" -s, --show show internal settings\n")); printf(_(" -S, --sync-only only sync data directory\n")); - printf(_(" -u, --copy-encryption-keys=DATADIR\n" - " copy the file encryption key from another cluster\n")); printf(_("\nOther options:\n")); printf(_(" -V, --version output version information, then exit\n")); printf(_(" -?, --help show this help, then exit\n")); @@ -2892,23 +2860,6 @@ initialize_data_directory(void) /* Top level PG_VERSION is checked by bootstrapper, so make it first */ write_version_file(NULL); - if (pass_terminal_fd) - { -#ifndef WIN32 - int terminal_fd = open("/dev/tty", O_RDWR, 0); -#else - int terminal_fd = open("CONOUT$", O_RDWR, 0); -#endif - - if (terminal_fd < 0) - { - pg_log_error(_("%s: could not open terminal: %s\n"), - progname, strerror(errno)); - exit(1); - } - term_fd_opt = psprintf("-R %d", terminal_fd); - } - /* Select suitable configuration settings */ set_null_conf(); test_config_settings(); @@ -2932,9 +2883,8 @@ initialize_data_directory(void) fflush(stdout); snprintf(cmd, sizeof(cmd), - "\"%s\" %s %s template1 >%s", + "\"%s\" %s template1 >%s", backend_exec, backend_options, - term_fd_opt ? term_fd_opt : "", DEVNULL); PG_CMD_OPEN; @@ -3007,11 +2957,7 @@ main(int argc, char *argv[]) {"waldir", required_argument, NULL, 'X'}, {"wal-segsize", required_argument, NULL, 12}, {"data-checksums", no_argument, NULL, 'k'}, - {"authprompt", no_argument, NULL, 'R'}, - {"file-encryption-keylen", required_argument, NULL, 'K'}, {"allow-group-access", no_argument, NULL, 'g'}, - {"cluster-key-command", required_argument, NULL, 'c'}, - {"copy-encryption-keys", required_argument, NULL, 'u'}, {NULL, 0, NULL, 0} }; @@ -3053,7 +2999,7 @@ main(int argc, char *argv[]) /* process command-line options */ - while ((c = getopt_long(argc, argv, "A:c:dD:E:gkK:L:nNRsST:u:U:WX:", long_options, &option_index)) != -1) + while ((c = getopt_long(argc, argv, "A:dD:E:gkL:nNsST:U:WX:", long_options, &option_index)) != -1) { switch (c) { @@ -3099,12 +3045,6 @@ main(int argc, char *argv[]) case 'N': do_sync = false; break; - case 'R': - pass_terminal_fd = true; - break; - case 'K': - file_encryption_keylen = atoi(optarg); - break; case 'S': sync_only = true; break; @@ -3141,12 +3081,6 @@ main(int argc, char *argv[]) case 9: pwfilename = pg_strdup(optarg); break; - case 'c': - cluster_key_cmd = pg_strdup(optarg); - break; - case 'u': - old_key_datadir = pg_strdup(optarg); - break; case 's': show_setting = true; break; @@ -3217,37 +3151,6 @@ main(int argc, char *argv[]) exit(1); } -#ifndef USE_OPENSSL - if (cluster_key_cmd) - { - pg_log_error("cluster file encryption is not supported because OpenSSL is not supported by this build"); - exit(1); - } -#endif - - if (old_key_datadir != NULL && cluster_key_cmd == NULL) - { - pg_log_error("copying encryption keys requires the cluster key command to be specified"); - exit(1); - } - - if (file_encryption_keylen != 0 && cluster_key_cmd == NULL) - { - pg_log_error("a non-zero file encryption key length requires the cluster key command to be specified"); - exit(1); - } - - if (file_encryption_keylen != 0 && file_encryption_keylen != 128 && - file_encryption_keylen != 192 && file_encryption_keylen != 256) - { - pg_log_error("invalid file encrypt key length; supported values are 0 (disabled), 128, 192, and 256"); - exit(1); - } - - /* set the default */ - if (file_encryption_keylen == 0 && cluster_key_cmd != NULL) - file_encryption_keylen = 128; - check_authmethod_unspecified(&authmethodlocal); check_authmethod_unspecified(&authmethodhost); @@ -3315,11 +3218,6 @@ main(int argc, char *argv[]) else printf(_("Data page checksums are disabled.\n")); - if (cluster_key_cmd) - printf(_("Cluster file encryption is enabled.\n")); - else - printf(_("Cluster file encryption is disabled.\n")); - if (pwprompt || pwfilename) get_su_pwd(); diff --git a/src/bin/pg_alterckey/.gitignore b/src/bin/pg_alterckey/.gitignore deleted file mode 100644 index 4c4f39f2cc..0000000000 --- a/src/bin/pg_alterckey/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/pg_alterckey diff --git a/src/bin/pg_alterckey/Makefile b/src/bin/pg_alterckey/Makefile deleted file mode 100644 index 7c465b4e29..0000000000 --- a/src/bin/pg_alterckey/Makefile +++ /dev/null @@ -1,38 +0,0 @@ -#------------------------------------------------------------------------- -# -# Makefile for src/bin/pg_alterckey -# -# Copyright (c) 1998-2020, PostgreSQL Global Development Group -# -# src/bin/pg_alterckey/Makefile -# -#------------------------------------------------------------------------- - -PGFILEDESC = "pg_alterckey - alter the cluster key" -PGAPPICON=win32 - -subdir = src/bin/pg_alterckey -top_builddir = ../../.. -include $(top_builddir)/src/Makefile.global - -OBJS = \ - $(WIN32RES) \ - pg_alterckey.o - -all: pg_alterckey - -pg_alterckey: $(OBJS) | submake-libpgport - $(CC) $(CFLAGS) $^ $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X) - -install: all installdirs - $(INSTALL_PROGRAM) pg_alterckey$(X) '$(DESTDIR)$(bindir)/pg_alterckey$(X)' - -installdirs: - $(MKDIR_P) '$(DESTDIR)$(bindir)' - -uninstall: - rm -f '$(DESTDIR)$(bindir)/pg_alterckey$(X)' - -clean distclean maintainer-clean: - rm -f pg_alterckey$(X) $(OBJS) - rm -rf tmp_check diff --git a/src/bin/pg_alterckey/pg_alterckey.c b/src/bin/pg_alterckey/pg_alterckey.c deleted file mode 100644 index 6c473e3397..0000000000 --- a/src/bin/pg_alterckey/pg_alterckey.c +++ /dev/null @@ -1,694 +0,0 @@ -/*------------------------------------------------------------------------- - * - * pg_alterckey.c - * A utility to change the cluster key (key encryption key, KEK) - * used for cluster file encryption. - * - * The theory of operation is fairly simple: - * 1. Create lock file - * 2. Retrieve current and new cluster key using the supplied - * commands. - * 3. Revert any failed alter operation. - * 4. Create a temporary directory in PGDATA - * 5. For each data encryption key in the pg_cryptokeys directory, - * decrypt it with the old cluster key and re-encrypt it - * with the new cluster key. - * 6. Make the temporary directory the new pg_cryptokeys directory. - * 7. Remove lock file - * - * - * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * src/bin/pg_alterckey/pg_alterckey.c - * - *------------------------------------------------------------------------- - */ - - -#define FRONTEND 1 - -#include "postgres_fe.h" - -#include -#include -#include - -#include "common/file_perm.h" -#include "common/file_utils.h" -#include "common/hex_decode.h" -#include "common/restricted_token.h" -#include "crypto/kmgr.h" -#include "common/logging.h" -#include "getopt_long.h" -#include "pg_getopt.h" - -typedef enum { - SUCCESS_EXIT = 0, - ERROR_EXIT, - RMDIR_EXIT, - REPAIR_EXIT -} exit_action; - -static int lock_fd = -1; -static bool pass_terminal_fd = false; -int terminal_fd = -1; -static bool repair_mode = false; -static char *old_cluster_key_cmd = NULL, - *new_cluster_key_cmd = NULL; -static char old_cluster_key[KMGR_CLUSTER_KEY_LEN], - new_cluster_key[KMGR_CLUSTER_KEY_LEN]; -static CryptoKey in_key, data_key, out_key; -static char top_path[MAXPGPATH], pid_path[MAXPGPATH], live_path[MAXPGPATH], - new_path[MAXPGPATH], old_path[MAXPGPATH]; - -static char *DataDir = NULL; -static const char *progname; - -static void create_lockfile(void); -static void recover_failure(void); -static void retrieve_cluster_keys(void); -static void bzero_keys_and_exit(exit_action action); -static void reencrypt_data_keys(void); -static void install_new_keys(void); - -static void -usage(const char *progname) -{ - printf(_("%s changes the cluster key of a PostgreSQL database cluster.\n\n"), progname); - printf(_("Usage:\n")); - printf(_(" %s [OPTION] old_cluster_key_command new_cluster_key_command [DATADIR]\n"), progname); - printf(_(" %s [repair_option] [DATADIR]\n"), progname); - printf(_("\nOptions:\n")); - printf(_(" -R, --authprompt prompt for a passphrase or PIN\n")); - printf(_(" [-D, --pgdata=]DATADIR data directory\n")); - printf(_(" -V, --version output version information, then exit\n")); - printf(_(" -?, --help show this help, then exit\n")); - printf(_("\nRepair options:\n")); - printf(_(" -r, --repair repair previous failure\n")); - printf(_("\nIf no data directory (DATADIR) is specified, " - "the environment variable PGDATA\nis used.\n\n")); - printf(_("Report bugs to <%s>.\n"), PACKAGE_BUGREPORT); - printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL); -} - - -int -main(int argc, char *argv[]) -{ - static struct option long_options1[] = { - {"authprompt", required_argument, NULL, 'R'}, - {"repair", required_argument, NULL, 'r'}, - {NULL, 0, NULL, 0} - }; - - static struct option long_options2[] = { - {"pgdata", required_argument, NULL, 'D'}, - {NULL, 0, NULL, 0} - }; - - int c; - - pg_logging_init(argv[0]); - set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_alterckey")); - progname = get_progname(argv[0]); - - if (argc > 1) - { - if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0) - { - usage(progname); - exit(0); - } - if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0) - { - puts("pg_alterckey (PostgreSQL) " PG_VERSION); - exit(0); - } - } - - /* check for -r/-R */ - while ((c = getopt_long(argc, argv, "rR", long_options1, NULL)) != -1) - { - switch (c) - { - case 'r': - repair_mode = true; - break; - - case 'R': - pass_terminal_fd = true; - break; - - default: - fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); - exit(1); - } - } - - if (!repair_mode) - { - /* get cluster key commands */ - if (optind < argc) - old_cluster_key_cmd = argv[optind++]; - else - { - pg_log_error("missing old_cluster_key_command"); - fprintf(stderr, _("Try \"%s --help\" for more information.\n"), - progname); - exit(1); - } - - if (optind < argc) - new_cluster_key_cmd = argv[optind++]; - else - { - pg_log_error("missing new_cluster_key_command"); - fprintf(stderr, _("Try \"%s --help\" for more information.\n"), - progname); - exit(1); - } - } - - /* check for datadir */ - argc -= optind; - argv += optind; - - while ((c = getopt_long(argc, argv, "D:", long_options2, NULL)) != -1) - { - switch (c) - { - case 'D': - DataDir = optarg; - break; - - default: - fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); - exit(1); - } - } - - if (DataDir == NULL) - { - if (optind < argc) - DataDir = argv[optind++]; - else - DataDir = getenv("PGDATA"); - } - - /* - * Disallow running as root because we create directories in PGDATA - */ -#ifndef WIN32 - if (geteuid() == 0) - { - pg_log_error("%s: cannot be run as root\n" - "Please log in (using, e.g., \"su\") as the " - "(unprivileged) user that will\n" - "own the server process.\n", - progname); - exit(1); - } -#endif - - get_restricted_token(); - - /* Set mask based on PGDATA permissions */ - if (!GetDataDirectoryCreatePerm(DataDir)) - { - pg_log_error("could not read permissions of directory \"%s\": %m", - DataDir); - exit(1); - } - - umask(pg_mode_mask); - - snprintf(top_path, sizeof(top_path), "%s/%s", DataDir, KMGR_DIR); - snprintf(pid_path, sizeof(pid_path), "%s/%s", DataDir, KMGR_DIR_PID); - snprintf(live_path, sizeof(live_path), "%s/%s", DataDir, LIVE_KMGR_DIR); - snprintf(new_path, sizeof(new_path), "%s/%s", DataDir, NEW_KMGR_DIR); - snprintf(old_path, sizeof(old_path), "%s/%s", DataDir, OLD_KMGR_DIR); - - /* Complain if any arguments remain */ - if (optind < argc) - { - pg_log_error("too many command-line arguments (first is \"%s\")", - argv[optind]); - fprintf(stderr, _("Try \"%s --help\" for more information.\n"), - progname); - exit(1); - } - - if (DataDir == NULL) - { - pg_log_error("no data directory specified"); - fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); - exit(1); - } - - create_lockfile(); - - recover_failure(); - - if (!repair_mode) - { - retrieve_cluster_keys(); - reencrypt_data_keys(); - install_new_keys(); - } - -#ifndef WIN32 - /* remove file system reference to file */ - if (unlink(pid_path) < 0) - { - pg_log_error("could not delete lock file \"%s\": %m", KMGR_DIR_PID); - exit(1); - } -#endif - - close (lock_fd); - - bzero_keys_and_exit(SUCCESS_EXIT); -} - -/* This prevents almost all cases of concurrent access */ -void -create_lockfile(void) -{ - struct stat buffer; - char lock_pid_str[20]; - - if (stat(top_path, &buffer) != 0 || !S_ISDIR(buffer.st_mode)) - { - pg_log_error("cluster file encryption directory \"%s\" is missing; is it enabled?", KMGR_DIR_PID); - fprintf(stderr, _("Exiting with no changes made.\n")); - exit(1); - } - - /* Does a lockfile exist? */ - if ((lock_fd = open(pid_path, O_RDONLY, 0)) != -1) - { - int lock_pid; - int len; - - /* read the PID */ - if ((len = read(lock_fd, lock_pid_str, sizeof(lock_pid_str) - 1)) == 0) - { - pg_log_error("cannot read pid from lock file \"%s\": %m", KMGR_DIR_PID); - fprintf(stderr, _("Exiting with no changes made.\n")); - exit(1); - } - lock_pid_str[len] = '\0'; - - if ((lock_pid = atoi(lock_pid_str)) == 0) - { - pg_log_error("invalid pid in lock file \"%s\": %m", KMGR_DIR_PID); - fprintf(stderr, _("Exiting with no changes made.\n")); - exit(1); - } - - /* Is the PID running? */ - if (kill(lock_pid, 0) == 0) - { - pg_log_error("active process %d currently holds a lock on this operation, recorded in \"%s\"", - lock_pid, KMGR_DIR_PID); - fprintf(stderr, _("Exiting with no changes made.\n")); - exit(1); - } - - close(lock_fd); - - if (repair_mode) - printf("old lock file removed\n"); - - /* - * pid is no longer running, so remove the lock file. - * This is not 100% safe from concurrent access, e.g.: - * - * process 1 exits and leaves stale lock file - * process 2 checks stale lock file of process 1 - * process 3 checks stale lock file of process 1 - * process 2 remove the lock file of process 1 - * process 4 creates a lock file - * process 3 remove the lock file of process 4 - * process 5 creates a lock file - * - * The sleep(2) helps with this since it reduces the likelihood - * a process that did an unlock will interfere with another unlock - * process. We could ask users to remove the lock, but that seems - * even more error-prone, especially since this might happen - * on server start. Many PG tools seem to have problems with - * concurrent access. - */ - unlink(pid_path); - - /* Sleep to reduce the likelihood of concurrent unlink */ - pg_usleep(2000000L); /* 2 seconds */ - } - - /* Create our own lockfile? */ -#ifndef WIN32 - lock_fd = open(pid_path, O_RDWR | O_CREAT | O_EXCL, pg_file_create_mode); -#else - /* delete on close */ - lock_fd = open(pid_path, O_RDWR | O_CREAT | O_EXCL | O_TEMPORARY, - pg_file_create_mode); -#endif - - if (lock_fd == -1) - { - if (errno == EEXIST) - pg_log_error("an active process currently holds a lock on this operation, recorded in \"%s\"", - KMGR_DIR_PID); - else - pg_log_error("unable to create lock file \"%s\": %m", KMGR_DIR_PID); - fprintf(stderr, _("Exiting with no changes made.\n")); - exit(1); - } - - snprintf(lock_pid_str, sizeof(lock_pid_str), "%d\n", getpid()); - if (write(lock_fd, lock_pid_str, strlen(lock_pid_str)) != strlen(lock_pid_str)) - { - pg_log_error("could not write pid to lock file \"%s\": %m", KMGR_DIR_PID); - fprintf(stderr, _("Exiting with no changes made.\n")); - exit(1); - } -} - -/* - * recover_failure - * - * A previous pg_alterckey might have failed, so it might need recovery. - * The normal operation is: - * 1. reencrypt LIVE_KMGR_DIR -> NEW_KMGR_DIR - * 2. rename KMGR_DIR -> OLD_KMGR_DIR - * 3. rename NEW_KMGR_DIR -> LIVE_KMGR_DIR - * remove OLD_KMGR_DIR - * - * There are eight possible directory configurations: - * - * LIVE_KMGR_DIR NEW_KMGR_DIR OLD_KMGR_DIR - * - * Normal: - * 0. normal X - * 1. remove new X X - * 2. install new X X - * 3. remove old X X - * - * Abnormal: - * fatal - * restore old X - * install new X - * remove old and new X X X - * - * We don't handle the abnormal cases, just report an error. - */ -static void -recover_failure(void) -{ - struct stat buffer; - bool is_live, is_new, is_old; - - is_live = !stat(live_path, &buffer); - is_new = !stat(new_path, &buffer); - is_old = !stat(old_path, &buffer); - - /* normal #0 */ - if (is_live && !is_new && !is_old) - { - if (repair_mode) - printf("repair unnecessary\n"); - return; - } - /* remove new #1 */ - else if (is_live && is_new && !is_old) - { - if (!rmtree(new_path, true)) - { - pg_log_error("unable to remove new directory \"%s\": %m", NEW_KMGR_DIR); - fprintf(stderr, _("Exiting with no changes made.\n")); - exit(1); - } - printf(_("removed files created during previously aborted alter operation\n")); - return; - } - /* install new #2 */ - else if (!is_live && is_new && is_old) - { - if (rename(new_path, live_path) != 0) - { - pg_log_error("unable to rename directory \"%s\" to \"%s\": %m", - NEW_KMGR_DIR, LIVE_KMGR_DIR); - fprintf(stderr, _("Exiting with no changes made.\n")); - exit(1); - } - printf(_("Installed new cluster password supplied in previous alter operation\n")); - return; - } - /* remove old #3 */ - else if (is_live && !is_new && is_old) - { - if (!rmtree(old_path, true)) - { - pg_log_error("unable to remove old directory \"%s\": %m", OLD_KMGR_DIR); - fprintf(stderr, _("Exiting with no changes made.\n")); - exit(1); - } - printf(_("Removed old files invalidated during previous alter operation\n")); - return; - } - else - { - pg_log_error("cluster file encryption directory \"%s\" is in an abnormal state and cannot be processed", - KMGR_DIR); - fprintf(stderr, _("Exiting with no changes made.\n")); - exit(1); - } -} - -/* Retrieve old and new cluster keys */ -void -retrieve_cluster_keys() -{ - int cluster_key_len; - char cluster_key_hex[ALLOC_KMGR_CLUSTER_KEY_LEN]; - - /* - * If we have been asked to pass an open file descriptor to the user - * terminal to the commands, set one up. - */ - if (pass_terminal_fd) - { -#ifndef WIN32 - terminal_fd = open("/dev/tty", O_RDWR, 0); -#else - terminal_fd = open("CONOUT$", O_RDWR, 0); -#endif - if (terminal_fd < 0) - { - pg_log_error(_("%s: could not open terminal: %s\n"), - progname, strerror(errno)); - exit(1); - } - } - - /* Get old key encryption key from the cluster key command */ - cluster_key_len = kmgr_run_cluster_key_command(old_cluster_key_cmd, - (char *) cluster_key_hex, - ALLOC_KMGR_CLUSTER_KEY_LEN, - live_path); - if (hex_decode(cluster_key_hex, cluster_key_len, (char *) old_cluster_key) != - KMGR_CLUSTER_KEY_LEN) - { - pg_log_error("cluster key must be at %d hex bytes", KMGR_CLUSTER_KEY_LEN); - bzero_keys_and_exit(ERROR_EXIT); - } - - /* - * Create new key directory here in case the new cluster key command needs it - * to exist. - */ - if (mkdir(new_path, pg_dir_create_mode) != 0) - { - pg_log_error("unable to create new cluster key directory \"%s\": %m", NEW_KMGR_DIR); - bzero_keys_and_exit(ERROR_EXIT); - } - - /* Get new key */ - cluster_key_len = kmgr_run_cluster_key_command(new_cluster_key_cmd, - (char *) cluster_key_hex, - ALLOC_KMGR_CLUSTER_KEY_LEN, - live_path); - if (hex_decode(cluster_key_hex, cluster_key_len, (char *) new_cluster_key) != - KMGR_CLUSTER_KEY_LEN) - { - pg_log_error("cluster key must be at %d hex bytes", KMGR_CLUSTER_KEY_LEN); - bzero_keys_and_exit(ERROR_EXIT); - } - - if (pass_terminal_fd) - close(terminal_fd); - - /* output newline */ - puts(""); - - if (strcmp(old_cluster_key, new_cluster_key) == 0) - { - pg_log_error("cluster keys are identical, exiting\n"); - bzero_keys_and_exit(RMDIR_EXIT); - } - -} - -/* Decrypt old keys encrypted with old pass phrase and reencrypt with new one */ -void -reencrypt_data_keys(void) -{ - DIR *dir; - struct dirent *de; - PgCipherCtx *old_ctx, *new_ctx; - - if ((dir = opendir(live_path)) == NULL) - { - pg_log_error("unable to open live cluster key directory \"%s\": %m", LIVE_KMGR_DIR); - bzero_keys_and_exit(RMDIR_EXIT); - } - - old_ctx = pg_cipher_ctx_create(PG_CIPHER_AES_GCM, - (unsigned char *)old_cluster_key, - KMGR_CLUSTER_KEY_LEN, true); - if (!old_ctx) - pg_log_error("could not initialize encryption context"); - - new_ctx = pg_cipher_ctx_create(PG_CIPHER_AES_GCM, - (unsigned char *)new_cluster_key, - KMGR_CLUSTER_KEY_LEN, true); - if (!new_ctx) - pg_log_error("could not initialize encryption context"); - - while ((de = readdir(dir)) != NULL) - { - /* - * We copy only the numeric files/keys, since there might be encrypted - * cluster key files in the old directory that only match the old key. - */ - if (strspn(de->d_name, "0123456789") == strlen(de->d_name)) - { - char src_path[MAXPGPATH], dst_path[MAXPGPATH]; - int src_fd, dst_fd; - int len; - uint32 id = strtoul(de->d_name, NULL, 10); - - CryptoKeyFilePath(src_path, live_path, id); - CryptoKeyFilePath(dst_path, new_path, id); - - if ((src_fd = open(src_path, O_RDONLY | PG_BINARY, 0)) < 0) - { - pg_log_error("could not open file \"%s\": %m", src_path); - bzero_keys_and_exit(RMDIR_EXIT); - } - - if ((dst_fd = open(dst_path, O_RDWR | O_CREAT | O_TRUNC | PG_BINARY, - pg_file_create_mode)) < 0) - { - pg_log_error("could not open file \"%s\": %m", dst_path); - bzero_keys_and_exit(RMDIR_EXIT); - } - - /* Read the source key */ - len = read(src_fd, &in_key, sizeof(CryptoKey)); - if (len != sizeof(CryptoKey)) - { - if (len < 0) - pg_log_error("could read file \"%s\": %m", src_path); - else - pg_log_error("could read file \"%s\": read %d of %zu", - src_path, len, sizeof(CryptoKey)); - bzero_keys_and_exit(RMDIR_EXIT); - } - - /* decrypt with old key */ - if (!kmgr_unwrap_key(old_ctx, &in_key, &data_key)) - { - pg_log_error("incorrect old key specified"); - bzero_keys_and_exit(RMDIR_EXIT); - } - - /* encrypt with new key */ - if (!kmgr_wrap_key(new_ctx, &data_key, &out_key)) - { - pg_log_error("could not encrypt new key"); - bzero_keys_and_exit(RMDIR_EXIT); - } - - /* Write to the dest key */ - len = write(dst_fd, &out_key, sizeof(CryptoKey)); - if (len != sizeof(CryptoKey)) - { - pg_log_error("could not write fie \"%s\"", dst_path); - bzero_keys_and_exit(RMDIR_EXIT); - } - - close(src_fd); - close(dst_fd); - } - } - - /* The cluster key is correct, free the cipher context */ - pg_cipher_ctx_free(old_ctx); - pg_cipher_ctx_free(new_ctx); - - closedir(dir); -} - -void -install_new_keys(void) -{ - /* add fsyncs? XXX */ - if (rename(live_path, old_path) != 0) - { - pg_log_error("unable to rename directory \"%s\" to \"%s\": %m", - LIVE_KMGR_DIR, OLD_KMGR_DIR); - bzero_keys_and_exit(RMDIR_EXIT); - } - - if (rename(new_path, live_path) != 0) - { - pg_log_error("unable to rename directory \"%s\" to \"%s\": %m", - NEW_KMGR_DIR, LIVE_KMGR_DIR); - bzero_keys_and_exit(REPAIR_EXIT); - } - - if (!rmtree(old_path, true)) - { - pg_log_error("unable to remove old directory \"%s\": %m", OLD_KMGR_DIR); - bzero_keys_and_exit(REPAIR_EXIT); - } -} - -void -bzero_keys_and_exit(exit_action action) -{ - explicit_bzero(old_cluster_key, sizeof(old_cluster_key)); - explicit_bzero(new_cluster_key, sizeof(new_cluster_key)); - - explicit_bzero(&in_key, sizeof(in_key)); - explicit_bzero(&data_key, sizeof(data_key)); - explicit_bzero(&out_key, sizeof(out_key)); - - if (action == RMDIR_EXIT) - { - if (!rmtree(new_path, true)) - pg_log_error("unable to remove new directory \"%s\": %m", NEW_KMGR_DIR); - printf("Re-running pg_alterckey to repair might be needed before the next server start\n"); - exit(1); - } - else if (action == REPAIR_EXIT) - { - unlink(pid_path); - printf("Re-running pg_alterckey to repair might be needed before the next server start\n"); - } - - /* return 0 or 1 */ - exit(action != SUCCESS_EXIT); -} diff --git a/src/bin/pg_controldata/pg_controldata.c b/src/bin/pg_controldata/pg_controldata.c index c3b38b7c51..3e00ac0f70 100644 --- a/src/bin/pg_controldata/pg_controldata.c +++ b/src/bin/pg_controldata/pg_controldata.c @@ -25,7 +25,6 @@ #include "access/xlog_internal.h" #include "catalog/pg_control.h" #include "common/controldata_utils.h" -#include "common/kmgr_utils.h" #include "common/logging.h" #include "getopt_long.h" #include "pg_getopt.h" @@ -335,7 +334,5 @@ main(int argc, char *argv[]) ControlFile->data_checksum_version); printf(_("Mock authentication nonce: %s\n"), mock_auth_nonce_str); - printf(_("File encryption key length: %d\n"), - ControlFile->file_encryption_keylen); return 0; } diff --git a/src/bin/pg_ctl/pg_ctl.c b/src/bin/pg_ctl/pg_ctl.c index 5fa1f72ae1..fc07f1aba6 100644 --- a/src/bin/pg_ctl/pg_ctl.c +++ b/src/bin/pg_ctl/pg_ctl.c @@ -79,7 +79,6 @@ typedef enum static bool do_wait = true; static int wait_seconds = DEFAULT_WAIT; static bool wait_seconds_arg = false; -static bool pass_terminal_fd = false; static bool silent_mode = false; static ShutdownMode shutdown_mode = FAST_MODE; static int sig = SIGINT; /* default */ @@ -443,7 +442,7 @@ free_readfile(char **optlines) static pgpid_t start_postmaster(void) { - char cmd[MAXPGPATH], *term_fd_opt = NULL; + char cmd[MAXPGPATH]; #ifndef WIN32 pgpid_t pm_pid; @@ -468,19 +467,6 @@ start_postmaster(void) /* fork succeeded, in child */ - if (pass_terminal_fd) - { - int terminal_fd = open("/dev/tty", O_RDWR, 0); - - if (terminal_fd < 0) - { - write_stderr(_("%s: could not open terminal: %s\n"), - progname, strerror(errno)); - exit(1); - } - term_fd_opt = psprintf(" -R %d", terminal_fd); - } - /* * If possible, detach the postmaster process from the launching process * group and make it a group leader, so that it doesn't get signaled along @@ -501,14 +487,12 @@ start_postmaster(void) * has the same PID as the current child process. */ if (log_file != NULL) - snprintf(cmd, MAXPGPATH, "exec \"%s\" %s%s%s < \"%s\" >> \"%s\" 2>&1", + snprintf(cmd, MAXPGPATH, "exec \"%s\" %s%s < \"%s\" >> \"%s\" 2>&1", exec_path, pgdata_opt, post_opts, - term_fd_opt ? term_fd_opt : "", DEVNULL, log_file); else - snprintf(cmd, MAXPGPATH, "exec \"%s\" %s%s%s < \"%s\" 2>&1", - exec_path, pgdata_opt, post_opts, - term_fd_opt ? term_fd_opt : "", DEVNULL); + snprintf(cmd, MAXPGPATH, "exec \"%s\" %s%s < \"%s\" 2>&1", + exec_path, pgdata_opt, post_opts, DEVNULL); (void) execl("/bin/sh", "/bin/sh", "-c", cmd, (char *) NULL); @@ -529,21 +513,6 @@ start_postmaster(void) PROCESS_INFORMATION pi; const char *comspec; - if (pass_terminal_fd) - { - /* Hopefully we can read and write CONOUT, see simple_prompt() XXX */ - /* Do CreateRestrictedProcess() children even inherit open file descriptors? XXX */ - int terminal_fd = open("CONOUT$", O_RDWR, 0); - - if (terminal_fd < 0) - { - write_stderr(_("%s: could not open terminal: %s\n"), - progname, strerror(errno)); - exit(1); - } - term_fd_opt = psprintf(" -R %d", terminal_fd); - } - /* Find CMD.EXE location using COMSPEC, if it's set */ comspec = getenv("COMSPEC"); if (comspec == NULL) @@ -584,14 +553,12 @@ start_postmaster(void) else close(fd); - snprintf(cmd, MAXPGPATH, "\"%s\" /C \"\"%s\" %s%s%s < \"%s\" >> \"%s\" 2>&1\"", - comspec, exec_path, pgdata_opt, post_opts, - term_fd_opt ? term_fd_opt : "", DEVNULL, log_file); + snprintf(cmd, MAXPGPATH, "\"%s\" /C \"\"%s\" %s%s < \"%s\" >> \"%s\" 2>&1\"", + comspec, exec_path, pgdata_opt, post_opts, DEVNULL, log_file); } else - snprintf(cmd, MAXPGPATH, "\"%s\" /C \"\"%s\" %s%s%s < \"%s\" 2>&1\"", - comspec, exec_path, pgdata_opt, post_opts, - term_fd_opt ? term_fd_opt : "", DEVNULL); + snprintf(cmd, MAXPGPATH, "\"%s\" /C \"\"%s\" %s%s < \"%s\" 2>&1\"", + comspec, exec_path, pgdata_opt, post_opts, DEVNULL); if (!CreateRestrictedProcess(cmd, &pi, false)) { @@ -722,8 +689,7 @@ wait_for_postmaster(pgpid_t pm_pid, bool do_checkpoint) } else #endif - if (!pass_terminal_fd) - print_msg("."); + print_msg("."); } pg_usleep(USEC_PER_SEC / WAITS_PER_SEC); @@ -2100,7 +2066,6 @@ do_help(void) printf(_(" -o, --options=OPTIONS command line options to pass to postgres\n" " (PostgreSQL server executable) or initdb\n")); printf(_(" -p PATH-TO-POSTGRES normally not necessary\n")); - printf(_(" -R, --authprompt prompt for a paasphrase or PIN\n")); printf(_("\nOptions for stop or restart:\n")); printf(_(" -m, --mode=MODE MODE can be \"smart\", \"fast\", or \"immediate\"\n")); @@ -2295,7 +2260,6 @@ main(int argc, char **argv) {"mode", required_argument, NULL, 'm'}, {"pgdata", required_argument, NULL, 'D'}, {"options", required_argument, NULL, 'o'}, - {"authprompt", no_argument, NULL, 'R'}, {"silent", no_argument, NULL, 's'}, {"timeout", required_argument, NULL, 't'}, {"core-files", no_argument, NULL, 'c'}, @@ -2368,7 +2332,7 @@ main(int argc, char **argv) /* process command-line options */ while (optind < argc) { - while ((c = getopt_long(argc, argv, "cD:e:l:m:N:o:p:P:RsS:t:U:wW", + while ((c = getopt_long(argc, argv, "cD:e:l:m:N:o:p:P:sS:t:U:wW", long_options, &option_index)) != -1) { switch (c) @@ -2421,9 +2385,6 @@ main(int argc, char **argv) case 'P': register_password = pg_strdup(optarg); break; - case 'R': - pass_terminal_fd = true; - break; case 's': silent_mode = true; break; diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c index 8f928b3129..cb6ef19182 100644 --- a/src/bin/pg_resetwal/pg_resetwal.c +++ b/src/bin/pg_resetwal/pg_resetwal.c @@ -804,8 +804,6 @@ PrintControlValues(bool guessed) (ControlFile.float8ByVal ? _("by value") : _("by reference"))); printf(_("Data page checksum version: %u\n"), ControlFile.data_checksum_version); - printf(_("File encryption key length: %d\n"), - ControlFile.file_encryption_keylen); } diff --git a/src/bin/pg_rewind/filemap.c b/src/bin/pg_rewind/filemap.c index b8775cab15..ba34dbac14 100644 --- a/src/bin/pg_rewind/filemap.c +++ b/src/bin/pg_rewind/filemap.c @@ -28,7 +28,6 @@ #include "catalog/pg_tablespace_d.h" #include "common/hashfn.h" -#include "common/kmgr_utils.h" #include "common/string.h" #include "datapagemap.h" #include "filemap.h" @@ -108,13 +107,6 @@ static const char *excludeDirContents[] = /* Contents removed on startup, see AsyncShmemInit(). */ "pg_notify", - /* - * Skip cryptographic keys. It's generally not a good idea to copy the - * cryptographic keys from source database because these might use - * different cluster key. - */ - KMGR_DIR, - /* * Old contents are loaded for possible debugging but are not required for * normal operation, see SerialInit(). diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index ef091cb3e4..f3afea9d56 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -10,7 +10,6 @@ #include "postgres_fe.h" #include "catalog/pg_authid_d.h" -#include "common/kmgr_utils.h" #include "fe_utils/string_utils.h" #include "mb/pg_wchar.h" #include "pg_upgrade.h" @@ -28,7 +27,6 @@ static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_reg_data_type_usage(ClusterInfo *cluster); static void check_for_jsonb_9_4_usage(ClusterInfo *cluster); static void check_for_pg_role_prefix(ClusterInfo *cluster); -static void check_for_cluster_key_failure(ClusterInfo *cluster); static void check_for_new_tablespace_dir(ClusterInfo *new_cluster); static char *get_canonical_locale_name(int category, const char *locale); @@ -141,9 +139,6 @@ check_and_dump_old_cluster(bool live_check) if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) check_for_pg_role_prefix(&old_cluster); - if (GET_MAJOR_VERSION(old_cluster.major_version) >= 1400) - check_for_cluster_key_failure(&old_cluster); - if (GET_MAJOR_VERSION(old_cluster.major_version) == 904 && old_cluster.controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) check_for_jsonb_9_4_usage(&old_cluster); @@ -178,9 +173,6 @@ check_new_cluster(void) check_loadable_libraries(); - if (GET_MAJOR_VERSION(old_cluster.major_version) >= 1400) - check_for_cluster_key_failure(&new_cluster); - switch (user_opts.transfer_mode) { case TRANSFER_MODE_CLONE: @@ -1277,32 +1269,6 @@ check_for_pg_role_prefix(ClusterInfo *cluster) } -/* - * check_for_cluster_key_failure() - * - * Make sure there was no unrepaired pg_alterckey failure - */ -static void -check_for_cluster_key_failure(ClusterInfo *cluster) -{ - struct stat buffer; - - if (stat (KMGR_DIR_PID, &buffer) == 0) - { - if (cluster == &old_cluster) - pg_fatal("The source cluster had a pg_alterckey failure that needs repair or\n" - "pg_alterckey is running. Run pg_alterckey --repair or wait for it\n" - "to complete.\n"); - else - pg_fatal("The target cluster had a pg_alterckey failure that needs repair or\n" - "pg_alterckey is running. Run pg_alterckey --repair or wait for it\n" - "to complete.\n"); - } - - check_ok(); -} - - /* * get_canonical_locale_name * diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index a0aa995bbd..39bcaa8fe1 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -9,16 +9,10 @@ #include "postgres_fe.h" -#include #include #include "pg_upgrade.h" -#include "access/xlog_internal.h" -#include "common/controldata_utils.h" -#include "common/file_utils.h" -#include "common/kmgr_utils.h" - /* * get_control_data() * @@ -65,7 +59,6 @@ get_control_data(ClusterInfo *cluster, bool live_check) bool got_date_is_int = false; bool got_data_checksum_version = false; bool got_cluster_state = false; - int got_file_encryption_keylen = 0; char *lc_collate = NULL; char *lc_ctype = NULL; char *lc_monetary = NULL; @@ -209,13 +202,6 @@ get_control_data(ClusterInfo *cluster, bool live_check) got_data_checksum_version = true; } - /* Only in <= 14 */ - if (GET_MAJOR_VERSION(cluster->major_version) <= 1400) - { - cluster->controldata.file_encryption_keylen = 0; - got_file_encryption_keylen = true; - } - /* we have the result of cmd in "output". so parse it line by line now */ while (fgets(bufin, sizeof(bufin), output)) { @@ -499,18 +485,6 @@ get_control_data(ClusterInfo *cluster, bool live_check) cluster->controldata.data_checksum_version = str2uint(p); got_data_checksum_version = true; } - else if ((p = strstr(bufin, "File encryption key length:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem\n", __LINE__); - - p++; /* remove ':' char */ - /* used later for contrib check */ - cluster->controldata.file_encryption_keylen = atoi(p); - got_file_encryption_keylen = true; - } } pclose(output); @@ -565,8 +539,7 @@ get_control_data(ClusterInfo *cluster, bool live_check) !got_index || !got_toast || (!got_large_object && cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || - !got_date_is_int || !got_data_checksum_version || - !got_file_encryption_keylen) + !got_date_is_int || !got_data_checksum_version) { if (cluster == &old_cluster) pg_log(PG_REPORT, @@ -632,10 +605,6 @@ get_control_data(ClusterInfo *cluster, bool live_check) if (!got_data_checksum_version) pg_log(PG_REPORT, " data checksum version\n"); - /* value added in Postgres 14 */ - if (!got_file_encryption_keylen) - pg_log(PG_REPORT, " file encryption key length\n"); - pg_fatal("Cannot continue without required control information, terminating\n"); } } @@ -700,15 +669,6 @@ check_control_data(ControlData *oldctrl, pg_fatal("old cluster uses data checksums but the new one does not\n"); else if (oldctrl->data_checksum_version != newctrl->data_checksum_version) pg_fatal("old and new cluster pg_controldata checksum versions do not match\n"); - - /* - * We cannot upgrade if the old cluster file encryption key length - * doesn't match the new one. - - */ - if (oldctrl->file_encryption_keylen != newctrl->file_encryption_keylen) - pg_fatal("old and new clusters use different file encryption key lengths or\n" - "one cluster uses encryption and the other does not"); } diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index c9851192ec..cc8a675d00 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -11,7 +11,6 @@ #include #include -#include #ifdef HAVE_COPYFILE_H #include #endif @@ -22,7 +21,6 @@ #include "access/visibilitymap.h" #include "common/file_perm.h" -#include "common/file_utils.h" #include "pg_upgrade.h" #include "storage/bufpage.h" #include "storage/checksum.h" diff --git a/src/bin/pg_upgrade/option.c b/src/bin/pg_upgrade/option.c index 4702998352..548d648e8c 100644 --- a/src/bin/pg_upgrade/option.c +++ b/src/bin/pg_upgrade/option.c @@ -52,7 +52,6 @@ parseCommandLine(int argc, char *argv[]) {"check", no_argument, NULL, 'c'}, {"link", no_argument, NULL, 'k'}, {"retain", no_argument, NULL, 'r'}, - {"authprompt", no_argument, NULL, 'R'}, {"jobs", required_argument, NULL, 'j'}, {"socketdir", required_argument, NULL, 's'}, {"verbose", no_argument, NULL, 'v'}, @@ -103,7 +102,7 @@ parseCommandLine(int argc, char *argv[]) if (os_user_effective_id == 0) pg_fatal("%s: cannot be run as root\n", os_info.progname); - while ((option = getopt_long(argc, argv, "d:D:b:B:cj:ko:O:p:P:rRs:U:v", + while ((option = getopt_long(argc, argv, "d:D:b:B:cj:ko:O:p:P:rs:U:v", long_options, &optindex)) != -1) { switch (option) @@ -181,10 +180,6 @@ parseCommandLine(int argc, char *argv[]) log_opts.retain = true; break; - case 'R': - user_opts.pass_terminal_fd = true; - break; - case 's': user_opts.socketdir = pg_strdup(optarg); break; diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index 53ce195963..ee70243c2e 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -11,7 +11,6 @@ #include #include "libpq-fe.h" -#include "common/kmgr_utils.h" /* Use port in the private/dynamic port number range */ #define DEF_PGUPORT 50432 @@ -220,7 +219,6 @@ typedef struct bool date_is_int; bool float8_pass_by_value; bool data_checksum_version; - int file_encryption_keylen; } ControlData; /* @@ -295,7 +293,6 @@ typedef struct int jobs; /* number of processes/threads to use */ char *socketdir; /* directory to use for Unix sockets */ bool ind_coll_unknown; /* mark unknown index collation versions */ - bool pass_terminal_fd; /* pass -R to pg_ctl? */ } UserOpts; typedef struct diff --git a/src/bin/pg_upgrade/server.c b/src/bin/pg_upgrade/server.c index 9208ad0d8a..713509f540 100644 --- a/src/bin/pg_upgrade/server.c +++ b/src/bin/pg_upgrade/server.c @@ -244,9 +244,8 @@ start_postmaster(ClusterInfo *cluster, bool report_and_exit_on_error) * vacuumdb --freeze actually freezes the tuples. */ snprintf(cmd, sizeof(cmd), - "\"%s/pg_ctl\" -w%s -l \"%s\" -D \"%s\" -o \"-p %d%s%s %s%s\" start", - cluster->bindir, user_opts.pass_terminal_fd ? " -R" : "", - SERVER_LOG_FILE, cluster->pgconfig, cluster->port, + "\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" -o \"-p %d%s%s %s%s\" start", + cluster->bindir, SERVER_LOG_FILE, cluster->pgconfig, cluster->port, (cluster->controldata.cat_ver >= BINARY_UPGRADE_SERVER_FLAG_CAT_VER) ? " -b" : " -c autovacuum=off -c autovacuum_freeze_max_age=2000000000", diff --git a/src/common/Makefile b/src/common/Makefile index 85d1388a64..f624977939 100644 --- a/src/common/Makefile +++ b/src/common/Makefile @@ -62,7 +62,6 @@ OBJS_COMMON = \ ip.o \ jsonapi.o \ keywords.o \ - kmgr_utils.o \ kwlookup.o \ link-canary.o \ md5_common.o \ @@ -83,12 +82,10 @@ OBJS_COMMON = \ ifeq ($(with_openssl),yes) OBJS_COMMON += \ - cipher_openssl.o \ protocol_openssl.o \ cryptohash_openssl.o else OBJS_COMMON += \ - cipher.o \ cryptohash.o \ md5.o \ sha2.o diff --git a/src/common/cipher.c b/src/common/cipher.c deleted file mode 100644 index 483cb610a3..0000000000 --- a/src/common/cipher.c +++ /dev/null @@ -1,70 +0,0 @@ -/*------------------------------------------------------------------------- - * - * cipher.c - * Shared frontend/backend for cryptographic functions - * - * Copyright (c) 2020, PostgreSQL Global Development Group - * - * IDENTIFICATION - * src/common/cipher.c - * - *------------------------------------------------------------------------- - */ - -#ifndef FRONTEND -#include "postgres.h" -#else -#include "postgres_fe.h" -#endif - -#include "common/cipher.h" - -static void cipher_failure(void) pg_attribute_noreturn(); - - -PgCipherCtx * -pg_cipher_ctx_create(int cipher, uint8 *key, int klen, bool enc) -{ - cipher_failure(); - return NULL; /* keep compiler quiet */ -} - -void -pg_cipher_ctx_free(PgCipherCtx *ctx) -{ - cipher_failure(); -} - -bool -pg_cipher_encrypt(PgCipherCtx *ctx, const unsigned char *plaintext, - const int inlen, unsigned char *ciphertext, int *outlen, - const unsigned char *iv, const int ivlen, - unsigned char *outtag, const int taglen) -{ - cipher_failure(); - return false; /* keep compiler quiet */ -} - -bool -pg_cipher_decrypt(PgCipherCtx *ctx, const unsigned char *ciphertext, - const int inlen, unsigned char *plaintext, int *outlen, - const unsigned char *iv, const int ivlen, - unsigned char *intag, const int taglen) -{ - cipher_failure(); - return false; /* keep compiler quiet */ -} - -static void -cipher_failure(void) -{ -#ifndef FRONTEND - ereport(ERROR, - (errcode(ERRCODE_CONFIG_FILE_ERROR), - (errmsg("cluster file encryption is not supported because OpenSSL is not supported by this build"), - errhint("Compile with --with-openssl to use this feature.")))); -#else - fprintf(stderr, _("cluster file encryption is not supported because OpenSSL is not supported by this build")); - exit(1); -#endif -} diff --git a/src/common/cipher_openssl.c b/src/common/cipher_openssl.c deleted file mode 100644 index e7a1dc7ad9..0000000000 --- a/src/common/cipher_openssl.c +++ /dev/null @@ -1,268 +0,0 @@ -/*------------------------------------------------------------------------- - * cipher_openssl.c - * Cryptographic function using OpenSSL - * - * This contains the common low-level functions needed in both frontend and - * backend, for implement the database encryption. - * - * Portions Copyright (c) 2020, PostgreSQL Global Development Group - * - * IDENTIFICATION - * src/common/cipher_openssl.c - * - *------------------------------------------------------------------------- - */ -#ifndef FRONTEND -#include "postgres.h" -#else -#include "postgres_fe.h" -#endif - -#include "common/cipher.h" -#include -#include -#include -#include - -/* - * prototype for the EVP functions that return an algorithm, e.g. - * EVP_aes_128_gcm(). - */ -typedef const EVP_CIPHER *(*ossl_EVP_cipher_func) (void); - -static ossl_EVP_cipher_func get_evp_aes_gcm(int klen); -static EVP_CIPHER_CTX *ossl_cipher_ctx_create(int cipher, uint8 *key, int klen, - bool enc); - -/* - * Return a newly created cipher context. 'cipher' specifies cipher algorithm - * by identifer like PG_CIPHER_XXX. - */ -PgCipherCtx * -pg_cipher_ctx_create(int cipher, uint8 *key, int klen, bool enc) -{ - PgCipherCtx *ctx = NULL; - - if (cipher >= PG_MAX_CIPHER_ID) - return NULL; - - ctx = ossl_cipher_ctx_create(cipher, key, klen, enc); - - return ctx; -} - -void -pg_cipher_ctx_free(PgCipherCtx *ctx) -{ - EVP_CIPHER_CTX_free(ctx); -} - -/* - * Encryption routine to encrypt data provided. - * - * ctx is the encryption context which must have been created previously. - * - * plaintext is the data we are going to encrypt - * inlen is the length of the data to encrypt - * - * ciphertext is the encrypted result - * outlen is the encrypted length - * - * iv is the IV to use. - * ivlen is the IV length to use. - * - * outtag is the resulting tag. - * taglen is the length of the tag. - */ -bool -pg_cipher_encrypt(PgCipherCtx *ctx, - const unsigned char *plaintext, const int inlen, - unsigned char *ciphertext, int *outlen, - const unsigned char *iv, const int ivlen, - unsigned char *outtag, const int taglen) -{ - int len; - int enclen; - - Assert(ctx != NULL); - - /* - * Here we are setting the IV for the context which was passed - * in. Note that we signal to OpenSSL that we are configuring - * a new value for the context by passing in 'NULL' for the - * 2nd ('type') parameter. - */ - - /* Set the IV length first */ - if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, ivlen, NULL)) - return false; - - /* Set the IV for this encryption. */ - if (!EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv)) - return false; - - /* - * This is the function which is actually performing the - * encryption for us. - */ - if (!EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, inlen)) - return false; - - enclen = len; - - /* Finalize the encryption, which could add more to output. */ - if (!EVP_EncryptFinal_ex(ctx, ciphertext + enclen, &len)) - return false; - - *outlen = enclen + len; - - /* - * Once all of the encryption has been completed we grab - * the tag. - */ - if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, taglen, outtag)) - return false; - - return true; -} -/* - * Decryption routine - * - * ctx is the encryption context which must have been created previously. - * - * ciphertext is the data we are going to decrypt - * inlen is the length of the data to decrypt - * - * plaintext is the decrypted result - * outlen is the decrypted length - * - * iv is the IV to use. - * ivlen is the length of the IV. - * - * intag is the tag to use to verify. - * taglen is the length of the tag. - */ -bool -pg_cipher_decrypt(PgCipherCtx *ctx, - const unsigned char *ciphertext, const int inlen, - unsigned char *plaintext, int *outlen, - const unsigned char *iv, const int ivlen, - unsigned char *intag, const int taglen) -{ - int declen; - int len; - - /* - * Here we are setting the IV for the context which was passed - * in. Note that we signal to OpenSSL that we are configuring - * a new value for the context by passing in 'NULL' for the - * 2nd ('type') parameter. - */ - - /* Set the IV length first */ - if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, ivlen, NULL)) - return false; - - /* Set the IV for this decryption. */ - if (!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv)) - return false; - - /* - * This is the function which is actually performing the - * decryption for us. - */ - if (!EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, inlen)) - return false; - - declen = len; - - /* Set the expected tag value. */ - if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, taglen, intag)) - return false; - - /* - * Finalize the decryption, which could add more to output, - * this is also the step which checks the tag and we MUST - * fail if this indicates an invalid tag! - */ - if (!EVP_DecryptFinal_ex(ctx, plaintext + declen, &len)) - return false; - - *outlen = declen + len; - - return true; -} - -/* - * Returns the correct cipher functions for OpenSSL based - * on the key length requested. - */ -static ossl_EVP_cipher_func -get_evp_aes_gcm(int klen) -{ - switch (klen) - { - case PG_AES128_KEY_LEN: - return EVP_aes_128_gcm; - case PG_AES192_KEY_LEN: - return EVP_aes_192_gcm; - case PG_AES256_KEY_LEN: - return EVP_aes_256_gcm; - default: - return NULL; - } -} - -/* - * Initialize and return an EVP_CIPHER_CTX. Returns NULL if the given - * cipher algorithm is not supported or on failure. - */ -static EVP_CIPHER_CTX * -ossl_cipher_ctx_create(int cipher, uint8 *key, int klen, bool enc) -{ - EVP_CIPHER_CTX *ctx; - ossl_EVP_cipher_func func; - int ret; - - ctx = EVP_CIPHER_CTX_new(); - - /* - * We currently only support AES GCM but others could be - * added in the future. - */ - switch (cipher) - { - case PG_CIPHER_AES_GCM: - func = get_evp_aes_gcm(klen); - if (!func) - goto failed; - break; - default: - goto failed; - } - - /* - * We create the context here based on the cipher requested and the provided - * key. Note that the IV will be provided in the actual encryption call - * through another EVP_EncryptInit_ex call- this is fine as long as 'type' - * is passed in as NULL! - */ - if (enc) - ret = EVP_EncryptInit_ex(ctx, (const EVP_CIPHER *) func(), NULL, key, NULL); - else - ret = EVP_DecryptInit_ex(ctx, (const EVP_CIPHER *) func(), NULL, key, NULL); - - if (!ret) - goto failed; - - /* Set the key length based on the key length requested. */ - if (!EVP_CIPHER_CTX_set_key_length(ctx, klen)) - goto failed; - - return ctx; - -failed: - EVP_CIPHER_CTX_free(ctx); - return NULL; -} - diff --git a/src/common/kmgr_utils.c b/src/common/kmgr_utils.c deleted file mode 100644 index f499e2525e..0000000000 --- a/src/common/kmgr_utils.c +++ /dev/null @@ -1,507 +0,0 @@ -/*------------------------------------------------------------------------- - * - * kmgr_utils.c - * Shared frontend/backend for cluster file encryption - * - * Copyright (c) 2020, PostgreSQL Global Development Group - * - * IDENTIFICATION - * src/common/kmgr_utils.c - * - *------------------------------------------------------------------------- - */ - -#ifndef FRONTEND -#include "postgres.h" -#else -#include "postgres_fe.h" -#endif - -#include -#include - -#ifdef FRONTEND -#include "common/logging.h" -#endif -#include "common/cryptohash.h" -#include "common/file_perm.h" -#include "common/kmgr_utils.h" -#include "common/hex_decode.h" -#include "common/string.h" -#include "crypto/kmgr.h" -#include "lib/stringinfo.h" -#include "postmaster/postmaster.h" -#include "storage/fd.h" - -#ifndef FRONTEND -#include "pgstat.h" -#include "storage/fd.h" -#endif - -#define KMGR_PROMPT_MSG "Enter authentication needed to generate the cluster key: " - -#ifdef FRONTEND -static FILE *open_pipe_stream(const char *command); -static int close_pipe_stream(FILE *file); -#endif - -static void read_one_keyfile(const char *dataDir, uint32 id, CryptoKey *key_p); - -/* - * Encrypt the given data. Return true and set encrypted data to 'out' if - * success. Otherwise return false. The caller must allocate sufficient space - * for cipher data calculated by using KmgrSizeOfCipherText(). Please note that - * this function modifies 'out' data even on failure case. - */ -bool -kmgr_wrap_key(PgCipherCtx *ctx, CryptoKey *in, CryptoKey *out) -{ - int len, enclen; - unsigned char iv[sizeof(in->pgkey_id) + sizeof(in->counter)]; - - Assert(ctx && in && out); - - /* Get the actual length of the key we are wrapping */ - memcpy(&len, in->encrypted_key, sizeof(len)); - - /* Key ID remains the same */ - out->pgkey_id = in->pgkey_id; - - /* Increment the counter */ - out->counter = in->counter + 1; - - /* Construct the IV we are going to use, see kmgr_utils.h */ - memcpy(iv, &out->pgkey_id, sizeof(out->pgkey_id)); - memcpy(iv + sizeof(out->pgkey_id), &out->counter, sizeof(out->counter)); - - if (!pg_cipher_encrypt(ctx, - in->encrypted_key, /* Plaintext source, key length + key */ - sizeof(in->encrypted_key), /* Full data length */ - out->encrypted_key, /* Ciphertext result */ - &enclen, /* Resulting length, must match input for us */ - iv, /* Generated IV from above */ - sizeof(iv), /* Length of the IV */ - out->tag, /* Resulting tag */ - sizeof(out->tag))) /* Length of our tag */ - return false; - - Assert(enclen == sizeof(in->encrypted_key)); - - return true; -} - -/* - * Decrypt the given Data. Return true and set plain text data to `out` if - * success. Otherwise return false. The caller must allocate sufficient space - * for cipher data calculated by using KmgrSizeOfPlainText(). Please note that - * this function modifies 'out' data even on failure case. - */ -bool -kmgr_unwrap_key(PgCipherCtx *ctx, CryptoKey *in, CryptoKey *out) -{ - int declen; - unsigned char iv[sizeof(in->pgkey_id) + sizeof(in->counter)]; - - Assert(ctx && in && out); - - out->pgkey_id = in->pgkey_id; - out->counter = in->counter; - memcpy(out->tag, in->tag, sizeof(in->tag)); - - /* Construct the IV we are going to use, see kmgr_utils.h */ - memcpy(iv, &out->pgkey_id, sizeof(out->pgkey_id)); - memcpy(iv + sizeof(out->pgkey_id), &out->counter, sizeof(out->counter)); - - /* Decrypt encrypted data */ - if (!pg_cipher_decrypt(ctx, - in->encrypted_key, /* Encrypted source */ - sizeof(in->encrypted_key), /* Length of encrypted data */ - out->encrypted_key, /* Plaintext result */ - &declen, /* Length of plaintext */ - iv, /* IV we constructed above */ - sizeof(iv), /* Size of our IV */ - in->tag, /* Tag which will be verified */ - sizeof(in->tag))) /* Size of our tag */ - return false; - - Assert(declen == sizeof(in->encrypted_key)); - - return true; -} - -/* - * Verify the correctness of the given cluster key by unwrapping the given keys. - * If the given cluster key is correct we set unwrapped keys to out_keys and return - * true. Otherwise return false. Please note that this function changes the - * contents of out_keys even on failure. Both in_keys and out_keys must be the - * same length, nkey. - */ -bool -kmgr_verify_cluster_key(unsigned char *cluster_key, - CryptoKey *in_keys, CryptoKey *out_keys, int nkeys) -{ - PgCipherCtx *ctx; - - /* - * Create decryption context with cluster KEK. - */ - ctx = pg_cipher_ctx_create(PG_CIPHER_AES_GCM, cluster_key, - KMGR_CLUSTER_KEY_LEN, false); - - for (int i = 0; i < nkeys; i++) - { - if (!kmgr_unwrap_key(ctx, &(in_keys[i]), &(out_keys[i]))) - { - /* The cluster key is not correct */ - pg_cipher_ctx_free(ctx); - return false; - } - explicit_bzero(&(in_keys[i]), sizeof(in_keys[i])); - } - - /* The cluster key is correct, free the cipher context */ - pg_cipher_ctx_free(ctx); - - return true; -} - -/* - * Run cluster key command. - * - * prompt will be substituted for %p, file descriptor for %R - * - * The result will be put in buffer buf, which is of size size. - * The return value is the length of the actual result. - */ -int -kmgr_run_cluster_key_command(char *cluster_key_command, char *buf, - int size, char *dir) -{ - StringInfoData command; - const char *sp; - FILE *fh; - int pclose_rc; - size_t len = 0; - - buf[0] = '\0'; - - Assert(size > 0); - - /* - * Build the command to be executed. - */ - initStringInfo(&command); - - for (sp = cluster_key_command; *sp; sp++) - { - if (*sp == '%') - { - switch (sp[1]) - { - case 'd': - { - char *nativePath; - - sp++; - - /* - * This needs to use a placeholder to not modify the - * input with the conversion done via - * make_native_path(). - */ - nativePath = pstrdup(dir); - make_native_path(nativePath); - appendStringInfoString(&command, nativePath); - pfree(nativePath); - break; - } - case 'p': - sp++; - appendStringInfoString(&command, KMGR_PROMPT_MSG); - break; - case 'R': - { - char fd_str[20]; - - if (terminal_fd == -1) - { -#ifdef FRONTEND - pg_log_fatal("cluster key command referenced %%R, but --authprompt not specified"); - exit(EXIT_FAILURE); -#else - ereport(ERROR, - (errcode(ERRCODE_INTERNAL_ERROR), - errmsg("cluster key command referenced %%R, but --authprompt not specified"))); -#endif - } - - sp++; - snprintf(fd_str, sizeof(fd_str), "%d", terminal_fd); - appendStringInfoString(&command, fd_str); - break; - } - case '%': - /* convert %% to a single % */ - sp++; - appendStringInfoChar(&command, *sp); - break; - default: - /* otherwise treat the % as not special */ - appendStringInfoChar(&command, *sp); - break; - } - } - else - { - appendStringInfoChar(&command, *sp); - } - } - -#ifdef FRONTEND - fh = open_pipe_stream(command.data); - if (fh == NULL) - { - pg_log_fatal("could not execute command \"%s\": %m", - command.data); - exit(EXIT_FAILURE); - } -#else - fh = OpenPipeStream(command.data, "r"); - if (fh == NULL) - ereport(ERROR, - (errcode_for_file_access(), - errmsg("could not execute command \"%s\": %m", - command.data))); -#endif - - if (!fgets(buf, size, fh)) - { - if (ferror(fh)) - { -#ifdef FRONTEND - pg_log_fatal("could not read from command \"%s\": %m", - command.data); - exit(EXIT_FAILURE); -#else - ereport(ERROR, - (errcode_for_file_access(), - errmsg("could not read from command \"%s\": %m", - command.data))); -#endif - } - } - -#ifdef FRONTEND - pclose_rc = close_pipe_stream(fh); -#else - pclose_rc = ClosePipeStream(fh); -#endif - - if (pclose_rc == -1) - { -#ifdef FRONTEND - pg_log_fatal("could not close pipe to external command: %m"); - exit(EXIT_FAILURE); -#else - ereport(ERROR, - (errcode_for_file_access(), - errmsg("could not close pipe to external command: %m"))); -#endif - } - else if (pclose_rc != 0) - { -#ifdef FRONTEND - pg_log_fatal("command \"%s\" failed", command.data); - exit(EXIT_FAILURE); -#else - ereport(ERROR, - (errcode_for_file_access(), - errmsg("command \"%s\" failed", - command.data), - errdetail_internal("%s", wait_result_to_str(pclose_rc)))); -#endif - } - - /* strip trailing newline and carriage return */ - len = pg_strip_crlf(buf); - - pfree(command.data); - - return len; -} - -#ifdef FRONTEND -static FILE * -open_pipe_stream(const char *command) -{ - FILE *res; - -#ifdef WIN32 - size_t cmdlen = strlen(command); - char *buf; - int save_errno; - - buf = malloc(cmdlen + 2 + 1); - if (buf == NULL) - { - errno = ENOMEM; - return NULL; - } - buf[0] = '"'; - memcpy(&buf[1], command, cmdlen); - buf[cmdlen + 1] = '"'; - buf[cmdlen + 2] = '\0'; - - res = _popen(buf, "r"); - - save_errno = errno; - free(buf); - errno = save_errno; -#else - res = popen(command, "r"); -#endif /* WIN32 */ - return res; -} - -static int -close_pipe_stream(FILE *file) -{ -#ifdef WIN32 - return _pclose(file); -#else - return pclose(file); -#endif /* WIN32 */ -} -#endif /* FRONTEND */ - -CryptoKey * -kmgr_get_cryptokeys(const char *path, int *nkeys) -{ - struct dirent *de; - DIR *dir; - CryptoKey *keys; - -#ifndef FRONTEND - if ((dir = AllocateDir(path)) == NULL) - ereport(ERROR, - (errcode_for_file_access(), - errmsg("could not open directory \"%s\": %m", - path))); -#else - if ((dir = opendir(path)) == NULL) - pg_log_fatal("could not open directory \"%s\": %m", path); -#endif - - keys = (CryptoKey *) palloc0(sizeof(CryptoKey) * KMGR_MAX_INTERNAL_KEYS); - *nkeys = 0; - -#ifndef FRONTEND - while ((de = ReadDir(dir, LIVE_KMGR_DIR)) != NULL) -#else - while ((de = readdir(dir)) != NULL) -#endif - { - if (strspn(de->d_name, "0123456789") == strlen(de->d_name)) - { - uint32 id = strtoul(de->d_name, NULL, 10); - - if (id < 0 || id >= KMGR_MAX_INTERNAL_KEYS) - { -#ifndef FRONTEND - elog(ERROR, "invalid cryptographic key identifier %u", id); -#else - pg_log_fatal("invalid cryptographic key identifier %u", id); -#endif - } - - if (*nkeys >= KMGR_MAX_INTERNAL_KEYS) - { -#ifndef FRONTEND - elog(ERROR, "too many cryptographic keys"); -#else - pg_log_fatal("too many cryptographic keys"); -#endif - } - - read_one_keyfile(path, id, &(keys[id])); - (*nkeys)++; - } - } - -#ifndef FRONTEND - FreeDir(dir); -#else - closedir(dir); -#endif - - return keys; -} - -static void -read_one_keyfile(const char *cryptoKeyDir, uint32 id, CryptoKey *key_p) -{ - char path[MAXPGPATH]; - int fd; - int r; - - CryptoKeyFilePath(path, cryptoKeyDir, id); - -#ifndef FRONTEND - if ((fd = OpenTransientFile(path, O_RDONLY | PG_BINARY)) == -1) - ereport(ERROR, - (errcode_for_file_access(), - errmsg("could not open file \"%s\" for reading: %m", - path))); -#else - if ((fd = open(path, O_RDONLY | PG_BINARY, 0)) == -1) - pg_log_fatal("could not open file \"%s\" for reading: %m", - path); -#endif - -#ifndef FRONTEND - pgstat_report_wait_start(WAIT_EVENT_KEY_FILE_READ); -#endif - - /* Get key bytes */ - r = read(fd, key_p, sizeof(CryptoKey)); - if (r != sizeof(CryptoKey)) - { - if (r < 0) - { -#ifndef FRONTEND - ereport(ERROR, - (errcode_for_file_access(), - errmsg("could not read file \"%s\": %m", path))); -#else - pg_log_fatal("could not read file \"%s\": %m", path); -#endif - } - else - { -#ifndef FRONTEND - ereport(ERROR, - (errcode(ERRCODE_DATA_CORRUPTED), - errmsg("could not read file \"%s\": read %d of %zu", - path, r, sizeof(CryptoKey)))); -#else - pg_log_fatal("could not read file \"%s\": read %d of %zu", - path, r, sizeof(CryptoKey)); -#endif - } - } - -#ifndef FRONTEND - pgstat_report_wait_end(); -#endif - -#ifndef FRONTEND - if (CloseTransientFile(fd) != 0) - ereport(ERROR, - (errcode_for_file_access(), - errmsg("could not close file \"%s\": %m", - path))); -#else - if (close(fd) != 0) - pg_log_fatal("could not close file \"%s\": %m", path); -#endif -} diff --git a/src/include/catalog/pg_control.h b/src/include/catalog/pg_control.h index a4c12599f7..06bed90c5e 100644 --- a/src/include/catalog/pg_control.h +++ b/src/include/catalog/pg_control.h @@ -22,7 +22,7 @@ /* Version identifier for this pg_control format */ -#define PG_CONTROL_VERSION 1400 +#define PG_CONTROL_VERSION 1300 /* Nonce key length, see below */ #define MOCK_AUTH_NONCE_LEN 32 @@ -226,9 +226,6 @@ typedef struct ControlFileData */ char mock_authentication_nonce[MOCK_AUTH_NONCE_LEN]; - /* File encryption key length. Zero if disabled. */ - int file_encryption_keylen; - /* CRC of all above ... MUST BE LAST! */ pg_crc32c crc; } ControlFileData; diff --git a/src/include/common/cipher.h b/src/include/common/cipher.h deleted file mode 100644 index 598ef11289..0000000000 --- a/src/include/common/cipher.h +++ /dev/null @@ -1,62 +0,0 @@ -/*------------------------------------------------------------------------- - * - * cipher.h - * Declarations for cryptographic functions - * - * Portions Copyright (c) 2020, PostgreSQL Global Development Group - * - * src/include/common/cipher.h - * - *------------------------------------------------------------------------- - */ -#ifndef PG_CIPHER_H -#define PG_CIPHER_H - -#ifdef USE_OPENSSL -#include -#include -#include -#endif - -/* - * Supported symmetric encryption algorithm. These identifiers are passed - * to pg_cipher_ctx_create() function, and then actual encryption - * implementations need to initialize their context of the given encryption - * algorithm. - */ -#define PG_CIPHER_AES_GCM 0 -#define PG_MAX_CIPHER_ID 1 - -/* AES128/192/256 various length definitions */ -#define PG_AES128_KEY_LEN (128 / 8) -#define PG_AES192_KEY_LEN (192 / 8) -#define PG_AES256_KEY_LEN (256 / 8) - -/* - * The encrypted data is a series of blocks of size. Initialization - * vector(IV) is the same size of cipher block. - */ -#define PG_AES_BLOCK_SIZE 16 -#define PG_AES_IV_SIZE (PG_AES_BLOCK_SIZE) - -#ifdef USE_OPENSSL -typedef EVP_CIPHER_CTX PgCipherCtx; -#else -typedef void PgCipherCtx; -#endif - -extern PgCipherCtx *pg_cipher_ctx_create(int cipher, uint8 *key, int klen, - bool enc); -extern void pg_cipher_ctx_free(PgCipherCtx *ctx); -extern bool pg_cipher_encrypt(PgCipherCtx *ctx, - const unsigned char *plaintext, const int inlen, - unsigned char *ciphertext, int *outlen, - const unsigned char *iv, const int ivlen, - unsigned char *tag, const int taglen); -extern bool pg_cipher_decrypt(PgCipherCtx *ctx, - const unsigned char *ciphertext, const int inlen, - unsigned char *plaintext, int *outlen, - const unsigned char *iv, const int ivlen, - unsigned char *intag, const int taglen); - -#endif /* PG_CIPHER_H */ diff --git a/src/include/common/kmgr_utils.h b/src/include/common/kmgr_utils.h deleted file mode 100644 index ce26df56fb..0000000000 --- a/src/include/common/kmgr_utils.h +++ /dev/null @@ -1,98 +0,0 @@ -/*------------------------------------------------------------------------- - * - * kmgr_utils.h - * Declarations for utility function for file encryption key - * - * Portions Copyright (c) 2020, PostgreSQL Global Development Group - * - * src/include/common/kmgr_utils.h - * - *------------------------------------------------------------------------- - */ -#ifndef KMGR_UTILS_H -#define KMGR_UTILS_H - -#include "common/cipher.h" - -/* Current version number */ -#define KMGR_VERSION 1 - -/* - * Directories where cluster file encryption keys reside within PGDATA. - */ -#define KMGR_DIR "pg_cryptokeys" -#define KMGR_DIR_PID KMGR_DIR"/pg_alterckey.pid" -#define LIVE_KMGR_DIR KMGR_DIR"/live" -/* used during cluster key rotation */ -#define NEW_KMGR_DIR KMGR_DIR"/new" -#define OLD_KMGR_DIR KMGR_DIR"/old" - -/* CryptoKey file name is keys id */ -#define CryptoKeyFilePath(path, dir, id) \ - snprintf((path), MAXPGPATH, "%s/%d", (dir), (id)) - -/* - * Identifiers of internal keys. - */ -#define KMGR_KEY_ID_REL 0 -#define KMGR_KEY_ID_WAL 1 -#define KMGR_MAX_INTERNAL_KEYS 2 - -/* We always, today, use a 256-bit AES key. */ -#define KMGR_CLUSTER_KEY_LEN PG_AES256_KEY_LEN - -/* double for hex format, plus some for spaces, \r,\n, and null byte */ -#define ALLOC_KMGR_CLUSTER_KEY_LEN (KMGR_CLUSTER_KEY_LEN * 2 + 10 + 2 + 1) - -/* Maximum length of key the key manager can store */ -#define KMGR_MAX_KEY_LEN 256 -#define KMGR_MAX_KEY_LEN_BYTES KMGR_MAX_KEY_LEN / 8 -#define KMGR_MAX_WRAPPED_KEY_LEN KmgrSizeOfCipherText(KMGR_MAX_KEY_LEN) - - -/* - * Cryptographic key data structure. - * - * This is the structure we use to write out the encrypted keys. - * - * pgkey_id is the identifier for this key (should be same as the - * file name and be one of KMGR_KEY_ID_* from above). This is what - * we consider our 'context' or 'fixed' portion of the deterministic - * IV we create. - * - * counter is updated each time we use the cluster KEK to encrypt a - * new key. This is our the 'invocation' field of the deterministic - * IV we create. - * - * Absolutely essential when using GCM (or CTR) is that the IV is unique, - * for a given key, but a deterministic IV such as this is perfectly - * acceptable and encouraged. If (and only if!) the KEK is changed to a - * new key, then we can re-initialize the counter. - * - * Detailed discussion of deterministic IV creation can be found here: - * - * https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf - * - * tag is the GCM tag which is produced and must be validated in order - * to be able to trust the results of our decryption. - * - * encrypted_key is the encrypted key length (as an int) + encrypted key. - */ -typedef struct CryptoKey -{ - uint64 pgkey_id; /* Upper half of IV */ - uint64 counter; /* Lower half of IV */ - unsigned char tag[16]; /* GCM tag */ - unsigned char encrypted_key[sizeof(int) + KMGR_MAX_KEY_LEN_BYTES]; -} CryptoKey; - -extern bool kmgr_wrap_key(PgCipherCtx *ctx, CryptoKey *in, CryptoKey *out); -extern bool kmgr_unwrap_key(PgCipherCtx *ctx, CryptoKey *in, CryptoKey *out); -extern bool kmgr_verify_cluster_key(unsigned char *cluster_key, - CryptoKey *in_keys, CryptoKey *out_keys, - int nkey); -extern int kmgr_run_cluster_key_command(char *cluster_key_command, - char *buf, int size, char *dir); -extern CryptoKey *kmgr_get_cryptokeys(const char *path, int *nkeys); - -#endif /* KMGR_UTILS_H */ diff --git a/src/include/crypto/kmgr.h b/src/include/crypto/kmgr.h deleted file mode 100644 index 386ac1cb4a..0000000000 --- a/src/include/crypto/kmgr.h +++ /dev/null @@ -1,29 +0,0 @@ -/*------------------------------------------------------------------------- - * - * kmgr.h - * - * Portions Copyright (c) 2020, PostgreSQL Global Development Group - * - * src/include/crypto/kmgr.h - * - *------------------------------------------------------------------------- - */ -#ifndef KMGR_H -#define KMGR_H - -#include "common/cipher.h" -#include "common/kmgr_utils.h" -#include "storage/relfilenode.h" -#include "storage/bufpage.h" - -/* GUC parameters */ -extern int file_encryption_keylen; -extern char *cluster_key_command; - -extern Size KmgrShmemSize(void); -extern void KmgrShmemInit(void); -extern void BootStrapKmgr(void); -extern void InitializeKmgr(void); -extern const CryptoKey *KmgrGetKey(int id); - -#endif /* KMGR_H */ diff --git a/src/include/pgstat.h b/src/include/pgstat.h index b8f98f9a58..5954068dec 100644 --- a/src/include/pgstat.h +++ b/src/include/pgstat.h @@ -1010,9 +1010,6 @@ typedef enum WAIT_EVENT_DATA_FILE_TRUNCATE, WAIT_EVENT_DATA_FILE_WRITE, WAIT_EVENT_DSM_FILL_ZERO_WRITE, - WAIT_EVENT_KEY_FILE_READ, - WAIT_EVENT_KEY_FILE_WRITE, - WAIT_EVENT_KEY_FILE_SYNC, WAIT_EVENT_LOCK_FILE_ADDTODATADIR_READ, WAIT_EVENT_LOCK_FILE_ADDTODATADIR_SYNC, WAIT_EVENT_LOCK_FILE_ADDTODATADIR_WRITE, diff --git a/src/include/postmaster/postmaster.h b/src/include/postmaster/postmaster.h index b1f0721b85..babc87dfc9 100644 --- a/src/include/postmaster/postmaster.h +++ b/src/include/postmaster/postmaster.h @@ -30,8 +30,6 @@ extern bool enable_bonjour; extern char *bonjour_name; extern bool restart_after_crash; -extern int terminal_fd; - #ifdef WIN32 extern HANDLE PostmasterHandle; #else diff --git a/src/include/utils/guc_tables.h b/src/include/utils/guc_tables.h index c0dbf69116..7f36e1146f 100644 --- a/src/include/utils/guc_tables.h +++ b/src/include/utils/guc_tables.h @@ -89,7 +89,6 @@ enum config_group STATS, STATS_MONITORING, STATS_COLLECTOR, - ENCRYPTION, AUTOVACUUM, CLIENT_CONN, CLIENT_CONN_STATEMENT, diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm index 0e2104a345..7f014a12c9 100644 --- a/src/tools/msvc/Mkvcbuild.pm +++ b/src/tools/msvc/Mkvcbuild.pm @@ -122,20 +122,18 @@ sub mkvcbuild archive.c base64.c checksum_helper.c config_info.c controldata_utils.c d2s.c encnames.c exec.c f2s.c file_perm.c file_utils.c hashfn.c hex_decode.c ip.c jsonapi.c - keywords.c kmgr_utils.c kwlookup.c link-canary.c md5_common.c + keywords.c kwlookup.c link-canary.c md5_common.c pg_get_line.c pg_lzcompress.c pgfnames.c psprintf.c relpath.c rmtree.c saslprep.c scram-common.c string.c stringinfo.c unicode_norm.c username.c wait_error.c wchar.c); if ($solution->{options}->{openssl}) { - push(@pgcommonallfiles, 'cipher_openssl.c'); push(@pgcommonallfiles, 'cryptohash_openssl.c'); push(@pgcommonallfiles, 'protocol_openssl.c'); } else { - push(@pgcommonallfiles, 'cipher.c'); push(@pgcommonallfiles, 'cryptohash.c'); push(@pgcommonallfiles, 'md5.c'); push(@pgcommonallfiles, 'sha2.c');