vpnmain.cgi: Allow for using a hybrid of ML-KEM 1024 and Curve 448

Message ID 45180abd-110b-4faa-b089-b7ee7db2c990@ipfire.org
State Staged
Commit c2e5946599ce18bb6ee6f7f27a99fbccf6e88693
Headers
Series vpnmain.cgi: Allow for using a hybrid of ML-KEM 1024 and Curve 448 |

Commit Message

Peter Müller 29 Oct 2026, 2:17 p.m. UTC
This matches efforts such as https://datatracker.ietf.org/doc/html/draft-preussmattsson-tls-mlkem1024-x448-01/,
where the security level of ML-KEM 1024 is paired with Curve 448 rather
than x25519, to achive the same strength as 265-bit AES, for both the
traditional and post-quantum algorithm.

Curve 448 seems not as widely supported as x25519, however, hence
keeping the hybrid of ML-KEM 1024 and x25519 available for IPsec peers
who would otherwise have to fall back to weaker encryption.

Signed-off-by: Peter Müller <peter.mueller@ipfire.org>
---
 html/cgi-bin/vpnmain.cgi | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)
  

Patch

diff --git a/html/cgi-bin/vpnmain.cgi b/html/cgi-bin/vpnmain.cgi
index b1048a802..ad838083c 100644
--- a/html/cgi-bin/vpnmain.cgi
+++ b/html/cgi-bin/vpnmain.cgi
@@ -2,7 +2,7 @@ 
 ###############################################################################
 #                                                                             #
 # IPFire.org - A linux based firewall                                         #
-# Copyright (C) 2007-2025  IPFire Team  <info@ipfire.org>                     #
+# Copyright (C) 2007-2026  IPFire Team  <info@ipfire.org>                     #
 #                                                                             #
 # This program is free software: you can redistribute it and/or modify        #
 # it under the terms of the GNU General Public License as published by        #
@@ -2374,11 +2374,11 @@  END
 	#use default advanced value
 	$cgiparams{'IKE_ENCRYPTION'}		= 'chacha20poly1305|aes256gcm128|aes256'; #[18];
 	$cgiparams{'IKE_INTEGRITY'}		= 'sha2_512|sha2_256'; #[19];
-	$cgiparams{'IKE_GROUPTYPE'}             = 'x25519-ke1_mlkem1024|x25519-ke1_mlkem768|x25519-ke1_mlkem512|curve448|curve25519|e521|e384|4096|3072'; #[20];
+	$cgiparams{'IKE_GROUPTYPE'}             = 'curve448-ke1_mlkem1024|x25519-ke1_mlkem1024|x25519-ke1_mlkem768|x25519-ke1_mlkem512|curve448|curve25519|e521|e384|4096|3072'; #[20];
 	$cgiparams{'IKE_LIFETIME'}		= '3'; #[16];
 	$cgiparams{'ESP_ENCRYPTION'}		= 'chacha20poly1305|aes256gcm128|aes256'; #[21];
 	$cgiparams{'ESP_INTEGRITY'}		= 'sha2_512|sha2_256'; #[22];
-	$cgiparams{'ESP_GROUPTYPE'}             = 'x25519-ke1_mlkem1024|x25519-ke1_mlkem768|x25519-ke1_mlkem512|curve448|curve25519|e521|e384|4096|3072'; #[23];
+	$cgiparams{'ESP_GROUPTYPE'}             = 'curve448-ke1_mlkem1024|x25519-ke1_mlkem1024|x25519-ke1_mlkem768|x25519-ke1_mlkem512|curve448|curve25519|e521|e384|4096|3072'; #[23];
 	$cgiparams{'ESP_KEYLIFE'}		= '1'; #[17];
 	$cgiparams{'COMPRESSION'}		= 'off'; #[13];
 	$cgiparams{'ONLY_PROPOSED'}		= 'on'; #[24];
@@ -2759,7 +2759,7 @@  if(($cgiparams{'ACTION'} eq _('Advanced')) ||
 			goto ADVANCED_ERROR;
 		}
 		foreach my $val (@temp) {
-			if ($val !~ /^(x25519-ke1_mlkem(1024|768|512)|curve448|curve25519|e521|e384|e256|e224|e192|e512bp|e384bp|e256bp|e224bp|768|1024|1536|2048|3072|4096|6144|8192)$/) {
+			if ($val !~ /^((x25519|curve448)-ke1_mlkem(1024|768|512)|curve448|curve25519|e521|e384|e256|e224|e192|e512bp|e384bp|e256bp|e224bp|768|1024|1536|2048|3072|4096|6144|8192)$/) {
 				$errormessage = _('Invalid Input');
 				goto ADVANCED_ERROR;
 			}
@@ -2800,7 +2800,7 @@  if(($cgiparams{'ACTION'} eq _('Advanced')) ||
 			goto ADVANCED_ERROR;
 		}
 		foreach my $val (@temp) {
-			if ($val !~ /^(x25519-ke1_mlkem(1024|768|512)|curve448|curve25519|e521|e384|e256|e224|e192|e512bp|e384bp|e256bp|e224bp|768|1024|1536|2048|3072|4096|6144|8192|none)$/) {
+			if ($val !~ /^((x25519|curve448)-ke1_mlkem(1024|768|512)|curve448|curve25519|e521|e384|e256|e224|e192|e512bp|e384bp|e256bp|e224bp|768|1024|1536|2048|3072|4096|6144|8192|none)$/) {
 				$errormessage = _('Invalid Input');
 				goto ADVANCED_ERROR;
 			}
@@ -2940,6 +2940,7 @@  if(($cgiparams{'ACTION'} eq _('Advanced')) ||
 	$checked{'IKE_INTEGRITY'}{'aesxcbc'} = '';
 	@temp = split('\|', $cgiparams{'IKE_INTEGRITY'});
 	foreach my $key (@temp) {$checked{'IKE_INTEGRITY'}{$key} = "selected='selected'"; }
+	$checked{'IKE_GROUPTYPE'}{'curve448-ke1_mlkem1024'} = '';
 	$checked{'IKE_GROUPTYPE'}{'x25519-ke1_mlkem1024'} = '';
 	$checked{'IKE_GROUPTYPE'}{'x25519-ke1_mlkem768'} = '';
 	$checked{'IKE_GROUPTYPE'}{'x25519-ke1_mlkem512'} = '';
@@ -2983,6 +2984,7 @@  if(($cgiparams{'ACTION'} eq _('Advanced')) ||
 	$checked{'ESP_INTEGRITY'}{'aesxcbc'} = '';
 	@temp = split('\|', $cgiparams{'ESP_INTEGRITY'});
 	foreach my $key (@temp) {$checked{'ESP_INTEGRITY'}{$key} = "selected='selected'"; }
+	$checked{'ESP_GROUPTYPE'}{'curve448-ke1_mlkem1024'} = '';
 	$checked{'ESP_GROUPTYPE'}{'x25519-ke1_mlkem1024'} = '';
 	$checked{'ESP_GROUPTYPE'}{'x25519-ke1_mlkem768'} = '';
 	$checked{'ESP_GROUPTYPE'}{'x25519-ke1_mlkem512'} = '';
@@ -3151,6 +3153,7 @@  if(($cgiparams{'ACTION'} eq _('Advanced')) ||
 			<td class='boldbase' width="15%">@{[ _('Group Type:') ]}</td>
 			<td class='boldbase'>
 				<select name='IKE_GROUPTYPE' multiple='multiple' size='6' style='width: 100%'>
+					<option value='curve448-ke1_mlkem1024' $checked{'IKE_GROUPTYPE'}{'curve448-ke1_mlkem1024'}>Curve 448 x ML-KEM 1024 (256 bit)</option>
 					<option value='x25519-ke1_mlkem1024' $checked{'IKE_GROUPTYPE'}{'x25519-ke1_mlkem1024'}>Curve 25519 x ML-KEM 1024 (256 bit)</option>
 					<option value='x25519-ke1_mlkem768' $checked{'IKE_GROUPTYPE'}{'x25519-ke1_mlkem768'}>Curve 25519 x ML-KEM 768 (192 bit)</option>
 					<option value='x25519-ke1_mlkem512' $checked{'IKE_GROUPTYPE'}{'x25519-ke1_mlkem512'}>Curve 25519 x ML-KEM 512 (128 bit)</option>
@@ -3177,6 +3180,7 @@  if(($cgiparams{'ACTION'} eq _('Advanced')) ||
 			</td>
 			<td class='boldbase'>
 				<select name='ESP_GROUPTYPE' multiple='multiple' size='6' style='width: 100%'>
+					<option value='curve448-ke1_mlkem1024' $checked{'ESP_GROUPTYPE'}{'curve448-ke1_mlkem1024'}>Curve 448 x ML-KEM 1024 (256 bit)</option>
 					<option value='x25519-ke1_mlkem1024' $checked{'ESP_GROUPTYPE'}{'x25519-ke1_mlkem1024'}>Curve 25519 x ML-KEM 1024 (256 bit)</option>
 					<option value='x25519-ke1_mlkem768' $checked{'ESP_GROUPTYPE'}{'x25519-ke1_mlkem768'}>Curve 25519 x ML-KEM 768 (192 bit)</option>
 					<option value='x25519-ke1_mlkem512' $checked{'ESP_GROUPTYPE'}{'x25519-ke1_mlkem512'}>Curve 25519 x ML-KEM 512 (128 bit)</option>
@@ -3771,7 +3775,7 @@  sub make_algos($$$$$) {
 				if ($mode eq "ike") {
 					push(@algo, $int);
 
-					if ($grp =~ m/^x25519-ke1_mlkem(\d+)$/) {
+					if ($grp =~ m/^(x25519|curve448)-ke1_mlkem(\d+)$/) {
 						push(@algo, "$grp");
 					} elsif ($grp =~ m/^e(.*)$/) {
 						push(@algo, "ecp$1");
@@ -3790,7 +3794,7 @@  sub make_algos($$$$$) {
 
 					if (!$pfs || $grp eq "none") {
 						# noop
-					} elsif ($grp =~ m/^x25519-ke1_mlkem(\d+)$/) {
+					} elsif ($grp =~ m/^(x25519|curve448)-ke1_mlkem(\d+)$/) {
 						push(@algo, "$grp");
 					} elsif ($grp =~ m/^e(.*)$/) {
 						push(@algo, "ecp$1");