Skip to content

Commit 035f99c

Browse files
pgcrypto: Make it possible to disable built-in crypto
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 <daniel@yesql.se> Author: Joe Conway <mail@joeconway.com> Reviewed-by: Joe Conway <mail@joeconway.com> Reviewed-by: Peter Eisentraut <peter@eisentraut.org> Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com> Discussion: https://postgr.es/m/16b4a157-9ea1-44d0-b7b3-4c85df5de97b@joeconway.com
1 parent 924d89a commit 035f99c

File tree

7 files changed

+121
-0
lines changed

7 files changed

+121
-0
lines changed

contrib/pgcrypto/expected/crypt-des.out

+7
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,11 @@ FROM ctest;
2828
t
2929
(1 row)
3030

31+
-- check disabling of built in crypto functions
32+
SET pgcrypto.builtin_crypto_enabled = off;
33+
UPDATE ctest SET salt = gen_salt('des');
34+
ERROR: use of built-in crypto functions is disabled
35+
UPDATE ctest SET res = crypt(data, salt);
36+
ERROR: use of built-in crypto functions is disabled
37+
RESET pgcrypto.builtin_crypto_enabled;
3138
DROP TABLE ctest;

contrib/pgcrypto/openssl.c

+26
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131

3232
#include "postgres.h"
3333

34+
#include <openssl/crypto.h>
3435
#include <openssl/evp.h>
3536
#include <openssl/err.h>
3637
#include <openssl/rand.h>
@@ -821,3 +822,28 @@ CheckFIPSMode(void)
821822

822823
return (fips_enabled == 1);
823824
}
825+
826+
/*
827+
* CheckBuiltinCryptoMode
828+
*
829+
* Function for erroring out in case built-in crypto is executed when the user
830+
* has disabled it. If builtin_crypto_enabled is set to BC_OFF or BC_FIPS and
831+
* OpenSSL is operating in FIPS mode the function will error out, else the
832+
* query executing built-in crypto can proceed.
833+
*/
834+
void
835+
CheckBuiltinCryptoMode(void)
836+
{
837+
if (builtin_crypto_enabled == BC_ON)
838+
return;
839+
840+
if (builtin_crypto_enabled == BC_OFF)
841+
ereport(ERROR,
842+
errmsg("use of built-in crypto functions is disabled"));
843+
844+
Assert(builtin_crypto_enabled == BC_FIPS);
845+
846+
if (CheckFIPSMode() == true)
847+
ereport(ERROR,
848+
errmsg("use of non-FIPS validated crypto not allowed when OpenSSL is in FIPS mode"));
849+
}

contrib/pgcrypto/pgcrypto.c

+31
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,47 @@
3838
#include "px-crypt.h"
3939
#include "px.h"
4040
#include "utils/builtins.h"
41+
#include "utils/guc.h"
4142
#include "varatt.h"
4243

4344
PG_MODULE_MAGIC;
4445

4546
/* private stuff */
4647

48+
static const struct config_enum_entry builtin_crypto_options[] = {
49+
{"on", BC_ON, false},
50+
{"off", BC_OFF, false},
51+
{"fips", BC_FIPS, false},
52+
{NULL, 0, false}
53+
};
54+
4755
typedef int (*PFN) (const char *name, void **res);
4856
static void *find_provider(text *name, PFN provider_lookup, const char *desc,
4957
int silent);
5058

59+
int builtin_crypto_enabled = BC_ON;
60+
61+
/*
62+
* Entrypoint of this module.
63+
*/
64+
void
65+
_PG_init(void)
66+
{
67+
DefineCustomEnumVariable("pgcrypto.builtin_crypto_enabled",
68+
"Sets if builtin crypto functions are enabled.",
69+
"\"on\" enables builtin crypto, \"off\" unconditionally disables and \"fips\" "
70+
"will disable builtin crypto if OpenSSL is in FIPS mode",
71+
&builtin_crypto_enabled,
72+
BC_ON,
73+
builtin_crypto_options,
74+
PGC_SUSET,
75+
0,
76+
NULL,
77+
NULL,
78+
NULL);
79+
MarkGUCPrefixReserved("pgcrypto");
80+
}
81+
5182
/* SQL function: hash(bytea, text) returns bytea */
5283
PG_FUNCTION_INFO_V1(pg_digest);
5384

contrib/pgcrypto/px-crypt.c

+4
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ px_crypt(const char *psw, const char *salt, char *buf, unsigned len)
9191
{
9292
const struct px_crypt_algo *c;
9393

94+
CheckBuiltinCryptoMode();
95+
9496
for (c = px_crypt_list; c->id; c++)
9597
{
9698
if (!c->id_len)
@@ -135,6 +137,8 @@ px_gen_salt(const char *salt_type, char *buf, int rounds)
135137
char *p;
136138
char rbuf[16];
137139

140+
CheckBuiltinCryptoMode();
141+
138142
for (g = gen_list; g->name; g++)
139143
if (pg_strcasecmp(g->name, salt_type) == 0)
140144
break;

contrib/pgcrypto/px.h

+9
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,21 @@
8989
#define PXE_PGP_UNSUPPORTED_PUBALGO -122
9090
#define PXE_PGP_MULTIPLE_SUBKEYS -123
9191

92+
typedef enum BuiltinCryptoOptions
93+
{
94+
BC_ON,
95+
BC_OFF,
96+
BC_FIPS,
97+
} BuiltinCryptoOptions;
9298

9399
typedef struct px_digest PX_MD;
94100
typedef struct px_alias PX_Alias;
95101
typedef struct px_hmac PX_HMAC;
96102
typedef struct px_cipher PX_Cipher;
97103
typedef struct px_combo PX_Combo;
98104

105+
extern int builtin_crypto_enabled;
106+
99107
struct px_digest
100108
{
101109
unsigned (*result_size) (PX_MD *h);
@@ -183,6 +191,7 @@ void px_set_debug_handler(void (*handler) (const char *));
183191
void px_memset(void *ptr, int c, size_t len);
184192

185193
bool CheckFIPSMode(void);
194+
void CheckBuiltinCryptoMode(void);
186195

187196
#ifdef PX_DEBUG
188197
void px_debug(const char *fmt,...) pg_attribute_printf(1, 2);

contrib/pgcrypto/sql/crypt-des.sql

+6
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,10 @@ UPDATE ctest SET res = crypt(data, salt);
1818
SELECT res = crypt(data, res) AS "worked"
1919
FROM ctest;
2020

21+
-- check disabling of built in crypto functions
22+
SET pgcrypto.builtin_crypto_enabled = off;
23+
UPDATE ctest SET salt = gen_salt('des');
24+
UPDATE ctest SET res = crypt(data, salt);
25+
RESET pgcrypto.builtin_crypto_enabled;
26+
2127
DROP TABLE ctest;

doc/src/sgml/pgcrypto.sgml

+38
Original file line numberDiff line numberDiff line change
@@ -1165,6 +1165,44 @@ fips_mode() returns boolean
11651165
</para>
11661166
</sect2>
11671167

1168+
<sect2 id="pgcrypto-configuration-parameters">
1169+
<title>Configuration Parameters</title>
1170+
1171+
<para>
1172+
There is one configuration parameter that controls the behavior of
1173+
<filename>pgcrypto</filename>.
1174+
</para>
1175+
1176+
<variablelist>
1177+
<varlistentry id="pgcrypto-configuration-parameters-builtin_crypto_enabled">
1178+
<term>
1179+
<varname>pgcrypto.builtin_crypto_enabled</varname> (<type>enum</type>)
1180+
<indexterm>
1181+
<primary><varname>pgcrypto.builtin_crypto_enabled</varname> configuration
1182+
parameter</primary>
1183+
</indexterm>
1184+
</term>
1185+
<listitem>
1186+
<para>
1187+
<varname>pgcrypto.builtin_crypto_enabled</varname> determines if the
1188+
built in crypto functions <function>gen_salt()</function>, and
1189+
<function>crypt()</function> are available for use. Setting this to
1190+
<literal>off</literal> disables these functions. <literal>on</literal>
1191+
(the default) enables these functions to work normally.
1192+
<literal>fips</literal> disables these functions if
1193+
<productname>OpenSSL</productname> is detected to operate in FIPS mode.
1194+
</para>
1195+
</listitem>
1196+
</varlistentry>
1197+
</variablelist>
1198+
1199+
<para>
1200+
In ordinary usage, this parameter is set
1201+
in <filename>postgresql.conf</filename>, although superusers can alter it
1202+
on-the-fly within their own sessions.
1203+
</para>
1204+
</sect2>
1205+
11681206
<sect2 id="pgcrypto-notes">
11691207
<title>Notes</title>
11701208

0 commit comments

Comments
 (0)