From 243326cc90d7824ac099b2d7b4c607d158cb76c9 Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson Date: Fri, 22 Nov 2024 14:49:31 +0100 Subject: [PATCH v2] Make it possible to disable built-in crypto --- contrib/pgcrypto/expected/crypt-des.out | 7 +++++ contrib/pgcrypto/openssl.c | 29 ++++++++++++++++++ contrib/pgcrypto/pgcrypto.c | 30 +++++++++++++++++++ contrib/pgcrypto/px-crypt.c | 4 +++ contrib/pgcrypto/px.h | 10 +++++++ contrib/pgcrypto/sql/crypt-des.sql | 6 ++++ doc/src/sgml/pgcrypto.sgml | 39 +++++++++++++++++++++++++ 7 files changed, 125 insertions(+) diff --git a/contrib/pgcrypto/expected/crypt-des.out b/contrib/pgcrypto/expected/crypt-des.out index a462dcd580a..8993a2d1044 100644 --- a/contrib/pgcrypto/expected/crypt-des.out +++ b/contrib/pgcrypto/expected/crypt-des.out @@ -28,4 +28,11 @@ FROM ctest; t (1 row) +-- check disabling of legacy crypto functions +SET pgcrypto.legacy_crypto_enabled = off; +UPDATE ctest SET salt = gen_salt('des'); +ERROR: use of built-in crypto functions is disabled +UPDATE ctest SET res = crypt(data, salt); +ERROR: use of built-in crypto functions is disabled +RESET pgcrypto.legacy_crypto_enabled; DROP TABLE ctest; diff --git a/contrib/pgcrypto/openssl.c b/contrib/pgcrypto/openssl.c index 26454bc3e29..c29940f3d06 100644 --- a/contrib/pgcrypto/openssl.c +++ b/contrib/pgcrypto/openssl.c @@ -794,3 +794,32 @@ ResOwnerReleaseOSSLCipher(Datum res) { free_openssl_cipher((OSSLCipher *) DatumGetPointer(res)); } + +/* + * CheckLegacyCryptoMode + * + * Function for erroring out in case built-in crypto is executed when the user + * has disabled it. If legacy_crypto_enabled is set to LGC_OFF or LGC_FIPS and + * OpenSSL is operating in FIPS mode the function will error out, else the + * query executing built-in crypto can proceed. + */ +void +CheckLegacyCryptoMode(void) +{ + if (legacy_crypto_enabled == LGC_ON) + return; + + if (legacy_crypto_enabled == LGC_OFF) + ereport(ERROR, + errmsg("use of built-in crypto functions is disabled")); + + Assert(legacy_crypto_enabled == LGC_FIPS); + +#if defined FIPS_mode + if (FIPS_mode()) +#else + if (EVP_default_properties_is_fips_enabled(OSSL_LIB_CTX_get0_global_default())) +#endif + ereport(ERROR, + errmsg("use of non-FIPS certified crypto not allowed when OpenSSL is in FIPS mode")); +} diff --git a/contrib/pgcrypto/pgcrypto.c b/contrib/pgcrypto/pgcrypto.c index ebd76eed702..fe0e2b9242a 100644 --- a/contrib/pgcrypto/pgcrypto.c +++ b/contrib/pgcrypto/pgcrypto.c @@ -38,16 +38,46 @@ #include "px-crypt.h" #include "px.h" #include "utils/builtins.h" +#include "utils/guc.h" #include "varatt.h" PG_MODULE_MAGIC; /* private stuff */ +static const struct config_enum_entry legacy_crypto_options[] = { + {"on", LGC_ON, false}, + {"off", LGC_OFF, false}, + {"fips", LGC_FIPS, false}, + {NULL, 0, false} +}; + typedef int (*PFN) (const char *name, void **res); static void *find_provider(text *name, PFN provider_lookup, const char *desc, int silent); +int legacy_crypto_enabled = LGC_ON; + +/* + * Entrypoint of this module. + */ +void +_PG_init(void) +{ + DefineCustomEnumVariable("pgcrypto.legacy_crypto_enabled", + "Sets if builtin crypto functions are enabled.", + "Yes enables builtin crypto, No unconditionally disables and OpenSSL " + "will disable if OpenSSL is in FIPS mode", + &legacy_crypto_enabled, + LGC_ON, + legacy_crypto_options, + PGC_SUSET, + 0, + NULL, + NULL, + NULL); +} + /* SQL function: hash(bytea, text) returns bytea */ PG_FUNCTION_INFO_V1(pg_digest); diff --git a/contrib/pgcrypto/px-crypt.c b/contrib/pgcrypto/px-crypt.c index 0913ff2c1bc..b97ea4fd36b 100644 --- a/contrib/pgcrypto/px-crypt.c +++ b/contrib/pgcrypto/px-crypt.c @@ -91,6 +91,8 @@ px_crypt(const char *psw, const char *salt, char *buf, unsigned len) { const struct px_crypt_algo *c; + CheckLegacyCryptoMode(); + for (c = px_crypt_list; c->id; c++) { if (!c->id_len) @@ -135,6 +137,8 @@ px_gen_salt(const char *salt_type, char *buf, int rounds) char *p; char rbuf[16]; + CheckLegacyCryptoMode(); + for (g = gen_list; g->name; g++) if (pg_strcasecmp(g->name, salt_type) == 0) break; diff --git a/contrib/pgcrypto/px.h b/contrib/pgcrypto/px.h index 471bb4ec727..8f21dad54ec 100644 --- a/contrib/pgcrypto/px.h +++ b/contrib/pgcrypto/px.h @@ -89,6 +89,12 @@ #define PXE_PGP_UNSUPPORTED_PUBALGO -122 #define PXE_PGP_MULTIPLE_SUBKEYS -123 +typedef enum LegacyCryptoOptions +{ + LGC_ON, + LGC_OFF, + LGC_FIPS, +} LegacyCryptoOptions; typedef struct px_digest PX_MD; typedef struct px_alias PX_Alias; @@ -96,6 +102,8 @@ typedef struct px_hmac PX_HMAC; typedef struct px_cipher PX_Cipher; typedef struct px_combo PX_Combo; +extern int legacy_crypto_enabled; + struct px_digest { unsigned (*result_size) (PX_MD *h); @@ -182,6 +190,8 @@ void px_set_debug_handler(void (*handler) (const char *)); void px_memset(void *ptr, int c, size_t len); +void CheckLegacyCryptoMode(void); + #ifdef PX_DEBUG void px_debug(const char *fmt,...) pg_attribute_printf(1, 2); #else diff --git a/contrib/pgcrypto/sql/crypt-des.sql b/contrib/pgcrypto/sql/crypt-des.sql index a85ec1e6555..5b75dc5bb49 100644 --- a/contrib/pgcrypto/sql/crypt-des.sql +++ b/contrib/pgcrypto/sql/crypt-des.sql @@ -18,4 +18,10 @@ UPDATE ctest SET res = crypt(data, salt); SELECT res = crypt(data, res) AS "worked" FROM ctest; +-- check disabling of legacy crypto functions +SET pgcrypto.legacy_crypto_enabled = off; +UPDATE ctest SET salt = gen_salt('des'); +UPDATE ctest SET res = crypt(data, salt); +RESET pgcrypto.legacy_crypto_enabled; + DROP TABLE ctest; diff --git a/doc/src/sgml/pgcrypto.sgml b/doc/src/sgml/pgcrypto.sgml index 396c67f0cde..c54b0e8459f 100644 --- a/doc/src/sgml/pgcrypto.sgml +++ b/doc/src/sgml/pgcrypto.sgml @@ -1222,6 +1222,45 @@ gen_random_uuid() returns uuid + + Configuration Parameters + + + There is one configuration parameter that controls the behavior of + pgcrypto. + + + + + + pgcrypto.legacy_crypto_enabled (enum) + + pgcrypto.legacy_crypto_enabled configuration + parameter + + + + + pgcrypto.legacy_crypto_enabled determines if the + built in legacy crypto functions pg_gen_salt, + pg_gen_salt_rounds, and pg_crypt + are available for use. Setting this to off + disables these functions. on (the default) enables + these functions to work normally. fips disables these + functions if OpenSSL is detected to operate + in FIPS mode. + + + + + + + In ordinary usage, these parameters are set + in postgresql.conf, although superusers can alter them + on-the-fly within their own sessions. + + + Author -- 2.39.3 (Apple Git-146)