From 1d91ce94b9ce9164f41c322f9415c3ffc67ed0bb Mon Sep 17 00:00:00 2001
From: Tim van Dijen <tim.dijen@minbzk.nl>
Date: Wed, 24 Mar 2021 20:30:22 +0100
Subject: [PATCH] Add sanity check to test matching key-pairs (#1408)

---
 modules/admin/lib/Controller/Config.php | 50 +++++++++++++++++++++++++
 1 file changed, 50 insertions(+)

diff --git a/modules/admin/lib/Controller/Config.php b/modules/admin/lib/Controller/Config.php
index 72c3878ad..fbfd9e111 100644
--- a/modules/admin/lib/Controller/Config.php
+++ b/modules/admin/lib/Controller/Config.php
@@ -7,6 +7,7 @@ namespace SimpleSAML\Module\admin\Controller;
 use SimpleSAML\Configuration;
 use SimpleSAML\HTTP\RunnableResponse;
 use SimpleSAML\Locale\Translate;
+use SimpleSAML\Metadata\MetaDataStorageHandler;
 use SimpleSAML\Module;
 use SimpleSAML\Session;
 use SimpleSAML\Utils;
@@ -340,6 +341,42 @@ class Config
             'enabled' => $this->config->getString('auth.adminpassword', '123') !== '123',
         ];
 
+        // perform some sanity checks on the configured certificates
+        if ($this->config->getString('enable.saml20-idp', false) !== false) {
+            $handler = MetaDataStorageHandler::getMetadataHandler();
+            $metadata = $handler->getMetaDataCurrent('saml20-idp-hosted');
+            $metadata_config = Configuration::loadfromArray($metadata);
+            $private = Utils\Crypto::loadPrivateKey($metadata_config, false);
+            $public = Utils\Crypto::loadPublicKey($metadata_config, false);
+
+            $matrix[] = [
+                'required' => 'required',
+                'descr' => Translate::noop('Matching key-pair for signing assertions'),
+                'enabled' => $this->matchingKeyPair($public['PEM'], [$private['PEM'], $private['password']]),
+            ];
+
+            $private = Utils\Crypto::loadPrivateKey($metadata_config, false, 'new_');
+            if ($private !== null) {
+                $public = Utils\Crypto::loadPublicKey($metadata_config, false, 'new_');
+                $matrix[] = [
+                    'required' => 'required',
+                    'descr' => Translate::noop('Matching key-pair for signing assertions (rollover key)'),
+                    'enabled' => $this->matchingKeyPair($public['PEM'], [$private['PEM'], $private['password']]),
+                ];
+            }
+        }
+
+        if ($this->config->getBoolean('metadata.sign.enable', false) !== false) {
+            $private = Utils\Crypto::loadPrivateKey($this->config, false, 'metadata.sign.');
+            $public = Utils\Crypto::loadPublicKey($this->config, false, 'metadata.sign.');
+            $matrix[] = [
+                'required' => 'required',
+                'descr' => Translate::noop('Matching key-pair for signing metadata'),
+                'enabled' => $this->matchingKeyPair($public['PEM'], [$private['PEM'], $private['password']]),
+            ];
+
+        }
+
         return $matrix;
     }
 
@@ -436,4 +473,17 @@ class Config
 
         return $warnings;
     }
+
+
+    /**
+     * Test whether public & private key are a matching pair
+     *
+     * @param string $publicKey
+     * @param string $privateKey
+     * @param string|null $password
+     * @return bool
+     */
+    private function matchingKeyPair(string $publicKey, string $privateKey, ?string $password) : bool {
+        return openssl_x509_check_private_key($publicKey, [$privateKey, $password]);
+    }
 }
-- 
GitLab