1717from archinstall .tui .types import Alignment , FrameProperties
1818
1919from ..menu .abstract_menu import AbstractSubMenu
20- from ..models .device_model import Fido2Device
20+ from ..models .device_model import DEFAULT_ITER_TIME , Fido2Device
2121from ..models .users import Password
2222from ..output import FormattedOutput
2323from ..utils .util import get_password
@@ -65,6 +65,14 @@ def _define_menu_options(self) -> list[MenuItem]:
6565 preview_action = self ._preview ,
6666 key = 'encryption_password' ,
6767 ),
68+ MenuItem (
69+ text = tr ('Iteration time' ),
70+ action = lambda x : select_iteration_time (x ),
71+ value = self ._enc_config .iter_time ,
72+ dependencies = [self ._check_dep_enc_type ],
73+ preview_action = self ._preview ,
74+ key = 'iter_time' ,
75+ ),
6876 MenuItem (
6977 text = tr ('Partitions' ),
7078 action = lambda x : select_partitions_to_encrypt (self ._device_modifications , x ),
@@ -120,6 +128,7 @@ def run(self, additional_title: str | None = None) -> DiskEncryption | None:
120128
121129 enc_type : EncryptionType | None = self ._item_group .find_by_key ('encryption_type' ).value
122130 enc_password : Password | None = self ._item_group .find_by_key ('encryption_password' ).value
131+ iter_time : int | None = self ._item_group .find_by_key ('iter_time' ).value
123132 enc_partitions = self ._item_group .find_by_key ('partitions' ).value
124133 enc_lvm_vols = self ._item_group .find_by_key ('lvm_volumes' ).value
125134
@@ -140,6 +149,7 @@ def run(self, additional_title: str | None = None) -> DiskEncryption | None:
140149 partitions = enc_partitions ,
141150 lvm_volumes = enc_lvm_vols ,
142151 hsm_device = self ._enc_config .hsm_device ,
152+ iter_time = iter_time or DEFAULT_ITER_TIME ,
143153 )
144154
145155 return None
@@ -153,6 +163,9 @@ def _preview(self, item: MenuItem) -> str | None:
153163 if (enc_pwd := self ._prev_password ()) is not None :
154164 output += f'\n { enc_pwd } '
155165
166+ if (iter_time := self ._prev_iter_time ()) is not None :
167+ output += f'\n { iter_time } '
168+
156169 if (fido_device := self ._prev_hsm ()) is not None :
157170 output += f'\n { fido_device } '
158171
@@ -214,6 +227,14 @@ def _prev_hsm(self) -> str | None:
214227 output += f' ({ fido_device .manufacturer } , { fido_device .product } )'
215228 return f'{ tr ("HSM device" )} : { output } '
216229
230+ def _prev_iter_time (self ) -> str | None :
231+ iter_time = self ._item_group .find_by_key ('iter_time' ).value
232+
233+ if iter_time and iter_time != DEFAULT_ITER_TIME :
234+ return f'{ tr ("Iteration time" )} : { iter_time } ms'
235+
236+ return None
237+
217238
218239def select_encryption_type (
219240 device_modifications : list [DeviceModification ],
@@ -354,3 +375,50 @@ def select_lvm_vols_to_encrypt(
354375 return volumes
355376
356377 return []
378+
379+
380+ def select_iteration_time (preset : int | None = None ) -> int | None :
381+ header = tr ('Enter iteration time for LUKS encryption (in milliseconds)' ) + '\n '
382+ header += tr ('Higher values increase security but slow down boot time' ) + '\n '
383+ header += tr (f'Default: { DEFAULT_ITER_TIME } ms, Recommended range: 1000-60000' ) + '\n '
384+
385+ def validate_iter_time (value : str | None ) -> str | None :
386+ if not value :
387+ return tr ('Iteration time cannot be empty' )
388+
389+ try :
390+ iter_time = int (value )
391+ if iter_time < 100 :
392+ return tr ('Iteration time must be at least 100ms' )
393+ if iter_time > 120000 :
394+ return tr ('Iteration time must be at most 120000ms' )
395+ return None
396+ except ValueError :
397+ return tr ('Please enter a valid number' )
398+
399+ try :
400+ from archinstall .tui .curses_menu import EditMenu
401+ from archinstall .tui .result import ResultType
402+ from archinstall .tui .types import Alignment
403+
404+ result = EditMenu (
405+ tr ('Iteration time (ms)' ),
406+ header = header ,
407+ alignment = Alignment .CENTER ,
408+ allow_skip = True ,
409+ default_text = str (preset ) if preset else str (DEFAULT_ITER_TIME ),
410+ validator = validate_iter_time ,
411+ ).input ()
412+
413+ match result .type_ :
414+ case ResultType .Skip :
415+ return preset
416+ case ResultType .Selection :
417+ if not result .text ():
418+ return preset
419+ return int (result .text ())
420+ case ResultType .Reset :
421+ return None
422+ except ImportError :
423+ # Fallback for non-interactive mode
424+ return preset or DEFAULT_ITER_TIME
0 commit comments