From e613fb1d5b6d09661004ec0f65627b2549af5634 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Renaud=20M=C3=A9trich?= <rmetrich@redhat.com>
Date: Mon, 15 Jun 2026 08:14:09 +0200
Subject: [PATCH v2 2/8] Reject alternate certificate with same key type as
 primary
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

If ssl_alt_cert_file specifies a certificate of the same key type as the
primary ssl_cert_file (e.g., both RSA), the alternate silently replaces
the primary, which is not useful.  Detect this by comparing
EVP_PKEY_get_base_id() on both certificates after loading, and report
a configuration error at startup or reload.

Author: Renaud Métrich <rmetrich@redhat.com>
---
 src/backend/libpq/be-secure-openssl.c | 33 +++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index cf7d981b697..bfbce535ac8 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -833,6 +833,39 @@ init_host_context(HostsLine *host, bool isServerStart)
 							SSLerrmessage(ERR_get_error()))));
 			goto error;
 		}
+
+		/*
+		 * Verify that the alternate certificate uses a different key type
+		 * than the primary.  If both are the same type (e.g. both RSA),
+		 * the alternate silently replaces the primary, which is not useful.
+		 */
+		{
+			X509	   *primary_cert;
+			X509	   *alt_cert;
+			int			primary_type;
+			int			alt_type;
+
+			SSL_CTX_set_current_cert(ctx, SSL_CERT_SET_FIRST);
+			primary_cert = SSL_CTX_get0_certificate(ctx);
+
+			SSL_CTX_set_current_cert(ctx, SSL_CERT_SET_NEXT);
+			alt_cert = SSL_CTX_get0_certificate(ctx);
+
+			if (primary_cert && alt_cert)
+			{
+				primary_type = EVP_PKEY_get_base_id(X509_get0_pubkey(primary_cert));
+				alt_type = EVP_PKEY_get_base_id(X509_get0_pubkey(alt_cert));
+
+				if (primary_type == alt_type)
+				{
+					ereport(isServerStart ? FATAL : LOG,
+							(errcode(ERRCODE_CONFIG_FILE_ERROR),
+							 errmsg("alternate certificate has the same key type (%s) as the primary certificate",
+									evp_pkey_type_name(alt_type))));
+					goto error;
+				}
+			}
+		}
 	}
 
 	/*
-- 
2.52.0

