From c222ac8a5c75b55f6f890616e775f925f712fb4d Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Tue, 21 Jan 2025 23:53:37 +0100
Subject: [PATCH v10 1/2] pgcrypto: Add function to check FIPS mode

This adds a SQL callable function for reading and returning the status
of FIPS configuration of OpenSSL.  If OpenSSL is operating with FIPS
enabled it will return true, otherwise false.  As this adds a function
to the SQL file, bump the extension version to 1.4.

Author: Daniel Gustafsson <daniel@yesql.se>
Discussion: https://postgr.es/m/8f979145-e206-475a-a31b-73c977a4134c@joeconway.com
---
 contrib/pgcrypto/Makefile               |  2 +-
 contrib/pgcrypto/meson.build            |  1 +
 contrib/pgcrypto/openssl.c              | 26 +++++++++++++++++++++++++
 contrib/pgcrypto/pgcrypto--1.3--1.4.sql |  9 +++++++++
 contrib/pgcrypto/pgcrypto.c             |  8 ++++++++
 contrib/pgcrypto/pgcrypto.control       |  2 +-
 contrib/pgcrypto/px.h                   |  2 ++
 doc/src/sgml/pgcrypto.sgml              | 16 +++++++++++++++
 8 files changed, 64 insertions(+), 2 deletions(-)
 create mode 100644 contrib/pgcrypto/pgcrypto--1.3--1.4.sql

diff --git a/contrib/pgcrypto/Makefile b/contrib/pgcrypto/Makefile
index 85f1c946813..d40216dd420 100644
--- a/contrib/pgcrypto/Makefile
+++ b/contrib/pgcrypto/Makefile
@@ -36,7 +36,7 @@ MODULE_big	= pgcrypto
 
 EXTENSION = pgcrypto
 DATA = pgcrypto--1.3.sql pgcrypto--1.2--1.3.sql pgcrypto--1.1--1.2.sql \
-	pgcrypto--1.0--1.1.sql
+	pgcrypto--1.0--1.1.sql pgcrypto--1.3--1.4.sql
 PGFILEDESC = "pgcrypto - cryptographic functions"
 
 REGRESS = init md5 sha1 hmac-md5 hmac-sha1 blowfish rijndael \
diff --git a/contrib/pgcrypto/meson.build b/contrib/pgcrypto/meson.build
index 0bcbe4cfe5a..7a4e8e76d64 100644
--- a/contrib/pgcrypto/meson.build
+++ b/contrib/pgcrypto/meson.build
@@ -93,6 +93,7 @@ install_data(
   'pgcrypto--1.1--1.2.sql',
   'pgcrypto--1.2--1.3.sql',
   'pgcrypto--1.3.sql',
+  'pgcrypto--1.3--1.4.sql',
   'pgcrypto.control',
   kwargs: contrib_data_args,
 )
diff --git a/contrib/pgcrypto/openssl.c b/contrib/pgcrypto/openssl.c
index 448db331a0f..b2984045980 100644
--- a/contrib/pgcrypto/openssl.c
+++ b/contrib/pgcrypto/openssl.c
@@ -794,3 +794,29 @@ ResOwnerReleaseOSSLCipher(Datum res)
 {
 	free_openssl_cipher((OSSLCipher *) DatumGetPointer(res));
 }
+
+/*
+ * CheckFIPSMode
+ *
+ * Returns the FIPS mode of the underlying OpenSSL installation.
+ */
+bool
+CheckFIPSMode(void)
+{
+	int			fips_enabled = 0;
+	/*
+	 * EVP_default_properties_is_fips_enabled was added in OpenSSL 3.0, before
+	 * that FIPS_mode() was used to test for FIPS being enabled.  The last
+	 * upstream OpenSSL version before 3.0 which supported FIPS was 1.0.2, but
+	 * there are forks of 1.1.1 which are FIPS certified so we still need to
+	 * test with FIPS_mode() even though we don't support 1.0.2.
+	 */
+	fips_enabled =
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+		EVP_default_properties_is_fips_enabled(NULL);
+#else
+		FIPS_mode();
+#endif
+
+	return (fips_enabled == 1);
+}
diff --git a/contrib/pgcrypto/pgcrypto--1.3--1.4.sql b/contrib/pgcrypto/pgcrypto--1.3--1.4.sql
new file mode 100644
index 00000000000..b942bde8427
--- /dev/null
+++ b/contrib/pgcrypto/pgcrypto--1.3--1.4.sql
@@ -0,0 +1,9 @@
+/* contrib/pgcrypto/pgcrypto--1.3--1.4.sql */
+
+-- complain if script is sourced in psql, rather than via ALTER EXTENSION
+\echo Use "ALTER EXTENSION pgcrypto UPDATE TO '1.4'" to load this file. \quit
+
+CREATE FUNCTION fips_mode()
+RETURNS bool
+AS 'MODULE_PATHNAME', 'pg_check_fipsmode'
+LANGUAGE C VOLATILE STRICT PARALLEL SAFE;
diff --git a/contrib/pgcrypto/pgcrypto.c b/contrib/pgcrypto/pgcrypto.c
index ebd76eed702..ee2a010e402 100644
--- a/contrib/pgcrypto/pgcrypto.c
+++ b/contrib/pgcrypto/pgcrypto.c
@@ -450,6 +450,14 @@ pg_random_uuid(PG_FUNCTION_ARGS)
 	return gen_random_uuid(fcinfo);
 }
 
+PG_FUNCTION_INFO_V1(pg_check_fipsmode);
+
+Datum
+pg_check_fipsmode(PG_FUNCTION_ARGS)
+{
+	PG_RETURN_BOOL(CheckFIPSMode());
+}
+
 static void *
 find_provider(text *name,
 			  PFN provider_lookup,
diff --git a/contrib/pgcrypto/pgcrypto.control b/contrib/pgcrypto/pgcrypto.control
index d2151d3bc4b..fcdd0b46f5b 100644
--- a/contrib/pgcrypto/pgcrypto.control
+++ b/contrib/pgcrypto/pgcrypto.control
@@ -1,6 +1,6 @@
 # pgcrypto extension
 comment = 'cryptographic functions'
-default_version = '1.3'
+default_version = '1.4'
 module_pathname = '$libdir/pgcrypto'
 relocatable = true
 trusted = true
diff --git a/contrib/pgcrypto/px.h b/contrib/pgcrypto/px.h
index 471bb4ec727..c2c2fc31245 100644
--- a/contrib/pgcrypto/px.h
+++ b/contrib/pgcrypto/px.h
@@ -182,6 +182,8 @@ void		px_set_debug_handler(void (*handler) (const char *));
 
 void		px_memset(void *ptr, int c, size_t len);
 
+bool		CheckFIPSMode(void);
+
 #ifdef PX_DEBUG
 void		px_debug(const char *fmt,...) pg_attribute_printf(1, 2);
 #else
diff --git a/doc/src/sgml/pgcrypto.sgml b/doc/src/sgml/pgcrypto.sgml
index 396c67f0cde..838d7532a52 100644
--- a/doc/src/sgml/pgcrypto.sgml
+++ b/doc/src/sgml/pgcrypto.sgml
@@ -1149,6 +1149,22 @@ gen_random_uuid() returns uuid
   </para>
  </sect2>
 
+ <sect2 id="pgcrypto-openssl-support-funcs">
+  <title>OpenSSL Support Functions</title>
+
+  <indexterm>
+   <primary>fips_mode</primary>
+  </indexterm>
+
+<synopsis>
+fips_mode() returns boolean
+</synopsis>
+  <para>
+   Returns <literal>true</literal> if <productname>OpenSSL</productname> is
+   running with FIPS mode enabled, otherwise <literal>false</literal>.
+  </para>
+ </sect2>
+
  <sect2 id="pgcrypto-notes">
   <title>Notes</title>
 
-- 
2.39.3 (Apple Git-146)

