vpnmain.cgi: Allow for using a hybrid of ML-KEM 1024 and Curve 448
Commit Message
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(-)
@@ -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");