Allow to configure PBKDF (#163)

* Allow to configure PBKDF.

* Also add PBKDF options to key add operation.

* Simplify code.

* Update plugins/modules/luks_device.py

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>

* Fix indent.

* Use more of the options.

* Bump iteration count.

* Increase memory limit.

* Fall back to default PBKDF.

* Apply suggestions from code review

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>
This commit is contained in:
Felix Fontein
2021-01-22 13:21:03 +01:00
committed by GitHub
parent 3ca4c48b00
commit d921ff1f68
7 changed files with 133 additions and 3 deletions

View File

@@ -170,6 +170,47 @@ options:
- "Will only be used on container creation."
type: str
version_added: '1.1.0'
pbkdf:
description:
- This option allows the user to configure the Password-Based Key Derivation
Function (PBKDF) used.
- Will only be used on container creation, and when adding keys to an existing
container.
type: dict
version_added: '1.4.0'
suboptions:
iteration_time:
description:
- Specify the iteration time used for the PBKDF.
- Note that this is in B(seconds), not in milliseconds as on the
command line.
- Mutually exclusive with I(iteration_count).
type: float
iteration_count:
description:
- Specify the iteration count used for the PBKDF.
- Mutually exclusive with I(iteration_time).
type: int
algorithm:
description:
- The algorithm to use.
- Only available for the LUKS 2 format.
choices:
- argon2i
- argon2id
- pbkdf2
type: str
memory:
description:
- The memory cost limit in kilobytes for the PBKDF.
- This is not used for PBKDF2, but only for the Argon PBKDFs.
type: int
parallel:
description:
- The parallel cost for the PBKDF. This is the number of threads that
run in parallel.
- This is not used for PBKDF2, but only for the Argon PBKDFs.
type: int
requirements:
- "cryptsetup"
@@ -399,7 +440,19 @@ class CryptHandler(Handler):
result = self._run_command([self._cryptsetup_bin, 'isLuks', device])
return result[RETURN_CODE] == 0
def run_luks_create(self, device, keyfile, passphrase, keysize, cipher, hash_):
def _add_pbkdf_options(self, options, pbkdf):
if pbkdf['iteration_time'] is not None:
options.extend(['--iter-time', str(int(pbkdf['iteration_time'] * 1000))])
if pbkdf['iteration_count'] is not None:
options.extend(['--pbkdf-force-iterations', str(pbkdf['iteration_count'])])
if pbkdf['algorithm'] is not None:
options.extend(['--pbkdf', pbkdf['algorithm']])
if pbkdf['memory'] is not None:
options.extend(['--pbkdf-memory', str(pbkdf['memory'])])
if pbkdf['parallel'] is not None:
options.extend(['--pbkdf-parallel', str(pbkdf['parallel'])])
def run_luks_create(self, device, keyfile, passphrase, keysize, cipher, hash_, pbkdf):
# create a new luks container; use batch mode to auto confirm
luks_type = self._module.params['type']
label = self._module.params['label']
@@ -416,6 +469,8 @@ class CryptHandler(Handler):
options.extend(['--cipher', cipher])
if hash_ is not None:
options.extend(['--hash', hash_])
if pbkdf is not None:
self._add_pbkdf_options(options, pbkdf)
args = [self._cryptsetup_bin, 'luksFormat']
args.extend(options)
@@ -456,13 +511,15 @@ class CryptHandler(Handler):
% (device, result[STDERR]))
def run_luks_add_key(self, device, keyfile, passphrase, new_keyfile,
new_passphrase):
new_passphrase, pbkdf):
''' Add new key from a keyfile or passphrase to given 'device';
authentication done using 'keyfile' or 'passphrase'.
Raises ValueError when command fails.
'''
data = []
args = [self._cryptsetup_bin, 'luksAddKey', device]
if pbkdf is not None:
self._add_pbkdf_options(args, pbkdf)
if keyfile:
args.extend(['--key-file', keyfile])
@@ -691,6 +748,17 @@ def run_module():
type=dict(type='str', choices=['luks1', 'luks2']),
cipher=dict(type='str'),
hash=dict(type='str'),
pbkdf=dict(
type='dict',
options=dict(
iteration_time=dict(type='float'),
iteration_count=dict(type='int'),
algorithm=dict(type='str', choices=['argon2i', 'argon2id', 'pbkdf2']),
memory=dict(type='int'),
parallel=dict(type='int'),
),
mutually_exclusive=[('iteration_time', 'iteration_count')],
),
)
mutually_exclusive = [
@@ -738,6 +806,7 @@ def run_module():
module.params['keysize'],
module.params['cipher'],
module.params['hash'],
module.params['pbkdf'],
)
except ValueError as e:
module.fail_json(msg="luks_device error: %s" % e)
@@ -799,7 +868,8 @@ def run_module():
module.params['keyfile'],
module.params['passphrase'],
module.params['new_keyfile'],
module.params['new_passphrase'])
module.params['new_passphrase'],
module.params['pbkdf'])
except ValueError as e:
module.fail_json(msg="luks_device error: %s" % e)
result['changed'] = True