When using OpenSSL and/or the underlying operating system in FIPS
mode no non-FIPS certified crypto implementations should be used.
While that is already possible by just not invoking the built-in
crypto in pgcrypto, this adds a GUC which prohibit the code from
being called. This doesn't change the FIPS status of PostgreSQL
but can make it easier for sites which target FIPS compliance to
ensure that violations cannot occur.
Author: Daniel Gustafsson <
[email protected]>
Author: Joe Conway <
[email protected]>
Reviewed-by: Joe Conway <[email protected]>
Reviewed-by: Peter Eisentraut <[email protected]>
Reviewed-by: Hayato Kuroda <[email protected]>
Discussion: https://postgr.es/m/
16b4a157-9ea1-44d0-b7b3-
4c85df5de97b@joeconway.com
t
(1 row)
+-- check disabling of built in crypto functions
+SET pgcrypto.builtin_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.builtin_crypto_enabled;
DROP TABLE ctest;
#include "postgres.h"
+#include <openssl/crypto.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/rand.h>
return (fips_enabled == 1);
}
+
+/*
+ * CheckBuiltinCryptoMode
+ *
+ * Function for erroring out in case built-in crypto is executed when the user
+ * has disabled it. If builtin_crypto_enabled is set to BC_OFF or BC_FIPS and
+ * OpenSSL is operating in FIPS mode the function will error out, else the
+ * query executing built-in crypto can proceed.
+ */
+void
+CheckBuiltinCryptoMode(void)
+{
+ if (builtin_crypto_enabled == BC_ON)
+ return;
+
+ if (builtin_crypto_enabled == BC_OFF)
+ ereport(ERROR,
+ errmsg("use of built-in crypto functions is disabled"));
+
+ Assert(builtin_crypto_enabled == BC_FIPS);
+
+ if (CheckFIPSMode() == true)
+ ereport(ERROR,
+ errmsg("use of non-FIPS validated crypto not allowed when OpenSSL is in FIPS mode"));
+}
#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 builtin_crypto_options[] = {
+ {"on", BC_ON, false},
+ {"off", BC_OFF, false},
+ {"fips", BC_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 builtin_crypto_enabled = BC_ON;
+
+/*
+ * Entrypoint of this module.
+ */
+void
+_PG_init(void)
+{
+ DefineCustomEnumVariable("pgcrypto.builtin_crypto_enabled",
+ "Sets if builtin crypto functions are enabled.",
+ "\"on\" enables builtin crypto, \"off\" unconditionally disables and \"fips\" "
+ "will disable builtin crypto if OpenSSL is in FIPS mode",
+ &builtin_crypto_enabled,
+ BC_ON,
+ builtin_crypto_options,
+ PGC_SUSET,
+ 0,
+ NULL,
+ NULL,
+ NULL);
+ MarkGUCPrefixReserved("pgcrypto");
+}
+
/* SQL function: hash(bytea, text) returns bytea */
PG_FUNCTION_INFO_V1(pg_digest);
{
const struct px_crypt_algo *c;
+ CheckBuiltinCryptoMode();
+
for (c = px_crypt_list; c->id; c++)
{
if (!c->id_len)
char *p;
char rbuf[16];
+ CheckBuiltinCryptoMode();
+
for (g = gen_list; g->name; g++)
if (pg_strcasecmp(g->name, salt_type) == 0)
break;
#define PXE_PGP_UNSUPPORTED_PUBALGO -122
#define PXE_PGP_MULTIPLE_SUBKEYS -123
+typedef enum BuiltinCryptoOptions
+{
+ BC_ON,
+ BC_OFF,
+ BC_FIPS,
+} BuiltinCryptoOptions;
typedef struct px_digest PX_MD;
typedef struct px_alias PX_Alias;
typedef struct px_cipher PX_Cipher;
typedef struct px_combo PX_Combo;
+extern int builtin_crypto_enabled;
+
struct px_digest
{
unsigned (*result_size) (PX_MD *h);
void px_memset(void *ptr, int c, size_t len);
bool CheckFIPSMode(void);
+void CheckBuiltinCryptoMode(void);
#ifdef PX_DEBUG
void px_debug(const char *fmt,...) pg_attribute_printf(1, 2);
SELECT res = crypt(data, res) AS "worked"
FROM ctest;
+-- check disabling of built in crypto functions
+SET pgcrypto.builtin_crypto_enabled = off;
+UPDATE ctest SET salt = gen_salt('des');
+UPDATE ctest SET res = crypt(data, salt);
+RESET pgcrypto.builtin_crypto_enabled;
+
DROP TABLE ctest;
</para>
</sect2>
+ <sect2 id="pgcrypto-configuration-parameters">
+ <title>Configuration Parameters</title>
+
+ <para>
+ There is one configuration parameter that controls the behavior of
+ <filename>pgcrypto</filename>.
+ </para>
+
+ <variablelist>
+ <varlistentry id="pgcrypto-configuration-parameters-builtin_crypto_enabled">
+ <term>
+ <varname>pgcrypto.builtin_crypto_enabled</varname> (<type>enum</type>)
+ <indexterm>
+ <primary><varname>pgcrypto.builtin_crypto_enabled</varname> configuration
+ parameter</primary>
+ </indexterm>
+ </term>
+ <listitem>
+ <para>
+ <varname>pgcrypto.builtin_crypto_enabled</varname> determines if the
+ built in crypto functions <function>gen_salt()</function>, and
+ <function>crypt()</function> are available for use. Setting this to
+ <literal>off</literal> disables these functions. <literal>on</literal>
+ (the default) enables these functions to work normally.
+ <literal>fips</literal> disables these functions if
+ <productname>OpenSSL</productname> is detected to operate in FIPS mode.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>
+ In ordinary usage, this parameter is set
+ in <filename>postgresql.conf</filename>, although superusers can alter it
+ on-the-fly within their own sessions.
+ </para>
+ </sect2>
+
<sect2 id="pgcrypto-notes">
<title>Notes</title>